-
-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
42 changed files
with
234 additions
and
203 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
src/app/storeEnhancer.ts → src/app/store/enhancers/injectExtension.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { merge, type PlainObject } from '@/common/utils' | ||
|
||
import { localStorageProvider } from './providers/localStorage' | ||
import { queryParamProvider } from './providers/queryParam' | ||
import type { PersistenceProvider } from './types' | ||
|
||
export const getCombinedProvider = <State extends PlainObject>(): PersistenceProvider<State> => { | ||
const providers: PersistenceProvider<State>[] = [localStorageProvider, queryParamProvider] | ||
return { | ||
read: () => providers.reduce((result, provider) => merge(result, provider.read()), {}), | ||
write: (state) => providers.forEach((provider) => provider.write(state)), | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
import { createSelector } from '@reduxjs/toolkit' | ||
import type { Test as TypeTest } from 'ts-toolbelt' | ||
|
||
import { merge } from '@/common/utils' | ||
import { controllerSlice } from '@/features/controller/controllerSlice' | ||
import { editorSlice } from '@/features/editor/editorSlice' | ||
|
||
import { getCombinedProvider } from './combinedProvider' | ||
import type { PersistenceProvider } from './types' | ||
|
||
const provider = getCombinedProvider() | ||
|
||
type PreloadedState = { | ||
[editorSlice.reducerPath]: ReturnType<typeof editorSlice.getInitialState> | ||
[controllerSlice.reducerPath]: ReturnType<typeof controllerSlice.getInitialState> | ||
} | ||
|
||
export const readStateFromPersistence = (): PreloadedState => { | ||
const persistedState = provider.read() | ||
// in case of future changes to the state shape | ||
return merge( | ||
{ | ||
[editorSlice.reducerPath]: editorSlice.getInitialState(), | ||
[controllerSlice.reducerPath]: controllerSlice.getInitialState(), | ||
}, | ||
persistedState, | ||
) | ||
} | ||
|
||
export const selectStateToPersist = createSelector( | ||
editorSlice.selectors.selectToPersist, | ||
controllerSlice.selectors.selectToPersist, | ||
(editorState, controllerState) => ({ | ||
[editorSlice.reducerPath]: editorState, | ||
[controllerSlice.reducerPath]: controllerState, | ||
}), | ||
) | ||
|
||
type StateToPersist = ReturnType<typeof selectStateToPersist> | ||
|
||
export const writeStateToPersistence: PersistenceProvider<StateToPersist>['write'] = provider.write | ||
|
||
if (import.meta.env.NEVER) { | ||
const { checkType, checkTypes } = await import('@/common/utils') | ||
checkTypes([ | ||
checkType<keyof PreloadedState, keyof StateToPersist, TypeTest.Pass>(), | ||
checkType<keyof StateToPersist, keyof PreloadedState, TypeTest.Pass>(), | ||
]) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import { name } from '@/../package.json' | ||
import { isPlainObject } from '@/common/utils' | ||
|
||
import type { PersistenceProvider } from '../types' | ||
|
||
const LOCAL_STORAGE_KEY = `persist:${name}` | ||
|
||
export const localStorageProvider: PersistenceProvider = { | ||
read: () => { | ||
try { | ||
const serializedState = localStorage.getItem(LOCAL_STORAGE_KEY) | ||
if (serializedState !== null) { | ||
const state: unknown = JSON.parse(serializedState) | ||
if (isPlainObject(state)) { | ||
return state | ||
} | ||
} | ||
} catch { | ||
// ignore error | ||
} | ||
return {} | ||
}, | ||
write: (state) => { | ||
try { | ||
const serializedState = JSON.stringify(state) | ||
localStorage.setItem(LOCAL_STORAGE_KEY, serializedState) | ||
} catch { | ||
// ignore write error | ||
} | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import * as Base64 from 'js-base64' | ||
import * as Pako from 'pako' | ||
|
||
import { isPlainObject } from '@/common/utils' | ||
|
||
import type { PersistenceProvider } from '../types' | ||
|
||
const QUERY_PARAMETER_NAME = 'shareable' | ||
|
||
const getShareUrl = (state: unknown) => { | ||
const url = new URL(window.location.href) | ||
const compressedData = Pako.deflate(JSON.stringify(state)) | ||
const encodedState = Base64.fromUint8Array(compressedData, /* urlsafe: */ true) | ||
url.searchParams.set(QUERY_PARAMETER_NAME, encodedState) | ||
return url | ||
} | ||
|
||
export const queryParamProvider: PersistenceProvider = { | ||
read: () => { | ||
const url = new URL(window.location.href) | ||
const encodedState = url.searchParams.get(QUERY_PARAMETER_NAME) | ||
if (encodedState !== null) { | ||
try { | ||
const compressedData = Base64.toUint8Array(encodedState) | ||
const decodedState = Pako.inflate(compressedData, { to: 'string' }) | ||
const state: unknown = JSON.parse(decodedState) | ||
if (isPlainObject(state)) { | ||
return state | ||
} | ||
} catch { | ||
// ignore error | ||
} | ||
} | ||
return {} | ||
}, | ||
write: (state) => { | ||
const shareUrl = getShareUrl(state) | ||
window.history.replaceState({}, '', shareUrl) | ||
}, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import type { PlainObject } from '@/common/utils' | ||
|
||
type Persisted<State> = State | Record<string, never> | ||
|
||
export interface PersistenceProvider<State extends PlainObject = PlainObject> { | ||
read: () => Persisted<State> | ||
write: (state: State) => void | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.