├── 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 | 
6 |
7 | Every action it can find, both those with shortcuts and those without, are added to the main shortcut library window:
8 |
9 | 
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 |
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 |
{
79 | ipcRenderer.send('save-gif', this.state.gif, this.state.listItem, this.state.appName);
80 | }}>
81 | Save
82 |
83 |
84 |
{
85 | this.setState({
86 | gif: null
87 | });
88 |
89 | ipcRenderer.send('keep-recording-gif');
90 | }}>
91 | Keep looking
92 |
93 |
94 |
{
95 | this.setState({
96 | gif: null
97 | });
98 |
99 | var windows = remote.BrowserWindow.getAllWindows();
100 | for (var i = 0; i < windows.length; i++) {
101 | let holdWindow = windows[i];
102 | if (holdWindow && holdWindow.getTitle() == "gifRecorderWindow") {
103 | holdWindow.hide();
104 | break;
105 | }
106 | }
107 |
108 | ipcRenderer.send('cancel-gif-recording');
109 | }}>
110 | Cancel recording
111 |
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 |
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 |
39 |
Searching
40 | The search field lets you search through all the menus and actions that are
41 |
42 | possible to do in the program that is focused. Searching is "fuzzy". It will try to
43 |
44 | find what you are looking for, even if you only type a few characters.
45 |
46 | The global shortcut to make ShortcutMagic visible (cmd+alt+shift+S) will focus the search
47 |
48 | field, so you can access the search from anywhere just by pressing the global shortcut.
49 |
50 |
51 |
52 |
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 |
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 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/ShortcutMagic/settings/miniIndex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 |
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 |
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 |
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 | [](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 |
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 |
2 | Photon
3 |
4 |
9 |
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 |
45 |
46 |
47 |
48 |
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 |
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 |
16 |
17 |
18 |
19 |
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 |
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 |
--------------------------------------------------------------------------------
/ShortcutMagic/vendor/photonkit/docs/components/buttons-large.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Buttons example
7 |
8 |
9 |
10 |
11 |
16 |
17 |
18 | Default
19 | Primary
20 | Positive
21 | Negative
22 | Warning
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 | Default
19 | Primary
20 | Positive
21 | Negative
22 | Warning
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 | Default
19 | Primary
20 | Positive
21 | Negative
22 | Warning
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 |
16 |
17 |
18 |
21 |
22 |
Main content pane
23 |
24 |
25 |
26 |
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 |
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 |
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 |
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 | Name
20 | Kind
21 | File Size
22 |
23 |
24 |
25 |
26 | photon.css
27 | CSS
28 | 28K
29 |
30 |
31 | photon.css
32 | CSS
33 | 28K
34 |
35 |
36 | photon.css
37 | CSS
38 | 28K
39 |
40 |
41 | photon.css
42 | CSS
43 | 28K
44 |
45 |
46 | photon.css
47 | CSS
48 | 28K
49 |
50 |
51 | photon.css
52 | CSS
53 | 28K
54 |
55 |
56 | photon.css
57 | CSS
58 | 28K
59 |
60 |
61 | photon.css
62 | CSS
63 | 28K
64 |
65 |
66 | photon.css
67 | CSS
68 | 28K
69 |
70 |
71 | photon.css
72 | CSS
73 | 28K
74 |
75 |
76 | photon.css
77 | CSS
78 | 28K
79 |
80 |
81 | photon.css
82 | CSS
83 | 28K
84 |
85 |
86 | photon.css
87 | CSS
88 | 28K
89 |
90 |
91 |
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 |
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 |
56 |
57 |
58 |
59 |
131 |
132 |
133 |
134 |
135 | Name
136 | Kind
137 | Date Modified
138 | Author
139 |
140 |
141 |
142 |
143 | bars.scss
144 | Document
145 | Oct 13, 2015
146 | connors
147 |
148 |
149 | base.scss
150 | Document
151 | Oct 13, 2015
152 | connors
153 |
154 |
155 | button-groups.scss
156 | Document
157 | Oct 13, 2015
158 | connors
159 |
160 |
161 | buttons.scss
162 | Document
163 | Oct 13, 2015
164 | connors
165 |
166 |
167 | docs.scss
168 | Document
169 | Oct 13, 2015
170 | connors
171 |
172 |
173 | forms.scss
174 | Document
175 | Oct 13, 2015
176 | connors
177 |
178 |
179 | grid.scss
180 | Document
181 | Oct 13, 2015
182 | connors
183 |
184 |
185 | icons.scss
186 | Document
187 | Oct 13, 2015
188 | connors
189 |
190 |
191 | images.scss
192 | Document
193 | Oct 13, 2015
194 | connors
195 |
196 |
197 | lists.scss
198 | Document
199 | Oct 13, 2015
200 | connors
201 |
202 |
203 | mixins.scss
204 | Document
205 | Oct 13, 2015
206 | connors
207 |
208 |
209 | navs.scss
210 | Document
211 | Oct 13, 2015
212 | connors
213 |
214 |
215 | normalize.scss
216 | Document
217 | Oct 13, 2015
218 | connors
219 |
220 |
221 | photon.scss
222 | Document
223 | Oct 13, 2015
224 | connors
225 |
226 |
227 | tables.scss
228 | Document
229 | Oct 13, 2015
230 | connors
231 |
232 |
233 | tabs.scss
234 | Document
235 | Oct 13, 2015
236 | connors
237 |
238 |
239 | utilities.scss
240 | Document
241 | Oct 13, 2015
242 | connors
243 |
244 |
245 | variables.scss
246 | Document
247 | Oct 13, 2015
248 | connors
249 |
250 |
251 |
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 |
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 |
98 | {% endhighlight %}
99 |
100 |
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 |
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 |
153 | {% endhighlight %}
154 |
155 |
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 |
179 | {% endhighlight %}
180 |
181 |
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 |
212 | {% endhighlight %}
213 |
214 |
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 |
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 |
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
--------------------------------------------------------------------------------