Skip to content

Commit

Permalink
feat: Safe App info button (#1726)
Browse files Browse the repository at this point in the history
* feat: Safe App info button

* fix: return type

* fix: mark apps agnostic of chain

* Revert "fix: mark apps agnostic of chain"

This reverts commit 35e7917.
  • Loading branch information
iamacook authored Aug 2, 2023
1 parent e78930a commit 2658166
Show file tree
Hide file tree
Showing 8 changed files with 294 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const SafeAppsDashboardSection = () => {
onBookmarkSafeApp={togglePin}
isBookmarked={pinnedSafeAppIds.has(rankedSafeApp.id)}
onClickSafeApp={() => openPreviewDrawer(rankedSafeApp)}
openPreviewDrawer={openPreviewDrawer}
/>
</Grid>
))}
Expand Down
17 changes: 17 additions & 0 deletions src/components/safe-apps/SafeAppActionButtons/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,22 @@ import ShareIcon from '@/public/images/common/share.svg'
import BookmarkIcon from '@/public/images/apps/bookmark.svg'
import BookmarkedIcon from '@/public/images/apps/bookmarked.svg'
import DeleteIcon from '@/public/images/common/delete.svg'
import InfoIcon from '@/public/images/notifications/info.svg'

type SafeAppActionButtonsProps = {
safeApp: SafeAppData
isBookmarked?: boolean
onBookmarkSafeApp?: (safeAppId: number) => void
removeCustomApp?: (safeApp: SafeAppData) => void
openPreviewDrawer?: (safeApp: SafeAppData) => void
}

const SafeAppActionButtons = ({
safeApp,
isBookmarked,
onBookmarkSafeApp,
removeCustomApp,
openPreviewDrawer,
}: SafeAppActionButtonsProps) => {
const isCustomApp = safeApp.id < 1
const shareSafeAppUrl = useShareSafeAppUrl(safeApp.url)
Expand All @@ -35,6 +38,20 @@ const SafeAppActionButtons = ({

return (
<Box display="flex" gap={1}>
{/* Open the preview drawer */}
{openPreviewDrawer && (
<IconButton
size="small"
onClick={(event) => {
event.preventDefault()
event.stopPropagation()
openPreviewDrawer(safeApp)
}}
>
<SvgIcon component={InfoIcon} inheritViewBox color="border" fontSize="small" />
</IconButton>
)}

{/* Copy share Safe App url button */}
<CopyButton
initialToolTipText={`Copy share URL for ${safeApp.name}`}
Expand Down
22 changes: 18 additions & 4 deletions src/components/safe-apps/SafeAppCard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import SafeAppTags from '@/components/safe-apps/SafeAppTags'
import { isOptimizedForBatchTransactions } from '@/components/safe-apps/utils'
import { AppRoutes } from '@/config/routes'
import BatchIcon from '@/public/images/apps/batch-icon.svg'
import { useOpenedSafeApps } from '@/hooks/safe-apps/useOpenedSafeApps'
import css from './styles.module.css'

export type SafeAppsViewMode = 'list-view' | 'grid-view'
Expand All @@ -33,6 +34,7 @@ type SafeAppCardProps = {
isBookmarked?: boolean
onBookmarkSafeApp?: (safeAppId: number) => void
removeCustomApp?: (safeApp: SafeAppData) => void
openPreviewDrawer?: (safeApp: SafeAppData) => void
}

const SafeAppCard = ({
Expand All @@ -42,6 +44,7 @@ const SafeAppCard = ({
isBookmarked,
onBookmarkSafeApp,
removeCustomApp,
openPreviewDrawer,
}: SafeAppCardProps) => {
const router = useRouter()

Expand All @@ -58,6 +61,7 @@ const SafeAppCard = ({
onBookmarkSafeApp={onBookmarkSafeApp}
removeCustomApp={removeCustomApp}
onClickSafeApp={onClickSafeApp}
openPreviewDrawer={openPreviewDrawer}
/>
)
}
Expand All @@ -71,6 +75,7 @@ const SafeAppCard = ({
onBookmarkSafeApp={onBookmarkSafeApp}
removeCustomApp={removeCustomApp}
onClickSafeApp={onClickSafeApp}
openPreviewDrawer={openPreviewDrawer}
/>
)
}
Expand All @@ -93,6 +98,7 @@ type SafeAppCardViewProps = {
isBookmarked?: boolean
onBookmarkSafeApp?: (safeAppId: number) => void
removeCustomApp?: (safeApp: SafeAppData) => void
openPreviewDrawer?: (safeApp: SafeAppData) => void
}

const SafeAppCardGridView = ({
Expand All @@ -102,9 +108,10 @@ const SafeAppCardGridView = ({
isBookmarked,
onBookmarkSafeApp,
removeCustomApp,
openPreviewDrawer,
}: SafeAppCardViewProps) => {
return (
<SafeAppCardContainer safeAppUrl={safeAppUrl} onClickSafeApp={onClickSafeApp} height={'100%'}>
<SafeAppCardContainer safeApp={safeApp} safeAppUrl={safeAppUrl} onClickSafeApp={onClickSafeApp} height={'100%'}>
{/* Safe App Header */}
<CardHeader
className={css.safeAppHeader}
Expand All @@ -127,6 +134,7 @@ const SafeAppCardGridView = ({
isBookmarked={isBookmarked}
onBookmarkSafeApp={onBookmarkSafeApp}
removeCustomApp={removeCustomApp}
openPreviewDrawer={openPreviewDrawer}
/>
</>
}
Expand Down Expand Up @@ -157,9 +165,10 @@ const SafeAppCardListView = ({
isBookmarked,
onBookmarkSafeApp,
removeCustomApp,
openPreviewDrawer,
}: SafeAppCardViewProps) => {
return (
<SafeAppCardContainer safeAppUrl={safeAppUrl} onClickSafeApp={onClickSafeApp}>
<SafeAppCardContainer safeApp={safeApp} safeAppUrl={safeAppUrl} onClickSafeApp={onClickSafeApp}>
<CardContent sx={{ pb: '16px !important' }}>
<Box display="flex" flexDirection="row" alignItems="center" gap={2}>
<div className={css.safeAppIconContainer}>
Expand All @@ -184,6 +193,7 @@ const SafeAppCardListView = ({
isBookmarked={isBookmarked}
onBookmarkSafeApp={onBookmarkSafeApp}
removeCustomApp={removeCustomApp}
openPreviewDrawer={openPreviewDrawer}
/>
</CardActions>
</Box>
Expand All @@ -194,6 +204,7 @@ const SafeAppCardListView = ({

type SafeAppCardContainerProps = {
onClickSafeApp?: () => void
safeApp?: SafeAppData
safeAppUrl: string
children: ReactNode
height?: string
Expand All @@ -202,15 +213,18 @@ type SafeAppCardContainerProps = {

export const SafeAppCardContainer = ({
children,
safeApp,
safeAppUrl,
onClickSafeApp,
height,
className,
}: SafeAppCardContainerProps) => {
const { openedSafeAppIds } = useOpenedSafeApps()

const handleClickSafeApp = (event: SyntheticEvent) => {
if (onClickSafeApp) {
if (safeApp && !openedSafeAppIds.includes(safeApp.id)) {
event.preventDefault()
onClickSafeApp()
onClickSafeApp?.()
}
}

Expand Down
1 change: 1 addition & 0 deletions src/components/safe-apps/SafeAppList/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ const SafeAppList = ({
onBookmarkSafeApp={onBookmarkSafeApp}
removeCustomApp={removeCustomApp}
onClickSafeApp={handleSafeAppClick(safeApp)}
openPreviewDrawer={openPreviewDrawer}
/>
</li>
))}
Expand Down
18 changes: 17 additions & 1 deletion src/components/safe-apps/SafeAppPreviewDrawer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import SafeAppActionButtons from '@/components/safe-apps/SafeAppActionButtons'
import SafeAppTags from '@/components/safe-apps/SafeAppTags'
import SafeAppSocialLinksCard from '@/components/safe-apps/SafeAppSocialLinksCard'
import CloseIcon from '@/public/images/common/close.svg'
import { useOpenedSafeApps } from '@/hooks/safe-apps/useOpenedSafeApps'
import css from './styles.module.css'

type SafeAppPreviewDrawerProps = {
Expand All @@ -27,9 +28,16 @@ type SafeAppPreviewDrawerProps = {
}

const SafeAppPreviewDrawer = ({ isOpen, safeApp, isBookmarked, onClose, onBookmark }: SafeAppPreviewDrawerProps) => {
const { markSafeAppOpened } = useOpenedSafeApps()
const router = useRouter()
const safeAppUrl = getSafeAppUrl(router, safeApp?.url || '')

const onOpenSafe = () => {
if (safeApp) {
markSafeAppOpened(safeApp.id)
}
}

return (
<Drawer anchor="right" open={isOpen} onClose={onClose}>
<Box className={css.drawerContainer}>
Expand Down Expand Up @@ -82,7 +90,15 @@ const SafeAppPreviewDrawer = ({ isOpen, safeApp, isBookmarked, onClose, onBookma

{/* Open Safe App button */}
<Link href={safeAppUrl} passHref>
<Button fullWidth variant="contained" color="primary" component={'a'} href={safeApp?.url} sx={{ mt: 3 }}>
<Button
fullWidth
variant="contained"
color="primary"
component="a"
href={safeApp?.url}
sx={{ mt: 3 }}
onClick={onOpenSafe}
>
Open Safe App
</Button>
</Link>
Expand Down
28 changes: 28 additions & 0 deletions src/hooks/safe-apps/useOpenedSafeApps.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
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'

type ReturnType = {
openedSafeAppIds: Array<SafeAppData['id']>
markSafeAppOpened: (id: SafeAppData['id']) => void
}

// 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 markSafeAppOpened = useCallback(
(id: SafeAppData['id']) => {
dispatch(markOpened({ id, chainId }))
},
[dispatch, chainId],
)

return { openedSafeAppIds, markSafeAppOpened }
}
Loading

0 comments on commit 2658166

Please sign in to comment.