├── .babelrc
├── .electron-vue
├── build.js
├── dev-client.js
├── dev-runner.js
├── webpack.main.config.js
├── webpack.renderer.config.js
└── webpack.web.config.js
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── appveyor.yml
├── build
└── icons
│ ├── 256x256.png
│ ├── icon.icns
│ └── icon.ico
├── dist
├── electron
│ └── .gitkeep
└── web
│ └── .gitkeep
├── package-lock.json
├── package.json
├── screenshots
├── loaded.png
├── profiles.png
├── saveas.png
├── search.png
└── updateNotice.png
├── src
├── index.ejs
├── main
│ ├── index.dev.js
│ └── index.js
└── renderer
│ ├── App.vue
│ ├── assets
│ ├── .gitkeep
│ ├── config.js
│ ├── css
│ │ ├── bootstrap.css
│ │ └── tooltip.css
│ ├── fonts
│ │ └── source-sans-pro-v13-latin-regular.woff2
│ ├── icon.png
│ └── photon
│ │ ├── css
│ │ └── photon.min.css
│ │ └── fonts
│ │ ├── photon-entypo.eot
│ │ ├── photon-entypo.svg
│ │ ├── photon-entypo.ttf
│ │ └── photon-entypo.woff
│ ├── components
│ ├── AppInfo.vue
│ ├── LandingPage.vue
│ └── LandingPage
│ │ ├── FileIngest.vue
│ │ └── Modal.vue
│ ├── main.js
│ ├── router
│ └── index.js
│ ├── services
│ ├── github.js
│ └── linuxparse.js
│ └── store
│ ├── index.js
│ └── modules
│ ├── Counter.js
│ └── index.js
└── static
└── .gitkeep
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "comments": false,
3 | "env": {
4 | "main": {
5 | "presets": [
6 | ["env", {
7 | "targets": { "node": 7 }
8 | }],
9 | "stage-0"
10 | ]
11 | },
12 | "renderer": {
13 | "presets": [
14 | ["env", {
15 | "modules": false
16 | }],
17 | "stage-0"
18 | ]
19 | },
20 | "web": {
21 | "presets": [
22 | ["env", {
23 | "modules": false
24 | }],
25 | "stage-0"
26 | ]
27 | }
28 | },
29 | "plugins": ["transform-runtime"]
30 | }
31 |
--------------------------------------------------------------------------------
/.electron-vue/build.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.NODE_ENV = 'production'
4 |
5 | const { say } = require('cfonts')
6 | const chalk = require('chalk')
7 | const del = require('del')
8 | const { spawn } = require('child_process')
9 | const webpack = require('webpack')
10 | const Multispinner = require('multispinner')
11 |
12 |
13 | const mainConfig = require('./webpack.main.config')
14 | const rendererConfig = require('./webpack.renderer.config')
15 | const webConfig = require('./webpack.web.config')
16 |
17 | const doneLog = chalk.bgGreen.white(' DONE ') + ' '
18 | const errorLog = chalk.bgRed.white(' ERROR ') + ' '
19 | const okayLog = chalk.bgBlue.white(' OKAY ') + ' '
20 | const isCI = process.env.CI || false
21 |
22 | if (process.env.BUILD_TARGET === 'clean') clean()
23 | else if (process.env.BUILD_TARGET === 'web') web()
24 | else build()
25 |
26 | function clean () {
27 | del.sync(['build/*', '!build/icons', '!build/icons/icon.*'])
28 | console.log(`\n${doneLog}\n`)
29 | process.exit()
30 | }
31 |
32 | function build () {
33 | greeting()
34 |
35 | del.sync(['dist/electron/*', '!.gitkeep'])
36 |
37 | const tasks = ['main', 'renderer']
38 | const m = new Multispinner(tasks, {
39 | preText: 'building',
40 | postText: 'process'
41 | })
42 |
43 | let results = ''
44 |
45 | m.on('success', () => {
46 | process.stdout.write('\x1B[2J\x1B[0f')
47 | console.log(`\n\n${results}`)
48 | console.log(`${okayLog}take it away ${chalk.yellow('`electron-builder`')}\n`)
49 | process.exit()
50 | })
51 |
52 | pack(mainConfig).then(result => {
53 | results += result + '\n\n'
54 | m.success('main')
55 | }).catch(err => {
56 | m.error('main')
57 | console.log(`\n ${errorLog}failed to build main process`)
58 | console.error(`\n${err}\n`)
59 | process.exit(1)
60 | })
61 |
62 | pack(rendererConfig).then(result => {
63 | results += result + '\n\n'
64 | m.success('renderer')
65 | }).catch(err => {
66 | m.error('renderer')
67 | console.log(`\n ${errorLog}failed to build renderer process`)
68 | console.error(`\n${err}\n`)
69 | process.exit(1)
70 | })
71 | }
72 |
73 | function pack (config) {
74 | return new Promise((resolve, reject) => {
75 | config.mode = 'production'
76 | webpack(config, (err, stats) => {
77 | if (err) reject(err.stack || err)
78 | else if (stats.hasErrors()) {
79 | let err = ''
80 |
81 | stats.toString({
82 | chunks: false,
83 | colors: true
84 | })
85 | .split(/\r?\n/)
86 | .forEach(line => {
87 | err += ` ${line}\n`
88 | })
89 |
90 | reject(err)
91 | } else {
92 | resolve(stats.toString({
93 | chunks: false,
94 | colors: true
95 | }))
96 | }
97 | })
98 | })
99 | }
100 |
101 | function web () {
102 | del.sync(['dist/web/*', '!.gitkeep'])
103 | webConfig.mode = 'production'
104 | webpack(webConfig, (err, stats) => {
105 | if (err || stats.hasErrors()) console.log(err)
106 |
107 | console.log(stats.toString({
108 | chunks: false,
109 | colors: true
110 | }))
111 |
112 | process.exit()
113 | })
114 | }
115 |
116 | function greeting () {
117 | const cols = process.stdout.columns
118 | let text = ''
119 |
120 | if (cols > 85) text = 'lets-build'
121 | else if (cols > 60) text = 'lets-|build'
122 | else text = false
123 |
124 | if (text && !isCI) {
125 | say(text, {
126 | colors: ['yellow'],
127 | font: 'simple3d',
128 | space: false
129 | })
130 | } else console.log(chalk.yellow.bold('\n lets-build'))
131 | console.log()
132 | }
--------------------------------------------------------------------------------
/.electron-vue/dev-client.js:
--------------------------------------------------------------------------------
1 | const hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
2 |
3 | hotClient.subscribe(event => {
4 | /**
5 | * Reload browser when HTMLWebpackPlugin emits a new index.html
6 | *
7 | * Currently disabled until jantimon/html-webpack-plugin#680 is resolved.
8 | * https://github.com/SimulatedGREG/electron-vue/issues/437
9 | * https://github.com/jantimon/html-webpack-plugin/issues/680
10 | */
11 | // if (event.action === 'reload') {
12 | // window.location.reload()
13 | // }
14 |
15 | /**
16 | * Notify `mainWindow` when `main` process is compiling,
17 | * giving notice for an expected reload of the `electron` process
18 | */
19 | if (event.action === 'compiling') {
20 | document.body.innerHTML += `
21 |
34 |
35 |
36 | Compiling Main Process...
37 |
38 | `
39 | }
40 | })
41 |
--------------------------------------------------------------------------------
/.electron-vue/dev-runner.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | const chalk = require('chalk')
4 | const electron = require('electron')
5 | const path = require('path')
6 | const { say } = require('cfonts')
7 | const { spawn } = require('child_process')
8 | const webpack = require('webpack')
9 | const WebpackDevServer = require('webpack-dev-server')
10 | const webpackHotMiddleware = require('webpack-hot-middleware')
11 |
12 | const mainConfig = require('./webpack.main.config')
13 | const rendererConfig = require('./webpack.renderer.config')
14 |
15 | let electronProcess = null
16 | let manualRestart = false
17 | let hotMiddleware
18 |
19 | function logStats (proc, data) {
20 | let log = ''
21 |
22 | log += chalk.yellow.bold(`┏ ${proc} Process ${new Array((19 - proc.length) + 1).join('-')}`)
23 | log += '\n\n'
24 |
25 | if (typeof data === 'object') {
26 | data.toString({
27 | colors: true,
28 | chunks: false
29 | }).split(/\r?\n/).forEach(line => {
30 | log += ' ' + line + '\n'
31 | })
32 | } else {
33 | log += ` ${data}\n`
34 | }
35 |
36 | log += '\n' + chalk.yellow.bold(`┗ ${new Array(28 + 1).join('-')}`) + '\n'
37 |
38 | console.log(log)
39 | }
40 |
41 | function startRenderer () {
42 | return new Promise((resolve, reject) => {
43 | rendererConfig.entry.renderer = [path.join(__dirname, 'dev-client')].concat(rendererConfig.entry.renderer)
44 | rendererConfig.mode = 'development'
45 | const compiler = webpack(rendererConfig)
46 | hotMiddleware = webpackHotMiddleware(compiler, {
47 | log: false,
48 | heartbeat: 2500
49 | })
50 |
51 | compiler.hooks.compilation.tap('compilation', compilation => {
52 | compilation.hooks.htmlWebpackPluginAfterEmit.tapAsync('html-webpack-plugin-after-emit', (data, cb) => {
53 | hotMiddleware.publish({ action: 'reload' })
54 | cb()
55 | })
56 | })
57 |
58 | compiler.hooks.done.tap('done', stats => {
59 | logStats('Renderer', stats)
60 | })
61 |
62 | const server = new WebpackDevServer(
63 | compiler,
64 | {
65 | contentBase: path.join(__dirname, '../'),
66 | quiet: true,
67 | before (app, ctx) {
68 | app.use(hotMiddleware)
69 | ctx.middleware.waitUntilValid(() => {
70 | resolve()
71 | })
72 | }
73 | }
74 | )
75 |
76 | server.listen(9080)
77 | })
78 | }
79 |
80 | function startMain () {
81 | return new Promise((resolve, reject) => {
82 | mainConfig.entry.main = [path.join(__dirname, '../src/main/index.dev.js')].concat(mainConfig.entry.main)
83 | mainConfig.mode = 'development'
84 | const compiler = webpack(mainConfig)
85 |
86 | compiler.hooks.watchRun.tapAsync('watch-run', (compilation, done) => {
87 | logStats('Main', chalk.white.bold('compiling...'))
88 | hotMiddleware.publish({ action: 'compiling' })
89 | done()
90 | })
91 |
92 | compiler.watch({}, (err, stats) => {
93 | if (err) {
94 | console.log(err)
95 | return
96 | }
97 |
98 | logStats('Main', stats)
99 |
100 | if (electronProcess && electronProcess.kill) {
101 | manualRestart = true
102 | process.kill(electronProcess.pid)
103 | electronProcess = null
104 | startElectron()
105 |
106 | setTimeout(() => {
107 | manualRestart = false
108 | }, 5000)
109 | }
110 |
111 | resolve()
112 | })
113 | })
114 | }
115 |
116 | function startElectron () {
117 | var args = [
118 | '--inspect=5858',
119 | path.join(__dirname, '../dist/electron/main.js')
120 | ]
121 |
122 | // detect yarn or npm and process commandline args accordingly
123 | if (process.env.npm_execpath.endsWith('yarn.js')) {
124 | args = args.concat(process.argv.slice(3))
125 | } else if (process.env.npm_execpath.endsWith('npm-cli.js')) {
126 | args = args.concat(process.argv.slice(2))
127 | }
128 |
129 | electronProcess = spawn(electron, args)
130 |
131 | electronProcess.stdout.on('data', data => {
132 | electronLog(data, 'blue')
133 | })
134 | electronProcess.stderr.on('data', data => {
135 | electronLog(data, 'red')
136 | })
137 |
138 | electronProcess.on('close', () => {
139 | if (!manualRestart) process.exit()
140 | })
141 | }
142 |
143 | function electronLog (data, color) {
144 | let log = ''
145 | data = data.toString().split(/\r?\n/)
146 | data.forEach(line => {
147 | log += ` ${line}\n`
148 | })
149 | if (/[0-9A-z]+/.test(log)) {
150 | console.log(
151 | chalk[color].bold('┏ Electron -------------------') +
152 | '\n\n' +
153 | log +
154 | chalk[color].bold('┗ ----------------------------') +
155 | '\n'
156 | )
157 | }
158 | }
159 |
160 | function greeting () {
161 | const cols = process.stdout.columns
162 | let text = ''
163 |
164 | if (cols > 104) text = 'electron-vue'
165 | else if (cols > 76) text = 'electron-|vue'
166 | else text = false
167 |
168 | if (text) {
169 | say(text, {
170 | colors: ['yellow'],
171 | font: 'simple3d',
172 | space: false
173 | })
174 | } else console.log(chalk.yellow.bold('\n electron-vue'))
175 | console.log(chalk.blue(' getting ready...') + '\n')
176 | }
177 |
178 | function init () {
179 | greeting()
180 |
181 | Promise.all([startRenderer(), startMain()])
182 | .then(() => {
183 | startElectron()
184 | })
185 | .catch(err => {
186 | console.error(err)
187 | })
188 | }
189 |
190 | init()
191 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.main.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'main'
4 |
5 | const path = require('path')
6 | const { dependencies } = require('../package.json')
7 | const webpack = require('webpack')
8 |
9 | const MinifyPlugin = require("babel-minify-webpack-plugin")
10 |
11 | let mainConfig = {
12 | entry: {
13 | main: path.join(__dirname, '../src/main/index.js')
14 | },
15 | externals: [
16 | ...Object.keys(dependencies || {}),
17 | {'electron-debug': 'electron-debug'}
18 | ],
19 | module: {
20 | rules: [
21 | {
22 | test: /\.(js)$/,
23 | enforce: 'pre',
24 | exclude: /node_modules/,
25 | use: {
26 | loader: 'eslint-loader',
27 | options: {
28 | formatter: require('eslint-friendly-formatter')
29 | }
30 | }
31 | },
32 | {
33 | test: /\.js$/,
34 | use: 'babel-loader',
35 | exclude: /node_modules/
36 | },
37 | {
38 | test: /\.node$/,
39 | use: 'node-loader'
40 | }
41 | ]
42 | },
43 | node: {
44 | __dirname: process.env.NODE_ENV !== 'production',
45 | __filename: process.env.NODE_ENV !== 'production'
46 | },
47 | output: {
48 | filename: '[name].js',
49 | libraryTarget: 'commonjs2',
50 | path: path.join(__dirname, '../dist/electron')
51 | },
52 | plugins: [
53 | new webpack.NoEmitOnErrorsPlugin()
54 | ],
55 | resolve: {
56 | extensions: ['.js', '.json', '.node']
57 | },
58 | target: 'electron-main'
59 | }
60 |
61 | /**
62 | * Adjust mainConfig for development settings
63 | */
64 | if (process.env.NODE_ENV !== 'production') {
65 | mainConfig.plugins.push(
66 | new webpack.DefinePlugin({
67 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
68 | })
69 | )
70 | }
71 |
72 | /**
73 | * Adjust mainConfig for production settings
74 | */
75 | if (process.env.NODE_ENV === 'production') {
76 | mainConfig.plugins.push(
77 | new MinifyPlugin(),
78 | new webpack.DefinePlugin({
79 | 'process.env.NODE_ENV': '"production"'
80 | })
81 | )
82 | }
83 |
84 | module.exports = mainConfig
85 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.renderer.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'renderer'
4 |
5 | const path = require('path')
6 | const { dependencies } = require('../package.json')
7 | const webpack = require('webpack')
8 |
9 | const MinifyPlugin = require("babel-minify-webpack-plugin")
10 | const CopyWebpackPlugin = require('copy-webpack-plugin')
11 | const MiniCssExtractPlugin = require('mini-css-extract-plugin')
12 | const HtmlWebpackPlugin = require('html-webpack-plugin')
13 | const { VueLoaderPlugin } = require('vue-loader')
14 |
15 | /**
16 | * List of node_modules to include in webpack bundle
17 | *
18 | * Required for specific packages like Vue UI libraries
19 | * that provide pure *.vue files that need compiling
20 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/webpack-configurations.html#white-listing-externals
21 | */
22 | let whiteListedModules = ['vue']
23 |
24 | let rendererConfig = {
25 | devtool: '#cheap-module-eval-source-map',
26 | entry: {
27 | renderer: path.join(__dirname, '../src/renderer/main.js')
28 | },
29 | externals: [
30 | ...Object.keys(dependencies || {}).filter(d => !whiteListedModules.includes(d))
31 | ],
32 | module: {
33 | rules: [
34 | {
35 | test: /\.(js|vue)$/,
36 | enforce: 'pre',
37 | exclude: /node_modules/,
38 | use: {
39 | loader: 'eslint-loader',
40 | options: {
41 | formatter: require('eslint-friendly-formatter')
42 | }
43 | }
44 | },
45 | {
46 | test: /\.scss$/,
47 | use: ['vue-style-loader', 'css-loader', 'sass-loader']
48 | },
49 | {
50 | test: /\.sass$/,
51 | use: ['vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax']
52 | },
53 | {
54 | test: /\.less$/,
55 | use: ['vue-style-loader', 'css-loader', 'less-loader']
56 | },
57 | {
58 | test: /\.css$/,
59 | use: ['vue-style-loader', 'css-loader']
60 | },
61 | {
62 | test: /\.html$/,
63 | use: 'vue-html-loader'
64 | },
65 | {
66 | test: /\.js$/,
67 | use: 'babel-loader',
68 | exclude: /node_modules/
69 | },
70 | {
71 | test: /\.node$/,
72 | use: 'node-loader'
73 | },
74 | {
75 | test: /\.vue$/,
76 | use: {
77 | loader: 'vue-loader',
78 | options: {
79 | extractCSS: process.env.NODE_ENV === 'production',
80 | loaders: {
81 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
82 | scss: 'vue-style-loader!css-loader!sass-loader',
83 | less: 'vue-style-loader!css-loader!less-loader'
84 | }
85 | }
86 | }
87 | },
88 | {
89 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
90 | use: [{
91 | loader: 'url-loader',
92 | query: {
93 | limit: 10000,
94 | esModule: false,
95 | name: 'imgs/[name]--[folder].[ext]'
96 | }
97 | }]
98 | },
99 | {
100 | test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
101 | loader: 'url-loader',
102 | options: {
103 | limit: 10000,
104 | name: 'media/[name]--[folder].[ext]'
105 | }
106 | },
107 | {
108 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
109 | use: {
110 | loader: 'url-loader',
111 | query: {
112 | limit: 10000,
113 | name: 'fonts/[name]--[folder].[ext]'
114 | }
115 | }
116 | }
117 | ]
118 | },
119 | node: {
120 | __dirname: process.env.NODE_ENV !== 'production',
121 | __filename: process.env.NODE_ENV !== 'production'
122 | },
123 | plugins: [
124 | new VueLoaderPlugin(),
125 | new MiniCssExtractPlugin({filename: 'styles.css'}),
126 | new HtmlWebpackPlugin({
127 | filename: 'index.html',
128 | template: path.resolve(__dirname, '../src/index.ejs'),
129 | minify: {
130 | collapseWhitespace: true,
131 | removeAttributeQuotes: true,
132 | removeComments: true
133 | },
134 | isBrowser: false,
135 | isDevelopment: process.env.NODE_ENV !== 'production',
136 | nodeModules: process.env.NODE_ENV !== 'production'
137 | ? path.resolve(__dirname, '../node_modules')
138 | : false
139 | }),
140 | new webpack.HotModuleReplacementPlugin(),
141 | new webpack.NoEmitOnErrorsPlugin()
142 | ],
143 | output: {
144 | filename: '[name].js',
145 | libraryTarget: 'commonjs2',
146 | path: path.join(__dirname, '../dist/electron')
147 | },
148 | resolve: {
149 | alias: {
150 | '@': path.join(__dirname, '../src/renderer'),
151 | 'vue$': 'vue/dist/vue.esm.js'
152 | },
153 | extensions: ['.js', '.vue', '.json', '.css', '.node']
154 | },
155 | target: 'electron-renderer'
156 | }
157 |
158 | /**
159 | * Adjust rendererConfig for development settings
160 | */
161 | if (process.env.NODE_ENV !== 'production') {
162 | rendererConfig.plugins.push(
163 | new webpack.DefinePlugin({
164 | '__static': `"${path.join(__dirname, '../static').replace(/\\/g, '\\\\')}"`
165 | })
166 | )
167 | }
168 |
169 | /**
170 | * Adjust rendererConfig for production settings
171 | */
172 | if (process.env.NODE_ENV === 'production') {
173 | rendererConfig.devtool = ''
174 |
175 | rendererConfig.plugins.push(
176 | new MinifyPlugin(),
177 | new CopyWebpackPlugin([
178 | {
179 | from: path.join(__dirname, '../static'),
180 | to: path.join(__dirname, '../dist/electron/static'),
181 | ignore: ['.*']
182 | }
183 | ]),
184 | new webpack.DefinePlugin({
185 | 'process.env.NODE_ENV': '"production"'
186 | }),
187 | new webpack.LoaderOptionsPlugin({
188 | minimize: true
189 | })
190 | )
191 | }
192 |
193 | module.exports = rendererConfig
194 |
--------------------------------------------------------------------------------
/.electron-vue/webpack.web.config.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 |
3 | process.env.BABEL_ENV = 'web'
4 |
5 | const path = require('path')
6 | const webpack = require('webpack')
7 |
8 | const MinifyPlugin = require("babel-minify-webpack-plugin")
9 | const CopyWebpackPlugin = require('copy-webpack-plugin')
10 | const MiniCssExtractPlugin = require('mini-css-extract-plugin')
11 | const HtmlWebpackPlugin = require('html-webpack-plugin')
12 | const { VueLoaderPlugin } = require('vue-loader')
13 |
14 | let webConfig = {
15 | devtool: '#cheap-module-eval-source-map',
16 | entry: {
17 | web: path.join(__dirname, '../src/renderer/main.js')
18 | },
19 | module: {
20 | rules: [
21 | {
22 | test: /\.(js|vue)$/,
23 | enforce: 'pre',
24 | exclude: /node_modules/,
25 | use: {
26 | loader: 'eslint-loader',
27 | options: {
28 | formatter: require('eslint-friendly-formatter')
29 | }
30 | }
31 | },
32 | {
33 | test: /\.scss$/,
34 | use: ['vue-style-loader', 'css-loader', 'sass-loader']
35 | },
36 | {
37 | test: /\.sass$/,
38 | use: ['vue-style-loader', 'css-loader', 'sass-loader?indentedSyntax']
39 | },
40 | {
41 | test: /\.less$/,
42 | use: ['vue-style-loader', 'css-loader', 'less-loader']
43 | },
44 | {
45 | test: /\.css$/,
46 | use: ['vue-style-loader', 'css-loader']
47 | },
48 | {
49 | test: /\.html$/,
50 | use: 'vue-html-loader'
51 | },
52 | {
53 | test: /\.js$/,
54 | use: 'babel-loader',
55 | include: [ path.resolve(__dirname, '../src/renderer') ],
56 | exclude: /node_modules/
57 | },
58 | {
59 | test: /\.vue$/,
60 | use: {
61 | loader: 'vue-loader',
62 | options: {
63 | extractCSS: true,
64 | loaders: {
65 | sass: 'vue-style-loader!css-loader!sass-loader?indentedSyntax=1',
66 | scss: 'vue-style-loader!css-loader!sass-loader',
67 | less: 'vue-style-loader!css-loader!less-loader'
68 | }
69 | }
70 | }
71 | },
72 | {
73 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
74 | use: {
75 | loader: 'url-loader',
76 | query: {
77 | limit: 10000,
78 | name: 'imgs/[name].[ext]'
79 | }
80 | }
81 | },
82 | {
83 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
84 | use: {
85 | loader: 'url-loader',
86 | query: {
87 | limit: 10000,
88 | name: 'fonts/[name].[ext]'
89 | }
90 | }
91 | }
92 | ]
93 | },
94 | plugins: [
95 | new VueLoaderPlugin(),
96 | new MiniCssExtractPlugin({filename: 'styles.css'}),
97 | new HtmlWebpackPlugin({
98 | filename: 'index.html',
99 | template: path.resolve(__dirname, '../src/index.ejs'),
100 | minify: {
101 | collapseWhitespace: true,
102 | removeAttributeQuotes: true,
103 | removeComments: true
104 | },
105 | nodeModules: false
106 | }),
107 | new webpack.DefinePlugin({
108 | 'process.env.IS_WEB': 'true'
109 | }),
110 | new webpack.HotModuleReplacementPlugin(),
111 | new webpack.NoEmitOnErrorsPlugin()
112 | ],
113 | output: {
114 | filename: '[name].js',
115 | path: path.join(__dirname, '../dist/web')
116 | },
117 | resolve: {
118 | alias: {
119 | '@': path.join(__dirname, '../src/renderer'),
120 | 'vue$': 'vue/dist/vue.esm.js'
121 | },
122 | extensions: ['.js', '.vue', '.json', '.css']
123 | },
124 | target: 'electron'
125 | }
126 |
127 | /**
128 | * Adjust webConfig for production settings
129 | */
130 | if (process.env.NODE_ENV === 'production') {
131 | webConfig.devtool = ''
132 |
133 | webConfig.plugins.push(
134 | new MinifyPlugin(),
135 | new CopyWebpackPlugin([
136 | {
137 | from: path.join(__dirname, '../static'),
138 | to: path.join(__dirname, '../dist/web/static'),
139 | ignore: ['.*']
140 | }
141 | ]),
142 | new webpack.DefinePlugin({
143 | 'process.env.NODE_ENV': '"production"'
144 | }),
145 | new webpack.LoaderOptionsPlugin({
146 | minimize: true
147 | })
148 | )
149 | }
150 |
151 | module.exports = webConfig
152 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/.eslintignore
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | browser: true,
5 | node: true
6 | },
7 | parserOptions: {
8 | parser: "babel-eslint",
9 | // specifying a module sourcetype prevent eslint from marking import statements as errors
10 | sourceType: "module",
11 | "ecmaFeatures": {
12 | "legacyDecorators": true
13 | }
14 | },
15 | extends: [
16 | // use the recommended rule set for both plain javascript and vue
17 | "eslint:recommended",
18 | "plugin:vue/recommended"
19 | ],
20 | globals: {
21 | "module": "writable",
22 | "process": "writable"
23 | },
24 | rules: {
25 | "no-unused-vars": ["warn", {"argsIgnorePattern": "^_" }],
26 | "require-atomic-updates": "off",
27 | "indent": ["warn",2],
28 | "quotes": ["warn","double"],
29 | "semi": ["warn","always"],
30 | "spaced-comment": ["warn", "always", {"exceptions": ["-","+"]}],
31 | "template-curly-spacing": ["off"]
32 | }
33 | };
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | dist/electron/*
3 | dist/web/*
4 | build/*
5 | !build/icons
6 | node_modules/
7 | npm-debug.log
8 | npm-debug.log.*
9 | thumbs.db
10 | !.gitkeep
11 | .vscode/*
12 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | osx_image: xcode8.3
2 | sudo: required
3 | dist: trusty
4 | language: c
5 | matrix:
6 | include:
7 | - os: osx
8 | - os: linux
9 | env: CC=clang CXX=clang++ npm_config_clang=1
10 | compiler: clang
11 | cache:
12 | directories:
13 | - node_modules
14 | - "$HOME/.electron"
15 | - "$HOME/.cache"
16 | addons:
17 | apt:
18 | packages:
19 | - libgnome-keyring-dev
20 | - icnsutils
21 | before_install:
22 | - mkdir -p /tmp/git-lfs && curl -L https://github.com/github/git-lfs/releases/download/v1.2.1/git-lfs-$([
23 | "$TRAVIS_OS_NAME" == "linux" ] && echo "linux" || echo "darwin")-amd64-1.2.1.tar.gz
24 | | tar -xz -C /tmp/git-lfs --strip-components 1 && /tmp/git-lfs/git-lfs pull
25 | - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install --no-install-recommends -y icnsutils graphicsmagick xz-utils; fi
26 | install:
27 | - nvm install 10
28 | - curl -o- -L https://yarnpkg.com/install.sh | bash
29 | - source ~/.bashrc
30 | - npm install -g xvfb-maybe
31 | - yarn
32 | script:
33 | - yarn run build
34 | branches:
35 | only:
36 | - master
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Stephen Thompson
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, 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,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Mult App Launcher
2 |
3 | > Cross Platform Multi App Launcher
4 |
5 | [](https://snapcraft.io/multi-app-launcher)
6 |
7 | This is a small [electron](https://www.electronjs.org/) application that allows multiple applications to be launched simultaneously.
8 |
9 | ## Install
10 | Go to the [release page](https://github.com/Arges86/multi-app-launcher/releases) and download the latest version.
11 | The portable, or installable .exe file both are available.
12 | The installable instance will be a little faster running.
13 |
14 | For linux with snap:
15 | [](https://snapcraft.io/multi-app-launcher)
16 |
17 | ## Usage
18 | Simple open the app, then choose as many programs as you would like.
19 | Increase the slider to get access to more program boxes.
20 |
21 | There are three ways to add a program to the list:
22 | * Find the program or shortcut manually by clicking the gear icon.
23 | * Drag and drop the program, or link thereto into `Drag and Drop` field.
24 | * Or search for it with the search dropdown, and find the program on the list.
25 |
26 | 
27 |
28 | Once All your programs are selected,
29 | Simply click the 'Start All Programs' button to launch them all.
30 | 
31 |
32 | Once you have all the programs you like, simple save your profile.
33 | 
34 |
35 | You can have as many profiles as you like.
36 | 
37 |
38 | Lastly, can you add optional arguments to the startup command.
39 | For instance, to start Chrome in 'Incognito', click the gear icon and type `-incognito`
40 | into the options modal.
41 | Many programs have startup options that can be set. Two examples are:
42 | Firefox's list can be found [here](https://developer.mozilla.org/en-US/docs/Mozilla/Command_Line_Options).
43 | Chrome's list can be found [here](https://peter.sh/experiments/chromium-command-line-switches/).
44 |
45 | ### Updates
46 | The program checks for any updates at launch.
47 | If there are any updates available, a notification will appear on the icon in the top left.
48 | Click the icon, to open the about window with a download link.
49 | 
50 |
51 | ### Theme
52 | The dark and light theme are dependant on the Operating System theme.
53 |
54 | ### How it works
55 | Each application is opened via `Electron.Shell.openItem`,
56 | Which should provide a platform agnostic way of launching each application.
57 | Profiles are saved in `%APPDATA%/`.
58 |
59 | Search looks in the default program list for the OS.
60 | For Windows: `C:\ProgramData\Microsoft\Windows\Start Menu\Programs`
61 | For others: `/usr/share/applications`
62 |
63 | Updates query Github for the newest release.
64 | if the semantic version at Github is greater than installed, a notification appears.
65 |
66 | ### Build Setup
67 |
68 | ``` bash
69 | # install dependencies
70 | npm install
71 |
72 | # serve with hot reload at localhost:9080
73 | npm run dev
74 |
75 | # build electron application for production
76 | npm run build
77 |
78 | # lint all JS/Vue component files in `src/`
79 | npm run lint
80 |
81 | ```
82 | The build step (for Windows) will create the installable and portable application for deployment.
83 |
84 | ---
85 |
86 | This project was generated with [electron-vue](https://github.com/SimulatedGREG/electron-vue)@[45a3e22](https://github.com/SimulatedGREG/electron-vue/tree/45a3e224e7bb8fc71909021ccfdcfec0f461f634) using [vue-cli](https://github.com/vuejs/vue-cli). Documentation about the original structure can be found [here](https://simulatedgreg.gitbooks.io/electron-vue/content/index.html).
87 |
--------------------------------------------------------------------------------
/appveyor.yml:
--------------------------------------------------------------------------------
1 | version: 0.1.{build}
2 |
3 | branches:
4 | only:
5 | - master
6 |
7 | image: Visual Studio 2017
8 | platform:
9 | - x64
10 |
11 | cache:
12 | - node_modules
13 | - '%APPDATA%\npm-cache'
14 | - '%USERPROFILE%\.electron'
15 | - '%USERPROFILE%\AppData\Local\Yarn\cache'
16 |
17 | init:
18 | - git config --global core.autocrlf input
19 |
20 | install:
21 | - ps: Install-Product node 8 x64
22 | - git reset --hard HEAD
23 | - yarn
24 | - node --version
25 |
26 | build_script:
27 | - yarn build
28 |
29 | test: off
30 |
--------------------------------------------------------------------------------
/build/icons/256x256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/build/icons/256x256.png
--------------------------------------------------------------------------------
/build/icons/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/build/icons/icon.icns
--------------------------------------------------------------------------------
/build/icons/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/build/icons/icon.ico
--------------------------------------------------------------------------------
/dist/electron/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/dist/electron/.gitkeep
--------------------------------------------------------------------------------
/dist/web/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/dist/web/.gitkeep
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "multi-app-launcher",
3 | "version": "0.3.0",
4 | "author": "Stephen Thompson",
5 | "description": "Multi App Launcher",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/Arges86/multi-app-launcher"
9 | },
10 | "license": "MIT",
11 | "main": "./dist/electron/main.js",
12 | "scripts": {
13 | "build": "node .electron-vue/build.js && electron-builder",
14 | "build:dir": "node .electron-vue/build.js && electron-builder --dir",
15 | "build:clean": "cross-env BUILD_TARGET=clean node .electron-vue/build.js",
16 | "build:web": "cross-env BUILD_TARGET=web node .electron-vue/build.js",
17 | "dev": "node .electron-vue/dev-runner.js",
18 | "lint": "eslint --ext .js,.vue src",
19 | "lint:fix": "eslint --ext .js,.vue --fix src",
20 | "pack": "npm run pack:main && npm run pack:renderer",
21 | "pack:main": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.main.config.js",
22 | "pack:renderer": "cross-env NODE_ENV=production webpack --progress --colors --config .electron-vue/webpack.renderer.config.js",
23 | "postinstall": "npm run lint:fix"
24 | },
25 | "keywords": [
26 | "Electron",
27 | "Application Launcher"
28 | ],
29 | "build": {
30 | "productName": "Multi App Launcher",
31 | "appId": "multi-app-launcher",
32 | "directories": {
33 | "output": "build"
34 | },
35 | "files": [
36 | "dist/electron/**/*"
37 | ],
38 | "dmg": {
39 | "contents": [
40 | {
41 | "x": 410,
42 | "y": 150,
43 | "type": "link",
44 | "path": "/Applications"
45 | },
46 | {
47 | "x": 130,
48 | "y": 150,
49 | "type": "file"
50 | }
51 | ]
52 | },
53 | "mac": {
54 | "icon": "build/icons/icon.icns"
55 | },
56 | "win": {
57 | "target": [
58 | "nsis",
59 | "portable"
60 | ],
61 | "icon": "build/icons/icon.ico"
62 | },
63 | "linux": {
64 | "target": [
65 | "AppImage",
66 | "snap"
67 | ],
68 | "icon": "build/icons"
69 | }
70 | },
71 | "dependencies": {
72 | "@electron/remote": "^2.0.1",
73 | "axios": "^0.25.0",
74 | "electron-context-menu": "^3.1.1",
75 | "electron-settings": "^4.0.2",
76 | "ini": "^2.0.0",
77 | "klaw-sync": "^6.0.0",
78 | "vue": "^2.6.14",
79 | "vue-electron": "^1.0.6",
80 | "vue-router": "^3.5.2",
81 | "vuex": "^3.6.2",
82 | "vuex-electron": "^1.0.0"
83 | },
84 | "devDependencies": {
85 | "@types/semver": "^7.3.8",
86 | "@vue/eslint-config-standard": "^6.1.0",
87 | "ajv": "^6.12.6",
88 | "babel-core": "^6.26.3",
89 | "babel-eslint": "^8.2.3",
90 | "babel-loader": "^7.1.4",
91 | "babel-minify-webpack-plugin": "^0.3.1",
92 | "babel-plugin-transform-runtime": "^6.23.0",
93 | "babel-preset-env": "^1.7.0",
94 | "babel-preset-stage-0": "^6.24.1",
95 | "babel-register": "^6.26.0",
96 | "cfonts": "^2.10.0",
97 | "chalk": "^4.1.2",
98 | "copy-webpack-plugin": "^4.5.1",
99 | "cross-env": "^7.0.3",
100 | "css-loader": "^3.6.0",
101 | "del": "^6.0.0",
102 | "devtron": "^1.4.0",
103 | "electron": "^17.0.0",
104 | "electron-builder": "^22.14.5",
105 | "electron-debug": "^3.2.0",
106 | "electron-devtools-installer": "^3.2.0",
107 | "eslint": "^7.32.0",
108 | "eslint-config-standard": "^16.0.3",
109 | "eslint-friendly-formatter": "^4.0.1",
110 | "eslint-loader": "^4.0.2",
111 | "eslint-plugin-html": "^6.2.0",
112 | "eslint-plugin-import": "^2.24.2",
113 | "eslint-plugin-node": "^11.1.0",
114 | "eslint-plugin-promise": "^5.1.0",
115 | "eslint-plugin-vue": "^7.19.1",
116 | "file-loader": "^6.2.0",
117 | "html-webpack-plugin": "^3.2.0",
118 | "mini-css-extract-plugin": "0.4.0",
119 | "multispinner": "^0.2.1",
120 | "node-loader": "^0.6.0",
121 | "node-sass": "^6.0.1",
122 | "sass-loader": "^8.0.2",
123 | "style-loader": "^1.2.1",
124 | "url-loader": "^4.1.0",
125 | "vue-html-loader": "^1.2.4",
126 | "vue-loader": "^15.9.8",
127 | "vue-style-loader": "^4.1.3",
128 | "vue-template-compiler": "^2.6.14",
129 | "webpack": "^4.46.0",
130 | "webpack-cli": "^3.3.12",
131 | "webpack-dev-server": "^3.11.2",
132 | "webpack-hot-middleware": "^2.25.1",
133 | "webpack-merge": "^4.1.3"
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/screenshots/loaded.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/screenshots/loaded.png
--------------------------------------------------------------------------------
/screenshots/profiles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/screenshots/profiles.png
--------------------------------------------------------------------------------
/screenshots/saveas.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/screenshots/saveas.png
--------------------------------------------------------------------------------
/screenshots/search.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/screenshots/search.png
--------------------------------------------------------------------------------
/screenshots/updateNotice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/screenshots/updateNotice.png
--------------------------------------------------------------------------------
/src/index.ejs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | MAL (Multi App Launcher)
6 | <% if (htmlWebpackPlugin.options.nodeModules) { %>
7 |
8 |
11 | <% } %>
12 |
13 |
14 |
15 |
16 | <% if (!htmlWebpackPlugin.options.isBrowser && !htmlWebpackPlugin.options.isDevelopment) { %>
17 |
20 | <% } %>
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/src/main/index.dev.js:
--------------------------------------------------------------------------------
1 | /**
2 | * This file is used specifically and only for development. It installs
3 | * `electron-debug` & `vue-devtools`. There shouldn't be any need to
4 | * modify this file, but it can be used to extend your development
5 | * environment.
6 | */
7 |
8 | /* eslint-disable */
9 |
10 | // Install `electron-debug` with `devtron`
11 | const debug = require('electron-debug');
12 |
13 | debug();
14 |
15 |
16 | // Install `vue-devtools`
17 | require('electron').app.on('ready', () => {
18 | let installExtension = require('electron-devtools-installer')
19 | installExtension.default(installExtension.VUEJS_DEVTOOLS)
20 | .then(() => { })
21 | .catch(err => {
22 | console.log('Unable to install `vue-devtools`: \n', err)
23 | })
24 | })
25 |
26 | // Require `main` process to boot app
27 | require('./index')
--------------------------------------------------------------------------------
/src/main/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 |
3 | import { app, BrowserWindow, ipcMain, dialog } from "electron";
4 | import settings from "electron-settings";
5 | import contextMenu from "electron-context-menu";
6 | import * as remoteMain from "@electron/remote/main";
7 | remoteMain.initialize();
8 |
9 | /**
10 | * Set `__static` path to static files in production
11 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
12 | */
13 | if (process.env.NODE_ENV !== "development") {
14 | global.__static = require("path").join(__dirname, "/static").replace(/\\/g, "\\\\");
15 | }
16 |
17 | ipcMain.handle("get-settings", async () => {
18 | const allSettings = await settings.get();
19 | return allSettings;
20 | });
21 |
22 | ipcMain.handle("delete-profile", async (event, profile) => {
23 | return settings.unsetSync(profile);
24 | });
25 |
26 | ipcMain.handle("set-profile", async (event, name, values) => {
27 | settings.setSync(name, values);
28 | });
29 |
30 | ipcMain.handle("file-picker", async (event, options) => {
31 | const filePath = await dialog.showOpenDialog(options);
32 | return filePath;
33 | });
34 |
35 | ipcMain.on("open-info", async (event) => {
36 | const window = createChildWindow();
37 |
38 | window.on("close", () => {
39 | event.reply("close-info", true);
40 | });
41 | });
42 |
43 | let childWindow;
44 | function createChildWindow () {
45 | const winURL =
46 | process.env.NODE_ENV === "development"
47 | ? "http://localhost:9080/#/info"
48 | : `file://${__dirname}/index.html#info`;
49 | const x = mainWindow.getPosition()[0] + 50;
50 | const y = mainWindow.getPosition()[1] + 50;
51 |
52 | childWindow = new BrowserWindow({
53 | height: 300,
54 | width: 300,
55 | x,
56 | y,
57 | minimizable: false,
58 | maximizable: false,
59 | useContentSize: true,
60 | type: "toolbar",
61 | frame: true,
62 | parent: mainWindow,
63 | modal: true,
64 | webPreferences: {
65 | nodeIntegration: true,
66 | contextIsolation: false,
67 | nodeIntegrationInWorker: true,
68 | enableRemoteModule: true
69 | }
70 | });
71 | childWindow.setMenu(null);
72 |
73 | remoteMain.enable(childWindow.webContents);
74 | childWindow.loadURL(winURL);
75 |
76 | return childWindow;
77 | }
78 |
79 | let mainWindow;
80 | const winURL = process.env.NODE_ENV === "development"
81 | ? "http://localhost:9080"
82 | : `file://${__dirname}/index.html`;
83 |
84 | function createWindow () {
85 | /**
86 | * Initial window options
87 | */
88 | mainWindow = new BrowserWindow({
89 | height: 563,
90 | useContentSize: true,
91 | width: 1000,
92 | transparent: true,
93 | backgroundColor: "#090979fa",
94 | frame: false,
95 | webPreferences: {
96 | nodeIntegration: true,
97 | contextIsolation: false,
98 | nodeIntegrationInWorker: true,
99 | enableRemoteModule: true
100 | }
101 | });
102 | mainWindow.setMenu(null);
103 |
104 | remoteMain.enable(mainWindow.webContents);
105 | mainWindow.loadURL(winURL);
106 |
107 | mainWindow.on("closed", () => {
108 | mainWindow = null;
109 | });
110 |
111 | // adds right click menu
112 | contextMenu({
113 | showInspectElement: false,
114 | showSearchWithGoogle: false
115 | });
116 | }
117 |
118 | app.on("ready", createWindow);
119 |
120 | app.on("window-all-closed", () => {
121 | app.quit();
122 | });
123 |
124 | app.on("activate", () => {
125 | if (mainWindow === null) {
126 | createWindow();
127 | }
128 | });
129 |
130 | /**
131 | * Auto Updater
132 | *
133 | * Uncomment the following code below and install `electron-updater` to
134 | * support auto updating. Code Signing with a valid certificate is required.
135 | * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-electron-builder.html#auto-updating
136 | */
137 |
138 | /*
139 | import { autoUpdater } from 'electron-updater'
140 |
141 | autoUpdater.on('update-downloaded', () => {
142 | autoUpdater.quitAndInstall()
143 | })
144 |
145 | app.on('ready', () => {
146 | if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates()
147 | })
148 | */
149 |
--------------------------------------------------------------------------------
/src/renderer/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
6 |
43 |
44 |
45 |
46 |
47 |
94 |
95 |
208 |
--------------------------------------------------------------------------------
/src/renderer/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/src/renderer/assets/.gitkeep
--------------------------------------------------------------------------------
/src/renderer/assets/config.js:
--------------------------------------------------------------------------------
1 |
2 | export default {
3 | WindowsPath: "C:\\ProgramData\\Microsoft\\Windows\\Start Menu\\Programs",
4 | LinuxPath: "/usr/share/applications",
5 | defaultIcon: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEaSURBVFhH7ZTbCoJAEIaFCCKCCKJnLTpQVBdB14HQ00T0CqUP4AN41puJAVe92F3HRZegHfgQFvH7/1nQMmPmZ+Z8uYJOCm01vJe64PF8cZ+Ftho89DxPC8IAeZ73QpZlJWmattsAfsBavsk0yRsD3Ox7ST3A4uTC/OjC7ODCdO/AZOfAeOvAaPOB4foDg1UVwLZtIUmSqG2AIq9vgNcc5coBKHIWgNec0RhAdAUUOSJrjsRxrLYBihxBMa85QzkARY7ImjOkAURXQJEjKOY1Z0RRpLYBihyRNUe5cgCKHEEprzmjMYDoCqjImiNhGKptgApvA3V57wFkzbUGEMmDIGgfAKH84ShypQBdyn3fFwfQSaE1Y+bvx7K+efsbU5+Ow3MAAAAASUVORK5CYII="
6 | };
7 |
--------------------------------------------------------------------------------
/src/renderer/assets/css/bootstrap.css:
--------------------------------------------------------------------------------
1 | /*!
2 | * Generated using the Bootstrap Customizer (https://getbootstrap.com/docs/3.4/customize/)
3 | */
4 | /*!
5 | * Bootstrap v3.4.1 (https://getbootstrap.com/)
6 | * Copyright 2011-2019 Twitter, Inc.
7 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
8 | */
9 | /*! normalize.css v3.0.3 | MIT License | github.com/necolas/normalize.css */
10 | hr {
11 | -webkit-box-sizing: content-box;
12 | box-sizing: content-box;
13 | height: 0;
14 | }
15 | hr {
16 | border: 0;
17 | border-top: 1px solid #eeeeee;
18 | }
19 | .container {
20 | padding-right: 15px;
21 | padding-left: 15px;
22 | margin-right: auto;
23 | margin-left: auto;
24 | }
25 | @media (min-width: 768px) {
26 | .container {
27 | width: 750px;
28 | }
29 | }
30 | @media (min-width: 992px) {
31 | .container {
32 | width: 970px;
33 | }
34 | }
35 | @media (min-width: 1200px) {
36 | .container {
37 | width: 1170px;
38 | }
39 | }
40 | .container-fluid {
41 | padding-right: 15px;
42 | padding-left: 15px;
43 | margin-right: auto;
44 | margin-left: auto;
45 | }
46 | .row {
47 | margin-right: -15px;
48 | margin-left: -15px;
49 | }
50 | .row-no-gutters {
51 | margin-right: 0;
52 | margin-left: 0;
53 | }
54 | .row-no-gutters [class*="col-"] {
55 | padding-right: 0;
56 | padding-left: 0;
57 | }
58 | .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
59 | position: relative;
60 | min-height: 1px;
61 | padding-right: 15px;
62 | padding-left: 15px;
63 | }
64 | @media (min-width: 992px) {
65 | .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
66 | float: left;
67 | }
68 | .col-md-12 {
69 | width: 100%;
70 | }
71 | .col-md-11 {
72 | width: 91.66666667%;
73 | }
74 | .col-md-10 {
75 | width: 83.33333333%;
76 | }
77 | .col-md-9 {
78 | width: 75%;
79 | }
80 | .col-md-8 {
81 | width: 66.66666667%;
82 | }
83 | .col-md-7 {
84 | width: 58.33333333%;
85 | }
86 | .col-md-6 {
87 | width: 50%;
88 | }
89 | .col-md-5 {
90 | width: 41.66666667%;
91 | }
92 | .col-md-4 {
93 | width: 33.33333333%;
94 | }
95 | .col-md-3 {
96 | width: 25%;
97 | }
98 | .col-md-2 {
99 | width: 16.66666667%;
100 | }
101 | .col-md-1 {
102 | width: 8.33333333%;
103 | }
104 | .col-md-pull-12 {
105 | right: 100%;
106 | }
107 | .col-md-pull-11 {
108 | right: 91.66666667%;
109 | }
110 | .col-md-pull-10 {
111 | right: 83.33333333%;
112 | }
113 | .col-md-pull-9 {
114 | right: 75%;
115 | }
116 | .col-md-pull-8 {
117 | right: 66.66666667%;
118 | }
119 | .col-md-pull-7 {
120 | right: 58.33333333%;
121 | }
122 | .col-md-pull-6 {
123 | right: 50%;
124 | }
125 | .col-md-pull-5 {
126 | right: 41.66666667%;
127 | }
128 | .col-md-pull-4 {
129 | right: 33.33333333%;
130 | }
131 | .col-md-pull-3 {
132 | right: 25%;
133 | }
134 | .col-md-pull-2 {
135 | right: 16.66666667%;
136 | }
137 | .col-md-pull-1 {
138 | right: 8.33333333%;
139 | }
140 | .col-md-pull-0 {
141 | right: auto;
142 | }
143 | .col-md-push-12 {
144 | left: 100%;
145 | }
146 | .col-md-push-11 {
147 | left: 91.66666667%;
148 | }
149 | .col-md-push-10 {
150 | left: 83.33333333%;
151 | }
152 | .col-md-push-9 {
153 | left: 75%;
154 | }
155 | .col-md-push-8 {
156 | left: 66.66666667%;
157 | }
158 | .col-md-push-7 {
159 | left: 58.33333333%;
160 | }
161 | .col-md-push-6 {
162 | left: 50%;
163 | }
164 | .col-md-push-5 {
165 | left: 41.66666667%;
166 | }
167 | .col-md-push-4 {
168 | left: 33.33333333%;
169 | }
170 | .col-md-push-3 {
171 | left: 25%;
172 | }
173 | .col-md-push-2 {
174 | left: 16.66666667%;
175 | }
176 | .col-md-push-1 {
177 | left: 8.33333333%;
178 | }
179 | .col-md-push-0 {
180 | left: auto;
181 | }
182 | .col-md-offset-12 {
183 | margin-left: 100%;
184 | }
185 | .col-md-offset-11 {
186 | margin-left: 91.66666667%;
187 | }
188 | .col-md-offset-10 {
189 | margin-left: 83.33333333%;
190 | }
191 | .col-md-offset-9 {
192 | margin-left: 75%;
193 | }
194 | .col-md-offset-8 {
195 | margin-left: 66.66666667%;
196 | }
197 | .col-md-offset-7 {
198 | margin-left: 58.33333333%;
199 | }
200 | .col-md-offset-6 {
201 | margin-left: 50%;
202 | }
203 | .col-md-offset-5 {
204 | margin-left: 41.66666667%;
205 | }
206 | .col-md-offset-4 {
207 | margin-left: 33.33333333%;
208 | }
209 | .col-md-offset-3 {
210 | margin-left: 25%;
211 | }
212 | .col-md-offset-2 {
213 | margin-left: 16.66666667%;
214 | }
215 | .col-md-offset-1 {
216 | margin-left: 8.33333333%;
217 | }
218 | .col-md-offset-0 {
219 | margin-left: 0%;
220 | }
221 | }
222 | .clearfix:before,
223 | .clearfix:after,
224 | .container:before,
225 | .container:after,
226 | .container-fluid:before,
227 | .container-fluid:after,
228 | .row:before,
229 | .row:after {
230 | display: table;
231 | content: " ";
232 | }
233 | .clearfix:after,
234 | .container:after,
235 | .container-fluid:after,
236 | .row:after {
237 | clear: both;
238 | }
239 | .center-block {
240 | display: block;
241 | margin-right: auto;
242 | margin-left: auto;
243 | }
244 | .pull-right {
245 | float: right !important;
246 | }
247 | .pull-left {
248 | float: left !important;
249 | }
250 | .hide {
251 | display: none !important;
252 | }
253 | .show {
254 | display: block !important;
255 | }
256 | .invisible {
257 | visibility: hidden;
258 | }
259 | .text-hide {
260 | font: 0/0 a;
261 | color: transparent;
262 | text-shadow: none;
263 | background-color: transparent;
264 | border: 0;
265 | }
266 | .hidden {
267 | display: none !important;
268 | }
269 | .affix {
270 | position: fixed;
271 | }
272 |
--------------------------------------------------------------------------------
/src/renderer/assets/css/tooltip.css:
--------------------------------------------------------------------------------
1 | /* Tooltip container */
2 | .tooltip {
3 | position: relative;
4 | display: inline-block;
5 | }
6 |
7 | /* Tooltip text */
8 | .tooltip .tooltiptext {
9 | visibility: hidden;
10 | width: 120px;
11 | background-color: #555;
12 | color: #fff;
13 | text-align: center;
14 | padding: 5px 0;
15 | border-radius: 6px;
16 |
17 | /* Position the tooltip text */
18 | position: absolute;
19 | z-index: 1;
20 | bottom: 125%;
21 | left: 50%;
22 | margin-left: -60px;
23 |
24 | /* Fade in tooltip */
25 | opacity: 0;
26 | transition: opacity 0.3s;
27 | }
28 |
29 | /* Tooltip arrow */
30 | .tooltip .tooltiptext::after {
31 | content: "";
32 | position: absolute;
33 | top: 100%;
34 | left: 50%;
35 | margin-left: -5px;
36 | border-width: 5px;
37 | border-style: solid;
38 | border-color: #555 transparent transparent transparent;
39 | }
40 |
41 | /* Show the tooltip text when you mouse over the tooltip container */
42 | .tooltip:hover .tooltiptext {
43 | visibility: visible;
44 | opacity: 1;
45 | }
--------------------------------------------------------------------------------
/src/renderer/assets/fonts/source-sans-pro-v13-latin-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/src/renderer/assets/fonts/source-sans-pro-v13-latin-regular.woff2
--------------------------------------------------------------------------------
/src/renderer/assets/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/src/renderer/assets/icon.png
--------------------------------------------------------------------------------
/src/renderer/assets/photon/css/photon.min.css:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";/*!
2 | * =====================================================
3 | * Photon v0.1.1
4 | * Copyright 2015 Connor Sears
5 | * Licensed under MIT (https://github.com/connors/proton/blob/master/LICENSE)
6 | *
7 | * v0.1.1 designed by @connors.
8 | * =====================================================
9 | */audio,canvas,progress,sub,sup,video{vertical-align:baseline}body,html{height:100%}hr,html,label{overflow:hidden}.clearfix:after,.toolbar-actions:after,.toolbar:after{clear:both}*,img{-webkit-user-drag:text}.list-group *,.nav-group-item,h1,h2,h3,h4,h5,h6,label,td,th{white-space:nowrap;text-overflow:ellipsis}audio:not([controls]){display:none}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:700}dfn{font-style:italic}h1{margin:.67em 0;font-size:36px}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative}sup{top:-.5em}.pane-group,.window{top:0;left:0;right:0}sub{bottom:-.25em}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}input[type=number]::-webkit-inner-spin-button,input[type=number]::-webkit-outer-spin-button{height:auto}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}legend{border:0;padding:0}*{cursor:default;-webkit-user-select:none;-webkit-box-sizing:border-box;box-sizing:border-box}html{width:100%}body{padding:0;margin:0;font-family:system,-apple-system,".SFNSDisplay-Regular","Helvetica Neue",Helvetica,"Segoe UI",sans-serif;font-size:13px;line-height:1.6;}.btn-dropdown:after,.icon:before{font-family:photon-entypo}hr{margin:15px 0;background:0 0;border:0;border-bottom:1px solid #ddd}h1,h2,h3,h4,h5,h6{margin-top:20px;margin-bottom:10px;font-weight:500;overflow:hidden}.btn .icon,.toolbar-header .title{margin-top:1px}h2{font-size:30px}h3{font-size:24px}h4{font-size:18px}h5{font-size:14px}.btn,h6{font-size:12px}.window{position:absolute;bottom:0;display:flex;flex-direction:column;background-color:#fff}.window-content{position:relative;overflow-y:auto;display:flex;flex:1}.selectable-text{cursor:text;-webkit-user-select:text}.btn,.title{cursor:default}.text-center{text-align:center}.text-right{text-align:right}.text-left{text-align:left}.btn,.title{text-align:center}.pull-left{float:left}.pull-right{float:right}.padded{padding:10px}.padded-less{padding:5px}.padded-more{padding:20px}.padded-vertically{padding-top:10px;padding-bottom:10px}.padded-vertically-less{padding-top:5px;padding-bottom:5px}.padded-vertically-more{padding-top:20px;padding-bottom:20px}.padded-horizontally{padding-right:10px;padding-left:10px}.padded-horizontally-less{padding-right:5px;padding-left:5px}.padded-horizontally-more{padding-right:20px;padding-left:20px}.padded-top{padding-top:10px}.padded-top-less{padding-top:5px}.padded-top-more{padding-top:20px}.padded-bottom{padding-bottom:10px}.padded-bottom-less{padding-bottom:5px}.padded-bottom-more{padding-bottom:20px}.sidebar{background-color:#f5f5f4}.draggable{-webkit-app-region:drag}.btn,.btn-group{vertical-align:middle;-webkit-app-region:no-drag}.clearfix:after,.clearfix:before{display:table;content:" "}.btn{display:inline-block;padding:3px 8px;margin-bottom:0;line-height:1.4;white-space:nowrap;background-image:none;border:1px solid transparent;border-radius:4px;box-shadow:0 1px 1px rgba(0,0,0,.06)}.btn:focus{outline:0;box-shadow:none}.btn-mini{padding:2px 6px}.btn-large{padding:6px 12px}.btn-form{padding-right:20px;padding-left:20px}.btn-default{color:#333;background-color:#fcfcfc;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fcfcfc),color-stop(100%,#f1f1f1));background-image:-webkit-linear-gradient(top,#fcfcfc 0,#f1f1f1 100%);background-image:linear-gradient(to bottom,#fcfcfc 0,#f1f1f1 100%);border-color:#c2c0c2 #c2c0c2 #a19fa1}.btn-default:active{background-color:#ddd;background-image:none}.btn-negative,.btn-positive,.btn-primary,.btn-warning{color:#fff;text-shadow:0 1px 1px rgba(0,0,0,.1)}.btn-primary{border-color:#388df8 #388df8 #0866dc;background-color:#6eb4f7;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#6eb4f7),color-stop(100%,#1a82fb));background-image:-webkit-linear-gradient(top,#6eb4f7 0,#1a82fb 100%);background-image:linear-gradient(to bottom,#6eb4f7 0,#1a82fb 100%)}.btn-primary:active{background-color:#3e9bf4;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#3e9bf4),color-stop(100%,#0469de));background-image:-webkit-linear-gradient(top,#3e9bf4 0,#0469de 100%);background-image:linear-gradient(to bottom,#3e9bf4 0,#0469de 100%)}.btn-positive{border-color:#29a03b #29a03b #248b34;background-color:#5bd46d;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#5bd46d),color-stop(100%,#29a03b));background-image:-webkit-linear-gradient(top,#5bd46d 0,#29a03b 100%);background-image:linear-gradient(to bottom,#5bd46d 0,#29a03b 100%)}.btn-positive:active{background-color:#34c84a;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#34c84a),color-stop(100%,#248b34));background-image:-webkit-linear-gradient(top,#34c84a 0,#248b34 100%);background-image:linear-gradient(to bottom,#34c84a 0,#248b34 100%)}.btn-negative{border-color:#fb2f29 #fb2f29 #fb1710;background-color:#fd918d;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fd918d),color-stop(100%,#fb2f29));background-image:-webkit-linear-gradient(top,#fd918d 0,#fb2f29 100%);background-image:linear-gradient(to bottom,#fd918d 0,#fb2f29 100%)}.btn-negative:active{background-color:#fc605b;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fc605b),color-stop(100%,#fb1710));background-image:-webkit-linear-gradient(top,#fc605b 0,#fb1710 100%);background-image:linear-gradient(to bottom,#fc605b 0,#fb1710 100%)}.btn-warning{border-color:#fcaa0e #fcaa0e #ee9d02;background-color:#fece72;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fece72),color-stop(100%,#fcaa0e));background-image:-webkit-linear-gradient(top,#fece72 0,#fcaa0e 100%);background-image:linear-gradient(to bottom,#fece72 0,#fcaa0e 100%)}.btn-warning:active{background-color:#fdbc40;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#fdbc40),color-stop(100%,#ee9d02));background-image:-webkit-linear-gradient(top,#fdbc40 0,#ee9d02 100%);background-image:linear-gradient(to bottom,#fdbc40 0,#ee9d02 100%)}.btn .icon{float:left;width:14px;height:14px;margin-bottom:1px;color:#737475;font-size:14px;line-height:1}.btn .icon-text{margin-right:5px}.btn-dropdown:after{margin-left:5px;content:""}.btn-group{position:relative;display:inline-block}.toolbar-actions:after,.toolbar-actions:before,.toolbar:after,.toolbar:before{display:table;content:" "}.btn-group .btn{position:relative;float:left}.btn-group .btn:active,.btn-group .btn:focus{z-index:2}.btn-group .btn.active{z-index:3}.btn-group .btn+.btn,.btn-group .btn+.btn-group,.btn-group .btn-group+.btn,.btn-group .btn-group+.btn-group{margin-left:-1px}.btn-group>.btn:first-child{border-top-right-radius:0;border-bottom-right-radius:0}.btn-group>.btn:last-child{border-top-left-radius:0;border-bottom-left-radius:0}.btn-group>.btn:not(:first-child):not(:last-child){border-radius:0}.btn-group .btn+.btn{border-left:1px solid #c2c0c2}.btn-group .btn+.btn.active{border-left:0}.btn-group .active{color:#fff;border:1px solid transparent;background-color:#6d6c6d;background-image:none}.btn-group .active .icon{color:#fff}.toolbar{min-height:22px;box-shadow:inset 0 1px 0 #f5f4f5;background-color:#e8e6e8;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#e8e6e8),color-stop(100%,#d1cfd1));background-image:-webkit-linear-gradient(top,#e8e6e8 0,#d1cfd1 100%);background-image:linear-gradient(to bottom,#e8e6e8 0,#d1cfd1 100%)}.toolbar-header{border-bottom:1px solid #c2c0c2}.toolbar-footer{border-top:1px solid #c2c0c2;-webkit-app-region:drag}.title{margin:0;font-size:12px;font-weight:400;color:#555}.toolbar-borderless{border-top:0;border-bottom:0}.toolbar-actions{margin-top:4px;margin-bottom:3px;padding-right:3px;padding-left:3px;padding-bottom:3px;-webkit-app-region:drag}.form-control,label{display:inline-block;font-size:13px}.toolbar-actions>.btn,.toolbar-actions>.btn-group{margin-left:4px;margin-right:4px}input[type=search]{-webkit-appearance:textfield;box-sizing:border-box}input[type=checkbox],input[type=radio]{margin:4px 0 0;line-height:normal}.checkbox,.form-group,.radio{margin-bottom:10px}.form-control{width:100%;min-height:25px;padding:5px 10px;line-height:1.6;background-color:#fff;border:1px solid #ddd;border-radius:4px;outline:0}.form-control:focus{border-color:#6db3fd;box-shadow:3px 3px 0 #6db3fd,-3px -3px 0 #6db3fd,-3px 3px 0 #6db3fd,3px -3px 0 #6db3fd}textarea{height:auto}.checkbox,.radio{position:relative;display:block;margin-top:10px}.checkbox label,.radio label{padding-left:20px;margin-bottom:0;font-weight:400}.checkbox input[type=checkbox],.checkbox-inline input[type=checkbox],.radio input[type=radio],.radio-inline input[type=radio]{position:absolute;margin-left:-20px;margin-top:4px}.form-actions .btn{margin-right:10px}.form-actions .btn:last-child{margin-right:0}.pane-group{position:absolute;bottom:0;display:flex}.icon:before,.pane,.tab-item{position:relative}.pane{overflow-y:auto;flex:1;border-left:1px solid #ddd}.list-group *,.media-body,.nav-group-item,td,th{overflow:hidden}.pane:first-child{border-left:0}.pane-sm{max-width:220px;min-width:150px}.pane-mini{width:80px;flex:none}.pane-one-fourth{width:25%;flex:none}.pane-one-third{width:33.3%}.img-circle{border-radius:50%}.img-rounded{border-radius:4px}.list-group{width:100%;list-style:none;margin:0;padding:0}.list-group *{margin:0}.list-group-item{padding:10px;font-size:12px;color:#414142;border-top:1px solid #ddd}.list-group-item:first-child{border-top:0}.list-group-item.active,.list-group-item.selected{color:#fff;background-color:#116cd6}.list-group-header{padding:10px}.media-object{margin-top:3px}.media-object.pull-left{margin-right:10px}.media-object.pull-right{margin-left:10px}.nav-group{font-size:14px}.nav-group-item{padding:2px 10px 2px 25px;display:block;color:#333;text-decoration:none}.nav-group-item.active,.nav-group-item:active{background-color:#dcdfe1}.nav-group-item .icon{width:19px;height:18px;float:left;color:#737475;margin-top:-3px;margin-right:7px;font-size:18px;text-align:center}.nav-group-title{margin:0;padding:10px 10px 2px;font-size:12px;font-weight:500;color:#666}.icon:before,th{font-weight:400}@font-face{font-family:photon-entypo;src:url(../fonts/photon-entypo.eot);src:url(../fonts/photon-entypo.eot?#iefix) format("eot"),url(../fonts/photon-entypo.woff) format("woff"),url(../fonts/photon-entypo.ttf) format("truetype");font-weight:400;font-style:normal}.icon:before{display:inline-block;speak:none;font-size:100%;font-style:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.icon-note:before{content:'\e800'}.icon-note-beamed:before{content:'\e801'}.icon-music:before{content:'\e802'}.icon-search:before{content:'\e803'}.icon-flashlight:before{content:'\e804'}.icon-mail:before{content:'\e805'}.icon-heart:before{content:'\e806'}.icon-heart-empty:before{content:'\e807'}.icon-star:before{content:'\e808'}.icon-star-empty:before{content:'\e809'}.icon-user:before{content:'\e80a'}.icon-users:before{content:'\e80b'}.icon-user-add:before{content:'\e80c'}.icon-video:before{content:'\e80d'}.icon-picture:before{content:'\e80e'}.icon-camera:before{content:'\e80f'}.icon-layout:before{content:'\e810'}.icon-menu:before{content:'\e811'}.icon-check:before{content:'\e812'}.icon-cancel:before{content:'\e813'}.icon-cancel-circled:before{content:'\e814'}.icon-cancel-squared:before{content:'\e815'}.icon-plus:before{content:'\e816'}.icon-plus-circled:before{content:'\e817'}.icon-plus-squared:before{content:'\e818'}.icon-minus:before{content:'\e819'}.icon-minus-circled:before{content:'\e81a'}.icon-minus-squared:before{content:'\e81b'}.icon-help:before{content:'\e81c'}.icon-help-circled:before{content:'\e81d'}.icon-info:before{content:'\e81e'}.icon-info-circled:before{content:'\e81f'}.icon-back:before{content:'\e820'}.icon-home:before{content:'\e821'}.icon-link:before{content:'\e822'}.icon-attach:before{content:'\e823'}.icon-lock:before{content:'\e824'}.icon-lock-open:before{content:'\e825'}.icon-eye:before{content:'\e826'}.icon-tag:before{content:'\e827'}.icon-bookmark:before{content:'\e828'}.icon-bookmarks:before{content:'\e829'}.icon-flag:before{content:'\e82a'}.icon-thumbs-up:before{content:'\e82b'}.icon-thumbs-down:before{content:'\e82c'}.icon-download:before{content:'\e82d'}.icon-upload:before{content:'\e82e'}.icon-upload-cloud:before{content:'\e82f'}.icon-reply:before{content:'\e830'}.icon-reply-all:before{content:'\e831'}.icon-forward:before{content:'\e832'}.icon-quote:before{content:'\e833'}.icon-code:before{content:'\e834'}.icon-export:before{content:'\e835'}.icon-pencil:before{content:'\e836'}.icon-feather:before{content:'\e837'}.icon-print:before{content:'\e838'}.icon-retweet:before{content:'\e839'}.icon-keyboard:before{content:'\e83a'}.icon-comment:before{content:'\e83b'}.icon-chat:before{content:'\e83c'}.icon-bell:before{content:'\e83d'}.icon-attention:before{content:'\e83e'}.icon-alert:before{content:'\e83f'}.icon-vcard:before{content:'\e840'}.icon-address:before{content:'\e841'}.icon-location:before{content:'\e842'}.icon-map:before{content:'\e843'}.icon-direction:before{content:'\e844'}.icon-compass:before{content:'\e845'}.icon-cup:before{content:'\e846'}.icon-trash:before{content:'\e847'}.icon-doc:before{content:'\e848'}.icon-docs:before{content:'\e849'}.icon-doc-landscape:before{content:'\e84a'}.icon-doc-text:before{content:'\e84b'}.icon-doc-text-inv:before{content:'\e84c'}.icon-newspaper:before{content:'\e84d'}.icon-book-open:before{content:'\e84e'}.icon-book:before{content:'\e84f'}.icon-folder:before{content:'\e850'}.icon-archive:before{content:'\e851'}.icon-box:before{content:'\e852'}.icon-rss:before{content:'\e853'}.icon-phone:before{content:'\e854'}.icon-cog:before{content:'\e855'}.icon-tools:before{content:'\e856'}.icon-share:before{content:'\e857'}.icon-shareable:before{content:'\e858'}.icon-basket:before{content:'\e859'}.icon-bag:before{content:'\e85a'}.icon-calendar:before{content:'\e85b'}.icon-login:before{content:'\e85c'}.icon-logout:before{content:'\e85d'}.icon-mic:before{content:'\e85e'}.icon-mute:before{content:'\e85f'}.icon-sound:before{content:'\e860'}.icon-volume:before{content:'\e861'}.icon-clock:before{content:'\e862'}.icon-hourglass:before{content:'\e863'}.icon-lamp:before{content:'\e864'}.icon-light-down:before{content:'\e865'}.icon-light-up:before{content:'\e866'}.icon-adjust:before{content:'\e867'}.icon-block:before{content:'\e868'}.icon-resize-full:before{content:'\e869'}.icon-resize-small:before{content:'\e86a'}.icon-popup:before{content:'\e86b'}.icon-publish:before{content:'\e86c'}.icon-window:before{content:'\e86d'}.icon-arrow-combo:before{content:'\e86e'}.icon-down-circled:before{content:'\e86f'}.icon-left-circled:before{content:'\e870'}.icon-right-circled:before{content:'\e871'}.icon-up-circled:before{content:'\e872'}.icon-down-open:before{content:'\e873'}.icon-left-open:before{content:'\e874'}.icon-right-open:before{content:'\e875'}.icon-up-open:before{content:'\e876'}.icon-down-open-mini:before{content:'\e877'}.icon-left-open-mini:before{content:'\e878'}.icon-right-open-mini:before{content:'\e879'}.icon-up-open-mini:before{content:'\e87a'}.icon-down-open-big:before{content:'\e87b'}.icon-left-open-big:before{content:'\e87c'}.icon-right-open-big:before{content:'\e87d'}.icon-up-open-big:before{content:'\e87e'}.icon-down:before{content:'\e87f'}.icon-left:before{content:'\e880'}.icon-right:before{content:'\e881'}.icon-up:before{content:'\e882'}.icon-down-dir:before{content:'\e883'}.icon-left-dir:before{content:'\e884'}.icon-right-dir:before{content:'\e885'}.icon-up-dir:before{content:'\e886'}.icon-down-bold:before{content:'\e887'}.icon-left-bold:before{content:'\e888'}.icon-right-bold:before{content:'\e889'}.icon-up-bold:before{content:'\e88a'}.icon-down-thin:before{content:'\e88b'}.icon-left-thin:before{content:'\e88c'}.icon-right-thin:before{content:'\e88d'}.icon-up-thin:before{content:'\e88e'}.icon-ccw:before{content:'\e88f'}.icon-cw:before{content:'\e890'}.icon-arrows-ccw:before{content:'\e891'}.icon-level-down:before{content:'\e892'}.icon-level-up:before{content:'\e893'}.icon-shuffle:before{content:'\e894'}.icon-loop:before{content:'\e895'}.icon-switch:before{content:'\e896'}.icon-play:before{content:'\e897'}.icon-stop:before{content:'\e898'}.icon-pause:before{content:'\e899'}.icon-record:before{content:'\e89a'}.icon-to-end:before{content:'\e89b'}.icon-to-start:before{content:'\e89c'}.icon-fast-forward:before{content:'\e89d'}.icon-fast-backward:before{content:'\e89e'}.icon-progress-0:before{content:'\e89f'}.icon-progress-1:before{content:'\e8a0'}.icon-progress-2:before{content:'\e8a1'}.icon-progress-3:before{content:'\e8a2'}.icon-target:before{content:'\e8a3'}.icon-palette:before{content:'\e8a4'}.icon-list:before{content:'\e8a5'}.icon-list-add:before{content:'\e8a6'}.icon-signal:before{content:'\e8a7'}.icon-trophy:before{content:'\e8a8'}.icon-battery:before{content:'\e8a9'}.icon-back-in-time:before{content:'\e8aa'}.icon-monitor:before{content:'\e8ab'}.icon-mobile:before{content:'\e8ac'}.icon-network:before{content:'\e8ad'}.icon-cd:before{content:'\e8ae'}.icon-inbox:before{content:'\e8af'}.icon-install:before{content:'\e8b0'}.icon-globe:before{content:'\e8b1'}.icon-cloud:before{content:'\e8b2'}.icon-cloud-thunder:before{content:'\e8b3'}.icon-flash:before{content:'\e8b4'}.icon-moon:before{content:'\e8b5'}.icon-flight:before{content:'\e8b6'}.icon-paper-plane:before{content:'\e8b7'}.icon-leaf:before{content:'\e8b8'}.icon-lifebuoy:before{content:'\e8b9'}.icon-mouse:before{content:'\e8ba'}.icon-briefcase:before{content:'\e8bb'}.icon-suitcase:before{content:'\e8bc'}.icon-dot:before{content:'\e8bd'}.icon-dot-2:before{content:'\e8be'}.icon-dot-3:before{content:'\e8bf'}.icon-brush:before{content:'\e8c0'}.icon-magnet:before{content:'\e8c1'}.icon-infinity:before{content:'\e8c2'}.icon-erase:before{content:'\e8c3'}.icon-chart-pie:before{content:'\e8c4'}.icon-chart-line:before{content:'\e8c5'}.icon-chart-bar:before{content:'\e8c6'}.icon-chart-area:before{content:'\e8c7'}.icon-tape:before{content:'\e8c8'}.icon-graduation-cap:before{content:'\e8c9'}.icon-language:before{content:'\e8ca'}.icon-ticket:before{content:'\e8cb'}.icon-water:before{content:'\e8cc'}.icon-droplet:before{content:'\e8cd'}.icon-air:before{content:'\e8ce'}.icon-credit-card:before{content:'\e8cf'}.icon-floppy:before{content:'\e8d0'}.icon-clipboard:before{content:'\e8d1'}.icon-megaphone:before{content:'\e8d2'}.icon-database:before{content:'\e8d3'}.icon-drive:before{content:'\e8d4'}.icon-bucket:before{content:'\e8d5'}.icon-thermometer:before{content:'\e8d6'}.icon-key:before{content:'\e8d7'}.icon-flow-cascade:before{content:'\e8d8'}.icon-flow-branch:before{content:'\e8d9'}.icon-flow-tree:before{content:'\e8da'}.icon-flow-line:before{content:'\e8db'}.icon-flow-parallel:before{content:'\e8dc'}.icon-rocket:before{content:'\e8dd'}.icon-gauge:before{content:'\e8de'}.icon-traffic-cone:before{content:'\e8df'}.icon-cc:before{content:'\e8e0'}.icon-cc-by:before{content:'\e8e1'}.icon-cc-nc:before{content:'\e8e2'}.icon-cc-nc-eu:before{content:'\e8e3'}.icon-cc-nc-jp:before{content:'\e8e4'}.icon-cc-sa:before{content:'\e8e5'}.icon-cc-nd:before{content:'\e8e6'}.icon-cc-pd:before{content:'\e8e7'}.icon-cc-zero:before{content:'\e8e8'}.icon-cc-share:before{content:'\e8e9'}.icon-cc-remix:before{content:'\e8ea'}.icon-github:before{content:'\e8eb'}.icon-github-circled:before{content:'\e8ec'}.icon-flickr:before{content:'\e8ed'}.icon-flickr-circled:before{content:'\e8ee'}.icon-vimeo:before{content:'\e8ef'}.icon-vimeo-circled:before{content:'\e8f0'}.icon-twitter:before{content:'\e8f1'}.icon-twitter-circled:before{content:'\e8f2'}.icon-facebook:before{content:'\e8f3'}.icon-facebook-circled:before{content:'\e8f4'}.icon-facebook-squared:before{content:'\e8f5'}.icon-gplus:before{content:'\e8f6'}.icon-gplus-circled:before{content:'\e8f7'}.icon-pinterest:before{content:'\e8f8'}.icon-pinterest-circled:before{content:'\e8f9'}.icon-tumblr:before{content:'\e8fa'}.icon-tumblr-circled:before{content:'\e8fb'}.icon-linkedin:before{content:'\e8fc'}.icon-linkedin-circled:before{content:'\e8fd'}.icon-dribbble:before{content:'\e8fe'}.icon-dribbble-circled:before{content:'\e8ff'}.icon-stumbleupon:before{content:'\e900'}.icon-stumbleupon-circled:before{content:'\e901'}.icon-lastfm:before{content:'\e902'}.icon-lastfm-circled:before{content:'\e903'}.icon-rdio:before{content:'\e904'}.icon-rdio-circled:before{content:'\e905'}.icon-spotify:before{content:'\e906'}.icon-spotify-circled:before{content:'\e907'}.icon-qq:before{content:'\e908'}.icon-instagram:before{content:'\e909'}.icon-dropbox:before{content:'\e90a'}.icon-evernote:before{content:'\e90b'}.icon-flattr:before{content:'\e90c'}.icon-skype:before{content:'\e90d'}.icon-skype-circled:before{content:'\e90e'}.icon-renren:before{content:'\e90f'}.icon-sina-weibo:before{content:'\e910'}.icon-paypal:before{content:'\e911'}.icon-picasa:before{content:'\e912'}.icon-soundcloud:before{content:'\e913'}.icon-mixi:before{content:'\e914'}.icon-behance:before{content:'\e915'}.icon-google-circles:before{content:'\e916'}.icon-vkontakte:before{content:'\e917'}.icon-smashing:before{content:'\e918'}.icon-sweden:before{content:'\e919'}.icon-db-shape:before{content:'\e91a'}.icon-logo-db:before{content:'\e91b'}table{border-spacing:0;width:100%;border:0;border-collapse:separate;font-size:12px;text-align:left}.table-striped tr:nth-child(even),thead{background-color:#f5f5f4}tbody{background-color:#fff}.table-striped tr:active:nth-child(even),tr:active{color:#fff;background-color:#116cd6}thead tr:active{color:#333;background-color:#f5f5f4}th{border-right:1px solid #ddd;border-bottom:1px solid #ddd}td,th{padding:2px 15px}td:last-child,th:last-child{border-right:0}.tab-group{margin-top:-1px;display:flex;border-top:1px solid #989698;border-bottom:1px solid #989698}.tab-item{flex:1;padding:3px;font-size:12px;text-align:center;border-left:1px solid #989698;background-color:#b8b6b8;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#b8b6b8),color-stop(100%,#b0aeb0));background-image:-webkit-linear-gradient(top,#b8b6b8 0,#b0aeb0 100%);background-image:linear-gradient(to bottom,#b8b6b8 0,#b0aeb0 100%)}.tab-item:first-child{border-left:0}.tab-item.active{background-color:#d4d2d4;background-image:-webkit-gradient(linear,left top,left bottom,color-stop(0,#d4d2d4),color-stop(100%,#cccacc));background-image:-webkit-linear-gradient(top,#d4d2d4 0,#cccacc 100%);background-image:linear-gradient(to bottom,#d4d2d4 0,#cccacc 100%)}.tab-item .icon-close-tab:hover,.tab-item:after{background-color:rgba(0,0,0,.08)}.tab-item .icon-close-tab{position:absolute;top:50%;left:5px;width:15px;height:15px;font-size:15px;line-height:15px;text-align:center;color:#666;opacity:0;transition:opacity .1s linear,background-color .1s linear;border-radius:3px;transform:translateY(-50%);z-index:10}.tab-item:after{position:absolute;top:0;right:0;bottom:0;left:0;content:"";opacity:0;transition:opacity .1s linear;z-index:1}.tab-item:hover .icon-close-tab,.tab-item:hover:not(.active):after{opacity:1}.tab-item-fixed{flex:none;padding:3px 10px}
--------------------------------------------------------------------------------
/src/renderer/assets/photon/fonts/photon-entypo.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/src/renderer/assets/photon/fonts/photon-entypo.eot
--------------------------------------------------------------------------------
/src/renderer/assets/photon/fonts/photon-entypo.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/renderer/assets/photon/fonts/photon-entypo.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/src/renderer/assets/photon/fonts/photon-entypo.ttf
--------------------------------------------------------------------------------
/src/renderer/assets/photon/fonts/photon-entypo.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/src/renderer/assets/photon/fonts/photon-entypo.woff
--------------------------------------------------------------------------------
/src/renderer/components/AppInfo.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
App Info
5 |
6 |
7 |
{{ updateStatus }}
8 |
9 |
Application Version: {{ version }}
10 |
Application Name: {{ name }}
11 |
App Resources:
12 |
13 | CPU Usage: {{ cpuUsage.toFixed(3) }} %
14 |
15 |
16 | Memory Usage: {{ memUsage.toLocaleString("en") }} KB
17 |
18 |
19 |
20 |
24 |
34 |
35 |
Release Notes:
36 |
{{ releases[0].body }}
37 |
38 |
39 |
40 |
41 |
42 |
102 |
103 |
--------------------------------------------------------------------------------
/src/renderer/components/LandingPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
9 |
15 |
21 |
27 |
28 |
29 |
33 |
34 | No Profiles saved
35 |
36 |
42 |
48 |
54 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
68 |
69 | How many programs: {{ numbers }}
70 |
71 |
79 |
80 |
81 |
82 |
88 |
94 |
95 |
233 |
234 |
235 |
243 |
244 |
245 |
246 |
247 |
667 |
668 |
982 |
--------------------------------------------------------------------------------
/src/renderer/components/LandingPage/FileIngest.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
17 |
78 |
79 |
--------------------------------------------------------------------------------
/src/renderer/components/LandingPage/Modal.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
23 |
27 |
42 |
49 |
50 |
51 |
52 |
53 |
54 |
65 |
70 |
85 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
158 |
159 |
232 |
--------------------------------------------------------------------------------
/src/renderer/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 |
3 | import App from "./App";
4 | import router from "./router";
5 | // import store from './store'
6 |
7 | if (!process.env.IS_WEB) Vue.use(require("vue-electron"));
8 | Vue.config.productionTip = false;
9 |
10 | /* eslint-disable no-new */
11 | new Vue({
12 | components: { App },
13 | router,
14 | template: ""
15 | }).$mount("#app");
16 |
--------------------------------------------------------------------------------
/src/renderer/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Router from "vue-router";
3 |
4 | Vue.use(Router);
5 |
6 | export default new Router({
7 | // mode: process.env.IS_ELECTRON ? 'hash' : 'history',
8 | // mode: process.env.NODE_ENV === 'development' ? 'hash' : 'history',
9 | routes: [
10 | {
11 | path: "/",
12 | name: "landing-page",
13 | component: require("@/components/LandingPage").default
14 | },
15 | {
16 | path: "/info",
17 | name: "app-info",
18 | component: require("@/components/AppInfo").default
19 | },
20 | {
21 | path: "*",
22 | redirect: "/"
23 | }
24 | ]
25 | });
26 |
--------------------------------------------------------------------------------
/src/renderer/services/github.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | export default {
4 | getReleases () {
5 | return axios.get("https://api.github.com/repos/Arges86/multi-app-launcher/releases")
6 | .then(response => {
7 | return response.data ? response.data.sort((a, b) => (a.published_at < b.published_at) ? 1 : -1) : response;
8 | });
9 | }
10 | };
11 |
--------------------------------------------------------------------------------
/src/renderer/services/linuxparse.js:
--------------------------------------------------------------------------------
1 | import config from "../assets/config";
2 |
3 | export default {
4 | async parseDesktop (data) {
5 | const fs = require("fs");
6 | const ini = require("ini");
7 | const util = require("util");
8 | const exec = util.promisify(require("child_process").exec);
9 | const text = ini.parse(fs.readFileSync(data, "utf-8"));
10 | const command = (text["Desktop Entry"].Exec).toLowerCase().replace(/ %u| %f/, "");
11 | // console.log(text['Desktop Entry'].Name, command)
12 | let icon = "";
13 |
14 | try {
15 | const { stdout } = await exec(`dpkg-query -L ${command} | grep png`);
16 | if (stdout) {
17 | // gets first icon from list
18 | icon = (stdout.split("\n"))[0];
19 | }
20 | // console.log(icon)
21 | const iconBuffer = fs.readFileSync(icon);
22 | const iconBase64 = Buffer.from(iconBuffer).toString("base64");
23 |
24 | return {
25 | url: command,
26 | icon: `data:image/png;base64,${iconBase64}`
27 | };
28 | } catch (error) {
29 | // console.log(`dpkg-query error: ${command} : `)
30 | return {
31 | url: command,
32 | icon: config.defaultIcon
33 | };
34 | }
35 | }
36 | };
37 |
--------------------------------------------------------------------------------
/src/renderer/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex from "vuex";
3 |
4 | import { createPersistedState, createSharedMutations } from "vuex-electron";
5 |
6 | import modules from "./modules";
7 |
8 | Vue.use(Vuex);
9 |
10 | export default new Vuex.Store({
11 | modules,
12 | plugins: [
13 | createPersistedState(),
14 | createSharedMutations()
15 | ],
16 | strict: process.env.NODE_ENV !== "production"
17 | });
18 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/Counter.js:
--------------------------------------------------------------------------------
1 | const state = {
2 | main: 0
3 | };
4 |
5 | const mutations = {
6 | DECREMENT_MAIN_COUNTER (state) {
7 | state.main--;
8 | },
9 | INCREMENT_MAIN_COUNTER (state) {
10 | state.main++;
11 | }
12 | };
13 |
14 | const actions = {
15 | someAsyncTask ({ commit }) {
16 | // do something async
17 | commit("INCREMENT_MAIN_COUNTER");
18 | }
19 | };
20 |
21 | export default {
22 | state,
23 | mutations,
24 | actions
25 | };
26 |
--------------------------------------------------------------------------------
/src/renderer/store/modules/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * The file enables `@/store/index.js` to import all vuex modules
3 | * in a one-shot manner. There should not be any reason to edit this file.
4 | */
5 |
6 | const files = require.context(".", false, /\.js$/);
7 | const modules = {};
8 |
9 | files.keys().forEach(key => {
10 | if (key === "./index.js") return;
11 | modules[key.replace(/(\.\/|\.js)/g, "")] = files(key).default;
12 | });
13 |
14 | export default modules;
15 |
--------------------------------------------------------------------------------
/static/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Arges86/multi-app-launcher/11849d3f7f110b12f717bc21898827085ab6f268/static/.gitkeep
--------------------------------------------------------------------------------