From 8a6c86bf656c0829168f954bdc81ab125cae96f7 Mon Sep 17 00:00:00 2001 From: Kelvin Wong Date: Thu, 28 Jun 2018 13:08:39 +0800 Subject: [PATCH 1/2] Add collapsed state for storage The root cause of this issue is that when the folder is clicked, the router pushed the path and the StorageItem component has been refreshed and isOpen has been reset - Add storing collapse state for storage - Add tests - Default as collapsed for fallback fix BoostIo/Boostnote#1979 BoostIo/Boostnote#1911 --- browser/main/SideNav/StorageItem.js | 16 +++++++- browser/main/lib/dataApi/addStorage.js | 6 ++- browser/main/lib/dataApi/index.js | 1 + .../main/lib/dataApi/resolveStorageData.js | 3 +- browser/main/lib/dataApi/toggleStorage.js | 28 ++++++++++++++ browser/main/store.js | 6 +++ tests/dataApi/toggleStorage-test.js | 38 +++++++++++++++++++ 7 files changed, 93 insertions(+), 5 deletions(-) create mode 100644 browser/main/lib/dataApi/toggleStorage.js create mode 100644 tests/dataApi/toggleStorage-test.js diff --git a/browser/main/SideNav/StorageItem.js b/browser/main/SideNav/StorageItem.js index 93e9157f..1c4b4d15 100644 --- a/browser/main/SideNav/StorageItem.js +++ b/browser/main/SideNav/StorageItem.js @@ -21,8 +21,10 @@ class StorageItem extends React.Component { constructor (props) { super(props) + const { storage } = this.props + this.state = { - isOpen: true + isOpen: !!storage.isOpen } } @@ -68,8 +70,18 @@ class StorageItem extends React.Component { } handleToggleButtonClick (e) { + const { storage, dispatch } = this.props + const isOpen = !this.state.isOpen + dataApi.toggleStorage(storage.key, isOpen) + .then((storage) => { + dispatch({ + type: 'EXPAND_STORAGE', + storage: storage, + isOpen: isOpen + }) + }) this.setState({ - isOpen: !this.state.isOpen + isOpen: isOpen }) } diff --git a/browser/main/lib/dataApi/addStorage.js b/browser/main/lib/dataApi/addStorage.js index 630c0bd3..bfd6698a 100644 --- a/browser/main/lib/dataApi/addStorage.js +++ b/browser/main/lib/dataApi/addStorage.js @@ -37,7 +37,8 @@ function addStorage (input) { key, name: input.name, type: input.type, - path: input.path + path: input.path, + isOpen: false } return Promise.resolve(newStorage) @@ -48,7 +49,8 @@ function addStorage (input) { key: newStorage.key, type: newStorage.type, name: newStorage.name, - path: newStorage.path + path: newStorage.path, + isOpen: false }) localStorage.setItem('storages', JSON.stringify(rawStorages)) diff --git a/browser/main/lib/dataApi/index.js b/browser/main/lib/dataApi/index.js index 7c57e016..4e2f0061 100644 --- a/browser/main/lib/dataApi/index.js +++ b/browser/main/lib/dataApi/index.js @@ -1,5 +1,6 @@ const dataApi = { init: require('./init'), + toggleStorage: require('./toggleStorage'), addStorage: require('./addStorage'), renameStorage: require('./renameStorage'), removeStorage: require('./removeStorage'), diff --git a/browser/main/lib/dataApi/resolveStorageData.js b/browser/main/lib/dataApi/resolveStorageData.js index af040c5d..681a102e 100644 --- a/browser/main/lib/dataApi/resolveStorageData.js +++ b/browser/main/lib/dataApi/resolveStorageData.js @@ -8,7 +8,8 @@ function resolveStorageData (storageCache) { key: storageCache.key, name: storageCache.name, type: storageCache.type, - path: storageCache.path + path: storageCache.path, + isOpen: storageCache.isOpen } const boostnoteJSONPath = path.join(storageCache.path, 'boostnote.json') diff --git a/browser/main/lib/dataApi/toggleStorage.js b/browser/main/lib/dataApi/toggleStorage.js new file mode 100644 index 00000000..dbb625c3 --- /dev/null +++ b/browser/main/lib/dataApi/toggleStorage.js @@ -0,0 +1,28 @@ +const _ = require('lodash') +const resolveStorageData = require('./resolveStorageData') + +/** + * @param {String} key + * @param {Boolean} isOpen + * @return {Object} Storage meta data + */ +function toggleStorage (key, isOpen) { + let cachedStorageList + try { + cachedStorageList = JSON.parse(localStorage.getItem('storages')) + if (!_.isArray(cachedStorageList)) throw new Error('invalid storages') + } catch (err) { + console.log('error got') + console.error(err) + return Promise.reject(err) + } + const targetStorage = _.find(cachedStorageList, {key: key}) + if (targetStorage == null) return Promise.reject('Storage') + + targetStorage.isOpen = isOpen + localStorage.setItem('storages', JSON.stringify(cachedStorageList)) + + return resolveStorageData(targetStorage) +} + +module.exports = toggleStorage diff --git a/browser/main/store.js b/browser/main/store.js index 7ea6decb..a1b6b791 100644 --- a/browser/main/store.js +++ b/browser/main/store.js @@ -360,6 +360,12 @@ function data (state = defaultDataMap(), action) { state.storageMap = new Map(state.storageMap) state.storageMap.set(action.storage.key, action.storage) return state + case 'EXPAND_STORAGE': + state = Object.assign({}, state) + state.storageMap = new Map(state.storageMap) + action.storage.isOpen = action.isOpen + state.storageMap.set(action.storage.key, action.storage) + return state } return state } diff --git a/tests/dataApi/toggleStorage-test.js b/tests/dataApi/toggleStorage-test.js new file mode 100644 index 00000000..5169a4f4 --- /dev/null +++ b/tests/dataApi/toggleStorage-test.js @@ -0,0 +1,38 @@ +const test = require('ava') +const toggleStorage = require('browser/main/lib/dataApi/toggleStorage') + +global.document = require('jsdom').jsdom('') +global.window = document.defaultView +global.navigator = window.navigator + +const Storage = require('dom-storage') +const localStorage = window.localStorage = global.localStorage = new Storage(null, { strict: true }) +const path = require('path') +const _ = require('lodash') +const TestDummy = require('../fixtures/TestDummy') +const sander = require('sander') +const os = require('os') + +const storagePath = path.join(os.tmpdir(), 'test/toggle-storage') + +test.beforeEach((t) => { + t.context.storage = TestDummy.dummyStorage(storagePath) + localStorage.setItem('storages', JSON.stringify([t.context.storage.cache])) +}) + +test.serial('Toggle a storage location', (t) => { + const storageKey = t.context.storage.cache.key + return Promise.resolve() + .then(function doTest () { + return toggleStorage(storageKey, true) + }) + .then(function assert (data) { + const cachedStorageList = JSON.parse(localStorage.getItem('storages')) + t.true(_.find(cachedStorageList, {key: storageKey}).isOpen === true) + }) +}) + +test.after(function after () { + localStorage.clear() + sander.rimrafSync(storagePath) +}) From ddd339851b4a418d08c7bdd626ea3af9984f790f Mon Sep 17 00:00:00 2001 From: Kelvin Wong Date: Fri, 29 Jun 2018 10:58:11 +0800 Subject: [PATCH 2/2] Fix code style --- browser/main/SideNav/StorageItem.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/browser/main/SideNav/StorageItem.js b/browser/main/SideNav/StorageItem.js index 1c4b4d15..8cb0e510 100644 --- a/browser/main/SideNav/StorageItem.js +++ b/browser/main/SideNav/StorageItem.js @@ -76,8 +76,8 @@ class StorageItem extends React.Component { .then((storage) => { dispatch({ type: 'EXPAND_STORAGE', - storage: storage, - isOpen: isOpen + storage, + isOpen }) }) this.setState({