diff --git a/package-lock.json b/package-lock.json index d9d08f93..34ac0c9c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1912,6 +1912,12 @@ "resolved": "https://registry.npmjs.org/@trodi/electron-splashscreen/-/electron-splashscreen-0.3.4.tgz", "integrity": "sha512-nYF+sfNIEUhZPyzYUOpcqyCZoDYmMfZq8jLhEolvQFSVwrJ7gAlPhhMxpuw/qpCzPErUkFLEtdGGvK1tGtLuvQ==" }, + "@types/auto-launch": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@types/auto-launch/-/auto-launch-5.0.1.tgz", + "integrity": "sha512-+KQ+/koZ7sJXnf5cnCANofY6yXAdYJNEoVZEuWcwJfuWbUp9u6l09I7KhwD+ivU+cdz7JId4V5ukxscWtHdSuw==", + "dev": true + }, "@types/babel__core": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.0.tgz", @@ -2971,6 +2977,11 @@ "default-require-extensions": "^2.0.0" } }, + "applescript": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/applescript/-/applescript-1.0.0.tgz", + "integrity": "sha1-u4evVoytA0pOSMS9r2Bno6JwExc=" + }, "aproba": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", @@ -3242,6 +3253,18 @@ "integrity": "sha1-0IiFvmubv5Q5/gh8dihyRfCoFFA=", "dev": true }, + "auto-launch": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/auto-launch/-/auto-launch-5.0.5.tgz", + "integrity": "sha512-ppdF4mihhYzMYLuCcx9H/c5TUOCev8uM7en53zWVQhyYAJrurd2bFZx3qQVeJKF2jrc7rsPRNN5cD+i23l6PdA==", + "requires": { + "applescript": "^1.0.0", + "mkdirp": "^0.5.1", + "path-is-absolute": "^1.0.0", + "untildify": "^3.0.2", + "winreg": "1.2.4" + } + }, "autoprefixer": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.1.tgz", @@ -21060,6 +21083,11 @@ } } }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==" + }, "unused-filename": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unused-filename/-/unused-filename-1.0.0.tgz", @@ -22477,6 +22505,11 @@ } } }, + "winreg": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/winreg/-/winreg-1.2.4.tgz", + "integrity": "sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs=" + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", diff --git a/package.json b/package.json index 2d266afb..f39230a4 100644 --- a/package.json +++ b/package.json @@ -163,6 +163,7 @@ "@trodi/electron-splashscreen": "^0.3.4", "about-window": "^1.13.1", "animate.css": "^3.7.0", + "auto-launch": "^5.0.5", "axios": "^0.18.1", "boom": "^7.3.0", "deep-extend": "^0.6.0", @@ -208,6 +209,7 @@ "@babel/preset-env": "^7.4.3", "@babel/runtime": "^7.4.3", "@mapbox/stylelint-processor-arbitrary-tags": "^0.2.0", + "@types/auto-launch": "^5.0.1", "@types/electron-json-storage": "^4.0.0", "@types/i18next": "^12.1.0", "@types/jest": "^24.0.15", diff --git a/spec/renderer/integration/store/Preferences/General.spec.ts b/spec/renderer/integration/store/Preferences/General.spec.ts index 9c73abeb..65d164fe 100644 --- a/spec/renderer/integration/store/Preferences/General.spec.ts +++ b/spec/renderer/integration/store/Preferences/General.spec.ts @@ -14,6 +14,9 @@ const state = (): GeneralState => { cw: false, nfsw: false, hideAllAttachments: false + }, + other: { + launch: false } }, loading: false @@ -31,7 +34,7 @@ const initStore = () => { const app = { namespaced: true, actions: { - loadPreferences (_) { + loadPreferences(_) { return true } } diff --git a/spec/renderer/unit/store/Preferences/General.spec.ts b/spec/renderer/unit/store/Preferences/General.spec.ts index 15d25632..5f624385 100644 --- a/spec/renderer/unit/store/Preferences/General.spec.ts +++ b/spec/renderer/unit/store/Preferences/General.spec.ts @@ -13,6 +13,9 @@ describe('Preferences/General', () => { cw: false, nfsw: false, hideAllAttachments: false + }, + other: { + launch: false } }, loading: false diff --git a/src/config/locales/de/translation.missing.json b/src/config/locales/de/translation.missing.json index ce0d96cc..6422c8fc 100644 --- a/src/config/locales/de/translation.missing.json +++ b/src/config/locales/de/translation.missing.json @@ -45,6 +45,10 @@ "general": { "timeline": { "description": "Customize view in your timelines." + }, + "other": { + "title": "Other options", + "launch": "Launch app on login" } } }, diff --git a/src/config/locales/en/translation.json b/src/config/locales/en/translation.json index 7fa0aad2..1eedd4cd 100644 --- a/src/config/locales/en/translation.json +++ b/src/config/locales/en/translation.json @@ -127,6 +127,10 @@ "cw": "Always ignore contents warnings", "nfsw": "Always ignore NFSW of medias", "hideAllAttachments": "Hide all medias" + }, + "other": { + "title": "Other options", + "launch": "Launch app on login" } }, "appearance": { diff --git a/src/config/locales/fr/translation.missing.json b/src/config/locales/fr/translation.missing.json index 72ced0ba..5b3eaa98 100644 --- a/src/config/locales/fr/translation.missing.json +++ b/src/config/locales/fr/translation.missing.json @@ -3,5 +3,13 @@ "shortcut": { "ctrl_r": "Reload current timeline" } + }, + "preferences": { + "general": { + "other": { + "title": "Other options", + "launch": "Launch app on login" + } + } } } diff --git a/src/config/locales/it/translation.missing.json b/src/config/locales/it/translation.missing.json index 5da1aab4..f1deffc4 100644 --- a/src/config/locales/it/translation.missing.json +++ b/src/config/locales/it/translation.missing.json @@ -6,6 +6,12 @@ "follow_requests": "Follow Requests" }, "preferences": { + "general": { + "other": { + "title": "Other options", + "launch": "Launch app on login" + } + }, "appearance": { "toot_padding": "Padding around toot" } diff --git a/src/config/locales/ja/translation.json b/src/config/locales/ja/translation.json index 824bd3b8..91fb4b55 100644 --- a/src/config/locales/ja/translation.json +++ b/src/config/locales/ja/translation.json @@ -127,6 +127,10 @@ "cw": "常にCWを表示する", "nfsw": "常にNFSWを表示する", "hideAllAttachments": "すべてのメディアを非表示にする" + }, + "other": { + "title": "その他", + "launch": "ログイン時にアプリを起動する" } }, "appearance": { diff --git a/src/config/locales/ko/translation.missing.json b/src/config/locales/ko/translation.missing.json index 494098ab..d65ee6ed 100644 --- a/src/config/locales/ko/translation.missing.json +++ b/src/config/locales/ko/translation.missing.json @@ -7,6 +7,10 @@ "cw": "Always ignore contents warnings", "nfsw": "Always ignore NFSW of medias", "hideAllAttachments": "Hide all medias" + }, + "other": { + "title": "Other options", + "launch": "Launch app on login" } }, "appearance": { diff --git a/src/config/locales/pl/translation.missing.json b/src/config/locales/pl/translation.missing.json index cd2396eb..5d902d7a 100644 --- a/src/config/locales/pl/translation.missing.json +++ b/src/config/locales/pl/translation.missing.json @@ -67,6 +67,10 @@ "cw": "Always ignore contents warnings", "nfsw": "Always ignore NFSW of medias", "hideAllAttachments": "Hide all medias" + }, + "other": { + "title": "Other options", + "launch": "Launch app on login" } }, "appearance": { diff --git a/src/config/locales/zh_cn/translation.missing.json b/src/config/locales/zh_cn/translation.missing.json index 72ced0ba..5b3eaa98 100644 --- a/src/config/locales/zh_cn/translation.missing.json +++ b/src/config/locales/zh_cn/translation.missing.json @@ -3,5 +3,13 @@ "shortcut": { "ctrl_r": "Reload current timeline" } + }, + "preferences": { + "general": { + "other": { + "title": "Other options", + "launch": "Launch app on login" + } + } } } diff --git a/src/main/index.ts b/src/main/index.ts index 060bcd37..7879d517 100644 --- a/src/main/index.ts +++ b/src/main/index.ts @@ -24,6 +24,7 @@ import { initSplashScreen, Config } from '@trodi/electron-splashscreen' import openAboutWindow from 'about-window' import { Status, Notification as RemoteNotification, Account as RemoteAccount } from 'megalodon' import sanitizeHtml from 'sanitize-html' +import AutoLaunch from 'auto-launch' import pkg from '~/package.json' import Authentication from './auth' @@ -107,6 +108,8 @@ const splashURL = // https://github.com/louischatriot/nedb/issues/459 const userData = app.getPath('userData') +const appPath = app.getPath('exe') + const accountDBPath = process.env.NODE_ENV === 'production' ? userData + '/db/account.db' : 'account.db' let accountDB = new Datastore({ filename: accountDBPath, @@ -139,6 +142,11 @@ const accountCache = new AccountCache(accountCachePath) const soundBasePath = process.env.NODE_ENV === 'development' ? path.join(__dirname, '../../build/sounds/') : path.join(process.resourcesPath!, 'build/sounds/') +const launcher = new AutoLaunch({ + name: 'Whalebird', + path: appPath +}) + async function listAccounts(): Promise> { try { const accounts = await accountManager.listAccounts() @@ -206,7 +214,7 @@ async function createWindow() { } /** - * Windows10 don' notify, so we have to set appId + * Windows10 don't notify, so we have to set appId * https://github.com/electron/electron/issues/10864 */ app.setAppUserModelId(appId) @@ -458,6 +466,17 @@ ipcMain.on('remove-all-accounts', (event: Event) => { }) }) +ipcMain.on('change-auto-launch', (event: Event, enable: boolean) => { + launcher.isEnabled().then(enabled => { + if (!enabled && enable) { + launcher.enable() + } else if (enabled && !enable) { + launcher.disable() + } + event.sender.send('response-change-auto-launch', enable) + }) +}) + // badge ipcMain.on('reset-badge', () => { if (process.platform === 'darwin') { @@ -861,16 +880,20 @@ ipcMain.on('toot-action-sound', () => { }) // preferences -ipcMain.on('get-preferences', (event: Event) => { +ipcMain.on('get-preferences', async (event: Event) => { const preferences = new Preferences(preferencesDBPath) - preferences - .load() - .then(conf => { - event.sender.send('response-get-preferences', conf) - }) - .catch(err => { - event.sender.send('error-get-preferences', err) + const enabled = await launcher.isEnabled() + await preferences + .update({ + general: { + other: enabled + } }) + .catch(err => console.error(err)) + const conf = await preferences.load().catch(err => { + event.sender.send('error-get-preferences', err) + }) + event.sender.send('response-get-preferences', conf) }) ipcMain.on('update-preferences', (event: Event, data: any) => { diff --git a/src/main/preferences.ts b/src/main/preferences.ts index 7f76dd0c..57a34753 100644 --- a/src/main/preferences.ts +++ b/src/main/preferences.ts @@ -11,7 +11,7 @@ import { Timeline } from '~/src/types/timeline' import { Notify } from '~/src/types/notify' import { Appearance } from '~/src/types/appearance' import { Language as LanguageSet } from '~/src/types/language' -import { General, State, Notification, BaseConfig } from '~/src/types/preference' +import { General, State, Notification, BaseConfig, Other } from '~/src/types/preference' const sound: Sound = { fav_rb: true, @@ -24,9 +24,14 @@ const timeline: Timeline = { hideAllAttachments: false } +const other: Other = { + launch: false +} + const general: General = { sound: sound, - timeline: timeline + timeline: timeline, + other: other } const state: State = { diff --git a/src/renderer/components/Preferences/General.vue b/src/renderer/components/Preferences/General.vue index 5d854baa..4918da89 100644 --- a/src/renderer/components/Preferences/General.vue +++ b/src/renderer/components/Preferences/General.vue @@ -1,50 +1,36 @@ diff --git a/src/renderer/store/Preferences/General.ts b/src/renderer/store/Preferences/General.ts index 721e4a5d..8f914884 100644 --- a/src/renderer/store/Preferences/General.ts +++ b/src/renderer/store/Preferences/General.ts @@ -3,7 +3,7 @@ import { Module, MutationTree, ActionTree } from 'vuex' import { RootState } from '@/store' import { Sound } from '~/src/types/sound' import { Timeline } from '~/src/types/timeline' -import { BaseConfig, General } from '~/src/types/preference' +import { BaseConfig, General, Other } from '~/src/types/preference' export type GeneralState = { general: General @@ -20,6 +20,9 @@ const state = (): GeneralState => ({ cw: false, nfsw: false, hideAllAttachments: false + }, + other: { + launch: false } }, loading: false @@ -93,7 +96,7 @@ const actions: ActionTree = { return new Promise((resolve, reject) => { ipcRenderer.once('error-update-preferences', (_, err: Error) => { ipcRenderer.removeAllListeners('response-update-preferences') - commit('changeLoading', false) + commit(MUTATION_TYPES.CHANGE_LOADING, false) reject(err) }) ipcRenderer.once('response-update-preferences', (_, conf: BaseConfig) => { @@ -105,6 +108,34 @@ const actions: ActionTree = { }) ipcRenderer.send('update-preferences', config) }) + }, + updateOther: ({ commit, state, dispatch }, other: {}) => { + commit(MUTATION_TYPES.CHANGE_LOADING, true) + const newOther: Other = Object.assign({}, state.general.other, other) + const newGeneral: General = Object.assign({}, state.general, { + other: newOther + }) + const config = { + general: newGeneral + } + return new Promise((resolve, reject) => { + ipcRenderer.once('response-change-auto-launch', () => { + ipcRenderer.once('error-update-preferences', (_, err: Error) => { + ipcRenderer.removeAllListeners('response-update-preferences') + commit(MUTATION_TYPES.CHANGE_LOADING, false) + reject(err) + }) + ipcRenderer.once('response-update-preferences', (_, conf: BaseConfig) => { + ipcRenderer.removeAllListeners('error-update-preferences') + commit(MUTATION_TYPES.UPDATE_GENERAL, conf.general as General) + commit(MUTATION_TYPES.CHANGE_LOADING, false) + dispatch('App/loadPreferences', null, { root: true }) + resolve(conf) + }) + ipcRenderer.send('update-preferences', config) + }) + ipcRenderer.send('change-auto-launch', newOther.launch) + }) } } diff --git a/src/types/preference.ts b/src/types/preference.ts index 3ed1b8fc..218c7703 100644 --- a/src/types/preference.ts +++ b/src/types/preference.ts @@ -4,9 +4,14 @@ import { Notify } from '~/src/types/notify' import { Appearance } from '~/src/types/appearance' import { Language } from '~/src/types/language' +export type Other = { + launch: boolean +} + export type General = { sound: Sound timeline: Timeline + other: Other } export type State = {