├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── ShortcutMagic ├── .babelrc ├── .gitignore ├── Gruntfile.js ├── _config.yml ├── about │ ├── AboutView.jsx │ └── index.html ├── app.global.css ├── assets │ ├── admin-access.png │ ├── bubble-window.png │ ├── fuzzy-search.png │ ├── learn │ │ ├── execute.gif │ │ ├── expand-settings.gif │ │ ├── favorite.gif │ │ ├── font-size.gif │ │ ├── hide.gif │ │ ├── loading.gif │ │ └── search.gif │ ├── learning.png │ ├── library.png │ ├── reverse-search.png │ ├── sw_bubble_icon.png │ ├── sw_full_view_icon.png │ ├── sw_hidden_icon.png │ ├── wizard.icns │ ├── wizard.ico │ ├── wizard.png │ └── wizard_16x16.png ├── attributions.txt ├── background │ ├── index.html │ ├── index.js │ ├── listener.html │ ├── listener.js │ └── parseShortcuts.js ├── bubble │ ├── BubbleView.jsx │ └── index.html ├── components │ ├── Home.css │ ├── Home.jsx │ └── index.html ├── fonts │ ├── photon-entypo.eot │ ├── photon-entypo.svg │ ├── photon-entypo.ttf │ └── photon-entypo.woff ├── gifRecorder │ ├── GifRecorderView.jsx │ └── gifRecorder.html ├── index.js ├── learn │ ├── LearnView.jsx │ └── index.html ├── main.js ├── package-lock.json ├── package.json ├── sass │ ├── appify.scss │ ├── bars.scss │ ├── base.scss │ ├── button-groups.scss │ ├── buttons.scss │ ├── docs.scss │ ├── forms.scss │ ├── grid.scss │ ├── icons.scss │ ├── images.scss │ ├── lists.scss │ ├── mixins.scss │ ├── navs.scss │ ├── normalize.scss │ ├── photon.scss │ ├── tables.scss │ ├── tabs.scss │ ├── utilities.scss │ └── variables.scss ├── settings │ ├── MiniSettingsView.jsx │ ├── SettingsView.jsx │ ├── index.html │ ├── miniIndex.html │ ├── settings.js │ └── settingsWorker.js ├── shared │ ├── appSwitchListener.js │ ├── executeMenu.scpt │ ├── executeMenuItem.js │ ├── executeShortcut.js │ ├── executeShortcut.scpt │ ├── readAllMenuItems.scpt │ ├── readAllShortcuts.js │ ├── readAppName.scpt │ ├── readMenuItems.scpt │ ├── readShortcuts.js │ ├── testAccessibility.scpt │ └── unwrapShortcuts.js ├── shortcutmagic.js ├── sign_app.sh ├── survey │ ├── SurveyView.jsx │ └── index.html ├── tooltip │ ├── TooltipView.jsx │ └── tooltip.html ├── utilities │ └── browserWindow.js ├── vendor │ └── photonkit │ │ ├── CONTRIBUTING.md │ │ ├── LICENSE │ │ ├── README.md │ │ └── docs │ │ ├── LICENSE │ │ ├── _includes │ │ ├── footer.html │ │ ├── header.html │ │ ├── javascript.html │ │ └── nav.html │ │ ├── _layouts │ │ └── default.html │ │ ├── assets │ │ ├── css │ │ │ ├── docs.css │ │ │ ├── docs.min.css │ │ │ ├── normalize.css │ │ │ └── pygments-manni.css │ │ ├── img │ │ │ ├── avatar.jpg │ │ │ ├── avatar2.png │ │ │ ├── avatar3.jpg │ │ │ ├── avatar4.jpg │ │ │ ├── avatar5.png │ │ │ ├── avatar6.jpg │ │ │ ├── avatar7.jpg │ │ │ └── photo-couch.png │ │ └── js │ │ │ ├── docs.js │ │ │ ├── jq.js │ │ │ └── sticky.js │ │ ├── components.html │ │ ├── components │ │ ├── bars-actions.html │ │ ├── bars-tabs.html │ │ ├── bars.html │ │ ├── basic-sidebar.html │ │ ├── basic-window.html │ │ ├── button-groups.html │ │ ├── buttons-large.html │ │ ├── buttons-mini.html │ │ ├── buttons.html │ │ ├── common-layout.html │ │ ├── forms.html │ │ ├── icons.html │ │ ├── lists.html │ │ ├── mini-sidebar.html │ │ ├── navs.html │ │ ├── tables.html │ │ └── three-paned.html │ │ ├── demo-app.html │ │ ├── getting-started.html │ │ └── index.html └── welcome │ ├── WelcomeView.jsx │ ├── index.html │ └── welcome.js └── _config.yml /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Helping the ShortcutMagic community 2 | 3 | ShortcutMagic was built with the purpose to help us humans use computers, no matter the skill level or technological understanding. 4 | 5 | 6 | There are many ways everyone can help and contribute to this vision. Sharing knowledge makes it better for everyone, makes it easier to learn, and easier to understand. 7 | 8 | - If you are a beginner, what and how you learn is valuable to share. Other beginners could find huge help in what you are learning. 9 | - If you are starting to get comfortable with the programs you use, your "advice to your former self" can help anyone striving to be at your level. 10 | - If you are an expert, everyone would love to learn your tricks. The little things you do differently, the small wins that make everything come together and you really use a program to its fullest. 11 | 12 | 13 | We use gifs as much as possible because it shows exactly what is happening. One of the best ways you can help is by simply recording a gif! And it is all built into ShortcutMagic - click a button to start recording, do your thing and click the stop button. That's it! 14 | 15 | Other ways to contribute are: 16 | 17 | - Create an account and let ShortcutMagic anonymously upload usage metrics, to help automatically adjust everyone's difficulty level _(not yet available)_ 18 | - Play around and test hiding useless shortcuts, adding your favorites, rating them, write a little comment here and there _(some available)_ 19 | - Introduce a friend or a loved one to ShortcutMagic! If there is a way we can help them use computers better, it's worth trying! 20 | - Submit ideas and wish lists https://github.com/codeluggage/ShortcutMagic/issues 21 | - Report a bug when you see one https://github.com/codeluggage/ShortcutMagic/issues 22 | - Share your experiences using ShortcutMagic with the world 23 | - Take a look at the code, maybe even try your hand at a little change! There is no danger and you can't ruin anything. Exploring the code and changing something can be fun, and that code might even become part of the ShortcutMagic everyone uses! 24 | - Contribute to Electron and Chromium, the foundation that ShortcutMagic was built on 25 | 26 | Thank you so much for considering to contribute to ShortcutMagic. It is a domino effect that keeps getting stronger, because your help will in turn help so many others. -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016-2017 Matias Forbord 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | 11 | 12 | 13 | All files located in the node_modules and external directories are 14 | externally maintained libraries used by this software which have their 15 | own licenses. 16 | 17 | Please read them because they may not be the same as this license. 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShortcutMagic 2 | 3 | ShortcutMagic is a productivity program to help you learn shortcuts. It does this by showing suggetsions, either when the program changes or a set time afterwards. 4 | 5 | ![Suggestion](./ShortcutMagic/assets/bubble-window.png?raw=true "Suggestion") 6 | 7 | Every action it can find, both those with shortcuts and those without, are added to the main shortcut library window: 8 | 9 | ![Library](./ShortcutMagic/assets/library.png?raw=true "Library") 10 | 11 | ## How does it work? 12 | 13 | It uses the accessibility API's through AppleScript to parse every action item listed under the menues and adds them to a simple local database. The global notifications for app switching and launching are used through Objective-C, so ShortcutMagic knows when to parse new shortcuts and when to show the suggestion. 14 | 15 | The majority of the code is in Javascript. [Node.js](https://github.com/nodejs/node), running in [Electron](https://github.com/electron/electron), rendered with [React.js](https://github.com/facebook/react). 16 | 17 | ## Can I contribute to this repo? Can I use the code? 18 | 19 | Yes and yes! The code freely available under the MIT license, and there are issues listed on [issues](https://github.com/codeluggage/ShortcutMagic/issues). 20 | 21 | ## License 22 | 23 | [MIT](https://github.com/codeluggage/ShortcutMagic/blob/master/LICENSE) 24 | -------------------------------------------------------------------------------- /ShortcutMagic/.babelrc: -------------------------------------------------------------------------------- 1 | { "presets": ["es2015", "react"] } 2 | -------------------------------------------------------------------------------- /ShortcutMagic/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | 5 | # Runtime data 6 | pids 7 | *.pid 8 | *.seed 9 | 10 | # Directory for instrumented libs generated by jscoverage/JSCover 11 | lib-cov 12 | 13 | # Coverage directory used by tools like istanbul 14 | coverage 15 | 16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 17 | .grunt 18 | 19 | # node-waf configuration 20 | .lock-wscript 21 | 22 | # Compiled binary addons (http://nodejs.org/api/addons.html) 23 | build/Release 24 | 25 | # Electron build folder 26 | ShortcutMagic-mac-darwin-x64/ 27 | 28 | # Dependency directory 29 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git 30 | node_modules 31 | 32 | # OSX 33 | .DS_Store 34 | 35 | # App packaged 36 | dist 37 | release 38 | main.js.map 39 | 40 | # Database 41 | db/*.db 42 | -------------------------------------------------------------------------------- /ShortcutMagic/Gruntfile.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Photon's Gruntfile 3 | * Copyright 2015 Connor Sears 4 | * Licensed under MIT (https://github.com/connors/photon/blob/master/LICENSE) 5 | */ 6 | 7 | module.exports = function(grunt) { 8 | 'use strict'; 9 | 10 | // Force use of Unix newlines 11 | grunt.util.linefeed = '\n'; 12 | 13 | // Project configuration. 14 | grunt.initConfig({ 15 | pkg: grunt.file.readJSON('package.json'), 16 | 17 | // Metadata. 18 | meta: { 19 | distPath: 'dist/', 20 | docsAssetsPath: 'docs/assets/', 21 | docsDistPath: 'docs/dist/', 22 | docsPath: 'docs/', 23 | srcPath: 'sass/', 24 | }, 25 | 26 | banner: '/*!\n' + 27 | ' * =====================================================\n' + 28 | ' * Photon v<%= pkg.version %>\n' + 29 | ' * Copyright <%= grunt.template.today("yyyy") %> <%= pkg.author %>\n' + 30 | ' * Licensed under <%= pkg.license %> (https://github.com/connors/proton/blob/master/LICENSE)\n' + 31 | ' *\n' + 32 | ' * v<%= pkg.version %> designed by @connors.\n' + 33 | ' * =====================================================\n' + 34 | ' */\n', 35 | 36 | clean: { 37 | dist: ['<%= meta.distPath %>/css', '<%= meta.docsDistPath %>/css'] 38 | }, 39 | 40 | sass: { 41 | options: { 42 | sourcemap: 'none', 43 | style: 'expanded', 44 | unixNewlines: true 45 | }, 46 | core: { 47 | src: 'sass/photon.scss', 48 | dest: '<%= meta.distPath %>css/<%= pkg.name %>.css' 49 | }, 50 | docs: { 51 | src: 'sass/docs.scss', 52 | dest: '<%= meta.docsAssetsPath %>css/docs.css' 53 | } 54 | }, 55 | 56 | usebanner: { 57 | dist: { 58 | options: { 59 | position: 'top', 60 | banner: '<%= banner %>' 61 | }, 62 | files: { 63 | src: [ 64 | '<%= meta.distPath %>css/*.css' 65 | ] 66 | } 67 | } 68 | }, 69 | 70 | copy: { 71 | fonts: { 72 | expand: true, 73 | src: 'fonts/*', 74 | dest: '<%= meta.distPath %>' 75 | }, 76 | docs: { 77 | expand: true, 78 | cwd: '<%= meta.distPath %>', 79 | src: [ 80 | '**/*' 81 | ], 82 | dest: '<%= meta.docsDistPath %>' 83 | } 84 | }, 85 | 86 | cssmin: { 87 | options: { 88 | keepSpecialComments: '*' // keep all important comments 89 | }, 90 | docs: { 91 | src: [ 92 | '<%= meta.docsAssetsPath %>css/docs.css', 93 | '<%= meta.docsAssetsPath %>css/pygments-manni.css', 94 | '<%= meta.docsAssetsPath %>css/normalize.css' 95 | ], 96 | dest: '<%= meta.docsAssetsPath %>css/docs.min.css' 97 | } 98 | }, 99 | 100 | watch: { 101 | options: { 102 | hostname: 'localhost', 103 | livereload: true, 104 | port: 8000 105 | }, 106 | css: { 107 | files: '<%= meta.srcPath %>**/*.scss', 108 | tasks: ['dist-css', 'copy'] 109 | }, 110 | html: { 111 | files: '<%= meta.docsPath %>**', 112 | tasks: ['jekyll'] 113 | } 114 | }, 115 | 116 | jekyll: { 117 | options: { 118 | config: '_config.yml' 119 | }, 120 | docs: {}, 121 | github: { 122 | options: { 123 | raw: 'github: true' 124 | } 125 | } 126 | }, 127 | 128 | connect: { 129 | site: { 130 | options: { 131 | base: '_site/', 132 | hostname: 'localhost', 133 | livereload: true, 134 | open: true, 135 | port: 8000 136 | } 137 | } 138 | } 139 | 140 | }); 141 | 142 | 143 | // Load the plugins 144 | require('load-grunt-tasks')(grunt, { scope: 'devDependencies' }); 145 | require('time-grunt')(grunt); 146 | 147 | // Tasks 148 | grunt.registerTask('dist-css', ['sass', 'usebanner', 'cssmin']); 149 | grunt.registerTask('dist', ['clean', 'dist-css', 'copy']); 150 | grunt.registerTask('server', ['dist', 'jekyll:docs', 'connect', 'watch']); 151 | 152 | grunt.registerTask('default', ['dist']); 153 | }; 154 | -------------------------------------------------------------------------------- /ShortcutMagic/_config.yml: -------------------------------------------------------------------------------- 1 | # Meta data 2 | name: Photon 3 | authors: Connor Sears 4 | description: Build desktop apps with simple HTML and CSS components. 5 | 6 | # Dependencies 7 | highlighter: rouge 8 | 9 | # Permalinks 10 | permalink: pretty 11 | 12 | # Server 13 | source: docs 14 | port: 4000 15 | url: http://photonkit.com 16 | -------------------------------------------------------------------------------- /ShortcutMagic/about/AboutView.jsx: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | 3 | import React, { Component } from 'react'; 4 | import ReactDOM from 'react-dom'; 5 | import { shell } from 'electron'; 6 | 7 | export default class AboutView extends Component { 8 | render() { 9 | return ( 10 |
18 | 21 | 22 |

About ShortcutMagic

23 | 24 |
25 | ShortcutMagic is an open project. You can contribute! 26 |
27 |
28 | Check out the { 29 | shell.openExternal('https://github.com/codeluggage/ShortcutMagic'); 30 | }}>code! 31 |
32 | Report something { 33 | shell.openExternal('https://github.com/codeluggage/ShortcutMagic/issues'); 34 | }}>missing or not working. 35 |
36 | Have a { 37 | shell.openExternal('https://github.com/codeluggage/ShortcutMagic/blob/master/CONTRIBUTING.md'); 38 | }}>cool idea or request? 39 |
40 |
41 | I would love to hear your feedback! 42 |
43 |
44 |
45 |
46 | ); 47 | } 48 | }; 49 | 50 | window.onload = function(){ 51 | ReactDOM.render(, document.getElementById("about-root")); 52 | }; 53 | -------------------------------------------------------------------------------- /ShortcutMagic/about/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /ShortcutMagic/app.global.css: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | @keyframes fadein { 6 | from { 7 | opacity: 0; 8 | } 9 | to { 10 | opacity: 1; 11 | } 12 | } 13 | 14 | .app { 15 | /* Disable text selection, or your app will feel like a web page */ 16 | -webkit-user-select: none; 17 | -webkit-app-region: drag; 18 | 19 | /* Cover the whole window */ 20 | height: 100%; 21 | 22 | /* Make sure this matches the native window background color that you pass to 23 | * electron.BrowserWindow({...}), otherwise your app startup will look janky. */ 24 | /*background: rgb(40, 40, 40);*/ 25 | 26 | /* Smoother startup */ 27 | animation: fadein 0.5s; 28 | } 29 | 30 | body { 31 | padding: 5px; 32 | /*background-color: rgba(050,050,050,0.4);*/ 33 | -webkit-app-region: drag; 34 | list-style-type: none; 35 | } 36 | 37 | .simple-button { 38 | align-self: flex-start; 39 | margin-right: 1em; 40 | border: 2px solid; 41 | border-radius: 4px; 42 | font: caption; 43 | font-size: 1.2em; 44 | margin-bottom: 10px; 45 | margin-left: 10px; 46 | margin-right: 10px; 47 | /*background-color: transparent;*/ 48 | /*border-color: hsl(0,0%,88%);*/ 49 | } 50 | .simple-button:focus { 51 | outline: none; 52 | /*background-color: white;*/ 53 | } 54 | .simple-button:active { 55 | /*border-color: hsl(0,0%,88%);*/ 56 | border-color: #000000 57 | } 58 | 59 | input { 60 | font-family:FontAwesome; 61 | } 62 | 63 | /*.simple-button-left simple-button { 64 | 65 | } 66 | 67 | .simple-button-right simple-button { 68 | 69 | } 70 | */ 71 | .filter-list { 72 | margin: auto; 73 | /*background: #3498db;*/ 74 | /*background-color:rgba(120,120,100,0.2); /*#D0D0D088/* hsl(0,0%,85%);*/*/ 75 | border-radius: 5px; 76 | } 77 | 78 | .filter-list input { 79 | width: 100%; 80 | display: block; 81 | padding: 10px; 82 | border-radius: 5px; 83 | border: 0; 84 | font-size: 1.5em; 85 | border: 1px solid #afafaf; 86 | } 87 | 88 | .filter-list input:focus { 89 | outline: none; 90 | border: 1px solid #afafaf; 91 | } 92 | 93 | .filter-list ul li{ 94 | color: #fff; 95 | padding: 10px 20px; 96 | border: 1px solid #afafaf; 97 | } 98 | 99 | .filter-list ul li:hover { 100 | /*background: #222980b9;*/ 101 | /*background: #FFFFFF;*/ 102 | border: 1px solid #afafaf; 103 | /*background: #000000;*/ 104 | } 105 | 106 | 107 | /* react-tab-view */ 108 | 109 | .react-tabs { 110 | margin: 0; 111 | padding: 1em; 112 | font-size: 150%; 113 | font-weight: 200; 114 | line-height: 1.5; 115 | } 116 | 117 | .react-tabs .hidden { 118 | display: none; 119 | } 120 | 121 | .react-tabs .react-tab { 122 | background: rgb(250, 250, 250); 123 | margin: 1em auto; 124 | border: 1px solid #ddd; 125 | padding: 1em; 126 | } 127 | 128 | .react-tabs tab-content { 129 | width: 80%; 130 | } 131 | 132 | .hidden { 133 | display: none; 134 | } 135 | 136 | .react-tabs ul{ 137 | margin: 0; 138 | padding: 0; 139 | list-style-type: none; 140 | text-align: center; 141 | } 142 | 143 | .react-tabs ul li { 144 | display: inline; 145 | } 146 | 147 | .react-tabs a { 148 | text-decoration: none; 149 | padding: .5em; 150 | color: #fff; 151 | background-color: #ddd; 152 | } 153 | 154 | .react-tabs .selected a { 155 | background-color: #b7b7b7 !important; 156 | color: #fff !important; 157 | font-weight: bold; 158 | } 159 | 160 | .react-tabs a:hover { 161 | color: #fff; 162 | background-color: #b7b7b7; 163 | } 164 | -------------------------------------------------------------------------------- /ShortcutMagic/assets/admin-access.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/admin-access.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/bubble-window.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/bubble-window.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/fuzzy-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/fuzzy-search.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/learn/execute.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/learn/execute.gif -------------------------------------------------------------------------------- /ShortcutMagic/assets/learn/expand-settings.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/learn/expand-settings.gif -------------------------------------------------------------------------------- /ShortcutMagic/assets/learn/favorite.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/learn/favorite.gif -------------------------------------------------------------------------------- /ShortcutMagic/assets/learn/font-size.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/learn/font-size.gif -------------------------------------------------------------------------------- /ShortcutMagic/assets/learn/hide.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/learn/hide.gif -------------------------------------------------------------------------------- /ShortcutMagic/assets/learn/loading.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/learn/loading.gif -------------------------------------------------------------------------------- /ShortcutMagic/assets/learn/search.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/learn/search.gif -------------------------------------------------------------------------------- /ShortcutMagic/assets/learning.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/learning.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/library.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/reverse-search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/reverse-search.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/sw_bubble_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/sw_bubble_icon.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/sw_full_view_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/sw_full_view_icon.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/sw_hidden_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/sw_hidden_icon.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/wizard.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/wizard.icns -------------------------------------------------------------------------------- /ShortcutMagic/assets/wizard.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/wizard.ico -------------------------------------------------------------------------------- /ShortcutMagic/assets/wizard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/wizard.png -------------------------------------------------------------------------------- /ShortcutMagic/assets/wizard_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/assets/wizard_16x16.png -------------------------------------------------------------------------------- /ShortcutMagic/attributions.txt: -------------------------------------------------------------------------------- 1 | Icon made by Freepik from www.flaticon.com: wizard.png - http://www.flaticon.com/free-icon/witch_207766 2 | -------------------------------------------------------------------------------- /ShortcutMagic/background/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ShortcutMagic/background/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const { ipcRenderer } = require('electron'); 4 | const executeMenuItem = require('../shared/executeMenuItem'); 5 | const executeShortcut = require('../shared/executeShortcut'); 6 | 7 | 8 | window.onload = function () { 9 | ipcRenderer.on('webview-execute-menu-item', (event, appName, listItem, menu) => { 10 | if (!appName) { 11 | executeMenuItem(appName, listItem, menu); 12 | } 13 | }); 14 | 15 | // This handler works sync not async 16 | ipcRenderer.on('read-last-app-name', (event) => { 17 | event.returnValue = readShortcuts.readAppName(); 18 | }); 19 | 20 | ipcRenderer.on('webview-execute-shortcut', (event, appName, listItem) => { 21 | console.log("webview-execute-shortcut called with ", appName, listItem); 22 | executeShortcut(appName, listItem); 23 | }); 24 | }; 25 | -------------------------------------------------------------------------------- /ShortcutMagic/background/listener.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ShortcutMagic/background/listener.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const { ipcRenderer } = require('electron'); 3 | const appSwitchListener = require('../shared/appSwitchListener'); 4 | 5 | window.onload = function () { 6 | appSwitchListener(function(appName) { 7 | ipcRenderer.send('main-app-switched-notification', appName); 8 | }); 9 | }; 10 | -------------------------------------------------------------------------------- /ShortcutMagic/background/parseShortcuts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const readShortcutsObj = require('../shared/readShortcuts'); 4 | const readShortcuts = readShortcutsObj(); 5 | 6 | 7 | module.exports = function(appName, cb) { 8 | if (appName) { 9 | cb(readShortcuts.readShortcuts(appName)); 10 | } 11 | }; 12 | -------------------------------------------------------------------------------- /ShortcutMagic/bubble/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 |
12 |
13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /ShortcutMagic/components/Home.css: -------------------------------------------------------------------------------- 1 | body, html { 2 | width: 100%; 3 | padding: 0; 4 | margin: 0; 5 | /*background-color: #282828*/ 6 | } 7 | .base { 8 | font: caption; 9 | /*padding: 10px;*/ 10 | box-sizing: border-box; 11 | width: 100%; 12 | height: 100%; 13 | } 14 | .base ul { 15 | list-style-type: none; 16 | margin: auto; 17 | width: 420px; 18 | max-width: 100%; 19 | padding: 15px; 20 | border: 1px dotted #999797; 21 | margin-top: 2.5%; 22 | } 23 | .base ul li { 24 | padding: 0; 25 | margin-bottom: 5px; 26 | } 27 | .base ul li:last-child { 28 | margin-bottom: 0; 29 | } 30 | .base h3 { 31 | color: #999797; 32 | text-align: center; 33 | display: block; 34 | margin-bottom: 10px; 35 | padding-bottom: 0; 36 | } 37 | .base .track { 38 | min-height: 87px; 39 | margin: 0; 40 | padding: 0; 41 | } 42 | .base .track:hover { 43 | background-color: #201F1F 44 | } 45 | .base .thumb { 46 | display: block; 47 | float: left; 48 | width: 87px; 49 | height: 87px; 50 | margin-right: 10px; 51 | background-size: cover; 52 | background-position: center; 53 | } 54 | .base .info { 55 | display: block; 56 | float: left; 57 | } 58 | .info a { 59 | text-decoration: none; 60 | } 61 | .info .title { 62 | font-size: 16px; 63 | color: #FFFFFF; 64 | line-height: 22px; 65 | margin-top: 5px; 66 | margin-bottom: 3px; 67 | display: block; 68 | } 69 | .info .artist { 70 | font-size: 14px; 71 | color: #999797; 72 | line-height: 15px; 73 | margin-bottom: 5px; 74 | display: block; 75 | } 76 | .info .timestamp { 77 | font-size: 12px; 78 | color: #999797; 79 | line-height: 15px; 80 | display: block; 81 | } 82 | .base-appear { 83 | transform: translateY(-10px); 84 | opacity: 0.01; 85 | } 86 | .base-appear.base-appear-active { 87 | opacity: 1; 88 | transform: translateY(0); 89 | transition: transform 300ms ease-in, opacity 300ms ease-in; 90 | } 91 | -------------------------------------------------------------------------------- /ShortcutMagic/components/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /ShortcutMagic/fonts/photon-entypo.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/fonts/photon-entypo.eot -------------------------------------------------------------------------------- /ShortcutMagic/fonts/photon-entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/fonts/photon-entypo.ttf -------------------------------------------------------------------------------- /ShortcutMagic/fonts/photon-entypo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/fonts/photon-entypo.woff -------------------------------------------------------------------------------- /ShortcutMagic/gifRecorder/GifRecorderView.jsx: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | import React, { Component } from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | import { ipcRenderer, remote } from 'electron'; 5 | 6 | export default class GifRecorderView extends Component { 7 | componentWillMount() { 8 | ipcRenderer.on('recording-for-shortcut-in-path', (event, listItem, gifPath, appName) => { 9 | this.setState({ 10 | appName: appName, 11 | listItem: listItem, 12 | shortcut: listItem.name, 13 | recordPath: gifPath, 14 | gif: null, 15 | }); 16 | }); 17 | 18 | ipcRenderer.on('file-detected', (event, path) => { 19 | this.setState({ 20 | gif: path 21 | }); 22 | }); 23 | } 24 | 25 | render() { 26 | let queryParameters = ""; 27 | if (this.state) { 28 | queryParameters = `?app=${this.state.appName}&shortcut=${this.state.shortcut}&gif=${this.state.gifPath}`; 29 | } 30 | 31 | let remoteUrl = (process.env.NODE_ENV === "development") ? `http://localhost:3000/upload${queryParameters}` : 32 | `https://shortcutmagic.meteorapp.com/upload${queryParameters}`; 33 | 34 | return ( 35 |
36 | 41 |
42 | ); 43 | 44 | // html, body { 45 | // height: 100%; 46 | // margin: 0; 47 | // } 48 | // 49 | // div { 50 | // display: flex; 51 | // flex-direction: column; 52 | // justify-content: center; 53 | // align-items: center; 54 | // height: 100%; 55 | // } 56 | //
57 | //

58 | // David 59 | //

60 | //
61 | 62 | 63 | return ( 64 |
67 |
75 |

Found gif! Is this the one you want to add to {this.state.shortcut}?

76 |
77 |
78 | 83 | 84 | 93 | 94 | 112 | 113 |
114 | 115 | 116 |
117 | ); 118 | } 119 | } 120 | 121 | window.onload = function(){ 122 | ReactDOM.render(, document.getElementById("gifRecorder-root")); 123 | }; 124 | -------------------------------------------------------------------------------- /ShortcutMagic/gifRecorder/gifRecorder.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ShortcutMagic 5 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /ShortcutMagic/learn/LearnView.jsx: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | import React, { Component } from 'react'; 3 | import Electron, { ipcRenderer, remote } from 'electron'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | export default class LearnView extends Component { 7 | render() { 8 | return ( 9 |
16 | 17 |

Learn ShortcutMagic

18 | 19 | 26 | 27 |
28 |

Loading shortcuts

29 | The first time you open or switch to a program, ShortcutMagic will load its shortcuts. 30 |
31 | It only needs to load the shortcuts once. After the first time, the shortcuts will load quickly. 32 |
33 |
34 | 35 |
36 |
37 | 38 | 53 | 54 |
55 |

Running

56 | You can run shortcuts 3 ways: 57 |
58 |
59 | * Using the original shortcut keys. These are listed in the ShortcutMagic window. 60 | * With ShortcutMagic focused, the 5 shortcuts at the top of the list can be ran with cmd+1, cmd+2 and so on 61 | * Clicking the play icon on the shortcut in the ShortcutMagic window. This tells ShortcutMagic to run the shortcut keys for you. 62 | 63 |
64 |
65 | 66 |
67 |

Favorites

68 | By clicking the star on a shortcut, you add it to your favorites. These always show up 69 |
70 | at the top of the list unless you are searching for something. 71 |
72 | Use this to make your most used shortcuts easily available from the top of the list any time. 73 |
74 |
75 | 76 |
77 |
78 | 79 |
80 |

Hiding

81 | You can hide the shortcuts you don't use by pressing the eye icon. 82 |
83 | This moves the shortcut to the bottom of the list, out of the way. 84 |
85 |
86 | 87 |
88 |
89 |
90 | ); 91 | } 92 | }; 93 | 94 | window.onload = function(){ 95 | ReactDOM.render(, document.getElementById("learn-root")); 96 | }; 97 | -------------------------------------------------------------------------------- /ShortcutMagic/learn/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /ShortcutMagic/main.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/main.js -------------------------------------------------------------------------------- /ShortcutMagic/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ShortcutMagic", 3 | "productName": "ShortcutMagic", 4 | "description": "ShortcutMagic is a simple tool to see every action in any program, and master them.", 5 | "version": "1.1.15", 6 | "license": "MIT", 7 | "private": true, 8 | "main": "shortcutmagic.js", 9 | "repository": "git@github.com:codeluggage/ShortcutMagic.git", 10 | "scripts": { 11 | "start": "NODE_ENV=production ./node_modules/.bin/electron shortcutmagic.js", 12 | "debug": "NODE_ENV=development ./node_modules/.bin/electron shortcutmagic.js --verbose --debug --icon=assets/wizard.icns", 13 | "pack": "NODE_ENV=production electron-packager . ShortcutMagic-mac --asar=false --overwrite --platform=darwin --arch=x64 --icon=assets/wizard.icns --prune=true --osx-sign.identity='Developer ID Application: Matias Forbord (A9ADPQA768)'", 14 | "pack-sign-mac": "npm run pack && rm -rf ShortcutMagic-mac-darwin-x64/ShortcutMagic-mac.app/Contents/Resources/app/db/* ShortcutMagic-mac-darwin-x64/ShortcutMagic-mac.app/Contents/Resources/app/sign_app.sh ShortcutMagic-mac-darwin-x64/ShortcutMagic-mac.app/Contents/Resources/app/dist/template-app && ./sign_app.sh ShortcutMagic-mac-darwin-x64/ShortcutMagic-mac.app ShortcutMagic-mac" 15 | }, 16 | "build": { 17 | "appId": "com.electron.shortcutmagic-mac", 18 | "mac": { 19 | "category": "Productivity" 20 | } 21 | }, 22 | "dependencies": { 23 | "babel-preset-es2015": "^6.24.1", 24 | "babel-preset-react": "^6.24.1", 25 | "babel-register": "^6.26.0", 26 | "deep-equal": "^1.0.1", 27 | "electron-localshortcut": "^2.0.2", 28 | "electron-log": "^2.2.11", 29 | "electron-osx-appearance": "^0.1.1", 30 | "electron-sudo": "^4.0.12", 31 | "font-awesome": "^4.7.0", 32 | "image-size": "^0.6.1", 33 | "mousetrap": "^1.6.1", 34 | "nedb": "^1.8.0", 35 | "nodobjc": "^2.1.0", 36 | "react": "^16.1.1", 37 | "react-color": "^2.13.8", 38 | "react-dom": "^16.1.1", 39 | "react-sortable-hoc": "^0.6.8", 40 | "react-tooltip": "^3.4.0" 41 | }, 42 | "devDependencies": { 43 | "devtron": "^1.4.0", 44 | "electron": "^1.7.9", 45 | "electron-packager": "^10.1.0", 46 | "electron-rebuild": "^1.6.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/appify.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Basic styles that make web elements behave more like native applications 3 | // ------------------------------------------------------------------------ 4 | 5 | * { 6 | cursor: default; 7 | -webkit-user-select: none; 8 | } 9 | 10 | // Forms 11 | input, 12 | textarea { 13 | -webkit-user-select: text; 14 | } 15 | 16 | form, 17 | input, 18 | optgroup, 19 | select, 20 | textarea { 21 | -webkit-user-select: text; 22 | -webkit-app-region: no-drag; 23 | } 24 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/bars.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Bars.css 3 | // -------------------------------------------------- 4 | 5 | .toolbar { 6 | min-height: 22px; 7 | box-shadow: inset 0 1px 0 #f5f4f5; 8 | @include linear-gradient(#e8e6e8, #d1cfd1); 9 | @include clearfix; 10 | } 11 | 12 | .toolbar-header { 13 | border-bottom: 1px solid $dark-border-color; 14 | 15 | .title { 16 | margin-top: 1px; 17 | } 18 | } 19 | 20 | .toolbar-footer { 21 | border-top: 1px solid $dark-border-color; 22 | -webkit-app-region: drag; 23 | } 24 | 25 | // Simple centered title to go in the toolbar 26 | .title { 27 | margin: 0; 28 | font-size: 12px; 29 | font-weight: 400; 30 | text-align: center; 31 | color: #555; 32 | cursor: default; 33 | } 34 | 35 | // Borderless toolbar for the clean look 36 | .toolbar-borderless { 37 | border-top: 0; 38 | border-bottom: 0; 39 | } 40 | 41 | // Buttons in toolbars 42 | .toolbar-actions { 43 | margin-top: 4px; 44 | margin-bottom: 3px; 45 | padding-right: 3px; 46 | padding-left: 3px; 47 | padding-bottom: 3px; 48 | -webkit-app-region: drag; 49 | @include clearfix; 50 | 51 | > .btn, 52 | > .btn-group { 53 | margin-left: 4px; 54 | margin-right: 4px; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/base.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Base styles 3 | // -------------------------------------------------- 4 | 5 | * { 6 | -webkit-box-sizing: border-box; 7 | box-sizing: border-box; 8 | } 9 | 10 | html { 11 | height: 100%; 12 | width: 100%; 13 | overflow: hidden; 14 | } 15 | 16 | body { 17 | height: 100%; 18 | padding: 0; 19 | margin: 0; 20 | font: caption; 21 | font-size: $font-size-default; 22 | line-height: $line-height-default; 23 | color: $gray-color; 24 | background-color: transparent; 25 | } 26 | 27 | hr { 28 | margin: 15px 0; 29 | overflow: hidden; 30 | background: transparent; 31 | border: 0; 32 | border-bottom: 1px solid $border-color; 33 | } 34 | 35 | // Typography 36 | h1, h2, h3, h4, h5, h6 { 37 | margin-top: 20px; 38 | margin-bottom: 10px; 39 | font-weight: 500; 40 | white-space: nowrap; 41 | overflow: hidden; 42 | text-overflow: ellipsis; 43 | } 44 | 45 | h1 { font-size: 36px; } 46 | h2 { font-size: 30px; } 47 | h3 { font-size: 24px; } 48 | h4 { font-size: 18px; } 49 | h5 { font-size: 14px; } 50 | h6 { font-size: 12px; } 51 | 52 | // Basic app structure 53 | .window { 54 | position: absolute; 55 | top: 0; 56 | right: 0; 57 | bottom: 0; 58 | left: 0; 59 | display: flex; 60 | flex-direction: column; 61 | background-color: $chrome-color; 62 | } 63 | 64 | .window-content { 65 | position: relative; 66 | overflow-y: auto; 67 | display: flex; 68 | flex: 1; 69 | } 70 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/button-groups.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Button-groups.css 3 | // Adapted from Bootstrap's button-groups.less (https://github.com/twbs/bootstrap/blob/master/less/button-groups.less) 4 | // -------------------------------------------------- 5 | 6 | // Button groups 7 | .btn-group { 8 | position: relative; 9 | display: inline-block; 10 | vertical-align: middle; // match .btn alignment given font-size hack above 11 | -webkit-app-region: no-drag; 12 | 13 | .btn { 14 | position: relative; 15 | float: left; 16 | 17 | // Bring the "active" button to the front 18 | &:focus, 19 | &:active{ 20 | z-index: 2; 21 | } 22 | 23 | &.active { 24 | z-index: 3; 25 | } 26 | } 27 | } 28 | 29 | // Prevent double borders when buttons are next to each other 30 | .btn-group { 31 | .btn + .btn, 32 | .btn + .btn-group, 33 | .btn-group + .btn, 34 | .btn-group + .btn-group { 35 | margin-left: -1px; 36 | } 37 | 38 | > .btn:first-child { 39 | border-top-right-radius: 0; 40 | border-bottom-right-radius: 0; 41 | } 42 | 43 | > .btn:last-child { 44 | border-top-left-radius: 0; 45 | border-bottom-left-radius: 0; 46 | } 47 | 48 | > .btn:not(:first-child):not(:last-child) { 49 | border-radius: 0; 50 | } 51 | 52 | .btn + .btn { 53 | border-left: 1px solid $dark-border-color; 54 | } 55 | 56 | .btn + .btn.active { 57 | border-left: 0; 58 | } 59 | 60 | // Selected state 61 | .active { 62 | color: #fff; 63 | border: 1px solid transparent; 64 | background-color: #6d6c6d; 65 | background-image: none; 66 | } 67 | 68 | // Invert the icon in the active button 69 | .active .icon { 70 | color: #fff; 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/buttons.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Buttons.css 3 | // -------------------------------------------------- 4 | 5 | .btn { 6 | display: inline-block; 7 | padding: 3px 8px; 8 | margin-bottom: 0; 9 | font-size: 12px; 10 | line-height: 1.4; 11 | text-align: center; 12 | white-space: nowrap; 13 | vertical-align: middle; 14 | cursor: default; 15 | background-image: none; 16 | border: 1px solid transparent; 17 | border-radius: $default-border-radius; 18 | box-shadow: 0 1px 1px rgba(0,0,0,.06); 19 | -webkit-app-region: no-drag; 20 | 21 | &:focus { 22 | outline: none; 23 | box-shadow: none; 24 | } 25 | } 26 | 27 | .btn-mini { 28 | padding: 2px 6px; 29 | } 30 | 31 | .btn-large { 32 | padding: 6px 12px; 33 | } 34 | 35 | .btn-form { 36 | padding-right: 20px; 37 | padding-left: 20px; 38 | } 39 | 40 | // Normal buttons 41 | .btn-default { 42 | color: $gray-color; 43 | border-top-color: $dark-border-color; 44 | border-right-color: $dark-border-color; 45 | border-bottom-color: $darker-bottom-border-color; 46 | border-left-color: $dark-border-color; 47 | @include linear-gradient(#fcfcfc, #f1f1f1); 48 | 49 | &:active { 50 | background-color: #ddd; 51 | background-image: none; 52 | } 53 | } 54 | 55 | // Button variations 56 | .btn-primary, 57 | .btn-positive, 58 | .btn-negative, 59 | .btn-warning { 60 | color: #fff; 61 | text-shadow: 0 1px 1px rgba(0,0,0,.1); 62 | } 63 | 64 | // For primary buttons 65 | .btn-primary { 66 | border-color: #388df8; 67 | border-bottom-color: darken(#388df8, 15%); 68 | @include linear-gradient(#6eb4f7, #1a82fb); 69 | 70 | &:active { 71 | @include linear-gradient(darken(#6eb4f7, 10%), darken(#1a82fb, 10%)); 72 | } 73 | } 74 | 75 | // For positive buttons 76 | .btn-positive { 77 | border-color: darken($positive-color, 10%); 78 | border-bottom-color: darken($positive-color, 15%); 79 | @include linear-gradient(lighten($positive-color, 10%), darken($positive-color, 10%)); 80 | 81 | &:active { 82 | @include linear-gradient($positive-color, darken($positive-color, 15%)); 83 | } 84 | } 85 | 86 | // For negative actions 87 | .btn-negative { 88 | border-color: darken($negative-color, 10%); 89 | border-bottom-color: darken($negative-color, 15%); 90 | @include linear-gradient(lighten($negative-color, 10%), darken($negative-color, 10%)); 91 | 92 | &:active { 93 | @include linear-gradient($negative-color, darken($negative-color, 15%)); 94 | } 95 | } 96 | 97 | // For warning actions 98 | .btn-warning { 99 | border-color: darken($warning-color, 10%); 100 | border-bottom-color: darken($warning-color, 15%); 101 | @include linear-gradient(lighten($warning-color, 10%), darken($warning-color, 10%)); 102 | 103 | &:active { 104 | @include linear-gradient($warning-color, darken($warning-color, 15%)); 105 | } 106 | } 107 | 108 | // Icons in buttons 109 | .btn .icon { 110 | float: left; 111 | width: 14px; 112 | height: 14px; 113 | margin-top: 1px; 114 | margin-bottom: 1px; 115 | color: #737475; 116 | font-size: 14px; 117 | line-height: 1; 118 | } 119 | 120 | // Add the margin next to the icon if there is text in the button too 121 | .btn .icon-text { 122 | margin-right: 5px; 123 | } 124 | 125 | // This utility class add a down arrow icon to the button 126 | .btn-dropdown:after { 127 | font-family: "photon-entypo"; 128 | margin-left: 5px; 129 | content: '\e873'; 130 | } 131 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/forms.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Forms.css 3 | // Adapted from Bootstrap's forms.less (https://github.com/twbs/bootstrap/blob/master/less/forms.less) 4 | // -------------------------------------------------- 5 | 6 | label { 7 | display: inline-block; 8 | font-size: $font-size-default; 9 | margin-bottom: 5px; 10 | white-space: nowrap; 11 | overflow: hidden; 12 | text-overflow: ellipsis; 13 | } 14 | 15 | input[type="search"] { 16 | box-sizing: border-box; 17 | } 18 | 19 | input[type="radio"], 20 | input[type="checkbox"] { 21 | margin: 4px 0 0; 22 | line-height: normal; 23 | } 24 | 25 | .form-control { 26 | display: inline-block; 27 | width: 100%; 28 | min-height: 25px; 29 | padding: $padding-less $padding; 30 | font-size: $font-size-default; 31 | line-height: $line-height-default; 32 | background-color: $chrome-color; 33 | border: 1px solid $border-color; 34 | border-radius: $default-border-radius; 35 | outline: none; 36 | 37 | &:focus { 38 | border-color: $focus-input-color; 39 | box-shadow: 0 0 0 3px $focus-input-color; 40 | } 41 | } 42 | 43 | // Reset height for `textarea`s 44 | textarea { 45 | height: auto; 46 | } 47 | 48 | // Form groups 49 | // 50 | // Designed to help with the organization and spacing of vertical forms. For 51 | // horizontal forms, use the predefined grid classes. 52 | 53 | .form-group { 54 | margin-bottom: 10px; 55 | } 56 | 57 | // Checkboxes and radios 58 | // 59 | // Indent the labels to position radios/checkboxes as hanging controls. 60 | 61 | .radio, 62 | .checkbox { 63 | position: relative; 64 | display: block; 65 | margin-top: 10px; 66 | margin-bottom: 10px; 67 | 68 | label { 69 | padding-left: 20px; 70 | margin-bottom: 0; 71 | font-weight: normal; 72 | } 73 | } 74 | 75 | .radio input[type="radio"], 76 | .radio-inline input[type="radio"], 77 | .checkbox input[type="checkbox"], 78 | .checkbox-inline input[type="checkbox"] { 79 | position: absolute; 80 | margin-left: -20px; 81 | margin-top: 4px; 82 | } 83 | 84 | // Form actions 85 | .form-actions .btn { 86 | margin-right: 10px; 87 | 88 | &:last-child { 89 | margin-right: 0; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/grid.scss: -------------------------------------------------------------------------------- 1 | // 2 | // The Grid.css 3 | // -------------------------------------------------- 4 | 5 | .pane-group { 6 | position: absolute; 7 | top: 0; 8 | right: 0; 9 | bottom: 0; 10 | left: 0; 11 | display: flex; 12 | } 13 | 14 | .pane { 15 | position: relative; 16 | overflow-y: auto; 17 | flex: 1; 18 | border-left: 1px solid $border-color; 19 | 20 | &:first-child { 21 | border-left: 0; 22 | } 23 | } 24 | 25 | .pane-sm { 26 | max-width: 220px; 27 | min-width: 150px; 28 | } 29 | 30 | .pane-mini { 31 | width: 80px; 32 | flex: none; 33 | } 34 | 35 | .pane-one-fourth { 36 | width: 25%; 37 | flex: none; 38 | } 39 | 40 | .pane-one-third { 41 | width: 33.3%; 42 | flex: none; 43 | } 44 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/images.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Images.scss 3 | // -------------------------------------------------- 4 | 5 | img { 6 | -webkit-user-drag: text; 7 | } 8 | 9 | .img-circle { 10 | border-radius: 50%; 11 | } 12 | 13 | .img-rounded { 14 | border-radius: $default-border-radius; 15 | } 16 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/lists.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Lists.scss 3 | // -------------------------------------------------- 4 | 5 | // List groups 6 | // These are to be used when shows list items that contain 7 | // more substanstial amounts of information. (headings, images, text, etc.) 8 | 9 | .list-group { 10 | width: 100%; 11 | list-style: none; 12 | margin: 0; 13 | padding: 0; 14 | 15 | 16 | * { 17 | margin: 0; 18 | white-space: nowrap; 19 | overflow: hidden; 20 | text-overflow: ellipsis; 21 | } 22 | } 23 | 24 | .list-group-item { 25 | padding: 10px; 26 | font-size: 12px; 27 | color: #414142; 28 | border-top: 1px solid $border-color; 29 | 30 | &:first-child { 31 | border-top: 0; 32 | } 33 | 34 | &.active, 35 | // `.selected` is deprecated. Use `.active` instead. 36 | &.selected { 37 | color: #fff; 38 | background-color: $active-color; 39 | } 40 | } 41 | 42 | .list-group-header { 43 | padding: 10px; 44 | } 45 | 46 | // Media objects in lists 47 | .media-object { 48 | margin-top: 3px; 49 | } 50 | 51 | .media-object.pull-left { 52 | margin-right: 10px 53 | } 54 | 55 | .media-object.pull-right { 56 | margin-left: 10px 57 | } 58 | 59 | .media-body { 60 | overflow: hidden; 61 | } 62 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/mixins.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Mixins 3 | // -------------------------------------------------- 4 | 5 | // General 6 | // -------------------------------------------------- 7 | 8 | // Clearfix 9 | // Source: http://nicolasgallagher.com/micro-clearfix-hack/ 10 | // 11 | // For modern browsers 12 | // 1. The space content is one way to avoid an Opera bug when the 13 | // contenteditable attribute is included anywhere else in the document. 14 | // Otherwise it causes space to appear at the top and bottom of elements 15 | // that are clearfixed. 16 | // 2. The use of `table` rather than `block` is only necessary if using 17 | // `:before` to contain the top-margins of child elements. 18 | @mixin clearfix() { 19 | &:before, 20 | &:after { 21 | display: table; // 2 22 | content: " "; // 1 23 | } 24 | &:after { 25 | clear: both; 26 | } 27 | } 28 | 29 | // Box shadow 30 | @mixin box-shadow($shadow...) { 31 | -webkit-box-shadow: $shadow; 32 | box-shadow: $shadow; 33 | } 34 | 35 | // Gradients 36 | 37 | // From top to bottom 38 | @mixin linear-gradient($color-from, $color-to) { 39 | background-color: $color-from; // Old browsers 40 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%,$color-from), color-stop(100%,$color-to)); // Chrome, Safari4+ 41 | background-image: -webkit-linear-gradient(top, $color-from 0%, $color-to 100%); // Chrome10+, Safari5.1+ 42 | background-image: linear-gradient(to bottom, $color-from 0%, $color-to 100%); // W3C 43 | } 44 | 45 | // From left to right 46 | @mixin split-linear-gradient($color-from, $color-to) { 47 | background-color: $color-from; // Old browsers 48 | background-image: -webkit-gradient(linear, left top, right top, color-stop(50%,$color-from), color-stop(50%,$color-to)); // Chrome, Safari4+ 49 | background-image: -webkit-linear-gradient(left, $color-from 50%, $color-to 50%); // Chrome10+, Safari5.1+ 50 | background-image: linear-gradient(to right, $color-from 50%, $color-to 50%); // W3C 51 | } 52 | 53 | // From bottom left to top right 54 | @mixin directional-gradient($color-from, $color-to, $deg: 45deg) { 55 | background-color: $color-from; // Old browsers 56 | background-image: -webkit-gradient(linear, left bottom, right top, color-stop(0%,$color-from), color-stop(100%,$color-to)); // Chrome, Safari4+ 57 | background-image: -webkit-linear-gradient($deg, $color-from 0%, $color-to 100%); // Chrome10+, Safari5.1+ 58 | background-image: -moz-linear-gradient($deg, $color-from 0%, $color-to 100%); // FF3.6+ 59 | background-image: linear-gradient($deg, $color-from 0%, $color-to 100%); // W3C 60 | } 61 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/navs.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Navs.scss 3 | // -------------------------------------------------- 4 | 5 | .nav-group { 6 | font-size: 14px; 7 | } 8 | 9 | .nav-group-item { 10 | padding: 2px 10px 2px 25px; 11 | display: block; 12 | color: $gray-color; 13 | text-decoration: none; 14 | white-space: nowrap; 15 | overflow: hidden; 16 | text-overflow: ellipsis; 17 | 18 | &:active, 19 | &.active { 20 | background-color: #dcdfe1; 21 | } 22 | 23 | .icon { 24 | width: 19px; // Prevents a one pixel cutoff 25 | height: 18px; 26 | float: left; 27 | color: #737475; 28 | margin-top: -3px; 29 | margin-right: 7px; 30 | font-size: 18px; 31 | text-align: center; 32 | } 33 | } 34 | 35 | .nav-group-title { 36 | margin: 0; 37 | padding: 10px 10px 2px; 38 | font-size: 12px; 39 | font-weight: 500; 40 | color: lighten($gray-color, 20%); 41 | } 42 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/normalize.scss: -------------------------------------------------------------------------------- 1 | // Based on normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css 2 | // This normalize aims to reduce the number of rules and focus on Chrome. 3 | 4 | // 5 | // 1. Normalize vertical alignment of `progress` in Chrome. 6 | // 7 | 8 | audio, 9 | canvas, 10 | progress, 11 | video { 12 | vertical-align: baseline; // 1 13 | } 14 | 15 | // 16 | // Prevent modern browsers from displaying `audio` without controls. 17 | // 18 | 19 | audio:not([controls]) { 20 | display: none; 21 | } 22 | 23 | // Links 24 | // ========================================================================== 25 | 26 | // 27 | // Improve readability of focused elements when they are also in an 28 | // active/hover state. 29 | // 30 | 31 | a:active, 32 | a:hover { 33 | outline: 0; 34 | } 35 | 36 | // Text-level semantics 37 | // ========================================================================== 38 | 39 | // 40 | // Address styling not present in IE 8/9/10/11, Safari, and Chrome. 41 | // 42 | 43 | abbr[title] { 44 | border-bottom: 1px dotted; 45 | } 46 | 47 | // 48 | // Address style set to `bolder` in Chrome. 49 | // 50 | 51 | b, 52 | strong { 53 | font-weight: bold; 54 | } 55 | 56 | // 57 | // Address styling not present in Chrome. 58 | // 59 | 60 | dfn { 61 | font-style: italic; 62 | } 63 | 64 | // 65 | // Address variable `h1` font-size and margin within `section` and `article` 66 | // contexts in Chrome. 67 | // 68 | 69 | h1 { 70 | font-size: 2em; 71 | margin: 0.67em 0; 72 | } 73 | 74 | // 75 | // Address inconsistent and variable font size. 76 | // 77 | 78 | small { 79 | font-size: 80%; 80 | } 81 | 82 | // 83 | // Prevent `sub` and `sup` affecting `line-height`. 84 | // 85 | 86 | sub, 87 | sup { 88 | font-size: 75%; 89 | line-height: 0; 90 | position: relative; 91 | vertical-align: baseline; 92 | } 93 | 94 | sup { 95 | top: -0.5em; 96 | } 97 | 98 | sub { 99 | bottom: -0.25em; 100 | } 101 | 102 | // Grouping content 103 | // ========================================================================== 104 | 105 | // 106 | // Contain overflow. 107 | // 108 | 109 | pre { 110 | overflow: auto; 111 | } 112 | 113 | // 114 | // Address odd `em`-unit font size rendering. 115 | // 116 | 117 | code, 118 | kbd, 119 | pre, 120 | samp { 121 | font-family: monospace, monospace; 122 | font-size: 1em; 123 | } 124 | 125 | // Forms 126 | // ========================================================================== 127 | 128 | // 129 | // Known limitation: by default, Chrome allows very limited 130 | // styling of `select`, unless a `border` property is set. 131 | // 132 | 133 | // 134 | // 1. Correct color not being inherited. 135 | // Known issue: affects color of disabled elements. 136 | // 2. Correct font properties not being inherited. 137 | // 3. Resets margin 138 | // 139 | 140 | button, 141 | input, 142 | optgroup, 143 | select, 144 | textarea { 145 | color: inherit; // 1 146 | font: caption; // 2 147 | margin: 0; // 3 148 | } 149 | 150 | // 151 | // Fix the cursor style for Chrome's increment/decrement buttons. For certain 152 | // `font-size` values of the `input`, it causes the cursor style of the 153 | // decrement button to change from `default` to `text`. 154 | // 155 | 156 | input[type="number"]::-webkit-inner-spin-button, 157 | input[type="number"]::-webkit-outer-spin-button { 158 | height: auto; 159 | } 160 | 161 | // 162 | // 1. Address `appearance` set to `searchfield` in Chrome. 163 | // 2. Address `box-sizing` set to `border-box` in Chrome. 164 | // 165 | 166 | input[type="search"] { 167 | -webkit-appearance: textfield; // 1 168 | box-sizing: content-box; // 2 169 | } 170 | 171 | // 172 | // Remove inner padding and search cancel button in Chrome on OS X. 173 | // 174 | 175 | input[type="search"]::-webkit-search-cancel-button, 176 | input[type="search"]::-webkit-search-decoration { 177 | -webkit-appearance: none; 178 | } 179 | 180 | // 181 | // Define consistent border, margin, and padding. 182 | // 183 | 184 | fieldset { 185 | border: 1px solid #c0c0c0; 186 | margin: 0 2px; 187 | padding: 0.35em 0.625em 0.75em; 188 | } 189 | 190 | // 191 | // 1. Correct `color` not being inherited in IE 8/9/10/11. 192 | // 2. Remove padding so people aren't caught out if they zero out fieldsets. 193 | // 194 | 195 | legend { 196 | border: 0; // 1 197 | padding: 0; // 2 198 | } 199 | 200 | // Tables 201 | // ========================================================================== 202 | 203 | // 204 | // Remove most spacing between table cells. 205 | // 206 | 207 | table { 208 | border-collapse: collapse; 209 | border-spacing: 0; 210 | } 211 | 212 | td, 213 | th { 214 | padding: 0; 215 | } 216 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/photon.scss: -------------------------------------------------------------------------------- 1 | // Variables 2 | @import "variables.scss"; 3 | 4 | // Mixins 5 | @import "mixins.scss"; 6 | 7 | // Normalize, Appify, Base, & Utilities CSS 8 | @import "normalize.scss"; 9 | @import "appify.scss"; 10 | @import "base.scss"; 11 | @import "utilities.scss"; 12 | 13 | // Components 14 | @import "buttons.scss"; 15 | @import "button-groups.scss"; 16 | @import "bars.scss"; 17 | @import "forms.scss"; 18 | @import "grid.scss"; 19 | @import "images.scss"; 20 | @import "lists.scss"; 21 | @import "navs.scss"; 22 | @import "icons.scss"; 23 | @import "tables.scss"; 24 | @import "tabs.scss"; 25 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/tables.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Navs.scss 3 | // -------------------------------------------------- 4 | 5 | table { 6 | width: 100%; 7 | border: 0; 8 | border-collapse: separate; 9 | font-size: 12px; 10 | text-align: left; 11 | } 12 | 13 | thead { 14 | background-color: #f5f5f4; 15 | } 16 | 17 | tbody { 18 | background-color: #fff; 19 | } 20 | 21 | .table-striped tr:nth-child(even) { 22 | background-color: #f5f5f4; 23 | } 24 | 25 | tr:active, 26 | .table-striped tr:active:nth-child(even) { 27 | color: #fff; 28 | background-color: $active-color; 29 | } 30 | 31 | thead tr:active { 32 | color: $gray-color; 33 | background-color: #f5f5f4; 34 | } 35 | 36 | th { 37 | font-weight: normal; 38 | border-right: 1px solid $border-color; 39 | border-bottom: 1px solid $border-color; 40 | } 41 | 42 | th, 43 | td { 44 | padding: 2px 15px; 45 | white-space: nowrap; 46 | overflow: hidden; 47 | text-overflow: ellipsis; 48 | 49 | &:last-child { 50 | border-right: 0; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/tabs.scss: -------------------------------------------------------------------------------- 1 | // Tabs 2 | 3 | .tab-group { 4 | margin-top: -1px; 5 | display: flex; 6 | border-top: 1px solid #989698; 7 | border-bottom: 1px solid #989698; 8 | } 9 | 10 | .tab-item { 11 | position: relative; 12 | flex: 1; 13 | padding: 3px; 14 | font-size: 12px; 15 | text-align: center; 16 | border-left: 1px solid #989698; 17 | @include linear-gradient(#b8b6b8, #b0aeb0); 18 | 19 | &:first-child { 20 | border-left: 0; 21 | } 22 | 23 | &.active { 24 | @include linear-gradient(#d4d2d4, #cccacc); 25 | } 26 | 27 | .icon-close-tab { 28 | position: absolute; 29 | top: 50%; 30 | left: 5px; 31 | width: 15px; 32 | height: 15px; 33 | font-size: 15px; 34 | line-height: 15px; 35 | text-align: center; 36 | color: #666; 37 | opacity: 0; 38 | transition: opacity .1s linear, background-color .1s linear; 39 | border-radius: 3px; 40 | transform: translateY(-50%); 41 | z-index: 10; 42 | } 43 | 44 | &:after { 45 | position: absolute; 46 | top: 0; 47 | right: 0; 48 | bottom: 0; 49 | left: 0; 50 | content: ""; 51 | background-color: rgba(0,0,0,.08); 52 | opacity: 0; 53 | transition: opacity .1s linear; 54 | z-index: 1; 55 | } 56 | 57 | // Okay, I know... this is nuts but... 58 | &:hover:not(.active):after { 59 | opacity: 1; 60 | } 61 | 62 | &:hover .icon-close-tab { 63 | opacity: 1; 64 | } 65 | 66 | .icon-close-tab:hover { 67 | background-color: rgba(0,0,0,.08); 68 | } 69 | } 70 | 71 | .tab-item-fixed { 72 | flex: none; 73 | padding: 3px 10px; 74 | } 75 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/utilities.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Utilities styles 3 | // -------------------------------------------------- 4 | 5 | // Utility classes 6 | .selectable-text { 7 | cursor: text; 8 | -webkit-user-select: text; 9 | } 10 | 11 | // Text alignment 12 | .text-center { 13 | text-align: center; 14 | } 15 | 16 | .text-right { 17 | text-align: right; 18 | } 19 | 20 | .text-left { 21 | text-align: left; 22 | } 23 | 24 | // Floats 25 | .pull-left { 26 | float: left; 27 | } 28 | 29 | .pull-right { 30 | float: right; 31 | } 32 | 33 | // Padding 34 | .padded { 35 | padding: $padding; 36 | } 37 | 38 | .padded-less { 39 | padding: $padding-less; 40 | } 41 | 42 | .padded-more { 43 | padding: $padding-more; 44 | } 45 | 46 | // Vertical Padding 47 | .padded-vertically { 48 | padding-top: $padding; 49 | padding-bottom: $padding; 50 | } 51 | 52 | .padded-vertically-less { 53 | padding-top: $padding-less; 54 | padding-bottom: $padding-less; 55 | } 56 | 57 | .padded-vertically-more { 58 | padding-top: $padding-more; 59 | padding-bottom: $padding-more; 60 | } 61 | 62 | // Horizontal Padding 63 | .padded-horizontally { 64 | padding-right: $padding; 65 | padding-left: $padding; 66 | } 67 | 68 | .padded-horizontally-less { 69 | padding-right: $padding-less; 70 | padding-left: $padding-less; 71 | } 72 | 73 | .padded-horizontally-more { 74 | padding-right: $padding-more; 75 | padding-left: $padding-more; 76 | } 77 | 78 | // Padding top 79 | .padded-top { 80 | padding-top: $padding; 81 | } 82 | 83 | .padded-top-less { 84 | padding-top: $padding-less; 85 | } 86 | 87 | .padded-top-more { 88 | padding-top: $padding-more; 89 | } 90 | 91 | // Padding bottom 92 | .padded-bottom { 93 | padding-bottom: $padding; 94 | } 95 | 96 | .padded-bottom-less { 97 | padding-bottom: $padding-less; 98 | } 99 | 100 | .padded-bottom-more { 101 | padding-bottom: $padding-more; 102 | } 103 | 104 | // Set the background-color to set a sidebar back a bit. 105 | .sidebar { 106 | background-color: #f5f5f4; 107 | } 108 | 109 | // Allow the window to be dragged around the desktop by any element in the application. 110 | .draggable { 111 | -webkit-app-region: drag; 112 | } 113 | 114 | // within draggable regions, allow specific elements to be exempted. 115 | .not-draggable { 116 | -webkit-app-region: no-drag; 117 | } 118 | 119 | // Clearfix 120 | .clearfix { 121 | @include clearfix(); 122 | } 123 | -------------------------------------------------------------------------------- /ShortcutMagic/sass/variables.scss: -------------------------------------------------------------------------------- 1 | // 2 | // Variables 3 | // -------------------------------------------------- 4 | 5 | // Type 6 | // -------------------------------------------------- 7 | 8 | $font-path: '../fonts/' !default; 9 | // Try to use the system's font on whatever platform the user is on. 10 | $font-family-default: system, -apple-system, ".SFNSDisplay-Regular", "Helvetica Neue", Helvetica, "Segoe UI", sans-serif !default; 11 | $font-size-default: 13px !default; 12 | $font-weight: 500 !default; 13 | $font-weight-bold: 700 !default; 14 | $font-weight-light: 300 !default; 15 | $line-height-default: 1.6 !default; 16 | 17 | 18 | // Colors 19 | // -------------------------------------------------- 20 | 21 | // Main colors 22 | $primary-color: #3b99fc !default; 23 | $chrome-color: #fff !default; 24 | 25 | // Copy 26 | $gray-color: #333 !default; 27 | 28 | // Borders 29 | $border-color: #ddd !default; 30 | $dark-border-color: #c2c0c2 !default; 31 | $darker-bottom-border-color: #a19fa1 !default; 32 | $toolbar-border-color: #939293 !default; 33 | 34 | // Action colors 35 | $default-color: #fff !default; 36 | $positive-color: #34c84a !default; 37 | $negative-color: #fc605b !default; 38 | $warning-color: #fdbc40 !default; 39 | 40 | // Shades 41 | $dark-color: #57acf5 !default; 42 | 43 | // Focus and active colors 44 | $active-color: #116cd6; 45 | $focus-input-color: lighten($primary-color, 10%) !default; 46 | 47 | // Other 48 | // -------------------------------------------------- 49 | 50 | // Border radius 51 | $default-border-radius: 4px; 52 | 53 | // Padding 54 | $padding: 10px; 55 | $padding-mini: 3px; 56 | $padding-less: 5px; 57 | $padding-more: 20px; 58 | -------------------------------------------------------------------------------- /ShortcutMagic/settings/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 |
12 |
13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /ShortcutMagic/settings/miniIndex.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 |
12 |
13 |
14 | 15 | 16 | -------------------------------------------------------------------------------- /ShortcutMagic/settings/settings.js: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | const path = require('path'); 3 | var Datastore = require('nedb'); 4 | import { ipcRenderer, remote } from 'electron'; 5 | 6 | // TODO: 7 | // - put all settings code here 8 | // - respond to settingsview logic 9 | // - send heavy tasks to settingsWorker - or will this be settingsWorker in itself? 10 | 11 | // Is there ever a risk that an app has on eof these names and will overwrite..? 12 | const GLOBAL_SETTINGS_KEY = "all programs"; 13 | var settingsInProgress = {}; 14 | var lastSavedSettings = {}; 15 | var cachedSettings = {}; 16 | var defaultSettings = {}; 17 | // TODO: Split startup settings from saved settings? 18 | 19 | var defaultFullBounds = {x: 1100, y: 100, width: 350, height: 800}; 20 | var defaultBubbleBounds = {x: 800, y: 10, width: 250, height: 200}; 21 | 22 | defaultSettings = { 23 | name: GLOBAL_SETTINGS_KEY, 24 | acceptFirstClick: true, 25 | defaultWindowMode: 'tray', 26 | alwaysOnTop: true, 27 | boundsPerApp: false, 28 | showMenuNames: false, 29 | frame: false, 30 | show: true, 31 | x: defaultFullBounds.x, 32 | y: defaultFullBounds.y, 33 | width: defaultFullBounds.width, 34 | height: defaultFullBounds.height, 35 | lastFullBounds: defaultFullBounds, 36 | lastBubbleBounds: defaultBubbleBounds, 37 | title: "mainWindow", 38 | }; 39 | 40 | // Pick word 1 and 2 (0 is an empty string because of the preceding slash) as the root of the path 41 | const folderPath = remote.getGlobal('folderPath'); 42 | console.log('folderPath: ', folderPath); 43 | const resolvedSettings = `${folderPath}/ShortcutMagic/settings.db`; 44 | console.log('resolvedSettings: ', resolvedSettings); 45 | 46 | let resolvedHistoryDb; 47 | let settingsHistoryDb; 48 | 49 | let settingsDb 50 | 51 | // No need for unique indexes here, we just keep inserting forever(?) 52 | try { 53 | resolvedHistoryDb = `${folderPath}/ShortcutMagic/settingsHistory.db`; 54 | console.log('resolvedHistoryDb: ', resolvedHistoryDb); 55 | settingsHistoryDb = new Datastore({ 56 | filename: resolvedHistoryDb, 57 | autoload: true 58 | }); 59 | 60 | settingsDb = new Datastore({ 61 | filename: resolvedSettings, 62 | autoload: true 63 | }); 64 | 65 | settingsDb.ensureIndex({ 66 | fieldName: 'name', 67 | unique: true // Setting unique value constraint on name 68 | }, function (err) { 69 | if (err) { 70 | console.log('ERROR: settings.ensureIndex failed to set unique constraint', err); 71 | } 72 | }); 73 | 74 | // TODO: send to worker? 75 | settingsDb.find({ 76 | name: GLOBAL_SETTINGS_KEY 77 | }, function(err, doc) { 78 | if (err) { 79 | console.log('Tried to find default settings, got error: ', err); 80 | return; 81 | } 82 | 83 | if (!doc || (doc == [] || doc.length == 0)) { 84 | settingsDb.insert(defaultSettings, function(err, doc) { 85 | if (err) { 86 | console.log('ERROR: inserting default settings into settings db failed with err', err); 87 | } 88 | }); 89 | } else { 90 | cachedSettings[GLOBAL_SETTINGS_KEY] = defaultSettings = doc[0]; 91 | } 92 | }); 93 | } catch (e) { 94 | log.error(e); 95 | } 96 | 97 | 98 | // make sure all of these are set ok for main window: 99 | // 'mainWindowSettings': { 100 | // title: "ShortcutMagic", 101 | // alwaysOnTop: useSettings.alwaysOnTop, 102 | // acceptFirstClick: useSettings.acceptFirstClick, 103 | // frame: useSettings.frame, 104 | // backgroundColor: useSettings.background 105 | // } 106 | 107 | export class Settings { 108 | create(settingsWindow) { 109 | this.settingsWindow = settingsWindow; 110 | 111 | // When settings are created the SettingsView needs to be initialized 112 | this.get(ipcRenderer.sendSync('get-app-name-sync'), (newSettings, globalSettings) => { 113 | cachedSettings[newSettings.name] = newSettings; 114 | this.settingsWindow.setState({ 115 | globalSettings: globalSettings, 116 | appSettings: newSettings 117 | }); 118 | }); 119 | 120 | this.registerListeners(); 121 | } 122 | 123 | // Return settings for appName, as well as global settings 124 | get(appName, cb) { 125 | if (!appName || appName == "") { 126 | cb(defaultSettings, cachedSettings[GLOBAL_SETTINGS_KEY]); 127 | return; 128 | } 129 | 130 | var val = cachedSettings[appName]; 131 | if (val) { 132 | cb(val, cachedSettings[GLOBAL_SETTINGS_KEY]); 133 | return; 134 | } 135 | 136 | // TODO: farm out to worker? make return value a callback instead? 137 | settingsDb.find({ 138 | name: appName 139 | }, function(err, res) { 140 | if (err) { 141 | console.log("Hit error trying to load setting in settings.get"); 142 | return; 143 | } 144 | 145 | if (res && res.length > 0 && res[0]) { 146 | cachedSettings[appName] = res[0] 147 | cb(res[0], cachedSettings[GLOBAL_SETTINGS_KEY]); 148 | } else { 149 | var fallback = defaultSettings; 150 | fallback["name"] = appName; 151 | cb(fallback, cachedSettings[GLOBAL_SETTINGS_KEY]); 152 | } 153 | }); 154 | } 155 | 156 | getHistory(appName, cb) { 157 | if (!appName || appName == "") { 158 | cb([ 159 | defaultSettings 160 | ]); 161 | return; 162 | } 163 | 164 | // TODO: Cache history too? 165 | // var val = cachedSettings[appName]; 166 | // if (val) { 167 | // cb(val); 168 | // return; 169 | // } 170 | 171 | // TODO: farm out to worker? make return value a callback instead? 172 | settingsHistoryDb.find({ 173 | name: appName 174 | }, function(err, res) { 175 | if (err) { 176 | console.log("Hit error trying to load setting in settings.get"); 177 | cb([ 178 | defaultSettings 179 | ]); 180 | return; 181 | } 182 | 183 | // Send entire res, not just res[0] 184 | if (res && res.length > 0) { 185 | // TODO: Cache history too? 186 | // cachedSettings[appName] = res[0] 187 | cb(res); 188 | } else { 189 | // Last resort is to send the default settings in a list... 190 | cb([ 191 | defaultSettings 192 | ]); 193 | } 194 | }); 195 | } 196 | 197 | set(appSettings, globalSettings) { 198 | delete appSettings._id; 199 | cachedSettings[appSettings.name] = appSettings; 200 | cachedSettings[GLOBAL_SETTINGS_KEY] = globalSettings; 201 | 202 | settingsDb.update({ 203 | name: GLOBAL_SETTINGS_KEY 204 | }, { 205 | $set: globalSettings 206 | }, { 207 | upsert: true 208 | }, function(err, doc) { 209 | if (err) { 210 | console.log("Error upserting in settings.js set", err, globalSettings); 211 | } else { 212 | console.log("Succeeded in saving settings to db: ", globalSettings); 213 | } 214 | }); 215 | 216 | settingsDb.update({ 217 | name: appSettings.name 218 | }, { 219 | $set: appSettings 220 | }, { 221 | upsert: true 222 | }, function(err, doc) { 223 | if (err) { 224 | console.log("Error upserting in settings.js set", err, appSettings); 225 | } else { 226 | console.log("Succeeded in saving settings to db: ", appSettings); 227 | } 228 | }); 229 | 230 | appSettings["date"] = new Date(); 231 | settingsHistoryDb.insert(appSettings, (err, doc) => { 232 | if (err) { 233 | console.log("error when inserting setting in settingsHistoryDb"); 234 | } 235 | }); 236 | } 237 | 238 | // TODO: How to make this work with the history? 239 | undoSettings(appName) { 240 | if (!appName) { 241 | console.log("cannot undo settings without appname"); 242 | return; 243 | } 244 | 245 | settingsDb.find({ 246 | name: appName 247 | }, function(err, doc) { 248 | var setDefaultSettings = defaultSettings; 249 | setDefaultSettings["name"] = appName; 250 | 251 | if (err) { 252 | // TODO: streamline default settings 253 | console.log('cound not find settings in undoSettings'); 254 | } else if (doc && doc != [] && doc.length > 0) { 255 | setDefaultSettings = doc[0]; 256 | } 257 | }); 258 | } 259 | // in window? unnecessary? 260 | // destroySettings(); 261 | 262 | registerListeners() { 263 | // TODO: Ideally show a "do you want to save your changes?" dialog if there were 264 | // changes done to the app settings (not for global) 265 | ipcRenderer.on('app-changed', (event, newName) => { 266 | var changeSettings = (newSettings, globalSettings) => { 267 | this.settingsWindow.setState({ 268 | globalSettings: globalSettings, 269 | appSettings: newSettings 270 | }); 271 | }; 272 | 273 | var cached = cachedSettings[newName]; 274 | if (cached) { 275 | changeSettings(cached, cachedSettings[GLOBAL_SETTINGS_KEY]); 276 | } else { 277 | this.get(newName, changeSettings); 278 | } 279 | }); 280 | 281 | // pseudocode: move window to left or right side depending on main window position 282 | // if (mainWindow.bounds().x < app.getScreenSize() / 2) { 283 | // // window is towards the left, put settings to the right: 284 | // settingsWindow.setBounds(mainWindowBounds.x - mainWindowBounds.width, 285 | // mainWindowBounds.y, 400, mainWindowBounds.height); 286 | // } else { 287 | // // window is towards the right, put settings to the left: 288 | // settingsWindow.setBounds(mainWindowBounds.x, 289 | // mainWindowBounds.y, 400, mainWindowBounds.height); 290 | 291 | 292 | 293 | // TODO: move the state updates into the SettingsView 294 | // ipcRenderer.on('get-default-settings', applySettingsToState); 295 | // ipcRenderer.on('get-settings', applySettingsToState); 296 | 297 | // ipcRenderer.on('create-shortcut-window', (event, cb) => { 298 | // console.log("inside create-shortcut-window::::::::::::::::: ", cb); 299 | // holdSettings = this.get("mainWindow"); 300 | // console.log("got holdSettings, calling cb function", holdSettings); 301 | // cb(holdSettings); 302 | // }); 303 | 304 | // ipcRenderer.on('temporarily-update-app-settings', (event, newSettings) => { 305 | // // TODO: don't save settings here, just pass them on to the shortcut window 306 | // if (this.shortcutsWindow) { 307 | // // TODO: test this shortcutsWindow reference properly 308 | // this.shortcutsWindow.webContents.send('update-app-setting', newSettings); 309 | // } 310 | // }); 311 | } 312 | }; 313 | -------------------------------------------------------------------------------- /ShortcutMagic/settings/settingsWorker.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { ipcRenderer } from 'electron'; -------------------------------------------------------------------------------- /ShortcutMagic/shared/appSwitchListener.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var $ = require('NodObjC'); 3 | $.import('Cocoa'); 4 | $.import('Foundation'); 5 | 6 | var sharedWorkspace = null; // NSWorkspace('allow', init) 7 | var listenerClass = $.NSObject.extend('listener'); 8 | var startedMainLoop = false; 9 | var savedCallback = null; 10 | var listenerObj = null; 11 | 12 | 13 | function triggerAppSwitch(notification) { 14 | console.log('triggerAppSwitch with notification', notification); 15 | if (savedCallback) { 16 | // TOOD: Cast this better/safer 17 | savedCallback("" + sharedWorkspace('frontmostApplication')('localizedName')); 18 | } else { 19 | console.log('app switch triggered without callback'); 20 | } 21 | } 22 | 23 | listenerClass.addMethod('listeningApplicationLaunched:', 'v@:@', function(self, _cmd, notification) { 24 | triggerAppSwitch(notification); 25 | }); 26 | 27 | listenerClass.addMethod('listeningApplicationActivated:', 'v@:@', function(self, _cmd, notification) { 28 | triggerAppSwitch(notification); 29 | }); 30 | 31 | listenerClass.register(); 32 | listenerObj = listenerClass('alloc')('init'); 33 | 34 | module.exports = function appSwitchListener(callback) { 35 | savedCallback = callback; 36 | if (!startedMainLoop) { 37 | 38 | sharedWorkspace = $.NSWorkspace('sharedWorkspace'); 39 | 40 | sharedWorkspace('notificationCenter')('addObserver', listenerObj, 'selector', 'listeningApplicationLaunched:', 41 | 'name', $.NSWorkspaceDidLaunchApplicationNotification, 'object', sharedWorkspace); 42 | 43 | sharedWorkspace('notificationCenter')('addObserver', listenerObj, 'selector', 'listeningApplicationActivated:', 44 | 'name', $.NSWorkspaceDidActivateApplicationNotification, 'object', sharedWorkspace); 45 | 46 | 47 | $.NSRunLoop('mainRunLoop')('run'); 48 | startedMainLoop = true; 49 | return true; 50 | } 51 | 52 | return false; 53 | }; 54 | -------------------------------------------------------------------------------- /ShortcutMagic/shared/executeMenu.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/shared/executeMenu.scpt -------------------------------------------------------------------------------- /ShortcutMagic/shared/executeMenuItem.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var $ = require('NodObjC'); 3 | $.import('OSAKit'); 4 | 5 | module.exports = function executeMenuItem(appName, menuItem, menu) { 6 | var scriptName = "executeMenu"; 7 | var encoding = $.NSUTF8StringEncoding; 8 | var dirName = $(`${__dirname}/${scriptName}.scpt`); 9 | var source = $.NSString('stringWithContentsOfFile', dirName, 'encoding', encoding, 'error', null); 10 | var hold = $.OSAScript('alloc')('initWithSource', source); 11 | 12 | // TODO: How to make this a useable pointer? http://tootallnate.github.io/$/class.html -> createPointer ? 13 | // NSDictionary *errorInfo; 14 | var errorInfo = $.alloc($.NSDictionary); 15 | var compiled = hold('compileAndReturnError', errorInfo.ref()); 16 | 17 | if (!compiled) { 18 | $.NSLog("Compile failed: %@", errorInfo); 19 | return null; 20 | } 21 | 22 | var arrayArgs = $.NSMutableArray('alloc')('init'); 23 | arrayArgs('addObject', $(appName)); 24 | arrayArgs('addObject', $(menuItem)); 25 | arrayArgs('addObject', $(menu)); 26 | 27 | hold('executeHandlerWithName', $(scriptName), 'arguments', arrayArgs, 'error', errorInfo.ref()); 28 | }; 29 | -------------------------------------------------------------------------------- /ShortcutMagic/shared/executeShortcut.scpt: -------------------------------------------------------------------------------- 1 | on run {executeFunction, processName, char} 2 | if (executeFunction is equal to "execute") then execute(processName, char) 3 | if (executeFunction is equal to "executeCmd") then return executeCmd(processName, char) 4 | if (executeFunction is equal to "executeOpt") then executeOpt(processName, char) 5 | if (executeFunction is equal to "executeCtrl") then executeCtrl(processName, char) 6 | if (executeFunction is equal to "executeShift") then executeShift(processName, char) 7 | if (executeFunction is equal to "executeCmdOpt") then executeCmdOpt(processName, char) 8 | if (executeFunction is equal to "executeCmdCtrl") then executeCmdCtrl(processName, char) 9 | if (executeFunction is equal to "executeCmdShift") then executeCmdShift(processName, char) 10 | if (executeFunction is equal to "executeOptCtrl") then executeOptCtrl(processName, char) 11 | if (executeFunction is equal to "executeOptShift") then executeOptShift(processName, char) 12 | if (executeFunction is equal to "executeShiftCtrl") then executeShiftCtrl(processName, char) 13 | if (executeFunction is equal to "executeCmdOptShift") then executeCmdOptShift(processName, char) 14 | if (executeFunction is equal to "executeCmdOptCtrl") then executeCmdOptCtrl(processName, char) 15 | if (executeFunction is equal to "executeCmdShiftCtrl") then executeCmdShiftCtrl(processName, char) 16 | if (executeFunction is equal to "executeOptCtrlShift") then executeOptCtrlShift(processName, char) 17 | if (executeFunction is equal to "executeCmdOptCtrlShift") then executeCmdOptCtrlShift(processName, char) 18 | end run 19 | 20 | on executeShortcut(executeFunction, processName, char) 21 | if (executeFunction is equal to "execute") then execute(processName, char) 22 | if (executeFunction is equal to "executeCmd") then executeCmd(processName, char) 23 | if (executeFunction is equal to "executeOpt") then executeOpt(processName, char) 24 | if (executeFunction is equal to "executeCtrl") then executeCtrl(processName, char) 25 | if (executeFunction is equal to "executeShift") then executeShift(processName, char) 26 | if (executeFunction is equal to "executeCmdOpt") then executeCmdOpt(processName, char) 27 | if (executeFunction is equal to "executeCmdCtrl") then executeCmdCtrl(processName, char) 28 | if (executeFunction is equal to "executeCmdShift") then executeCmdShift(processName, char) 29 | if (executeFunction is equal to "executeOptCtrl") then executeOptCtrl(processName, char) 30 | if (executeFunction is equal to "executeOptShift") then executeOptShift(processName, char) 31 | if (executeFunction is equal to "executeShiftCtrl") then executeShiftCtrl(processName, char) 32 | if (executeFunction is equal to "executeCmdOptShift") then executeCmdOptShift(processName, char) 33 | if (executeFunction is equal to "executeCmdOptCtrl") then executeCmdOptCtrl(processName, char) 34 | if (executeFunction is equal to "executeCmdShiftCtrl") then executeCmdShiftCtrl(processName, char) 35 | if (executeFunction is equal to "executeOptCtrlShift") then executeOptCtrlShift(processName, char) 36 | if (executeFunction is equal to "executeCmdOptCtrlShift") then executeCmdOptCtrlShift(processName, char) 37 | 38 | return "run done" 39 | end executeShortcut 40 | 41 | 42 | -- Just char 43 | on execute(processName, char) 44 | try 45 | tell application "System Events" 46 | set bId to (bundle identifier of first process whose name is equal to processName) 47 | end tell 48 | 49 | tell application id bId to activate 50 | 51 | tell application "System Events" 52 | key code char 53 | end tell 54 | end try 55 | 56 | return "execute" 57 | end execute 58 | 59 | 60 | 61 | 62 | -- SINGLE 63 | ---------- 64 | 65 | 66 | 67 | 68 | on executeCmd(processName, char) 69 | try 70 | tell application "System Events" 71 | set bId to (bundle identifier of first process whose name is equal to processName) 72 | end tell 73 | 74 | tell application id bId to activate 75 | 76 | tell application "System Events" 77 | key code char using {command down} 78 | end tell 79 | end try 80 | end executeCmd 81 | 82 | on executeOpt(processName, char) 83 | try 84 | tell application "System Events" 85 | set bId to (bundle identifier of first process whose name is equal to processName) 86 | end tell 87 | 88 | tell application id bId to activate 89 | 90 | tell application "System Events" 91 | key code char using {option down} 92 | end tell 93 | end try 94 | end executeOpt 95 | 96 | on executeCtrl(processName, char) 97 | try 98 | tell application "System Events" 99 | set bId to (bundle identifier of first process whose name is equal to processName) 100 | end tell 101 | 102 | tell application id bId to activate 103 | 104 | tell application "System Events" 105 | key code char using {control down} 106 | end tell 107 | end try 108 | end executeCtrl 109 | 110 | on executeShift(processName, char) 111 | try 112 | tell application "System Events" 113 | set bId to (bundle identifier of first process whose name is equal to processName) 114 | end tell 115 | 116 | tell application id bId to activate 117 | 118 | tell application "System Events" 119 | key code char using {shift down} 120 | end tell 121 | end try 122 | end executeShift 123 | 124 | 125 | 126 | 127 | -- DOUBLES, CMD 128 | ---------- 129 | 130 | 131 | 132 | 133 | on executeCmdOpt(processName, char) 134 | try 135 | tell application "System Events" 136 | set bId to (bundle identifier of first process whose name is equal to processName) 137 | end tell 138 | 139 | tell application id bId to activate 140 | 141 | tell application "System Events" 142 | key code char using {command down, option down} 143 | end tell 144 | end try 145 | end executeCmdOpt 146 | 147 | on executeCmdCtrl(processName, char) 148 | try 149 | tell application "System Events" 150 | set bId to (bundle identifier of first process whose name is equal to processName) 151 | end tell 152 | 153 | tell application id bId to activate 154 | 155 | tell application "System Events" 156 | key code char using {command down, control down} 157 | end tell 158 | end try 159 | end executeCmdCtrl 160 | 161 | on executeCmdShift(processName, char) 162 | try 163 | tell application "System Events" 164 | set bId to (bundle identifier of first process whose name is equal to processName) 165 | end tell 166 | 167 | tell application id bId to activate 168 | 169 | tell application "System Events" 170 | key code char using {command down, shift down} 171 | end tell 172 | end try 173 | end executeCmdShift 174 | 175 | 176 | 177 | -- DOUBLES, OPTION (no cmd) 178 | ---------- 179 | 180 | 181 | 182 | on executeOptCtrl(processName, char) 183 | try 184 | tell application "System Events" 185 | set bId to (bundle identifier of first process whose name is equal to processName) 186 | end tell 187 | 188 | tell application id bId to activate 189 | 190 | tell application "System Events" 191 | key code char using {option down, control down} 192 | end tell 193 | end try 194 | end executeOptCtrl 195 | 196 | on executeOptShift(processName, char) 197 | try 198 | tell application "System Events" 199 | set bId to (bundle identifier of first process whose name is equal to processName) 200 | end tell 201 | 202 | tell application id bId to activate 203 | 204 | tell application "System Events" 205 | key code char using {option down, shift down} 206 | end tell 207 | end try 208 | end executeOptShift 209 | 210 | 211 | 212 | 213 | -- DOUBLES, SHIFT (no alt, cmd) 214 | ---------- 215 | 216 | 217 | 218 | 219 | on executeShiftCtrl(processName, char) 220 | try 221 | tell application "System Events" 222 | set bId to (bundle identifier of first process whose name is equal to processName) 223 | end tell 224 | 225 | tell application id bId to activate 226 | 227 | tell application "System Events" 228 | key code char using {shift down, control down} 229 | end tell 230 | end try 231 | end executeShiftCtrl 232 | 233 | 234 | 235 | 236 | -- TRIPLES 237 | ---------- 238 | 239 | 240 | 241 | 242 | on executeCmdOptShift(processName, char) 243 | try 244 | tell application "System Events" 245 | set bId to (bundle identifier of first process whose name is equal to processName) 246 | end tell 247 | 248 | tell application id bId to activate 249 | 250 | tell application "System Events" 251 | key code char using {command down, option down, shift down} 252 | end tell 253 | end try 254 | end executeCmdOptShift 255 | 256 | on executeCmdOptCtrl(processName, char) 257 | try 258 | tell application "System Events" 259 | set bId to (bundle identifier of first process whose name is equal to processName) 260 | end tell 261 | 262 | tell application id bId to activate 263 | 264 | tell application "System Events" 265 | key code char using {command down, option down, control down} 266 | end tell 267 | end try 268 | end executeCmdOptCtrl 269 | 270 | on executeCmdShiftCtrl(processName, char) 271 | try 272 | tell application "System Events" 273 | set bId to (bundle identifier of first process whose name is equal to processName) 274 | end tell 275 | 276 | tell application id bId to activate 277 | 278 | tell application "System Events" 279 | key code char using {command down, shift down, control down} 280 | end tell 281 | end try 282 | end executeCmdShiftCtrl 283 | 284 | on executeOptCtrlShift(processName, char) 285 | try 286 | tell application "System Events" 287 | set bId to (bundle identifier of first process whose name is equal to processName) 288 | end tell 289 | 290 | tell application id bId to activate 291 | 292 | tell application "System Events" 293 | key code char using {option down, shift down, control down} 294 | end tell 295 | end try 296 | end executeOptCtrlShift 297 | 298 | -- QUADRUPLES 299 | ------------- 300 | 301 | on executeCmdOptCtrlShift(processName, char) 302 | try 303 | tell application "System Events" 304 | set bId to (bundle identifier of first process whose name is equal to processName) 305 | end tell 306 | 307 | tell application id bId to activate 308 | 309 | tell application "System Events" 310 | key code char using {command down, option down, control down, shift down} 311 | end tell 312 | end try 313 | end executeCmdOptCtrlShift 314 | -------------------------------------------------------------------------------- /ShortcutMagic/shared/readAllMenuItems.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/shared/readAllMenuItems.scpt -------------------------------------------------------------------------------- /ShortcutMagic/shared/readAllShortcuts.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const { exec } = require('child_process') 4 | 5 | module.exports = function(programName, cb) { 6 | exec(`osascript shared/readAllMenuItems.scpt "${programName}"`, (err, res) => { 7 | let allShortcuts = [] 8 | 9 | res.split('?????').filter(m => m && m.length).forEach(menu => { 10 | const shortcutsStartPos = menu.indexOf('||') 11 | const menuName = menu.substr(0, shortcutsStartPos) 12 | const shortcuts = menu.substr(shortcutsStartPos, menu.length - 1).split('!!!!!') 13 | 14 | shortcuts.filter(f => f && f.length).forEach(shortcut => { 15 | const splitShortcuts = shortcut.split('||').filter(f => f && f.length) 16 | const [ name, pos, char, mod, glyph ] = splitShortcuts 17 | 18 | if (splitShortcuts.length < 5 || !name || name === 'missing value') { 19 | return 20 | } 21 | 22 | let finalShortcut = { 23 | menuName, 24 | name, 25 | pos, 26 | } 27 | 28 | if (char && char !== 'missing value') { 29 | finalShortcut["char"] = char 30 | } 31 | // Default mod for command is 0, so double check that it is not an "empty command" entry when there are no other keys 32 | if (mod !== 'missing value' && ((char && char !== 'missing value' && char.length) || (glyph && glyph !== 'missing value' && glyph.length))) { 33 | finalShortcut["mod"] = unwrapMod[mod] 34 | } 35 | if (glyph !== 'missing value') { 36 | finalShortcut["glyph"] = unwrapGlyph[glyph] 37 | } 38 | 39 | allShortcuts.push(finalShortcut) 40 | }) 41 | }) 42 | 43 | cb({ 44 | name: programName, 45 | shortcuts: allShortcuts 46 | }) 47 | }) 48 | } 49 | 50 | let unwrapMod = [] 51 | unwrapMod[0] = '⌘' 52 | unwrapMod[1] = '⇧⌘' 53 | unwrapMod[2] = '⌥⌘' 54 | unwrapMod[3] = '⌥⇧⌘' 55 | unwrapMod[4] = '⌃⌘' 56 | unwrapMod[5] = '⌃⇧⌘' 57 | unwrapMod[6] = '⌃⌥⌘' 58 | unwrapMod[7] = '⌃⌥⇧⌘' 59 | 60 | // TOOD: Determine what '8' actually means 61 | // unwrapMod[8] = '-' 62 | unwrapMod[8] = '' 63 | 64 | unwrapMod[9] = '⇧' 65 | unwrapMod[10] = '⌥' 66 | unwrapMod[11] = '⌥⇧' 67 | unwrapMod[12] = '⌃' 68 | unwrapMod[13] = '⌃⇧' 69 | unwrapMod[14] = '⌃⌥' 70 | unwrapMod[15] = '⌃⌥⇧' 71 | 72 | // "2 ⇥ 3 ⇤ 4 ⌤ 9 ␣ 10 ⌦ 11 ↩ 16 ↓ 23 ⌫ 24 ← 25 ↑ 26 → 27 ⎋ 28 ⌧ 98 ⇞ 99 ⇪ 100 ← 101 → 102 ↖ 104 ↑ 105 ↘ 106 ↓ 107 ⇟ 111 F1 112 F2 113 F3 114 F4 115 F5 116 F6 117 F7 118 F8 119 F9 120 F10 121 F11 122 F12 135 F13 136 F14 137 F15 140 ⏏ 143 F16 144 F17 145 F18 146 F19" 73 | let unwrapGlyph = [] 74 | unwrapGlyph[2] = '⇥' 75 | unwrapGlyph[3] = '⇤' 76 | unwrapGlyph[4] = '⌤' 77 | unwrapGlyph[9] = 'Space' 78 | unwrapGlyph[10] = '⌦' 79 | unwrapGlyph[11] = '↩' 80 | unwrapGlyph[16] = '↓' 81 | unwrapGlyph[23] = '⌫' 82 | unwrapGlyph[24] = '←' 83 | unwrapGlyph[25] = '↑' 84 | unwrapGlyph[26] = '→' 85 | unwrapGlyph[27] = '⎋' 86 | unwrapGlyph[28] = '⌧' 87 | unwrapGlyph[98] = '⇞' 88 | unwrapGlyph[99] = '⇪' 89 | unwrapGlyph[100] = '←' 90 | unwrapGlyph[101] = '→' 91 | unwrapGlyph[102] = '↖' 92 | unwrapGlyph[104] = '↑' 93 | unwrapGlyph[105] = '↘' 94 | unwrapGlyph[106] = '↓' 95 | unwrapGlyph[107] = '⇟' 96 | unwrapGlyph[111] = 'F1' 97 | unwrapGlyph[112] = 'F2' 98 | unwrapGlyph[113] = 'F3' 99 | unwrapGlyph[114] = 'F4' 100 | unwrapGlyph[115] = 'F5' 101 | unwrapGlyph[116] = 'F6' 102 | unwrapGlyph[117] = 'F7' 103 | unwrapGlyph[118] = 'F8' 104 | unwrapGlyph[119] = 'F9' 105 | unwrapGlyph[120] = 'F10' 106 | unwrapGlyph[121] = 'F11' 107 | unwrapGlyph[122] = 'F12' 108 | unwrapGlyph[135] = 'F13' 109 | unwrapGlyph[136] = 'F14' 110 | unwrapGlyph[137] = 'F15' 111 | unwrapGlyph[140] = '⏏' 112 | unwrapGlyph[143] = 'F16' 113 | unwrapGlyph[144] = 'F17' 114 | unwrapGlyph[145] = 'F18' 115 | unwrapGlyph[146] = 'F19' 116 | -------------------------------------------------------------------------------- /ShortcutMagic/shared/readAppName.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/shared/readAppName.scpt -------------------------------------------------------------------------------- /ShortcutMagic/shared/readMenuItems.scpt: -------------------------------------------------------------------------------- 1 | -- TODO: Improve fetching of all windows with this code: (http://stackoverflow.com/questions/14551419/listing-all-windows-of-all-applications) -- tell application "System Events" -- repeat with theProcess in processes -- if not background only of theProcess then -- tell theProcess -- set processName to name -- set theWindows to windows -- end tell -- set windowsCount to count of theWindows -- if processName is "Google Chrome" then -- say "Chrome woo hoo" -- say windowsCount as text -- else if processName is not "Finder" then -- say processName -- say windowsCount as text -- if windowsCount is greater than 0 then -- repeat with theWindow in theWindows -- say "found a window of " & processName -- tell theProcess -- set frontmost to true -- tell theWindow -- click button 2 -- end tell -- end tell -- end repeat -- end if -- end if -- end if -- end repeat -- end tell -- tell application "System Events" -- set this_info to {} -- repeat with theProcess in (application processes where visible is true) -- set this_info to this_info & (value of (first attribute whose name is "AXWindows") of theProcess) -- end repeat -- this_info -- display list in results window of AppleScript Editor -- end tell on readShortcuts(argv) tell application "System Events" tell application process argv set liste to {} set liste2 to {} set holdMenuBarItems to {} set holdTopBar to menu bar 1 -- TODO: read menu items from each active window - how? -- from 2 because 1 is Apple menu repeat with y from 2 to (count every menu bar item of holdTopBar) set innerBarItem to menu bar item y of holdTopBar innerBarItem repeat with x from 1 to (count every menu of innerBarItem) set innerMenu to menu x of innerBarItem repeat with z from 1 to (count every menu item of innerMenu) set miniList to {} set shortcut to menu item z of innerMenu try set holdName to get name of shortcut if (holdName is not equal to missing value) then set end of miniList to holdName end if on error set holdName to missing value end try try set innerBarName to get name of innerBarItem if (innerBarName is not equal to missing value) then set end of miniList to {"menuName", innerBarName} end if on error set innerBarName to missing value end try set holdPosition to missing value try set holdPosition to get value of attribute "AXPosition" of shortcut if (holdPosition is not equal to missing value) then set end of miniList to {"position", (first item of holdPosition as string) & "," & last item of holdPosition as string} end if on error set holdPosition to missing value end try set holdCmdChar to missing value try set holdCmdChar to get value of attribute "AXMenuItemCmdChar" of shortcut if (holdCmdChar is not equal to missing value) then set end of miniList to {"AXMenuItemCmdChar", holdCmdChar} end if on error set holdCmdChar to missing value end try set holdCmdMod to missing value try set holdCmdMod to get value of attribute "AXMenuItemCmdModifiers" of shortcut if (holdCmdMod is not equal to 0) then set end of miniList to {"AXMenuItemCmdModifiers", holdCmdMod} end if on error set holdCmdMod to missing value end try set holdCmdGlyph to missing value try set holdCmdGlyph to (value of attribute "AXMenuItemCmdGlyph" of shortcut) as text if (holdCmdGlyph is not equal to "missing value") then set end of miniList to {"AXMenuItemCmdGlyph", holdCmdGlyph} end if on error set holdCmdGlyph to missing value end try --set holdCmd???? to (value of attribute "AXMenuItemCmdGlyph" of shortcut) as text --try -- holdCmd??? --on error -- set holdCmd??? to missing value --end try -- how to extract: -- set menuglyphs to text items of "2 ⇥ 3 ⇤ 4 ⌤ 9 ␣ 10 ⌦ 11 ↩ 16 ↓ 23 ⌫ 24 ← 25 ↑ 26 → 27 ⎋ 28 ⌧ 98 ⇞ 99 ⇪ 100 ← 101 → 102 ↖ 104 ↑ 105 ↘ 106 ↓ 107 ⇟ 111 F1 112 F2 113 F3 114 F4 115 F5 116 F6 117 F7 118 F8 119 F9 120 F10 121 F11 122 F12 135 F13 136 F14 137 F15 140 ⏏ 143 F16 144 F17 145 F18 146 F19" -- set cmdmods to text items of "⌘ ⇧⌘ ⌥⌘ ⌥⇧⌘ ⌃⌘ ⌃⇧⌘ ⌃⌥⌘ ⌃⌥⇧⌘ - ⇧ ⌥ ⌥⇧ ⌃ ⌃⇧ ⌃⌥ ⌃⌥⇧" -- repeat with i from 1 to (count menuglyphs) -- if item i of holdCmdGlyph is glyph then -- return modifier & item (i + 1) of menuglyphs -- end -- end repeat if ((count of miniList) > 1 and holdName is not equal to missing value and (holdCmdChar is not equal to missing value or holdCmdGlyph is not equal to missing value)) then set end of liste2 to miniList end if -- set holdMenuItemChild to menu item i -- set mName to get name of holdMenuItemChild end repeat end repeat set end of liste to liste2 set liste2 to {} end repeat return liste end tell end tell end readShortcuts on run(argv) return readShortcuts(argv) end run -------------------------------------------------------------------------------- /ShortcutMagic/shared/readShortcuts.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var unwrapShortcuts = require('./unwrapShortcuts'); 3 | var $ = require('NodObjC'); 4 | $.import('OSAKit'); 5 | 6 | 7 | function compileAndRunNameFetch() { 8 | // console.log(bundle); 9 | var scriptName = "readAppName"; 10 | var encoding = $.NSUTF8StringEncoding; 11 | var dirName = $(`${__dirname}/${scriptName}.scpt`); 12 | var source = $.NSString('stringWithContentsOfFile', dirName, 'encoding', encoding, 'error', null); 13 | var hold = $.OSAScript('alloc')('initWithSource', source); 14 | 15 | // TODO: How to make this a useable pointer? http://tootallnate.github.io/$/class.html -> createPointer ? 16 | // NSDictionary *errorInfo; 17 | var errorInfo = $.alloc($.NSDictionary); 18 | var compiled = hold('compileAndReturnError', errorInfo.ref()); 19 | 20 | if (!compiled) { 21 | $.NSLog("Compile failed: %@", errorInfo); 22 | return null; 23 | } 24 | 25 | var arrayArgs = $.NSMutableArray('alloc')('init'); 26 | arrayArgs('addObject', $("true")); 27 | 28 | console.log("script", scriptName); 29 | console.log("path", dirName); 30 | 31 | var executed = hold('executeHandlerWithName', $(scriptName), 'arguments', arrayArgs, 'error', errorInfo.ref()); 32 | if (executed) { 33 | return executed; 34 | } else { 35 | console.log("reading app name failed, ", $(errorInfo)); 36 | return null; 37 | } 38 | 39 | return executed; 40 | } 41 | 42 | function readShortcuts(appName) { 43 | // NSToolbarSidebarItem 44 | // NSToolbarItemGroup 45 | // NSInspectorBarItem 46 | // NSToolbarItemConfigWrapper 47 | // NSToolbarItem 48 | // NSToolbarItemViewer 49 | // NSToolbarToggleSidebarItemIdentifier 50 | 51 | 52 | // create an NSString of the applescript command that will be run 53 | // var command = $('tell application "System Preferences" activate set current pane to pane id "com.apple.preference.security" reveal anchor "Privacy_Accessibility" of current pane end tell'); 54 | 55 | var pool = $.NSAutoreleasePool('alloc')('init') 56 | var dirName = $(__dirname + '/readMenuItems.scpt'); 57 | // var bundle = $.NSBundle('mainBundle')('pathForResource', dirName, 'ofType', $("scpt")); 58 | var source = $.NSString('stringWithContentsOfFile', dirName, 'encoding', $.NSUTF8StringEncoding, 'error', null); 59 | var hold = $.OSAScript('alloc')('initWithSource', source); 60 | 61 | // TODO: How to make this a useable pointer? http://tootallnate.github.io/$/class.html -> createPointer ? 62 | // NSDictionary *errorInfo; 63 | var errorInfo = $.alloc($.NSDictionary); 64 | var compiled = hold('compileAndReturnError', errorInfo.ref()); 65 | 66 | if (!compiled) { 67 | return null; 68 | } 69 | 70 | var arrayArgs = $.NSMutableArray('alloc')('init'); 71 | arrayArgs('addObject', appName); 72 | var executed = hold('executeHandlerWithName', $("readShortcuts"), 'arguments', arrayArgs, 'error', errorInfo.ref()); 73 | 74 | console.log("appName", appName); 75 | console.log("args", arrayArgs); 76 | console.log("dirName", dirName); 77 | 78 | if (executed) { 79 | return executed; 80 | } else { 81 | console.log("reading shortcuts failed, ", appName); 82 | console.log(errorInfo); 83 | return null; 84 | } 85 | } 86 | 87 | module.exports = function() { 88 | return { 89 | readShortcuts: function(appName) { 90 | var shortcutNameString; 91 | if (appName && typeof appName == "string") { 92 | shortcutNameString = $(appName); 93 | } 94 | if (!shortcutNameString || shortcutNameString('length') == 0) { 95 | shortcutNameString = compileAndRunNameFetch(); 96 | if (shortcutNameString) { 97 | shortcutNameString = shortcutNameString('stringValue'); 98 | } 99 | appName = "" + shortcutNameString; 100 | } 101 | 102 | var shortcuts = readShortcuts(shortcutNameString); 103 | var unwrapped = unwrapShortcuts(shortcuts); 104 | 105 | if (shortcuts && unwrapped) { 106 | return { 107 | name: appName, 108 | shortcuts: unwrapped 109 | }; 110 | } 111 | }, 112 | readAppName: function() { 113 | // TODO: Combine with above to keep DRY 114 | var shortcutNameString = compileAndRunNameFetch(); 115 | if (shortcutNameString) { 116 | shortcutNameString = shortcutNameString('stringValue'); 117 | } 118 | return shortcutNameString; 119 | } 120 | } 121 | }; 122 | -------------------------------------------------------------------------------- /ShortcutMagic/shared/testAccessibility.scpt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/shared/testAccessibility.scpt -------------------------------------------------------------------------------- /ShortcutMagic/shortcutmagic.js: -------------------------------------------------------------------------------- 1 | // install babel hooks in the main process 2 | require('babel-register'); 3 | require('./index.js'); 4 | -------------------------------------------------------------------------------- /ShortcutMagic/sign_app.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Invoke this script with a relative '.app' path, for example: 3 | # codesign-electron.sh "darwin-x64/Electron.app" 4 | 5 | # 1. Run the following command to get a list of identities: 6 | # security find-identity 7 | 8 | # 2. Now set the value of the identity variable below to the identity you want to use: 9 | identity="Developer ID Application: Matias Forbord (A9ADPQA768)" 10 | 11 | appPath="$PWD/$1" 12 | appName=$2 13 | 14 | echo "Signing..." 15 | # When you sign frameworks, you have to sign a specific version. 16 | # For example, you have to sign "Electron Framework.framework/Versions/A" 17 | # Signing the top level folder ("Electron Framework.framework") will fail. 18 | # Signing "Electron Framework.framework/Versions/Current" will also fail (because it is a symbolic link). 19 | # Apple recommends NOT using --deep, but rather signing each item explictly (which is how XCode does it). 20 | # Other scripts sometimes resign items multiple times in the process because of --deep which is slow. 21 | # The following signs the bare minimum needed to get Gatekeeper acceptance. 22 | # If you renamed "Electron Helper.app", "Electron Helper EH.app" and "Electron Helper NP.app" then rename below. 23 | codesign --verbose --force --sign "$identity" "$appPath/Contents/Frameworks/Electron Framework.framework/Versions/A" 24 | codesign --verbose --force --sign "$identity" "$appPath/Contents/Frameworks/$appName Helper EH.app" 25 | codesign --verbose --force --sign "$identity" "$appPath/Contents/Frameworks/$appName Helper NP.app" 26 | codesign --verbose --force --sign "$identity" "$appPath/Contents/Frameworks/$appName Helper.app" 27 | codesign --verbose --force --sign "$identity" "$appPath/Contents/Frameworks/Mantle.framework/Versions/A" 28 | codesign --verbose --force --sign "$identity" "$appPath/Contents/Frameworks/ReactiveCocoa.framework/Versions/A" 29 | codesign --verbose --force --sign "$identity" "$appPath/Contents/Frameworks/Squirrel.framework/Versions/A" 30 | codesign --verbose --force --sign "$identity" "$appPath" 31 | 32 | # This will often pass, even if Gatekeeper fails. 33 | echo "" 34 | echo "Verifying signatures..." 35 | codesign --verify --deep --display --verbose=4 "$appPath" 36 | 37 | # This is what really counts and what the user will see. 38 | echo "" 39 | echo "Veriyfing Gatekeeper acceptance..." 40 | spctl --ignore-cache --no-cache --assess --type execute --verbose=4 "$appPath" 41 | 42 | # Thanks to http://jbavari.github.io/blog/2015/08/14/codesigning-electron-applications/ 43 | -------------------------------------------------------------------------------- /ShortcutMagic/survey/SurveyView.jsx: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | import React, { Component } from 'react'; 3 | import Electron, { ipcRenderer, remote } from 'electron'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | export default class SurveyView extends Component { 7 | render() { 8 | // TODO: Write logic for not recurring if the last path of the survey is reached in the webview 9 | return ( 10 |
11 | 16 |
17 | ); 18 | } 19 | }; 20 | 21 | window.onload = function(){ 22 | ReactDOM.render(, document.getElementById("survey-root")); 23 | }; 24 | -------------------------------------------------------------------------------- /ShortcutMagic/survey/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /ShortcutMagic/tooltip/TooltipView.jsx: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | import React, { Component } from 'react'; 3 | import ReactDOM from 'react-dom'; 4 | import { ipcRenderer, remote } from 'electron'; 5 | 6 | export default class TooltipView extends Component { 7 | componentWillMount() { 8 | ipcRenderer.on('set-gif', (event, listItem) => { 9 | console.log(`setting listItem.gif: ${listItem}`); 10 | this.setState({ 11 | gif: (listItem) ? listItem.gif : null 12 | }); 13 | }); 14 | 15 | // ipcRenderer.on('reset', (event) => { 16 | // }); 17 | 18 | // this.changeFontDown = this.changeFontDown.bind(this); 19 | } 20 | 21 | // changeFontDown() { 22 | // 23 | // } 24 | 25 | render() { 26 | // console.log('render() called'); 27 | // 28 | if (this.state && this.state.gif) { 29 | return ( 30 | 31 | ); 32 | } 33 | 34 | return ( 35 |
36 | No recorded gifs for this shortcut... Why not make one? Click to start! 37 |
38 | ); 39 | } 40 | } 41 | 42 | window.onload = function(){ 43 | ReactDOM.render(, document.getElementById("tooltip-root")); 44 | }; 45 | -------------------------------------------------------------------------------- /ShortcutMagic/tooltip/tooltip.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | ShortcutMagic 5 | 9 | 10 | 11 |
12 |
13 |
14 |
15 | 16 | 17 | -------------------------------------------------------------------------------- /ShortcutMagic/utilities/browserWindow.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | const log = require('electron-log'); 4 | 5 | log.transports.console.level = 'info'; 6 | log.transports.file.level = 'info'; 7 | 8 | const debugAllWindows = (allWindows) => { 9 | if (!allWindows) { 10 | log.info('Could not open dev tools for no windows') 11 | return 12 | } 13 | 14 | allWindows.forEach(w => debugWindow(w)) 15 | } 16 | 17 | const debugWindow = (browserWindow) => { 18 | if (!browserWindow) { 19 | log.info('Could not open dev tools for window that does not exist') 20 | return 21 | } 22 | 23 | log.info('Opening dev tools for ', browserWindow.title) 24 | browserWindow.openDevTools() 25 | } 26 | 27 | module.exports = { 28 | debugAllWindows, 29 | debugWindow 30 | } -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Photon 2 | 3 | ## Types of issues 4 | 5 | The GitHub issue tracker should only be used for one of the 6 | following: 7 | 8 | + **Bugs** — when a feature of the project has been _identified as 9 | broken_. 10 | 11 | + **Feature requests** — when you ask for a _new feature_ to be added to a 12 | project. 13 | 14 | + **Contribution enquiries** — when you want to discuss whether a _new 15 | feature_ or _change_ would be accepted in a project before you begin 16 | development work on it. 17 | 18 | These are some things that don't belong in the issue tracker: 19 | 20 | + **Please avoid personal support requests.** We cannot 21 | provide personal support for implementation issues. The best place for help 22 | is generally going to be StackOverflow, Twitter, IRC, etc. 23 | 24 | + **Please avoid derailing issues.** Keep the discussion on topic and respect 25 | the opinions of others. 26 | 27 | ## Bugs 28 | 29 | A bug is a _demonstrable problem_ that is caused by the code in the 30 | repository. 31 | 32 | If you've come across a problem with the code and you're letting us know about 33 | it, _thank you_. We appreciate your time and the effort you're making to help 34 | improve the code for everyone else! 35 | 36 | Please read the following guidelines for reporting bugs: 37 | 38 | 1. **Use the GitHub issue search** — check if the issue has already been 39 | reported. If it has been, please comment on the existing issue. 40 | 41 | 2. **Check if the issue has been fixed** — the latest `master` or 42 | development branch may already contain a fix. 43 | 44 | 3. **Isolate the demonstrable problem** — make sure that the code in the 45 | project's repository is _definitely_ responsible for the issue. Create a 46 | [reduced test case](http://css-tricks.com/6263-reduced-test-cases/) - an 47 | extremely simple and immediately viewable example of the issue. 48 | 49 | 4. **Include a live example** — provide a link to your reduced test case 50 | when appropriate (e.g. if the issue is related to front-end technologies). 51 | Please use [jsFiddle](http://jsfiddle.net) to host examples. 52 | 53 | Please try to be as detailed as possible in your report too. What is your 54 | environment? What steps will reproduce the issue? What browser(s) and OS 55 | experience the problem? What would you expect to be the outcome? All these 56 | details will help me and others to assess and fix any potential bugs. 57 | 58 | ### Example of a good bug report 59 | 60 | > Short and descriptive title 61 | > 62 | > A summary of the issue and the browser/OS environment in which it occurs. If 63 | > suitable, include the steps required to reproduce the bug. 64 | > 65 | > 1. This is the first step 66 | > 2. This is the second step 67 | > 3. Further steps, etc. 68 | > 69 | > `` - a link to the reduced test case 70 | > 71 | > Any other information you want to share that is relevant to the issue being 72 | > reported. This might include the lines of code that you have identified as 73 | > causing the bug, and potential solutions (and your opinions on their 74 | > merits). 75 | 76 | A good bug report shouldn't leave us needing to chase you up to get further 77 | information that is required to assess or fix the bug. 78 | 79 | ## Feature requests 80 | 81 | Feature requests are welcome! Please provide links to examples or articles that 82 | help to illustrate the specifics of a feature you're requesting. The more 83 | detail, the better. It will help us to decide whether the feature is something I 84 | agree should become part of the project. 85 | 86 | ## Contribution enquiries 87 | 88 | Contribution enquiries should take place before any significant pull request, 89 | otherwise you risk spending a lot of time working on something that we might not 90 | want to pull into the repository. 91 | 92 | In this regard, some contribution enquires may be feature requests that you 93 | would like to have a go at implementing yourself if they are wanted. Other 94 | enquiries might revolve around refactoring code or porting a project to 95 | different languages. 96 | 97 | ## Pull requests 98 | 99 | Good pull requests - patches, improvements, new features - are a fantastic 100 | help. 101 | 102 | If you've spotted any small, obvious errors and want to help out by patching it, 103 | that will be much appreciated. 104 | 105 | If your contribution involves a significant amount of work or substantial 106 | changes to any part of the project, please open a "contribution enquiry" issue 107 | first to check that the work is wanted or matches the goals of the project. 108 | 109 | All pull requests should remain focused in scope and avoid containing unrelated 110 | commits. 111 | 112 | Please follow this process; it's the best way to get your work included in the 113 | project: 114 | 115 | 1. [Fork](https://github.com/connors/photon/fork) the project. 116 | 117 | 2. Clone your fork (`git clone 118 | git@github.com:/.git`). 119 | 120 | 3. Add an `upstream` remote (`git remote add upstream 121 | git://github.com//.git`). 122 | 123 | 4. Get the latest changes from upstream (e.g. `git pull upstream 124 | `). 125 | 126 | 5. Create a new topic branch to contain your feature, change, or fix (`git 127 | checkout -b `). 128 | 129 | 6. Make sure that your changes adhere to the current coding conventions used 130 | throughout the project - indentation, accurate comments, etc. 131 | 132 | 7. Commit your changes in logical chunks; use git's [interactive 133 | rebase](https://help.github.com/articles/interactive-rebase) feature to tidy 134 | up your commits before making them public. Please adhere to these [git commit 135 | message guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html) 136 | or your pull request is unlikely be merged into the main project. 137 | 138 | 8. Locally merge (or rebase) the upstream branch into your topic branch. 139 | 140 | 9. Push your topic branch up to your fork (`git push origin 141 | `). 142 | 143 | 10. [Open a Pull Request](http://help.github.com/send-pull-requests/) with a 144 | clear title and description. Please mention which browsers you tested in. 145 | 146 | If you have any other questions about contributing, please feel free to contact 147 | us. 148 | 149 | **Don't edit files in `dist/`.** You should edit files in `sass/` and `js/`. 150 | 151 | ## Special thanks to @necolas 152 | 153 | For writing the original [issue-guidelines](https://github.com/necolas/issue-guidelines/) from which these were adapted. 154 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 connors and other contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/README.md: -------------------------------------------------------------------------------- 1 | # [Photon](http://photonkit.com/) 2 | 3 | [![Build Status](https://img.shields.io/travis/connors/photon/master.svg)](https://travis-ci.org/connors/photon) 4 | 5 | UI toolkit for building desktop apps with Electron. 6 | 7 | ## Getting started 8 | 9 | * Clone the repo with `git clone https://github.com/connors/photon.git` 10 | * [Read the docs](http://photonkit.com) to learn about the components and how to get your new application started 11 | 12 | Take note that our master branch is our active, unstable development branch and that if you're looking to download a stable copy of the repo, check the [tagged downloads](https://github.com/connors/photon/tags). 13 | 14 | ### What's included 15 | 16 | Within the download you'll find the following directories and files, logically grouping common assets. You'll see something like this: 17 | 18 | ``` 19 | photon/ 20 | ├── css/ 21 | │ ├── photon.css 22 | ├── fonts/ 23 | │ ├── photon-entypo.eot 24 | │ ├── photon-entypo.svg 25 | │ ├── photon-entypo.ttf 26 | │ └── photon-entypo.woff 27 | └── template-app/ 28 | ├── js/ 29 | │ └── menu.js 30 | ├── app.js 31 | ├── index.html 32 | └── package.json 33 | ``` 34 | 35 | We provide compiled CSS (`photon.*`). We also include the Entypo fonts and a template Electron application for you to quickly get started. 36 | 37 | ## Documentation 38 | 39 | Photon's documentation is built with [Jekyll](http://jekyllrb.com) and publicly hosted on GitHub Pages at . The docs may also be run locally. 40 | 41 | ### Running documentation locally 42 | 43 | 1. If necessary, [install Jekyll](http://jekyllrb.com/docs/installation) (requires v2.5.x). 44 | * **Windows users:** Read [this unofficial guide](http://jekyll-windows.juthilo.com/) to get Jekyll up and running without problems. 45 | 2. Install the Ruby-based syntax highlighter, [Rouge](https://github.com/jneen/rouge), with `gem install rouge`. 46 | 3. From the root `/photon` directory, run `jekyll serve` in the command line. 47 | 4. Open in your browser, and boom! 48 | 49 | Learn more about using Jekyll by reading its [documentation](http://jekyllrb.com/docs/home/). 50 | 51 | ## Contributing 52 | 53 | Please file a GitHub issue to [report a bug](https://github.com/connors/photon/issues). When reporting a bug, be sure to follow the [contributor guidelines](https://github.com/connors/photon/blob/master/CONTRIBUTING.md). 54 | 55 | 56 | ## Development 57 | 58 | 1. Install node dependencies: `npm install`. 59 | 2. Open the example app: `npm start`. 60 | 61 | Modifying source Sass files? Open a second Terminal tab and run `npm run build` to kick off a build of the compiled `photon.css`. 62 | 63 | ## Versioning 64 | 65 | For transparency into our release cycle and in striving to maintain backward compatibility, Photon is maintained under the Semantic Versioning guidelines. Sometimes we screw up, but we'll adhere to these rules whenever possible. 66 | 67 | Releases will be numbered with the following format: 68 | 69 | `..` 70 | 71 | And constructed with the following guidelines: 72 | 73 | * Breaking backward compatibility **bumps the major** while resetting minor and patch 74 | * New additions without breaking backward compatibility **bumps the minor** while resetting the patch 75 | * Bug fixes and misc changes **bumps only the patch** 76 | 77 | For more information on SemVer, please visit . 78 | 79 | ## Maintainers 80 | 81 | Connor Sears 82 | 83 | * 84 | * 85 | 86 | ## License 87 | 88 | Copyright @connors. Released under MIT. 89 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/_includes/footer.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 23 |
24 |
25 |
26 |
27 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/_includes/header.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ page.title }} 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/_includes/javascript.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 15 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/_includes/nav.html: -------------------------------------------------------------------------------- 1 | 10 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {% include header.html %} 5 | 6 | 7 | {{ content }} 8 | {% include footer.html %} 9 | {% include javascript.html %} 10 | 11 | 12 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/css/docs.min.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8";.btn,a{text-decoration:none}.col,.masthead{position:relative}.btn,.photo-credit{white-space:nowrap}.container:after,.nav:after{clear:both}.masthead-title,.oss-section,.sub-masthead{text-shadow:0 0 3px rgba(0,0,0,.3)}.btn,.text-centered{text-align:center}.icon:before,button,select{text-transform:none}*{-webkit-box-sizing:border-box;box-sizing:border-box}body{font:16px/1.7 Roboto,"Helvetica Neue",Helvetica,arial,sans-serif;font-weight:300;color:#333}.btn,.icon:before,.nav-item{line-height:1}h1,h2,h3,h4,h5,h6{margin-top:0;font-weight:300}h2{margin-bottom:.18em;font-size:1.6em}h3{margin-bottom:.15em;font-size:1.3em}h5{font-weight:400}p{margin-top:.5em;margin-bottom:.5em;font-size:1em;color:#555}.download-decription{margin-bottom:1em}.lead{font-size:1.1em;color:#777}a{color:#4b92c6}.highlight{margin:0;font-size:.9em}.btn{display:inline-block;padding:10px 15px;margin-bottom:0;font-size:14px;vertical-align:middle;color:#666;background-image:none;border:1px solid #ddd;border-radius:4px;transition:all .2s linear}.nav-item,.photo-credit{transition:opacity .15s linear}.btn:hover{border-color:#999}.btn-components,.btn-download{margin-right:1rem;margin-left:1rem;padding:12px 30px;display:block}.btn-download{margin-bottom:1rem;color:#0f2b3c;border-color:transparent;background-color:rgba(255,255,255,.9)}.btn-download:hover{border-color:transparent;background-color:#fff}@media (min-width:32em){.btn-components,.btn-download{margin-right:0;margin-left:0;display:inline-block}.btn-download{margin-right:1rem;margin-bottom:0;margin-left:0}}.btn-inversed{color:#fff;border-color:rgba(255,255,255,.7)}.btn-inversed:hover{border-color:#fff}.container{margin-left:auto;margin-right:auto;padding-left:1rem;padding-right:1rem}.container:after,.container:before{display:table;content:" "}.col{padding:3rem 1rem}@media (min-width:32em){.container{padding-left:0;padding-right:0;max-width:65rem}.col-group{display:-webkit-flex;display:-ms-flex;display:flex}.col{min-width:0;padding-right:3rem;padding-left:3rem;flex:1}.col-one-third{max-width:33.333%}}.masthead{padding-bottom:80px;color:#fff;background-image:url(/assets/img/photo-couch.png);background-size:cover}.masthead:after{position:absolute;top:0;right:0;bottom:0;left:0;content:"";background-color:#000;opacity:.25;z-index:1}.masthead-content{position:relative;margin-top:50px;z-index:10}.subpage-lead,.subpage-title{margin-top:0;margin-bottom:0;font-weight:300}.masthead-title{margin:0;padding:0 1rem 1.5rem;font-size:1.5em}@media (min-width:32em){.masthead{background-position:center}.masthead:after{display:none}.masthead-title{padding:0 8rem 3rem;font-size:2.1em}}.photo-credit{position:absolute;left:50%;bottom:1em;font-size:.8em;color:#fff;transform:translatex(-50%);opacity:.5;z-index:10}.photo-credit:hover{opacity:.9}.sub-masthead{color:#fff;background-color:#000;background-image:-webkit-gradient(linear,left bottom,right top,color-stop(0,#000),color-stop(100%,#0f2b3c));background-image:-webkit-linear-gradient(45deg,#000 0,#0f2b3c 100%);background-image:-moz-linear-gradient(45deg,#000 0,#0f2b3c 100%);background-image:linear-gradient(45deg,#000 0,#0f2b3c 100%)}.subpage-header-content{padding:2.5rem 1rem 3rem}@media (min-width:32em){.subpage-header-content{padding:3rem 3rem 4rem}}.subpage-lead{color:#fff;font-size:1.3em;opacity:.8}.nav{position:relative;padding-top:1.2rem;padding-bottom:1.2rem;margin-left:1rem;margin-right:1rem;display:block;font-weight:500;border-bottom:1px solid rgba(255,255,255,.2);z-index:10}.nav:after,.nav:before{display:table;content:" "}.nav-group,.title{display:block}.title{font-size:1em;color:#fff}.nav-item{margin-right:.7rem;font-size:.8em;color:#fff;opacity:.7}.nav-item:hover{opacity:1}.example-component-window{height:300px;overflow:hidden;box-shadow:0 0 30px rgba(0,0,0,.1);border:1px solid #bebebe;border-radius:6px}@media (min-width:32em){.nav,.nav-item{margin-right:3rem}.nav{margin-left:3rem}.title{float:left}.nav-group{margin-top:.5em;float:right}.nav-item{float:left}.nav-item:last-child{margin-right:0}.example-component-container{position:-webkit-sticky;position:-moz-sticky;position:-ms-sticky;position:-o-sticky;position:sticky;top:3rem;min-width:310px;margin-bottom:3rem}}.icon:before,.oss-section,sub,sup{position:relative}.demo-app-container{height:450px;margin-right:3rem;margin-bottom:3rem;margin-left:3rem;display:none;border-radius:6px;overflow:hidden;box-shadow:0 0 60px rgba(0,0,0,.3)}@media (min-width:32em){.demo-app-container{display:block}}.component-example,.demo-app{width:100%;height:100%;display:block;border:0}.footer-links li,.icon:before{display:inline-block}.component-section,.docs-section{border-bottom:1px solid #ddd}.docs-section-gray{background-color:#f8f8f8}.oss-section{color:#fff;background-color:#000;background-image:-webkit-gradient(linear,left bottom,right top,color-stop(0,#000),color-stop(100%,#0f2b3c));background-image:-webkit-linear-gradient(45deg,#000 0,#0f2b3c 100%);background-image:-moz-linear-gradient(45deg,#000 0,#0f2b3c 100%);background-image:linear-gradient(45deg,#000 0,#0f2b3c 100%)}.oss-section a:not(.btn){color:#fff}.oss-section p{color:#ccc}.oss-section .btn{margin-top:20px}.oss-section .col:last-child{padding-top:0}@media (min-width:32em){.basic-template-section{border-top:1px solid #ddd}.oss-section .col:last-child{padding-top:3rem}}.component-section{margin-bottom:1rem}.component-section.last-component-section{margin-bottom:0}.component-section .col:last-child{padding-top:0}@media (min-width:32em){.component-section{margin-bottom:0;border-bottom:0;background-color:#fff;background-image:-webkit-gradient(linear,left top,right top,color-stop(50%,#fff),color-stop(50%,#f5f5f5));background-image:-webkit-linear-gradient(left,#fff 50%,#f5f5f5 50%);background-image:linear-gradient(to right,#fff 50%,#f5f5f5 50%)}.component-section .col{padding-top:3rem;border-left:1px solid #ddd}.component-section .col:first-child{border-left:0}.component-section .col:last-child{padding-top:3rem;padding-bottom:0}}.component-description,.docs-hr{margin-bottom:2rem}legend,td,th{padding:0}.footer{margin-top:-1px;border-top:1px solid #ddd}.footer-content{font-size:.8em;font-weight:500;opacity:.8}.footer-links{padding-left:0;list-style:none}@media (min-width:32em){.footer-content{margin-right:5rem;margin-left:5rem}}.docs-hr{margin-top:2rem;background:0 0;border:0;border-bottom:1px solid #ddd}@font-face{font-family:photon-entypo;src:url(/dist/fonts/photon-entypo.eot);src:url(/dist/fonts/photon-entypo.eot?#iefix) format("eot"),url(/dist/fonts/photon-entypo.woff) format("woff"),url(/dist/fonts/photon-entypo.ttf) format("truetype");font-weight:400;font-style:normal}.icon:before{font-family:photon-entypo;speak:none;font-size:100%;font-style:normal;font-weight:400;font-variant:normal;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.ge,.sd,dfn{font-style:italic}.icon-bucket:before{content:'\e8d5'}.icon-code:before{content:'\e834'}.icon-window:before{content:'\e86d'}.buttons-component{height:80px}.button-groups-component{height:110px}.forms-component{height:430px}.icons-component{height:700px;overflow:hidden}.hll{background-color:#ffc}.c{color:#999}.err{color:#A00;background-color:#FAA}.k{color:#069}.o{color:#555}.cm{color:#999}.cp{color:#099}.c1,.cs{color:#999}.gd{background-color:#FCC;border:1px solid #C00}.gr{color:red}.gh{color:#030}.gi{background-color:#CFC;border:1px solid #0C0}img,legend{border:0}.go{color:#AAA}.gp{color:#009}.gu{color:#030}.gt{color:#9C6}.kc,.kd,.kn,.kp,.kr{color:#069}.kt{color:#078}.m{color:#F60}.s{color:#d44950}.na{color:#4f9fcf}.nb{color:#366}.nc{color:#0A8}.no{color:#360}.nd{color:#99F}.ni{color:#999}.ne{color:#C00}.nf{color:#C0F}.nl{color:#99F}.nn{color:#0CF}.nt{color:#2f6f9f}.nv{color:#033}.ow{color:#000}.w{color:#bbb}.mf,.mh,.mi,.mo{color:#F60}.s2,.sb,.sc,.sd,.se,.sh{color:#C30}.si{color:#A00}.sx{color:#C30}.sr{color:#3AA}.s1{color:#C30}.ss{color:#FC3}.bp{color:#366}.vc,.vg,.vi{color:#033}.il{color:#F60}.css .nt+.nt,.css .o,.css .o+.nt{color:#999}/*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,menu,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background-color:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,optgroup,strong{font-weight:700}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;vertical-align:baseline}sup{top:-.5em}sub{bottom:-.25em}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{box-sizing:content-box;height:0}pre,textarea{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,html input[type=button],input[type=reset],input[type=submit]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}input[type=search]{-webkit-appearance:textfield;box-sizing:content-box}input[type=search]::-webkit-search-cancel-button,input[type=search]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}table{border-collapse:collapse;border-spacing:0} -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/css/normalize.css: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS and IE text size adjust after device orientation change, 6 | * without disabling user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/10/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability of focused elements when they are also in an 95 | * active/hover state. 96 | */ 97 | 98 | a:active, 99 | a:hover { 100 | outline: 0; 101 | } 102 | 103 | /* Text-level semantics 104 | ========================================================================== */ 105 | 106 | /** 107 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 108 | */ 109 | 110 | abbr[title] { 111 | border-bottom: 1px dotted; 112 | } 113 | 114 | /** 115 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 116 | */ 117 | 118 | b, 119 | strong { 120 | font-weight: bold; 121 | } 122 | 123 | /** 124 | * Address styling not present in Safari and Chrome. 125 | */ 126 | 127 | dfn { 128 | font-style: italic; 129 | } 130 | 131 | /** 132 | * Address variable `h1` font-size and margin within `section` and `article` 133 | * contexts in Firefox 4+, Safari, and Chrome. 134 | */ 135 | 136 | h1 { 137 | font-size: 2em; 138 | margin: 0.67em 0; 139 | } 140 | 141 | /** 142 | * Address styling not present in IE 8/9. 143 | */ 144 | 145 | mark { 146 | background: #ff0; 147 | color: #000; 148 | } 149 | 150 | /** 151 | * Address inconsistent and variable font size in all browsers. 152 | */ 153 | 154 | small { 155 | font-size: 80%; 156 | } 157 | 158 | /** 159 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 160 | */ 161 | 162 | sub, 163 | sup { 164 | font-size: 75%; 165 | line-height: 0; 166 | position: relative; 167 | vertical-align: baseline; 168 | } 169 | 170 | sup { 171 | top: -0.5em; 172 | } 173 | 174 | sub { 175 | bottom: -0.25em; 176 | } 177 | 178 | /* Embedded content 179 | ========================================================================== */ 180 | 181 | /** 182 | * Remove border when inside `a` element in IE 8/9/10. 183 | */ 184 | 185 | img { 186 | border: 0; 187 | } 188 | 189 | /** 190 | * Correct overflow not hidden in IE 9/10/11. 191 | */ 192 | 193 | svg:not(:root) { 194 | overflow: hidden; 195 | } 196 | 197 | /* Grouping content 198 | ========================================================================== */ 199 | 200 | /** 201 | * Address margin not present in IE 8/9 and Safari. 202 | */ 203 | 204 | figure { 205 | margin: 1em 40px; 206 | } 207 | 208 | /** 209 | * Address differences between Firefox and other browsers. 210 | */ 211 | 212 | hr { 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome. 354 | */ 355 | 356 | input[type="search"] { 357 | -webkit-appearance: textfield; /* 1 */ 358 | box-sizing: content-box; /* 2 */ 359 | } 360 | 361 | /** 362 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 363 | * Safari (but not Chrome) clips the cancel button when the search input has 364 | * padding (and `textfield` appearance). 365 | */ 366 | 367 | input[type="search"]::-webkit-search-cancel-button, 368 | input[type="search"]::-webkit-search-decoration { 369 | -webkit-appearance: none; 370 | } 371 | 372 | /** 373 | * Define consistent border, margin, and padding. 374 | */ 375 | 376 | fieldset { 377 | border: 1px solid #c0c0c0; 378 | margin: 0 2px; 379 | padding: 0.35em 0.625em 0.75em; 380 | } 381 | 382 | /** 383 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 384 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 385 | */ 386 | 387 | legend { 388 | border: 0; /* 1 */ 389 | padding: 0; /* 2 */ 390 | } 391 | 392 | /** 393 | * Remove default vertical scrollbar in IE 8/9/10/11. 394 | */ 395 | 396 | textarea { 397 | overflow: auto; 398 | } 399 | 400 | /** 401 | * Don't inherit the `font-weight` (applied by a rule above). 402 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 403 | */ 404 | 405 | optgroup { 406 | font-weight: bold; 407 | } 408 | 409 | /* Tables 410 | ========================================================================== */ 411 | 412 | /** 413 | * Remove most spacing between table cells. 414 | */ 415 | 416 | table { 417 | border-collapse: collapse; 418 | border-spacing: 0; 419 | } 420 | 421 | td, 422 | th { 423 | padding: 0; 424 | } 425 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/css/pygments-manni.css: -------------------------------------------------------------------------------- 1 | .hll { background-color: #ffffcc } 2 | /*{ background: #f0f3f3; }*/ 3 | .c { color: #999; } /* Comment */ 4 | .err { color: #AA0000; background-color: #FFAAAA } /* Error */ 5 | .k { color: #006699; } /* Keyword */ 6 | .o { color: #555555 } /* Operator */ 7 | .cm { color: #999; } /* Comment.Multiline */ /* Edited to remove italics and make into comment */ 8 | .cp { color: #009999 } /* Comment.Preproc */ 9 | .c1 { color: #999; } /* Comment.Single */ 10 | .cs { color: #999; } /* Comment.Special */ 11 | .gd { background-color: #FFCCCC; border: 1px solid #CC0000 } /* Generic.Deleted */ 12 | .ge { font-style: italic } /* Generic.Emph */ 13 | .gr { color: #FF0000 } /* Generic.Error */ 14 | .gh { color: #003300; } /* Generic.Heading */ 15 | .gi { background-color: #CCFFCC; border: 1px solid #00CC00 } /* Generic.Inserted */ 16 | .go { color: #AAAAAA } /* Generic.Output */ 17 | .gp { color: #000099; } /* Generic.Prompt */ 18 | .gs { } /* Generic.Strong */ 19 | .gu { color: #003300; } /* Generic.Subheading */ 20 | .gt { color: #99CC66 } /* Generic.Traceback */ 21 | .kc { color: #006699; } /* Keyword.Constant */ 22 | .kd { color: #006699; } /* Keyword.Declaration */ 23 | .kn { color: #006699; } /* Keyword.Namespace */ 24 | .kp { color: #006699 } /* Keyword.Pseudo */ 25 | .kr { color: #006699; } /* Keyword.Reserved */ 26 | .kt { color: #007788; } /* Keyword.Type */ 27 | .m { color: #FF6600 } /* Literal.Number */ 28 | .s { color: #d44950 } /* Literal.String */ 29 | .na { color: #4f9fcf } /* Name.Attribute */ 30 | .nb { color: #336666 } /* Name.Builtin */ 31 | .nc { color: #00AA88; } /* Name.Class */ 32 | .no { color: #336600 } /* Name.Constant */ 33 | .nd { color: #9999FF } /* Name.Decorator */ 34 | .ni { color: #999999; } /* Name.Entity */ 35 | .ne { color: #CC0000; } /* Name.Exception */ 36 | .nf { color: #CC00FF } /* Name.Function */ 37 | .nl { color: #9999FF } /* Name.Label */ 38 | .nn { color: #00CCFF; } /* Name.Namespace */ 39 | .nt { color: #2f6f9f; } /* Name.Tag */ 40 | .nv { color: #003333 } /* Name.Variable */ 41 | .ow { color: #000000; } /* Operator.Word */ 42 | .w { color: #bbbbbb } /* Text.Whitespace */ 43 | .mf { color: #FF6600 } /* Literal.Number.Float */ 44 | .mh { color: #FF6600 } /* Literal.Number.Hex */ 45 | .mi { color: #FF6600 } /* Literal.Number.Integer */ 46 | .mo { color: #FF6600 } /* Literal.Number.Oct */ 47 | .sb { color: #CC3300 } /* Literal.String.Backtick */ 48 | .sc { color: #CC3300 } /* Literal.String.Char */ 49 | .sd { color: #CC3300; font-style: italic } /* Literal.String.Doc */ 50 | .s2 { color: #CC3300 } /* Literal.String.Double */ 51 | .se { color: #CC3300; } /* Literal.String.Escape */ 52 | .sh { color: #CC3300 } /* Literal.String.Heredoc */ 53 | .si { color: #AA0000 } /* Literal.String.Interpol */ 54 | .sx { color: #CC3300 } /* Literal.String.Other */ 55 | .sr { color: #33AAAA } /* Literal.String.Regex */ 56 | .s1 { color: #CC3300 } /* Literal.String.Single */ 57 | .ss { color: #FFCC33 } /* Literal.String.Symbol */ 58 | .bp { color: #336666 } /* Name.Builtin.Pseudo */ 59 | .vc { color: #003333 } /* Name.Variable.Class */ 60 | .vg { color: #003333 } /* Name.Variable.Global */ 61 | .vi { color: #003333 } /* Name.Variable.Instance */ 62 | .il { color: #FF6600 } /* Literal.Number.Integer.Long */ 63 | 64 | .css .o, 65 | .css .o + .nt, 66 | .css .nt + .nt { color: #999; } 67 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/img/avatar.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/vendor/photonkit/docs/assets/img/avatar.jpg -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/img/avatar2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/vendor/photonkit/docs/assets/img/avatar2.png -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/img/avatar3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/vendor/photonkit/docs/assets/img/avatar3.jpg -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/img/avatar4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/vendor/photonkit/docs/assets/img/avatar4.jpg -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/img/avatar5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/vendor/photonkit/docs/assets/img/avatar5.png -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/img/avatar6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/vendor/photonkit/docs/assets/img/avatar6.jpg -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/img/avatar7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/vendor/photonkit/docs/assets/img/avatar7.jpg -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/img/photo-couch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeluggage/ShortcutMagic/b0d9e1dd84e118c845d82693c2069e6cb5042507/ShortcutMagic/vendor/photonkit/docs/assets/img/photo-couch.png -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/js/docs.js: -------------------------------------------------------------------------------- 1 | $('.example-component-container').Stickyfill(); 2 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/assets/js/sticky.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Stickyfill -- `position: sticky` polyfill 3 | * v. 1.1.3 | https://github.com/wilddeer/stickyfill 4 | * Copyright Oleg Korsunsky | http://wd.dizaina.net/ 5 | * 6 | * MIT License 7 | */ 8 | !function(a,b){function c(){y=D=z=A=B=C=K}function d(a,b){for(var c in b)b.hasOwnProperty(c)&&(a[c]=b[c])}function e(a){return parseFloat(a)||0}function f(){F={top:b.pageYOffset,left:b.pageXOffset}}function g(){return b.pageXOffset!=F.left?(f(),void z()):void(b.pageYOffset!=F.top&&(f(),i()))}function h(){setTimeout(function(){b.pageYOffset!=F.top&&(F.top=b.pageYOffset,i())},0)}function i(){for(var a=H.length-1;a>=0;a--)j(H[a])}function j(a){if(a.inited){var b=F.top<=a.limit.start?0:F.top>=a.limit.end?2:1;a.mode!=b&&p(a,b)}}function k(){for(var a=H.length-1;a>=0;a--)if(H[a].inited){var b=Math.abs(t(H[a].clone)-H[a].docOffsetTop),c=Math.abs(H[a].parent.node.offsetHeight-H[a].parent.height);if(b>=2||c>=2)return!1}return!0}function l(a){isNaN(parseFloat(a.computed.top))||a.isCell||"none"==a.computed.display||(a.inited=!0,a.clone||q(a),"absolute"!=a.parent.computed.position&&"relative"!=a.parent.computed.position&&(a.parent.node.style.position="relative"),j(a),a.parent.height=a.parent.node.offsetHeight,a.docOffsetTop=t(a.clone))}function m(a){var b=!0;a.clone&&r(a),d(a.node.style,a.css);for(var c=H.length-1;c>=0;c--)if(H[c].node!==a.node&&H[c].parent.node===a.parent.node){b=!1;break}b&&(a.parent.node.style.position=a.parent.css.position),a.mode=-1}function n(){for(var a=H.length-1;a>=0;a--)l(H[a])}function o(){for(var a=H.length-1;a>=0;a--)m(H[a])}function p(a,b){var c=a.node.style;switch(b){case 0:c.position="absolute",c.left=a.offset.left+"px",c.right=a.offset.right+"px",c.top=a.offset.top+"px",c.bottom="auto",c.width="auto",c.marginLeft=0,c.marginRight=0,c.marginTop=0;break;case 1:c.position="fixed",c.left=a.box.left+"px",c.right=a.box.right+"px",c.top=a.css.top,c.bottom="auto",c.width="auto",c.marginLeft=0,c.marginRight=0,c.marginTop=0;break;case 2:c.position="absolute",c.left=a.offset.left+"px",c.right=a.offset.right+"px",c.top="auto",c.bottom=0,c.width="auto",c.marginLeft=0,c.marginRight=0}a.mode=b}function q(a){a.clone=document.createElement("div");var b=a.node.nextSibling||a.node,c=a.clone.style;c.height=a.height+"px",c.width=a.width+"px",c.marginTop=a.computed.marginTop,c.marginBottom=a.computed.marginBottom,c.marginLeft=a.computed.marginLeft,c.marginRight=a.computed.marginRight,c.padding=c.border=c.borderSpacing=0,c.fontSize="1em",c.position="static",c.cssFloat=a.computed.cssFloat,a.node.parentNode.insertBefore(a.clone,b)}function r(a){a.clone.parentNode.removeChild(a.clone),a.clone=void 0}function s(a){var b=getComputedStyle(a),c=a.parentNode,d=getComputedStyle(c),f=a.style.position;a.style.position="relative";var g={top:b.top,marginTop:b.marginTop,marginBottom:b.marginBottom,marginLeft:b.marginLeft,marginRight:b.marginRight,cssFloat:b.cssFloat,display:b.display},h={top:e(b.top),marginBottom:e(b.marginBottom),paddingLeft:e(b.paddingLeft),paddingRight:e(b.paddingRight),borderLeftWidth:e(b.borderLeftWidth),borderRightWidth:e(b.borderRightWidth)};a.style.position=f;var i={position:a.style.position,top:a.style.top,bottom:a.style.bottom,left:a.style.left,right:a.style.right,width:a.style.width,marginTop:a.style.marginTop,marginLeft:a.style.marginLeft,marginRight:a.style.marginRight},j=u(a),k=u(c),l={node:c,css:{position:c.style.position},computed:{position:d.position},numeric:{borderLeftWidth:e(d.borderLeftWidth),borderRightWidth:e(d.borderRightWidth),borderTopWidth:e(d.borderTopWidth),borderBottomWidth:e(d.borderBottomWidth)}},m={node:a,box:{left:j.win.left,right:J.clientWidth-j.win.right},offset:{top:j.win.top-k.win.top-l.numeric.borderTopWidth,left:j.win.left-k.win.left-l.numeric.borderLeftWidth,right:-j.win.right+k.win.right-l.numeric.borderRightWidth},css:i,isCell:"table-cell"==b.display,computed:g,numeric:h,width:j.win.right-j.win.left,height:j.win.bottom-j.win.top,mode:-1,inited:!1,parent:l,limit:{start:j.doc.top-h.top,end:k.doc.top+c.offsetHeight-l.numeric.borderBottomWidth-a.offsetHeight-h.top-h.marginBottom}};return m}function t(a){for(var b=0;a;)b+=a.offsetTop,a=a.offsetParent;return b}function u(a){var c=a.getBoundingClientRect();return{doc:{top:c.top+b.pageYOffset,left:c.left+b.pageXOffset},win:c}}function v(){G=setInterval(function(){!k()&&z()},500)}function w(){clearInterval(G)}function x(){I&&(document[L]?w():v())}function y(){I||(f(),n(),b.addEventListener("scroll",g),b.addEventListener("wheel",h),b.addEventListener("resize",z),b.addEventListener("orientationchange",z),a.addEventListener(M,x),v(),I=!0)}function z(){if(I){o();for(var a=H.length-1;a>=0;a--)H[a]=s(H[a].node);n()}}function A(){b.removeEventListener("scroll",g),b.removeEventListener("wheel",h),b.removeEventListener("resize",z),b.removeEventListener("orientationchange",z),a.removeEventListener(M,x),w(),I=!1}function B(){A(),o()}function C(){for(B();H.length;)H.pop()}function D(a){for(var b=H.length-1;b>=0;b--)if(H[b].node===a)return;var c=s(a);H.push(c),I?l(c):y()}function E(a){for(var b=H.length-1;b>=0;b--)H[b].node===a&&(m(H[b]),H.splice(b,1))}var F,G,H=[],I=!1,J=a.documentElement,K=function(){},L="hidden",M="visibilitychange";void 0!==a.webkitHidden&&(L="webkitHidden",M="webkitvisibilitychange"),b.getComputedStyle||c();for(var N=["","-webkit-","-moz-","-ms-"],O=document.createElement("div"),P=N.length-1;P>=0;P--){try{O.style.position=N[P]+"sticky"}catch(Q){}""!=O.style.position&&c()}f(),b.Stickyfill={stickies:H,add:D,remove:E,init:y,rebuild:z,pause:A,stop:B,kill:C}}(document,window),window.jQuery&&!function($){$.fn.Stickyfill=function(){return this.each(function(){Stickyfill.add(this)}),this}}(window.jQuery); 9 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/bars-actions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Bars example 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

Header with actions

15 | 16 |
17 |
18 | 21 | 24 | 27 | 30 | 33 |
34 | 35 | 39 | 40 | 43 |
44 |
45 | 46 |
47 | 48 |
49 |
50 | 53 | 54 | 57 |
58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/bars-tabs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Bars example 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

Header with tabs

15 |
16 | 17 |
18 |
19 | 20 | Tab 21 |
22 |
23 | 24 | Tab active 25 |
26 |
27 | 28 | Tab 29 |
30 |
31 | 32 |
33 |
34 |
35 | 36 | 37 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/bars.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Bars example 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

Header

15 |
16 | 17 |
18 | 19 |
20 |

Footer

21 |
22 |
23 | 24 | 25 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/basic-sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Sidebar layout 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 18 |
19 |
Main content pane
20 |
21 |
22 |
23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/basic-window.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Basic window structure 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 | Your application's content goes inside .window-content. 15 |
16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/button-groups.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Buttons example 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 |
19 | 22 | 25 | 28 | 31 | 34 |
35 | 36 |
37 | 38 |
39 | 42 | 45 | 48 | 51 | 54 |
55 | 56 |
57 | 58 |
59 | 62 | 65 | 68 | 71 | 74 |
75 | 76 | 77 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/buttons-large.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Buttons example 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/buttons-mini.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Buttons example 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/buttons.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Buttons example 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/common-layout.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Sidebar layout 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |

Header

15 |
16 |
17 |
18 | 21 |
22 |
Main content pane
23 |
24 |
25 |
26 |
27 |

Footer

28 |
29 |
30 | 31 | 32 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/forms.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Forms example 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 |
20 |
21 | 22 | 23 |
24 |
25 | 26 | 27 |
28 |
29 | 30 | 31 |
32 | 42 |
43 | 46 |
47 |
48 | 51 |
52 |
53 | 57 |
58 |
59 | 63 |
64 |
65 | 66 | 67 |
68 |
69 | 70 | 71 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/lists.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Lists example 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 |
19 |
20 |
21 | 70 |
71 |
72 |
73 |
74 |
75 | 76 | 77 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/mini-sidebar.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Sidebar layout 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 | 18 |
19 |
Main content pane
20 |
21 |
22 |
23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/navs.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Navs example 7 | 8 | 9 | 10 | 11 | 16 | 17 | 18 |
19 |
20 |
21 | 90 |
91 |
92 |
93 |
94 |
95 | 96 | 97 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/tables.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Tables example 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |
NameKindFile Size
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
photon.cssCSS28K
92 |
93 |
94 |
95 |
96 | 97 | 98 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/components/three-paned.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Two paned layout 7 | 8 | 9 | 10 | 11 | 12 |
13 |
14 |
15 |
16 |
First pane
17 |
18 |
19 |
Second pane
20 |
21 |
22 |
Third pane
23 |
24 |
25 |
26 |
27 | 28 | 29 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/demo-app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Demo App 7 | 8 | 9 | 10 | 11 | 20 | 21 | 22 |
23 |
24 |

Photon

25 | 26 |
27 | 28 |
29 | 32 | 35 | 38 | 41 | 44 |
45 | 46 | 50 | 51 | 54 |
55 |
56 | 57 |
58 |
59 | 131 |
132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 |
NameKindDate ModifiedAuthor
bars.scssDocumentOct 13, 2015connors
base.scssDocumentOct 13, 2015connors
button-groups.scssDocumentOct 13, 2015connors
buttons.scssDocumentOct 13, 2015connors
docs.scssDocumentOct 13, 2015connors
forms.scssDocumentOct 13, 2015connors
grid.scssDocumentOct 13, 2015connors
icons.scssDocumentOct 13, 2015connors
images.scssDocumentOct 13, 2015connors
lists.scssDocumentOct 13, 2015connors
mixins.scssDocumentOct 13, 2015connors
navs.scssDocumentOct 13, 2015connors
normalize.scssDocumentOct 13, 2015connors
photon.scssDocumentOct 13, 2015connors
tables.scssDocumentOct 13, 2015connors
tabs.scssDocumentOct 13, 2015connors
utilities.scssDocumentOct 13, 2015connors
variables.scssDocumentOct 13, 2015connors
252 |
253 |
254 |
255 |
256 | 257 | 258 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/getting-started.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Photon · Getting started 4 | --- 5 | 6 | 7 |
8 |
9 | {% include nav.html %} 10 |
11 |

Getting started

12 |

Just download Photon and you'll be well on your way

13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 |

What's included

22 |

Photon is downloadable in two forms, within which you'll find the following directories and files, logically grouping common and compiled resources.

23 | 24 |
25 | 26 |

Precompiled Photon

27 |

Once downloaded, unzip the compressed folder to see the structure of (the compiled) photon. You'll see something like this:

28 | 29 | {% highlight html %} 30 | photon/ 31 | ├── css/ 32 | │ ├── photon.css 33 | ├── fonts/ 34 | │ ├── photon-entypo.eot 35 | │ ├── photon-entypo.svg 36 | │ ├── photon-entypo.ttf 37 | │ └── photon-entypo.woff 38 | └── template-app/ 39 | ├── js/ 40 | │ └── menu.js 41 | ├── app.js 42 | ├── index.html 43 | └── package.json 44 | {% endhighlight %} 45 | 46 |

This is the most basic form of Photon: precompiled files for quick drop-in usage in nearly any Electron project. We provide compiled CSS (`photon.*`). We also include the Entypo fonts and a template Electron application for you to quickly get started.

47 | 48 | 49 |
50 | 51 |

Photon source code

52 |

The Photon source code download includes the precompiled CSS, and font assets, along with source Sass, and documentation. More specifically, it includes the following and more:

53 | {% highlight html %} 54 | photon/ 55 | ├── sass/ 56 | ├── fonts/ 57 | ├── dist/ 58 | │ ├── css/ 59 | │ ├── fonts/ 60 | │ └── template-app/ 61 | └── docs/ 62 | {% endhighlight %} 63 | 64 |

The sass/ and fonts/ are the source code for our CSS and icon fonts (respectively). 65 | The dist/ folder includes everything listed in the precompiled download section above. 66 | The docs/ folder includes the source code for our documentation, and examples/ of Photon usage. 67 | Beyond that, any other included file provides support for packages, license information, and development.

68 |
69 |
70 |

Photon

71 |

Compiled CSS and fonts. No docs or original source files are included.

72 | Download 73 | 74 |
75 | 76 | 77 |

Source code

78 |

If you haven't already, download the source code for Photon.

79 | Download 80 |
81 |
82 |
83 |
84 | 85 |
86 |
87 |
88 |
89 |

Application layout

90 |

Every Photon application has the same basic structure that consists of 91 | a main .window element and cooresponding .window-content wrapper.

92 | {% highlight html %} 93 |
94 |
95 | ... 96 |
97 |
98 | {% endhighlight %} 99 |
100 |
101 |
102 | 103 |
104 |
105 |
106 |
107 |
108 | 109 |
110 |
111 |
112 |
113 |

Paned layout

114 |

Divide up your applications content any way you want using .pane-group and .pane elements. 115 | Add as many panes as you need. They'll layout out evenly across the application.

116 | {% highlight html %} 117 |
118 |
119 |
120 |
...
121 |
...
122 |
...
123 |
124 |
125 |
126 | {% endhighlight %} 127 |
128 |
129 |
130 | 131 |
132 |
133 |
134 |
135 |
136 | 137 |
138 |
139 |
140 |
141 |

Sidebar layout

142 |

Sidebars are useful for housing navigation or other supplemental information in your application. 143 | The optional .sidebar class sets the pane's background color to gray.

144 | {% highlight html %} 145 |
146 |
147 |
148 | 149 |
...
150 |
151 |
152 |
153 | {% endhighlight %} 154 |
155 |
156 |
157 | 158 |
159 |
160 |
161 |
162 |
163 | 164 |
165 |
166 |
167 |
168 |

Mini-sidebar layout

169 |

If a smaller sidebar is what you need, look no further.

170 | {% highlight html %} 171 |
172 |
173 |
174 | 175 |
...
176 |
177 |
178 |
179 | {% endhighlight %} 180 |
181 |
182 |
183 | 184 |
185 |
186 |
187 |
188 |
189 | 190 |
191 |
192 |
193 |
194 |

Common layout

195 |

Many applications follow the same simple layout with a header, content, and footer structure. 196 | That's super easy to build in Photon.

197 | {% highlight html %} 198 |
199 |
200 |

Header

201 |
202 |
203 |
204 | 205 |
...
206 |
207 |
208 |
209 |

Footer

210 |
211 |
212 | {% endhighlight %} 213 |
214 |
215 |
216 | 217 |
218 |
219 |
220 |
221 |
222 | 223 |
224 |
225 |
226 |
227 |

Basic Template

228 |

229 | {% highlight html %} 230 | 231 | 232 | 233 | Photon 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 |
245 | 246 |
247 |

Photon

248 |
249 | 250 | 251 |
252 |
253 |

Welcome to Photon

254 |

255 | Thanks for downloading Photon. This is an example HTML page that's linked up to compiled Photon CSS, has the proper meta tags 256 | and the HTML structure. 257 |

258 |
259 |
260 |
261 | 262 | 263 | {% endhighlight %} 264 |
265 |
266 |
267 |
268 | -------------------------------------------------------------------------------- /ShortcutMagic/vendor/photonkit/docs/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Photon 4 | --- 5 | 6 |
7 |
8 | {% include nav.html %} 9 | 10 |
11 |

The fastest way to build beautiful Electron apps using simple HTML and CSS

12 | 13 |
14 | 15 |
16 | 17 | Download Photon 18 | See all components 19 |
20 | Desktop photo by Bill Couch 21 |
22 |
23 | 24 |
25 |
26 |
27 |
28 |

Powered by Electron

29 |

Underneath it all is Electron. Originally built for GitHub's 30 | Atom text editor, Electron is the easiest way to build cross-platform desktop applications.

31 | 32 |

If you can write a bit of HTML, CSS, and JS, you can build full featured applications. 33 | Companies like Microsoft, Facebook, and Slack are using it – why aren't you?

34 | 35 | Learn more 36 |
37 |
38 |

Become a contributor

39 |

There's still a lot to do before Photon reaches version 1.0. If you're interested in working towards that goal, 40 | be sure to head over to the GitHub project and look over the open 41 | issues and pull requests. 42 |

43 | 44 |

Have something specific in mind? Open a pull request and tell everyone why it's awesome.

45 | 46 | View the GitHub project 47 |
48 |
49 |
50 |
51 | -------------------------------------------------------------------------------- /ShortcutMagic/welcome/WelcomeView.jsx: -------------------------------------------------------------------------------- 1 | 'use babel'; 2 | import React, { Component } from 'react'; 3 | import Electron, { ipcRenderer, remote } from 'electron'; 4 | import ReactDOM from 'react-dom'; 5 | 6 | export default class WelcomeView extends Component { 7 | componentWillMount() { 8 | this.setState({ 9 | accessGranted: false 10 | }); 11 | } 12 | 13 | render() { 14 | const unlockPage = ( 15 |
16 |
23 |
24 |

Allowing access to read shortcuts

25 | 26 | ShortcutMagic needs administrative access. 27 |
28 |
29 | This window will pop up when you click "Start": 30 | 31 | 32 |
33 | 34 |
41 |
{ 42 | ipcRenderer.send('welcome-window-ready'); 43 | }} style={{ 44 | flex: 1, 45 | paddingRight: '40px', 46 | paddingLeft: '40px', 47 | fontSize: 28, 48 | margin: '10px', 49 | }}>Start
50 |
{ 51 | ipcRenderer.send('quit'); 52 | }} style={{ 53 | flex: 1, 54 | paddingRight: '40px', 55 | paddingLeft: '40px', 56 | fontSize: 28, 57 | margin: '10px', 58 | }}>Cancel
59 |
60 |
61 | ); 62 | 63 | const onboarding = ( 64 |
69 |
72 |
73 |

Welcome to ShortcutMagic!

74 |

How often would you like to see shortcut suggestions like these?

75 |
76 |
77 | 78 |
89 | 92 |
93 | 94 |
102 |
{ 112 | ipcRenderer.send('configure-suggestions', 0); 113 | this.setState({ 114 | modePicked: true, 115 | }); 116 | }}> 117 |

Never

122 |
    125 |
  • Hide suggestions
  • 126 |
127 |
128 | 129 |
{ 139 | ipcRenderer.send('configure-suggestions', 1); 140 | this.setState({ 141 | modePicked: true, 142 | }); 143 | }}> 144 |

Sometimes

149 |
    152 |
  • Once in a while
  • 153 |
154 |
155 | 156 |
{ 166 | ipcRenderer.send('configure-suggestions', 2); 167 | this.setState({ 168 | modePicked: true, 169 | }); 170 | }}> 171 |

Often

176 |
    179 |
  • Each time app switches
  • 180 |
  • Also once in a while
  • 181 |
182 |
183 | 184 |
185 |
186 | ); 187 | 188 | const iconComponent = ( 189 | 197 | ); 198 | 199 | const helpComponent = ( 200 | { 206 | ipcRenderer.send('open-about'); 207 | }} className="icon icon-help-circled"> 208 | ); 209 | 210 | return ( 211 |
219 | {iconComponent} 220 | {helpComponent} 221 | 222 | {this.state && this.state.modePicked ? unlockPage : onboarding} 223 |
224 | ); 225 | } 226 | }; 227 | 228 | window.onload = function(){ 229 | ReactDOM.render(, document.getElementById("welcome-root")); 230 | }; 231 | -------------------------------------------------------------------------------- /ShortcutMagic/welcome/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | -------------------------------------------------------------------------------- /ShortcutMagic/welcome/welcome.js: -------------------------------------------------------------------------------- 1 | // TODO: 2 | // load anything from here? 3 | // attempt to do an assistive access operation that will cause it to open a confirmation window? 4 | // save show/hide welcome window checkbox settings 5 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman --------------------------------------------------------------------------------