Skip to content

Commit

Permalink
fix: mark apps agnostic of chain
Browse files Browse the repository at this point in the history
  • Loading branch information
iamacook committed Aug 1, 2023
1 parent 6af5086 commit 35e7917
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 69 deletions.
4 changes: 3 additions & 1 deletion src/components/settings/DataManagement/FileListCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,9 @@ const getItems = ({
items.push(settingsPreview)
}

const hasBookmarkedSafeApps = Object.values(safeApps || {}).some((chainId) => chainId.pinned?.length > 0)
const hasBookmarkedSafeApps = Object.values(safeApps || {}).some(
(value) => !Array.isArray(value) && value.pinned?.length > 0,
)
if (hasBookmarkedSafeApps) {
const safeAppsPreview: ListItemTextProps = {
primary: (
Expand Down
9 changes: 3 additions & 6 deletions src/hooks/safe-apps/useOpenedSafeApps.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useCallback } from 'react'
import type { SafeAppData } from '@safe-global/safe-gateway-typescript-sdk'

import useChainId from '@/hooks/useChainId'
import { useAppDispatch, useAppSelector } from '@/store'
import { selectOpened, markOpened } from '@/store/safeAppsSlice'

Expand All @@ -12,16 +11,14 @@ type ReturnType = {

// Return the ids of Safe Apps previously opened by the user
export const useOpenedSafeApps = (): ReturnType => {
const chainId = useChainId()

const dispatch = useAppDispatch()
const openedSafeAppIds = useAppSelector((state) => selectOpened(state, chainId))
const openedSafeAppIds = useAppSelector(selectOpened)

const markSafeAppOpened = useCallback(
(id: SafeAppData['id']) => {
dispatch(markOpened({ id, chainId }))
dispatch(markOpened({ id }))
},
[dispatch, chainId],
[dispatch],
)

return { openedSafeAppIds, markSafeAppOpened }
Expand Down
66 changes: 23 additions & 43 deletions src/store/__tests__/safeAppsSlice.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('safeAppsSlice', () => {
describe('pinned', () => {
it('sets pinned apps', () => {
// Empty state
const initialState1: SafeAppsState = {}
const initialState1 = {} as unknown as SafeAppsState
const state1 = safeAppsSlice.reducer(
initialState1,
setPinned({
Expand All @@ -20,17 +20,15 @@ describe('safeAppsSlice', () => {
expect(state1).toStrictEqual({
['1']: {
pinned: [safeAppId1],
opened: [],
},
})

// State if only pinned existed
const initialState2: SafeAppsState = {
// @ts-ignore
const initialState2 = {
'5': {
pinned: [safeAppId1, safeAppId2],
},
}
} as unknown as SafeAppsState
const state2 = safeAppsSlice.reducer(
initialState2,
setPinned({
Expand All @@ -45,12 +43,9 @@ describe('safeAppsSlice', () => {
})

// State if only opened existed
const initialState3: SafeAppsState = {
// @ts-ignore
'100': {
opened: [safeAppId1, safeAppId2],
},
}
const initialState3 = {
opened: [safeAppId1, safeAppId2],
} as unknown as SafeAppsState
const state3 = safeAppsSlice.reducer(
initialState3,
setPinned({
Expand All @@ -61,20 +56,19 @@ describe('safeAppsSlice', () => {
expect(state3).toStrictEqual({
['100']: {
pinned: [safeAppId1, safeAppId2, safeAppId3],
opened: [safeAppId1, safeAppId2],
},
opened: [safeAppId1, safeAppId2],
})
})

it('should not pin duplicates', () => {
// Existing state
const initialState: SafeAppsState = {
// @ts-ignore
const initialState = {
'5': {
pinned: [safeAppId1, safeAppId2],
opened: [],
},
}
opened: [],
} as unknown as SafeAppsState
const state = safeAppsSlice.reducer(
initialState,
setPinned({
Expand All @@ -85,93 +79,79 @@ describe('safeAppsSlice', () => {
expect(state).toStrictEqual({
['5']: {
pinned: [safeAppId1, safeAppId2],
opened: [],
},
opened: [],
})
})
})

describe('opened', () => {
it('marks an app open', () => {
// Empty state
const initialState1: SafeAppsState = {}
const initialState1 = {} as unknown as SafeAppsState
const state1 = safeAppsSlice.reducer(
initialState1,
markOpened({
chainId: '1',
id: safeAppId1,
}),
)
expect(state1).toStrictEqual({
['1']: {
pinned: [],
opened: [safeAppId1],
},
opened: [safeAppId1],
})

// State if only pinned existed
const initialState2: SafeAppsState = {
// @ts-ignore
const initialState2 = {
'5': {
pinned: [safeAppId1, safeAppId2],
},
}
} as unknown as SafeAppsState
const state2 = safeAppsSlice.reducer(
initialState2,
markOpened({
chainId: '5',
id: safeAppId2,
}),
)
expect(state2).toStrictEqual({
['5']: {
pinned: [safeAppId1, safeAppId2],
opened: [safeAppId2],
},
opened: [safeAppId2],
})

// State if only opened existed
const initialState3: SafeAppsState = {
// @ts-ignore
'100': {
opened: [safeAppId1, safeAppId2],
},
}
const initialState3 = {
opened: [safeAppId1, safeAppId2],
} as unknown as SafeAppsState
const state3 = safeAppsSlice.reducer(
initialState3,
markOpened({
chainId: '100',
id: safeAppId3,
}),
)
expect(state3).toStrictEqual({
['100']: {
opened: [safeAppId1, safeAppId2, safeAppId3],
},
opened: [safeAppId1, safeAppId2, safeAppId3],
})
})

it('should not mark duplicates open', () => {
// Existing state
const initialState: SafeAppsState = {
// @ts-ignore
'5': {
pinned: [safeAppId1, safeAppId2],
opened: [],
},
}
opened: [],
} as unknown as SafeAppsState
const state = safeAppsSlice.reducer(
initialState,
markOpened({
chainId: '5',
id: safeAppId2,
}),
)
expect(state).toStrictEqual({
['5']: {
pinned: [safeAppId1, safeAppId2],
opened: [safeAppId2],
},
opened: [safeAppId2],
})
})
})
Expand Down
31 changes: 12 additions & 19 deletions src/store/safeAppsSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,32 @@ import type { RootState } from '@/store'

type SafeAppsPerChain = {
pinned: Array<SafeAppData['id']>
opened: Array<SafeAppData['id']>
}

export type SafeAppsState = {
[chainId: string]: SafeAppsPerChain
}
} & { opened: Array<SafeAppData['id']> }

const initialState: SafeAppsState = {}
const initialState = {
opened: [],
} as unknown as SafeAppsState

export const safeAppsSlice = createSlice({
name: 'safeApps',
initialState,
reducers: {
setPinned: (state, { payload }: PayloadAction<{ chainId: string; pinned: SafeAppsPerChain['pinned'] }>) => {
const { pinned, chainId } = payload

// Initialise chain-specific state
state[chainId] ??= { pinned: [], opened: [] }
// If apps were opened before any were pinned, no pinned array exists
state[chainId].pinned ??= []
state[chainId] ??= { pinned: [] }

state[chainId].pinned = pinned
},
markOpened: (state, { payload }: PayloadAction<{ chainId: string; id: SafeAppData['id'] }>) => {
const { id, chainId } = payload

// Initialise chain-specific state
state[chainId] ??= { pinned: [], opened: [] }
// If apps were pinned before any were opened, no opened array exists
state[chainId].opened ??= []
markOpened: (state, { payload }: PayloadAction<{ id: SafeAppData['id'] }>) => {
const { id } = payload
state.opened ??= []

if (!state[chainId].opened.includes(id)) {
state[chainId].opened.push(id)
if (!state.opened.includes(id)) {
state.opened.push(id)
}
},
setSafeApps: (_, { payload }: PayloadAction<SafeAppsState>) => {
Expand All @@ -65,6 +58,6 @@ export const selectPinned = createSelector([selectSafeAppsPerChain], (safeAppsPe
return safeAppsPerChain?.pinned || []
})

export const selectOpened = createSelector([selectSafeAppsPerChain], (safeAppsPerChain) => {
return safeAppsPerChain?.opened || []
export const selectOpened = createSelector([selectSafeApps], (safeApps) => {
return safeApps?.opened || []
})

0 comments on commit 35e7917

Please sign in to comment.