Skip to content

Commit

Permalink
feat(Calendar): mf-6373 new events list (#11934)
Browse files Browse the repository at this point in the history
* fix: hooks

* feat(Calendar): mf-6373 new events list

* fix: mf-6147 adjust calendar tab header for dark mode

* fixup! feat(Calendar): mf-6373 new events list

* fix: prettier

---------

Co-authored-by: swkatmask <swkatmask@users.noreply.github.com>
  • Loading branch information
swkatmask and swkatmask authored Nov 19, 2024
1 parent 0016e61 commit 7ff417f
Show file tree
Hide file tree
Showing 21 changed files with 518 additions and 309 deletions.
3 changes: 1 addition & 2 deletions cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,5 @@
],
"ignoreRegExpList": ["/[A-Za-z0-9]{44}/", "/[A-Za-z0-9]{46}/", "/[A-Za-z0-9]{59}/"],
"overrides": [],
"words": ["endregion"]
"words": ["endregion", "linkedin", "Luma", "tiktok", "waitlist", "youtube"]
}

Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export function ProfileCardTitle({
disablePortal
anchorPosition={{
top: 50,
left: itsMe ? 390 : 370,
left: itsMe ? 490 : 470,
}}
anchorReference="anchorPosition"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,14 @@ export function SearchResultInspector(props: SearchResultInspectorProps) {
const keyword = props.keyword || keyword_
const activatedPlugins = useActivatedPluginsSiteAdaptorNotMinimal()

const resultList = useAsyncRetry(async () => {
const { value: resultList } = useAsyncRetry(async () => {
if (!keyword) return
return props.searchResults ?? DSearch.search(keyword)
}, [keyword, props.searchResults])

useEffect(() => {
if (profileTabType || !resultList.value?.length) return
const type = resultList.value[0].type
if (profileTabType || !resultList?.length) return
const type = resultList[0].type
let timer1: NodeJS.Timeout | undefined
let timer2: NodeJS.Timeout | undefined
if (
Expand All @@ -83,31 +83,31 @@ export function SearchResultInspector(props: SearchResultInspectorProps) {
timer1 && clearTimeout(timer1)
timer2 && clearTimeout(timer2)
}
}, [resultList.value, profileTabType])
}, [resultList, profileTabType])

const currentResult = props.currentSearchResult ?? resultList.value?.[0]
const currentResult = props.currentSearchResult ?? resultList?.[0]

const { classes } = useStyles({ isProfilePage, searchType: currentResult?.type })
const contentComponent = useMemo(() => {
if (!currentResult || !resultList.value?.length) return null
if (!currentResult || !resultList?.length) return null

const Component =
profileTabType ? getSearchResultContentForProfileTab(currentResult) : getSearchResultContent(currentResult)

return (
<Component
resultList={resultList.value}
resultList={resultList}
currentResult={currentResult}
isProfilePage={isProfilePage}
identity={identity}
/>
)
}, [currentResult, resultList.value, isProfilePage, identity, profileTabType])
}, [currentResult, resultList, isProfilePage, identity, profileTabType])

const tabs = useMemo(() => {
if (!currentResult) return EMPTY_LIST
return getSearchResultTabs(activatedPlugins, currentResult, translate)
}, [activatedPlugins, resultList.value, translate])
}, [activatedPlugins, resultList, translate])

const defaultTab = first(tabs)?.id ?? PluginID.Collectible
const [currentTab, onChange, , setTab] = useTabs(defaultTab, ...tabs.map((tab) => tab.id))
Expand All @@ -119,7 +119,7 @@ export function SearchResultInspector(props: SearchResultInspectorProps) {
if (!currentResult) return null
const Component = getSearchResultTabContent(currentTab)
return <Component result={currentResult} />
}, [currentTab, resultList.value])
}, [currentTab, resultList])

if (isMinimalMode && !isProfilePage) return null
if (!keyword && !currentResult) return null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { MutationObserverWatcher } from '@dimensiondev/holoflows-kit'
import { querySelector } from '../utils/selector.js'
import { startWatch } from '../../../utils/startWatch.js'
import { Calendar } from '@masknet/plugin-calendar'
import { attachReactTreeWithContainer } from '../../../utils/shadow-root/renderInShadowRoot.js'
import { CalendarContent } from '@masknet/plugin-calendar'
import { startWatch } from '../../../utils/startWatch.js'
import { querySelector } from '../utils/selector.js'

function sidebarSearchSelector() {
return querySelector<HTMLElement>(
Expand All @@ -28,13 +28,11 @@ export function injectCalendar(signal: AbortSignal) {
startWatch(watcher, signal)
startWatch(exploreWatcher, signal)
startWatch(searchWatcher, signal)
attachReactTreeWithContainer(watcher.firstDOMProxy.afterShadow, { untilVisible: true, signal }).render(
<CalendarContent />,
)
attachReactTreeWithContainer(watcher.firstDOMProxy.afterShadow, { untilVisible: true, signal }).render(<Calendar />)
attachReactTreeWithContainer(exploreWatcher.firstDOMProxy.beforeShadow, { untilVisible: true, signal }).render(
<CalendarContent target="/explore" />,
<Calendar target="/explore" />,
)
attachReactTreeWithContainer(searchWatcher.firstDOMProxy.beforeShadow, { untilVisible: true, signal }).render(
<CalendarContent target="/search" />,
<Calendar target="/search" />,
)
}
21 changes: 21 additions & 0 deletions packages/plugins/Calendar/src/SiteAdaptor/Calendar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { useIsMinimalMode } from '@masknet/plugin-infra/content-script'
import { PluginID } from '@masknet/shared-base'
import { useLocationChange } from '@masknet/shared-base-ui'
import { useState } from 'react'
import { CalendarContent } from './CalendarContent.js'

interface Props {
target?: '/explore' | '/search'
}

export function Calendar({ target }: Props) {
const [pathname, setPathname] = useState(location.pathname)
const isMinimalMode = useIsMinimalMode(PluginID.Calendar)

useLocationChange(() => {
setPathname(location.pathname)
})
if (isMinimalMode || (target && !pathname.includes(target))) return null

return <CalendarContent style={{ marginTop: pathname.includes('explore') ? 24 : 0 }} />
}
116 changes: 48 additions & 68 deletions packages/plugins/Calendar/src/SiteAdaptor/CalendarContent.tsx
Original file line number Diff line number Diff line change
@@ -1,98 +1,78 @@
import { safeUnreachable } from '@masknet/kit'
import { useIsMinimalMode } from '@masknet/plugin-infra/content-script'
import { EMPTY_OBJECT, PluginID } from '@masknet/shared-base'
import { useLocationChange } from '@masknet/shared-base-ui'
import { Trans } from '@lingui/macro'
import { EMPTY_LIST } from '@masknet/shared-base'
import { MaskTabList, makeStyles, useTabs } from '@masknet/theme'
import { TabContext, TabPanel } from '@mui/lab'
import { Tab } from '@mui/material'
import { useMemo, useState } from 'react'
import { useNFTList, useNewsList } from '../hooks/useEventList.js'
import { useState, type HTMLProps } from 'react'
import { DatePickerTab } from './components/DatePickerTab.js'
import { EventList } from './components/EventList.js'
import { Footer } from './components/Footer.js'
import { NFTList } from './components/NFTList.js'
import { NewsList } from './components/NewsList.js'
import { Trans } from '@lingui/macro'

const useStyles = makeStyles()((theme) => ({
calendar: {
display: 'flex',
flexDirection: 'column',
borderRadius: '12px',
border: `1px solid ${theme.palette.maskColor.line}`,
position: 'relative',
marginBottom: '20px',
},
tab: {
fontSize: 16,
fontWeight: 700,
},
tabList: {
background:
'linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, rgba(255, 255, 255, 0.80) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.20) 0%, rgba(69, 163, 251, 0.20) 100%), #FFF',
padding: '8px 16px 0 16px',
borderRadius: '12px 12px 0 0',
},
tabPanel: {
padding: '0 4px 0 12px',
},
}))
const useStyles = makeStyles()((theme) => {
const isDark = theme.palette.mode === 'dark'
return {
calendar: {
display: 'flex',
flexDirection: 'column',
borderRadius: '12px',
border: `1px solid ${theme.palette.maskColor.line}`,
position: 'relative',
marginBottom: '20px',
},
tab: {
fontSize: 16,
fontWeight: 700,
},
tabList: {
background:
isDark ?
'linear-gradient(180deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0.06) 100%)'
: 'linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, rgba(255, 255, 255, 0.80) 100%), linear-gradient(90deg, rgba(28, 104, 243, 0.20) 0%, rgba(69, 163, 251, 0.20) 100%), #FFF',
padding: '8px 16px 0 16px',
borderRadius: '12px 12px 0 0',
},
tabPanel: {
padding: '0 4px 0 12px',
},
}
})

interface Props {
interface Props extends HTMLProps<HTMLDivElement> {
target?: string
disableSetting?: boolean
}

export function CalendarContent({ target, disableSetting }: Props) {
const { classes } = useStyles()
const [pathname, setPathname] = useState(location.pathname)
const isMinimalMode = useIsMinimalMode(PluginID.Calendar)
const [currentTab, onChange, tabs] = useTabs('news', 'nfts')
const [selectedDate, setSelectedDate] = useState(() => new Date())
export function CalendarContent(props: Props) {
const { classes, cx } = useStyles()
const [currentTab, onChange, tabs] = useTabs('news', 'events')
const [date, setDate] = useState(() => new Date())
const [open, setOpen] = useState(false)
const { data: newsList = EMPTY_OBJECT, isPending: newsLoading } = useNewsList(selectedDate, currentTab === 'news')
const { data: nftList = EMPTY_OBJECT, isPending: nftLoading } = useNFTList(selectedDate, currentTab === 'nfts')
const list = useMemo(() => {
switch (currentTab) {
case 'news':
return newsList
case 'nfts':
return nftList
default:
safeUnreachable(currentTab)
return null
}
}, [currentTab, newsList, nftList])
const dateString = useMemo(() => selectedDate.toLocaleDateString(), [selectedDate])

useLocationChange(() => {
setPathname(location.pathname)
})
if (isMinimalMode || (target && !pathname.includes(target))) return null
const [allowedDates, setAllowedDates] = useState<string[]>(EMPTY_LIST)

return (
<div className={classes.calendar} style={{ marginTop: pathname.includes('explore') ? 24 : 0 }}>
<div {...props} className={cx(classes.calendar, props.className)}>
<TabContext value={currentTab}>
<div className={classes.tabList}>
<MaskTabList variant="base" onChange={onChange} aria-label="">
<Tab className={classes.tab} label={<Trans>News</Trans>} value={tabs.news} />
<Tab className={classes.tab} label={<Trans>NFTs</Trans>} value={tabs.nfts} />
<Tab className={classes.tab} label={<Trans>Events</Trans>} value={tabs.events} />
</MaskTabList>
</div>
<DatePickerTab
open={open}
setOpen={setOpen}
selectedDate={selectedDate}
setSelectedDate={setSelectedDate}
list={list}
currentTab={currentTab}
onToggle={setOpen}
date={date}
onChange={setDate}
allowedDates={allowedDates}
/>
<TabPanel value={tabs.news} className={classes.tabPanel}>
<NewsList list={newsList} isLoading={newsLoading} dateString={dateString} />
<NewsList date={date} />
</TabPanel>
<TabPanel value={tabs.nfts} className={classes.tabPanel}>
<NFTList list={nftList} isLoading={nftLoading} dateString={dateString} />
<TabPanel value={tabs.events} className={classes.tabPanel}>
<EventList date={date} onDatesUpdate={setAllowedDates} />
</TabPanel>
<Footer provider={currentTab} disableSetting={disableSetting} />
<Footer provider={currentTab} />
</TabContext>
</div>
)
Expand Down
Loading

0 comments on commit 7ff417f

Please sign in to comment.