Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ej/zustand store schema #740

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,258 changes: 1,714 additions & 544 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,6 @@
"clone-deep": "^4.0.1",
"clsx": "^1.0.4",
"compare-versions": "^3.6.0",
"conf": "^6.2.4",
"core-js": "^3.3.5",
"d3-dsv": "^1.1.1",
"date-fns": "^2.1.0",
Expand All @@ -114,6 +113,7 @@
"electron-debug": "^1.5.0",
"electron-is-dev": "^2.0.0",
"electron-rabbit": "^1.0.3",
"electron-store": "^8.1.0",
"electron-timber": "^0.5.1",
"electron-updater": "^4.3.9",
"flat": "^5.0.0",
Expand Down Expand Up @@ -185,7 +185,8 @@
"validate-color": "^2.2.1",
"winston": "^3.2.1",
"winston-daily-rotate-file": "^4.4.2",
"yazl": "^2.5.1"
"yazl": "^2.5.1",
"zustand": "^4.3.9"
},
"devDependencies": {
"@babel/cli": "^7.17.10",
Expand Down
2 changes: 1 addition & 1 deletion src/logger.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const DailyRotateFile = require('winston-daily-rotate-file')
const util = require('util')
const { format } = require('date-fns')

const store = require('./store')
const store = require('./persist-store')
const appVersion = require('./build-config').version

let Bugsnag
Expand Down
2 changes: 1 addition & 1 deletion src/main/auto-updater.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const compareVersions = require('compare-versions')
const currentVersion = require('../build-config').version

const networkSpeed = require('./network-speed')
const store = require('../store')
const store = require('../persist-store')
const logger = require('../logger')

// MapeoUpdater emits the 'error' event when there is an internal error with
Expand Down
2 changes: 1 addition & 1 deletion src/main/i18n.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { EventEmitter } = require('events')
const { app } = require('electron')
const logger = require('../logger')
const store = require('../store')
const store = require('../persist-store')

const translations = {
en: require('../../messages/main/en.json'),
Expand Down
16 changes: 14 additions & 2 deletions src/main/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const contextMenu = require('electron-context-menu')
const mkdirp = require('mkdirp')
const Database = require('better-sqlite3')
const createMapServer = require('@mapeo/map-server')
const Store = require('electron-store')

const onExit = require('./exit-hook')
const BackgroundProcessManager = require('./background-process')
Expand Down Expand Up @@ -105,11 +106,19 @@ async function startup ({
const backgroundProcesses = new BackgroundProcessManager()
backgroundProcesses.createProcess(
path.join(__dirname, '../background/mapeo-core'),
{ id: 'mapeoCore', args: mapeoCoreArgs, devTools: debug }
{
id: 'mapeoCore',
args: mapeoCoreArgs,
devTools: debug
}
)
backgroundProcesses.createProcess(
path.join(__dirname, '../background/map-printer'),
{ id: 'mapPrinter', args: mapPrinterArgs, devTools: debug }
{
id: 'mapPrinter',
args: mapPrinterArgs,
devTools: debug
}
)

// Subscribe the main window to background process state changes
Expand All @@ -136,6 +145,9 @@ async function startup ({
const port = event.ports[0]
backgroundProcesses.addClient('mapeoCore', port)
// TODO: Remove client when window reloads? Is this a significant leak?

// Initialise the store so it can be called in the render process
Store.initRenderer()
})

try {
Expand Down
2 changes: 1 addition & 1 deletion src/main/window-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
const remote = require('@electron/remote/main')
const electron = require('electron')

const store = require('../store')
const store = require('../persist-store')

const defaults = {
maximize: false,
Expand Down
71 changes: 71 additions & 0 deletions src/persist-store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const Store = require('electron-store')

const schema = {
'experiments-flags': {
type: 'object',
properties: {
state: {
type: 'object',
properties: {
backgroundMaps: { type: 'boolean' },
storeVersion: { type: 'string' }
}
},
version: { type: 'number' }
}
},
'background-maps': {
type: 'object',
properties: {
state: {
type: 'object',
properties: {
mapStyle: { type: 'string' },
storeVersion: { type: 'string' }
}
},
version: { type: 'number' }
}
},
ui: {
type: 'object',
properties: {
state: {
type: 'object',
properties: {
tabIndex: { type: 'number' }
}
},
version: { type: 'number' }
}
},
state: {
type: 'object',
properties: {
maximize: { type: 'boolean' },
fullscreen: { type: 'boolean' },
defaultWidth: { type: 'number' },
defaultHeight: { type: 'number' },
isMaximized: true,
show: { type: 'boolean' },
x: { type: 'number' },
y: { type: 'number' },
width: { type: 'number' },
height: { type: 'number' },
isFullScreen: { type: 'boolean' },
displayBounds: {
type: 'object',
properties: {
x: { type: 'number' },
y: { type: 'number' },
width: { type: 'number' },
height: { type: 'number' }
}
}
}
}
}

const persistedStore = new Store({ schema })

module.exports = persistedStore
9 changes: 5 additions & 4 deletions src/renderer/components/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@ import ErrorDialog from './dialogs/Error'
import ChangeLanguage from './dialogs/ChangeLanguage'
import TitleBarShim from './TitleBarShim'
import { defineMessages, useIntl } from 'react-intl'
import createPersistedState from '../hooks/createPersistedState'
import SyncView from './SyncView'
import { STATES as updateStates, UpdaterView, UpdateTab } from './UpdaterView'
import useUpdater from './UpdaterView/useUpdater'
import Loading from './Loading'
import buildConfig from '../../build-config'
import { usePersistedUiStore } from '../hooks/store'

const MapFilter = React.lazy(() =>
import(
Expand Down Expand Up @@ -218,12 +218,13 @@ function TabPanel (props) {
) : null
}

const useTabIndex = createPersistedState('currentView')

export default function Home ({ onSelectLanguage }) {
const [dialog, setDialog] = React.useState(null)
const [error, setError] = React.useState(null)
const [tabIndex, setTabIndex] = useTabIndex(0)
const [tabIndex, setTabIndex] = usePersistedUiStore(store => [
store.tabIndex,
store.setTabIndex
])
const [update, setUpdate] = useUpdater()
const { formatMessage: t } = useIntl()

Expand Down
25 changes: 0 additions & 25 deletions src/renderer/hooks/createPersistedState.js

This file was deleted.

101 changes: 101 additions & 0 deletions src/renderer/hooks/store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// @ts-check
import { create } from 'zustand'
import { persist, createJSONStorage } from 'zustand/middleware'
import store from '../../persist-store'

/**
* @type {import('zustand/middleware').StateStorage}
*/
const storage = {
/**
* @param {string} key - A string key to reference the stored item by.
* @returns {string | null}
*/
getItem: key => {
return /** @type {string | null} */ (store.get(key)) || null
},
/**
* @param {string} key - A string key to reference the stored item by.
* @param {string} state - The state to be persisted - stringified JSON.
* @returns {void}
*/
setItem: (key, state) => {
store.set(key, JSON.parse(state))
},
/**
* @param {string} key - A string key to reference the stored item to be removed.
*/
removeItem: key => {
store.delete(key)
}
}

/**
* @template T
* @param {import('zustand').StateCreator<T>} slice
* @param {string} storeName
* @returns {import('zustand').UseBoundStore<import('zustand').StoreApi<T>>}
*/
const createPersistedStore = (slice, storeName) =>
create(
persist(slice, {
name: storeName,
storage: createJSONStorage(() => storage)
})
)

/**
* @typedef {{
* backgroundMaps: boolean,
* setBackgroundMapsFlag: (backgroundMaps:boolean) => void,
* }} ExperimentsFlagsStoreSlice
*/

/**
* @type {import('zustand').StateCreator<ExperimentsFlagsStoreSlice>}
*/
const experimentsFlagsStoreSlice = (set, get) => ({
backgroundMaps: false,
setBackgroundMapsFlag: backgroundMaps => set({ backgroundMaps })
})

/**
* @typedef {{
* mapStyle: string,
* setMapStyle: (mapStyle: string) => void
* }} BackgroundMapStoreSlice
*/
/**
* @type {import('zustand').StateCreator<BackgroundMapStoreSlice>}
*/
const backgroundMapStoreSlice = (set, get) => ({
mapStyle: '',
setMapStyle: mapStyle => set({ mapStyle })
})

/**
* @typedef {{
* tabIndex: number,
* setTabIndex: (tabIndex: number) => void
* }} PersistedUiStoreSlice
*/
/**
* @type {import('zustand').StateCreator<PersistedUiStoreSlice>}
*/
const persistedUiStoreSlice = (set, get) => ({
tabIndex: 0,
setTabIndex: tabIndex => set({ tabIndex })
})

export const useExperimentsFlagsStore = createPersistedStore(
experimentsFlagsStoreSlice,
'experiments-flags'
)
export const useBackgroundMapStore = createPersistedStore(
backgroundMapStoreSlice,
'background-maps'
)
export const usePersistedUiStore = createPersistedStore(
persistedUiStoreSlice,
'ui'
)
9 changes: 0 additions & 9 deletions src/store.js

This file was deleted.

Loading