Allow to remove a Safe-app added manually (#1260)
* partial imp * Delete safe apps added manually * Fix and review changes * remove unnecesary exports * Fix deleteApp and sort in modal list
This commit is contained in:
parent
50995c3f0c
commit
4dc28942c0
|
@ -164,7 +164,7 @@
|
|||
"dependencies": {
|
||||
"@gnosis.pm/safe-apps-sdk": "0.3.1",
|
||||
"@gnosis.pm/safe-contracts": "1.1.1-dev.2",
|
||||
"@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#45c746a12661b9c38e839e76022b6a0a92285db7",
|
||||
"@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#fd4498f",
|
||||
"@gnosis.pm/util-contracts": "2.0.6",
|
||||
"@ledgerhq/hw-transport-node-hid": "5.19.1",
|
||||
"@material-ui/core": "4.11.0",
|
||||
|
|
|
@ -71,6 +71,7 @@ const AddApp = ({ appList, closeModal, formId, onAppAdded, setIsSubmitDisabled }
|
|||
<StyledText size="xl">Add custom app</StyledText>
|
||||
|
||||
<AppUrl appList={appList} />
|
||||
{/* Fetch app from url and return a SafeApp */}
|
||||
<AppInfoUpdater onAppInfo={setAppInfo} />
|
||||
|
||||
<AppInfo>
|
||||
|
|
|
@ -11,9 +11,10 @@ type Props = {
|
|||
appList: Array<SafeApp>
|
||||
onAppAdded: (app: SafeApp) => void
|
||||
onAppToggle: (appId: string, enabled: boolean) => void
|
||||
onAppRemoved: (appId: string) => void
|
||||
}
|
||||
|
||||
const ManageApps = ({ appList, onAppAdded, onAppToggle }: Props): React.ReactElement => {
|
||||
const ManageApps = ({ appList, onAppAdded, onAppToggle, onAppRemoved }: Props): React.ReactElement => {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [isSubmitDisabled, setIsSubmitDisabled] = useState(true)
|
||||
|
||||
|
@ -54,12 +55,14 @@ const ManageApps = ({ appList, onAppAdded, onAppToggle }: Props): React.ReactEle
|
|||
{isOpen && (
|
||||
<ManageListModal
|
||||
addButtonLabel="Add custom app"
|
||||
showDeleteButton
|
||||
defaultIconUrl={appsIconSvg}
|
||||
formBody={Form}
|
||||
isSubmitFormDisabled={isSubmitDisabled}
|
||||
itemList={getItemList()}
|
||||
onClose={closeModal}
|
||||
onItemToggle={onItemToggle}
|
||||
onItemDeleted={onAppRemoved}
|
||||
onSubmitForm={onSubmitForm}
|
||||
/>
|
||||
)}
|
||||
|
|
|
@ -7,12 +7,14 @@ const APPS_STORAGE_KEY = 'APPS_STORAGE_KEY'
|
|||
|
||||
type onAppToggleHandler = (appId: string, enabled: boolean) => Promise<void>
|
||||
type onAppAddedHandler = (app: SafeApp) => void
|
||||
type onAppRemovedHandler = (appId: string) => void
|
||||
|
||||
type UseAppListReturnType = {
|
||||
appList: SafeApp[]
|
||||
loadingAppList: boolean
|
||||
onAppToggle: onAppToggleHandler
|
||||
onAppAdded: onAppAddedHandler
|
||||
onAppRemoved: onAppRemovedHandler
|
||||
}
|
||||
|
||||
const useAppList = (): UseAppListReturnType => {
|
||||
|
@ -26,32 +28,40 @@ const useAppList = (): UseAppListReturnType => {
|
|||
// * third-party apps added by the user
|
||||
// * disabled status for both static and third-party apps
|
||||
const persistedAppList = (await loadFromStorage<StoredSafeApp[]>(APPS_STORAGE_KEY)) || []
|
||||
const list = [...persistedAppList]
|
||||
const list: (StoredSafeApp & { isDeletable?: boolean })[] = persistedAppList.map((a) => ({
|
||||
...a,
|
||||
isDeletable: true,
|
||||
}))
|
||||
|
||||
staticAppsList.forEach((staticApp) => {
|
||||
if (!list.some((persistedApp) => persistedApp.url === staticApp.url)) {
|
||||
list.push(staticApp)
|
||||
const app = list.find((persistedApp) => persistedApp.url === staticApp.url)
|
||||
if (!app) {
|
||||
list.push({ ...staticApp, isDeletable: false })
|
||||
} else {
|
||||
app.isDeletable = false
|
||||
}
|
||||
})
|
||||
|
||||
const apps = []
|
||||
let apps = []
|
||||
// using the appURL to recover app info
|
||||
for (let index = 0; index < list.length; index++) {
|
||||
try {
|
||||
const currentApp = list[index]
|
||||
|
||||
const appInfo: any = await getAppInfoFromUrl(currentApp.url)
|
||||
const appInfo: SafeApp = await getAppInfoFromUrl(currentApp.url)
|
||||
if (appInfo.error) {
|
||||
throw Error(`There was a problem trying to load app ${currentApp.url}`)
|
||||
}
|
||||
|
||||
appInfo.disabled = currentApp.disabled === undefined ? false : currentApp.disabled
|
||||
appInfo.disabled = Boolean(currentApp.disabled)
|
||||
appInfo.isDeletable = Boolean(currentApp.isDeletable) === undefined ? true : currentApp.isDeletable
|
||||
|
||||
apps.push(appInfo)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
}
|
||||
apps = apps.sort((a, b) => a.name.localeCompare(b.name))
|
||||
|
||||
setAppList(apps)
|
||||
setLoadingAppList(false)
|
||||
|
@ -69,8 +79,8 @@ const useAppList = (): UseAppListReturnType => {
|
|||
if (!app) {
|
||||
return
|
||||
}
|
||||
|
||||
app.disabled = !enabled
|
||||
|
||||
setAppList(appListCopy)
|
||||
|
||||
// update storage list
|
||||
|
@ -91,7 +101,19 @@ const useAppList = (): UseAppListReturnType => {
|
|||
]
|
||||
saveToStorage(APPS_STORAGE_KEY, newAppList)
|
||||
|
||||
setAppList([...appList, { ...app, disabled: false }])
|
||||
setAppList([...appList, { ...app, isDeletable: true }])
|
||||
},
|
||||
[appList],
|
||||
)
|
||||
|
||||
const onAppRemoved: onAppRemovedHandler = useCallback(
|
||||
(appId) => {
|
||||
const appListCopy = appList.filter((a) => a.id !== appId)
|
||||
|
||||
setAppList(appListCopy)
|
||||
|
||||
const listToPersist: StoredSafeApp[] = appListCopy.map(({ url, disabled }) => ({ url, disabled }))
|
||||
saveToStorage(APPS_STORAGE_KEY, listToPersist)
|
||||
},
|
||||
[appList],
|
||||
)
|
||||
|
@ -101,6 +123,7 @@ const useAppList = (): UseAppListReturnType => {
|
|||
loadingAppList,
|
||||
onAppToggle,
|
||||
onAppAdded,
|
||||
onAppRemoved,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ type AppsProps = {
|
|||
}
|
||||
|
||||
const Apps = ({ closeModal, openModal }: AppsProps): React.ReactElement => {
|
||||
const { appList, loadingAppList, onAppToggle, onAppAdded } = useAppList()
|
||||
const { appList, loadingAppList, onAppToggle, onAppAdded, onAppRemoved } = useAppList()
|
||||
|
||||
const [appIsLoading, setAppIsLoading] = useState<boolean>(true)
|
||||
const [selectedAppId, setSelectedAppId] = useState<string>()
|
||||
|
@ -111,7 +111,7 @@ const Apps = ({ closeModal, openModal }: AppsProps): React.ReactElement => {
|
|||
return (
|
||||
<>
|
||||
<Menu>
|
||||
<ManageApps appList={appList} onAppAdded={onAppAdded} onAppToggle={onAppToggle} />
|
||||
<ManageApps appList={appList} onAppAdded={onAppAdded} onAppToggle={onAppToggle} onAppRemoved={onAppRemoved} />
|
||||
</Menu>
|
||||
{enabledApps.length ? (
|
||||
<LCL.Wrapper>
|
||||
|
|
|
@ -4,6 +4,7 @@ export type SafeApp = {
|
|||
name: string
|
||||
iconUrl: string
|
||||
disabled?: boolean
|
||||
isDeletable?: boolean
|
||||
error: boolean
|
||||
description: string
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue