diff --git a/package-lock.json b/package-lock.json index a906354b..bb03cfe2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -494,7 +494,6 @@ "version": "2.6.0", "resolved": "https://registry.npmjs.org/async/-/async-2.6.0.tgz", "integrity": "sha512-xAfGg1/NTLBBKlHFmnd7PlmUW9KhVQIUuSrYem9xzFUZy13ScvtyGGejaae9iAVRiRq9+Cx7DPFaAAhCpyxyPw==", - "dev": true, "requires": { "lodash": "4.17.5" } @@ -4510,6 +4509,18 @@ "integrity": "sha1-FOb9pcaOnk7L7/nM8DfL18BcWv4=", "dev": true }, + "electron-json-storage": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/electron-json-storage/-/electron-json-storage-4.0.2.tgz", + "integrity": "sha1-wNZizNAbxlZ9YHjxemhCrHQyjOQ=", + "requires": { + "async": "2.6.0", + "lodash": "4.17.5", + "mkdirp": "0.5.1", + "rimraf": "2.6.2", + "rwlock": "5.0.0" + } + }, "electron-localshortcut": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/electron-localshortcut/-/electron-localshortcut-3.1.0.tgz", @@ -13270,6 +13281,11 @@ "aproba": "1.2.0" } }, + "rwlock": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/rwlock/-/rwlock-5.0.0.tgz", + "integrity": "sha1-iI1qd6M1HMGiCSBO8u4XIgk4Ns8=" + }, "rx": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", diff --git a/package.json b/package.json index 33977bbc..fec5347e 100644 --- a/package.json +++ b/package.json @@ -83,6 +83,7 @@ }, "dependencies": { "axios": "^0.18.0", + "electron-json-storage": "^4.0.2", "electron-log": "^2.2.14", "electron-window-state": "^4.1.1", "element-ui": "^2.2.1", diff --git a/src/main/index.js b/src/main/index.js index 91652087..c3a560e2 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -11,6 +11,7 @@ import path from 'path' import Authentication from './auth' import Account from './account' import Streaming from './streaming' +import Preferences from './preferences' /** * Set log level @@ -33,17 +34,24 @@ const winURL = process.env.NODE_ENV === 'development' // https://github.com/louischatriot/nedb/issues/459 const userData = app.getPath('userData') -const databasePath = process.env.NODE_ENV === 'production' +const accountDBPath = process.env.NODE_ENV === 'production' ? userData + '/db/account.db' : 'account.db' -let db = new Datastore({ - filename: databasePath, +let accountDB = new Datastore({ + filename: accountDBPath, autoload: true }) +const preferencesDBPath = process.env.NODE_ENV === 'production' + ? userData + './db/preferences.json' + : 'preferences.json' + +const soundBasePath = process.env.NODE_ENV === 'development' + ? path.join(__dirname, '../../build/sounds/') + : path.join(process.resourcesPath, 'build/sounds/') async function listAccounts () { try { - const account = new Account(db) + const account = new Account(accountDB) await account.cleanup() const accounts = await account.listAccounts() return accounts @@ -221,7 +229,7 @@ app.on('activate', () => { } }) -let auth = new Authentication(new Account(db)) +let auth = new Authentication(new Account(accountDB)) ipcMain.on('get-auth-url', (event, domain) => { auth.getAuthorizationUrl(domain) @@ -244,7 +252,7 @@ ipcMain.on('get-access-token', (event, code) => { event.sender.send('error-get-access-token', err) }) .then((token) => { - db.findOne({ + accountDB.findOne({ accessToken: token }, (err, doc) => { if (err) return event.sender.send('error-get-access-token', err) @@ -265,7 +273,7 @@ ipcMain.on('get-social-token', (event, _) => { // nedb ipcMain.on('list-accounts', (event, _) => { - const account = new Account(db) + const account = new Account(accountDB) account.listAccounts() .catch((err) => { log.error(err) @@ -277,7 +285,7 @@ ipcMain.on('list-accounts', (event, _) => { }) ipcMain.on('get-local-account', (event, id) => { - const account = new Account(db) + const account = new Account(accountDB) account.getAccount(id) .catch((err) => { log.error(err) @@ -289,7 +297,7 @@ ipcMain.on('get-local-account', (event, id) => { }) ipcMain.on('update-account', (event, acct) => { - const account = new Account(db) + const account = new Account(accountDB) const id = acct._id delete acct._id account.updateAccount(id, acct) @@ -302,7 +310,7 @@ ipcMain.on('update-account', (event, acct) => { }) ipcMain.on('remove-account', (event, id) => { - const account = new Account(db) + const account = new Account(accountDB) account.removeAccount(id) .then(() => { event.sender.send('response-remove-account') @@ -313,7 +321,7 @@ ipcMain.on('remove-account', (event, id) => { }) ipcMain.on('forward-account', (event, acct) => { - const account = new Account(db) + const account = new Account(accountDB) account.forwardAccount(acct) .then(() => { event.sender.send('response-forward-account') @@ -324,7 +332,7 @@ ipcMain.on('forward-account', (event, acct) => { }) ipcMain.on('backward-account', (event, acct) => { - const account = new Account(db) + const account = new Account(accountDB) account.backwardAccount(acct) .then(() => { event.sender.send('response-backward-account') @@ -338,7 +346,7 @@ ipcMain.on('backward-account', (event, acct) => { let userStreaming = null ipcMain.on('start-user-streaming', (event, ac) => { - const account = new Account(db) + const account = new Account(accountDB) account.getAccount(ac._id) .catch((err) => { log.error(err) @@ -377,7 +385,7 @@ ipcMain.on('stop-user-streaming', (event, _) => { let localStreaming = null ipcMain.on('start-local-streaming', (event, ac) => { - const account = new Account(db) + const account = new Account(accountDB) account.getAccount(ac._id) .catch((err) => { log.error(err) @@ -412,7 +420,7 @@ ipcMain.on('stop-local-streaming', (event, _) => { let publicStreaming = null ipcMain.on('start-public-streaming', (event, ac) => { - const account = new Account(db) + const account = new Account(accountDB) account.getAccount(ac._id) .catch((err) => { log.error(err) @@ -445,22 +453,55 @@ ipcMain.on('stop-public-streaming', (event, _) => { }) // sounds -ipcMain.on('operation-sound01', (event, _) => { - const sound = process.env.NODE_ENV === 'development' - ? path.join(__dirname, '../../build/sounds/operation_sound01.wav') - : path.join(process.resourcesPath, 'build/sounds/operation_sound01.wav') - simplayer(sound, (err) => { - if (err) log.error(err) - }) +ipcMain.on('fav-rt-action-sound', (event, _) => { + const preferences = new Preferences(preferencesDBPath) + preferences.load() + .then((conf) => { + if (conf.general.sound.fav_rb) { + const sound = path.join(soundBasePath, 'operation_sound01.wav') + simplayer(sound, (err) => { + if (err) log.error(err) + }) + } + }) + .catch(err => log.error(err)) }) -ipcMain.on('operation-sound02', (event, _) => { - const sound = process.env.NODE_ENV === 'development' - ? path.join(__dirname, '../../build/sounds/operation_sound02.wav') - : path.join(process.resourcesPath, 'build/sounds/operation_sound02.wav') - simplayer(sound, (err) => { - if (err) log.error(err) - }) +ipcMain.on('toot-action-sound', (event, _) => { + const preferences = new Preferences(preferencesDBPath) + preferences.load() + .then((conf) => { + if (conf.general.sound.toot) { + const sound = path.join(soundBasePath, 'operation_sound02.wav') + simplayer(sound, (err) => { + if (err) log.error(err) + }) + } + }) + .catch(err => log.error(err)) +}) + +// preferences +ipcMain.on('get-preferences', (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) + }) +}) + +ipcMain.on('save-preferences', (event, data) => { + const preferences = new Preferences(preferencesDBPath) + preferences.save(data) + .then((conf) => { + event.sender.send('response-save-preferences', conf) + }) + .catch((err) => { + event.sender.send('error-save-preferences', err) + }) }) /** diff --git a/src/main/preferences.js b/src/main/preferences.js new file mode 100644 index 00000000..21de9631 --- /dev/null +++ b/src/main/preferences.js @@ -0,0 +1,48 @@ +import empty from 'is-empty' +import storage from 'electron-json-storage' + +const Base = { + general: { + sound: { + fav_rb: true, + toot: true + } + } +} + +export default class Preferences { + constructor (path) { + this.path = path + this.data = Base + } + + async load () { + try { + const preferences = await this.get() + if (empty(preferences)) return Base + return preferences + } catch (err) { + return Base + } + } + + get () { + return new Promise((resolve, reject) => { + storage.get(this.path, (err, data) => { + if (err) return reject(err) + this.data = data + return resolve(data) + }) + }) + } + + save (data) { + return new Promise((resolve, reject) => { + storage.set(this.path, data, (err) => { + if (err) return reject(err) + this.data = data + return resolve(data) + }) + }) + } +} diff --git a/src/renderer/components/Preferences/General.vue b/src/renderer/components/Preferences/General.vue index 4ca592e6..4cbc6c8e 100644 --- a/src/renderer/components/Preferences/General.vue +++ b/src/renderer/components/Preferences/General.vue @@ -1,14 +1,94 @@ diff --git a/src/renderer/store/App.js b/src/renderer/store/App.js index 6a1b70c9..83c9ea7d 100644 --- a/src/renderer/store/App.js +++ b/src/renderer/store/App.js @@ -8,7 +8,7 @@ const App = { actions: { watchShortcutsEvents () { ipcRenderer.on('open-preferences', (event) => { - router.push('/preferences/account') + router.push('/preferences/general') }) }, removeShortcutsEvents () { diff --git a/src/renderer/store/Preferences/General.js b/src/renderer/store/Preferences/General.js index 6c55d116..518e28d0 100644 --- a/src/renderer/store/Preferences/General.js +++ b/src/renderer/store/Preferences/General.js @@ -1,8 +1,63 @@ +import { ipcRenderer } from 'electron' + const General = { namespaced: true, - state: {}, - mutations: {}, - actions: {} + state: { + general: { + sound: { + fav_rb: true, + toot: true + } + }, + loading: false + }, + mutations: { + updateGeneral (state, conf) { + state.general = conf + }, + changeLoading (state, value) { + state.loading = value + } + }, + actions: { + loadGeneral ({ commit }) { + return new Promise((resolve, reject) => { + commit('changeLoading', true) + ipcRenderer.send('get-preferences') + ipcRenderer.once('error-get-preferences', (event, err) => { + ipcRenderer.removeAllListeners('response-get-preferences') + commit('changeLoading', false) + reject(err) + }) + ipcRenderer.once('response-get-preferences', (event, conf) => { + ipcRenderer.removeAllListeners('error-get-preferences') + commit('updateGeneral', conf.general) + commit('changeLoading', false) + resolve(conf) + }) + }) + }, + updateSound ({ commit, state }, sound) { + commit('changeLoading', true) + const newSound = Object.assign({}, state.general.sound, sound) + const newGeneral = Object.assign({}, state.general, { + sound: newSound + }) + const config = { + general: newGeneral + } + ipcRenderer.send('save-preferences', config) + ipcRenderer.once('error-save-preferences', (event, err) => { + ipcRenderer.removeAllListeners('response-save-preferences') + commit('changeLoading', false) + }) + ipcRenderer.once('response-save-preferences', (event, conf) => { + ipcRenderer.removeAllListeners('error-save-preferences') + commit('updateGeneral', conf.general) + commit('changeLoading', false) + }) + } + } } export default General diff --git a/src/renderer/store/TimelineSpace/Contents/Cards/Toot.js b/src/renderer/store/TimelineSpace/Contents/Cards/Toot.js index 32c0f8e9..452ae3a1 100644 --- a/src/renderer/store/TimelineSpace/Contents/Cards/Toot.js +++ b/src/renderer/store/TimelineSpace/Contents/Cards/Toot.js @@ -20,7 +20,7 @@ const Toot = { // Reblog target status is in the data.reblog. // So I send data.reblog as status for update local timeline. commit('TimelineSpace/updateToot', data.reblog, { root: true }) - ipcRenderer.send('operation-sound01') + ipcRenderer.send('fav-rt-action-sound') resolve(data.reblog) }) }) @@ -51,7 +51,7 @@ const Toot = { client.post(`/statuses/${message.id}/favourite`, {}, (err, data, res) => { if (err) return reject(err) commit('TimelineSpace/updateToot', data, { root: true }) - ipcRenderer.send('operation-sound01') + ipcRenderer.send('fav-rt-action-sound') resolve(data) }) }) diff --git a/src/renderer/store/TimelineSpace/Modals/NewToot.js b/src/renderer/store/TimelineSpace/Modals/NewToot.js index ace6ed27..0b3ca821 100644 --- a/src/renderer/store/TimelineSpace/Modals/NewToot.js +++ b/src/renderer/store/TimelineSpace/Modals/NewToot.js @@ -48,7 +48,7 @@ const NewToot = { ) client.post('/statuses', form, (err, data, res) => { if (err) return reject(err) - ipcRenderer.send('operation-sound02') + ipcRenderer.send('toot-action-sound') resolve(res) }) })