diff --git a/src/components/CalendarEventContent/index.tsx b/src/components/CalendarEventContent/index.tsx index 91226966..050d9564 100644 --- a/src/components/CalendarEventContent/index.tsx +++ b/src/components/CalendarEventContent/index.tsx @@ -10,12 +10,13 @@ import { useFetchCalendarRsvps } from '@/hooks/useFetchCalendarRsvps' import { useNostr } from '@/providers/NostrProvider' import { toProfile } from '@/lib/link' import { useSecondaryPage } from '@/PageManager' +import MarkdownArticle from '@/components/Note/MarkdownArticle/MarkdownArticle' import { Event } from 'nostr-tools' import { useTranslation } from 'react-i18next' import { useMemo } from 'react' import Collapsible from '../Collapsible' import { Button } from '../ui/button' -import { Calendar, Clock, Video, CheckCircle, HelpCircle, XCircle } from 'lucide-react' +import { Calendar, Clock, ExternalLink, MapPin, CheckCircle, HelpCircle, XCircle } from 'lucide-react' import { cn } from '@/lib/utils' import { DropdownMenu, @@ -32,22 +33,44 @@ type RsvpStatus = 'accepted' | 'tentative' | 'declined' export default function CalendarEventContent({ event, className, - showRsvp = true + showRsvp = true, + showFull = false }: { event: Event className?: string showRsvp?: boolean + /** Note page / full detail: markdown body + complete tag list. */ + showFull?: boolean }) { const { t } = useTranslation() const { push } = useSecondaryPage() const { pubkey: myPubkey, publish } = useNostr() const { rsvps, isFetching, getRsvpStatus: getStatus } = useFetchCalendarRsvps(event) - if (!isCalendarEventKind(event.kind)) return null + const meta = useMemo(() => { + if (!isCalendarEventKind(event.kind)) return null + return getCalendarEventMeta(event) + }, [event]) + + const markdownBody = useMemo(() => { + if (!meta) return '' + const s = meta.summary.trim() + const c = event.content?.trim() ?? '' + if (s && c) return `${s}\n\n${c}` + return s || c || '' + }, [meta, event.content]) + + const eventForMarkdown = useMemo((): Event => { + if (!markdownBody) return event + return { ...event, content: markdownBody } + }, [event, markdownBody]) + + const duplicateWebPreviewHints = useMemo( + () => + !meta ? [] : [...meta.rUrls, ...(meta.image?.trim() ? [meta.image.trim()] : [])], + [meta] + ) - const { title, summary, image, start, end, startDate, endDate, isDateBased, joinUrl, topics } = - getCalendarEventMeta(event) - const description = summary || event.content?.trim() || '' const myRsvp = myPubkey ? rsvps.find((r) => r.pubkey === myPubkey) : undefined const myStatus = myRsvp ? getStatus(myRsvp) : undefined @@ -71,6 +94,23 @@ export default function CalendarEventContent({ }) }, [event.pubkey, event.tags, rsvps]) + if (!meta) return null + + const { + title, + image, + start, + end, + startDate, + endDate, + isDateBased, + rUrls, + location, + startTzid, + endTzid, + topics + } = meta + const handleRsvp = async (status: RsvpStatus) => { if (!myPubkey) { toast.error(t('You need to log in to RSVP')) @@ -105,17 +145,47 @@ export default function CalendarEventContent({ ) : ( -
- +
+
)}
-

+

{title || t('Scheduled video call')}

+ {!showFull && scheduleLine ? ( +

+ + {scheduleLine} +

+ ) : null} + {!showFull && location ? ( +

+ + {location} +

+ ) : null} {topics.length > 0 && (
{topics.map((topic) => ( @@ -130,31 +200,66 @@ export default function CalendarEventContent({ )}
- {scheduleLine ? ( + {showFull && scheduleLine ? (
-

{scheduleLine}

+
+

{scheduleLine}

+ {(startTzid || endTzid) && ( +

+ {startTzid ? ( + <> + start_tzid: {startTzid} + + ) : null} + {startTzid && endTzid && endTzid !== startTzid ? ' · ' : ''} + {endTzid && endTzid !== startTzid ? ( + <> + end_tzid: {endTzid} + + ) : null} +

+ )} +
) : null} - {description ? ( - <> - {/* NIP-52 31922/31923: collapse long summary+body only; card chrome stays outside MainNoteCard Collapsible. */} - -

- {description} -

-
- + {showFull && location ? ( +
+ +

{location}

+
+ ) : null} + {markdownBody ? ( + showFull ? ( +
+ +
+ ) : ( + <> + {/* NIP-52 31922/31923: collapse long summary+body only; card chrome stays outside MainNoteCard Collapsible. */} + +

+ {markdownBody} +

+
+ + ) ) : null}
- {joinUrl && ( - - )} + ))} {showRsvp && myPubkey && ( @@ -245,6 +350,25 @@ export default function CalendarEventContent({
)} + {showFull && event.tags.length > 0 ? ( +
+
+ {t('All tags')} +
+
+ {event.tags.map((tag, idx) => ( +
+
+ {tag[0] || '—'} +
+
+ {tag.length > 1 ? tag.slice(1).join(' · ') : '—'} +
+
+ ))} +
+
+ ) : null}
) } diff --git a/src/components/Embedded/EmbeddedCalendarEvent.tsx b/src/components/Embedded/EmbeddedCalendarEvent.tsx index 61ca077e..f94e12c1 100644 --- a/src/components/Embedded/EmbeddedCalendarEvent.tsx +++ b/src/components/Embedded/EmbeddedCalendarEvent.tsx @@ -9,7 +9,7 @@ import { Event } from 'nostr-tools' import { useTranslation } from 'react-i18next' import Collapsible from '../Collapsible' import { Button } from '../ui/button' -import { Calendar, Clock, Video } from 'lucide-react' +import { Calendar, Clock, ExternalLink, MapPin } from 'lucide-react' export function EmbeddedCalendarEvent({ event, @@ -20,7 +20,7 @@ export function EmbeddedCalendarEvent({ }) { const { t } = useTranslation() if (!isCalendarEventKind(event.kind)) return null - const { title, summary, image, start, end, startDate, endDate, isDateBased, joinUrl, topics } = + const { title, summary, image, start, end, startDate, endDate, isDateBased, rUrls, topics, location } = getCalendarEventMeta(event) const description = summary || event.content?.trim() || '' @@ -44,17 +44,31 @@ export function EmbeddedCalendarEvent({ ) : ( -
- +
+
)}
- + {title || t('Scheduled video call')} + {scheduleLine ? ( +

+ + {scheduleLine} +

+ ) : null} + {location ? ( +

+ + {location} +

+ ) : null} {topics.length > 0 && (
{topics.map((topic) => ( @@ -69,12 +83,6 @@ export function EmbeddedCalendarEvent({ )}
- {scheduleLine ? ( -
- -

{scheduleLine}

-
- ) : null} {description ? ( <> {/* NIP-52 31922/31923 embedded preview: long description only. */} @@ -85,19 +93,14 @@ export function EmbeddedCalendarEvent({ ) : null} - {joinUrl && ( - - )} + ))}
) } diff --git a/src/components/Note/MarkdownArticle/MarkdownArticle.tsx b/src/components/Note/MarkdownArticle/MarkdownArticle.tsx index 210d4a9b..a1e43237 100644 --- a/src/components/Note/MarkdownArticle/MarkdownArticle.tsx +++ b/src/components/Note/MarkdownArticle/MarkdownArticle.tsx @@ -28,6 +28,7 @@ import { Event, kinds } from 'nostr-tools' import Emoji, { EMOJI_IMG_INLINE_CLASS } from '@/components/Emoji' import { ExtendedKind, + isNip52CalendarCardKind, SPOTIFY_OPEN_URL_REGEX, WS_URL_REGEX, YOUTUBE_URL_REGEX, @@ -5898,7 +5899,10 @@ export default function MarkdownArticle({

{metadata.summary}

)} - {hideMetadata && metadata.title && event.kind !== ExtendedKind.DISCUSSION && ( + {hideMetadata && + metadata.title && + event.kind !== ExtendedKind.DISCUSSION && + !isNip52CalendarCardKind(event.kind) && (

{metadata.title}

)} diff --git a/src/components/Note/index.tsx b/src/components/Note/index.tsx index e35c86cd..b022756c 100644 --- a/src/components/Note/index.tsx +++ b/src/components/Note/index.tsx @@ -396,7 +396,9 @@ export default function Note({ } else if (event.kind === ExtendedKind.RELAY_REVIEW) { content = } else if (isCalendarEventKind(event.kind)) { - content = + content = ( + + ) } else if (event.kind === ExtendedKind.PUBLIC_MESSAGE) { content = renderEventContent({ hideMetadata: true }) } else if (event.kind === ExtendedKind.ZAP_REQUEST || event.kind === ExtendedKind.ZAP_RECEIPT) { diff --git a/src/components/Sidebar/SidebarCalendarWeekWidget.tsx b/src/components/Sidebar/SidebarCalendarWeekWidget.tsx index 0629bafb..6c29e93b 100644 --- a/src/components/Sidebar/SidebarCalendarWeekWidget.tsx +++ b/src/components/Sidebar/SidebarCalendarWeekWidget.tsx @@ -2,6 +2,7 @@ import { calendarOccurrenceOverlapsRange, formatCalendarSidebarRow, formatSidebarWeekLabel, + getCalendarEventMeta, getCalendarOccurrenceWindowMs, getLocalMondayWeekBounds } from '@/lib/calendar-event' @@ -262,7 +263,9 @@ export default function SidebarCalendarWeekWidget() { ) : (
    {sortedForWeek.map((ev) => { - const title = ev.tags.find((t) => t[0] === 'title')?.[1]?.trim() || t('Scheduled video call') + const meta = getCalendarEventMeta(ev) + const title = meta.title?.trim() || t('Scheduled video call') + const cover = meta.image?.trim() const sub = formatCalendarSidebarRow(ev) return (
  • @@ -270,16 +273,29 @@ export default function SidebarCalendarWeekWidget() { type="button" onClick={() => openEvent(ev)} className={cn( - 'w-full rounded-md border border-transparent px-1.5 py-1.5 text-left transition-colors', + 'flex w-full gap-2 rounded-md border border-transparent px-1.5 py-1.5 text-left transition-colors', 'hover:border-border/80 hover:bg-muted/50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring' )} > - {title} - {sub ? ( - - {sub} - - ) : null} + {cover ? ( + + ) : ( +
    + )} + + {title} + {sub ? ( + + {sub} + + ) : null} +
  • ) diff --git a/src/i18n/locales/cs.ts b/src/i18n/locales/cs.ts index 4b357a7b..4fca24e5 100644 --- a/src/i18n/locales/cs.ts +++ b/src/i18n/locales/cs.ts @@ -228,6 +228,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Add at least one invitee (paste nostr:npub or nostr:nprofile links)", "Scheduled call created and {{count}} invite(s) sent": "Scheduled call created and {{count}} invite(s) sent", "Join video call": "Join video call", + "Open link": "Open link", + "All tags": "All tags", "Scheduled video call": "Scheduled video call", "Video call": "Video call", "Schedule and send invite": "Schedule and send invite", diff --git a/src/i18n/locales/de.ts b/src/i18n/locales/de.ts index 64f2048e..db26fda7 100644 --- a/src/i18n/locales/de.ts +++ b/src/i18n/locales/de.ts @@ -228,6 +228,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Mindestens eine Person hinzufügen (nostr:npub- oder nostr:nprofile-Links einfügen)", "Scheduled call created and {{count}} invite(s) sent": "Geplanter Anruf erstellt und {{count}} Einladung(en) gesendet", "Join video call": "Videoanruf beitreten", + "Open link": "Link öffnen", + "All tags": "Alle Tags", "Scheduled video call": "Geplanter Videoanruf", "Video call": "Videoanruf", "Schedule and send invite": "Planen und Einladung senden", diff --git a/src/i18n/locales/en.ts b/src/i18n/locales/en.ts index f3de647a..99c5ab23 100644 --- a/src/i18n/locales/en.ts +++ b/src/i18n/locales/en.ts @@ -232,6 +232,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Add at least one invitee (paste nostr:npub or nostr:nprofile links)", "Scheduled call created and {{count}} invite(s) sent": "Scheduled call created and {{count}} invite(s) sent", "Join video call": "Join video call", + "Open link": "Open link", + "All tags": "All tags", "Scheduled video call": "Scheduled video call", "Video call": "Video call", "Schedule and send invite": "Schedule and send invite", diff --git a/src/i18n/locales/es.ts b/src/i18n/locales/es.ts index c16d4314..60d44bf5 100644 --- a/src/i18n/locales/es.ts +++ b/src/i18n/locales/es.ts @@ -228,6 +228,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Add at least one invitee (paste nostr:npub or nostr:nprofile links)", "Scheduled call created and {{count}} invite(s) sent": "Scheduled call created and {{count}} invite(s) sent", "Join video call": "Join video call", + "Open link": "Open link", + "All tags": "All tags", "Scheduled video call": "Scheduled video call", "Video call": "Video call", "Schedule and send invite": "Schedule and send invite", diff --git a/src/i18n/locales/fr.ts b/src/i18n/locales/fr.ts index 53109bb7..af9969f3 100644 --- a/src/i18n/locales/fr.ts +++ b/src/i18n/locales/fr.ts @@ -228,6 +228,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Add at least one invitee (paste nostr:npub or nostr:nprofile links)", "Scheduled call created and {{count}} invite(s) sent": "Scheduled call created and {{count}} invite(s) sent", "Join video call": "Join video call", + "Open link": "Open link", + "All tags": "All tags", "Scheduled video call": "Scheduled video call", "Video call": "Video call", "Schedule and send invite": "Schedule and send invite", diff --git a/src/i18n/locales/nl.ts b/src/i18n/locales/nl.ts index 4b357a7b..4fca24e5 100644 --- a/src/i18n/locales/nl.ts +++ b/src/i18n/locales/nl.ts @@ -228,6 +228,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Add at least one invitee (paste nostr:npub or nostr:nprofile links)", "Scheduled call created and {{count}} invite(s) sent": "Scheduled call created and {{count}} invite(s) sent", "Join video call": "Join video call", + "Open link": "Open link", + "All tags": "All tags", "Scheduled video call": "Scheduled video call", "Video call": "Video call", "Schedule and send invite": "Schedule and send invite", diff --git a/src/i18n/locales/pl.ts b/src/i18n/locales/pl.ts index a2feeb2f..48dd05e0 100644 --- a/src/i18n/locales/pl.ts +++ b/src/i18n/locales/pl.ts @@ -228,6 +228,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Add at least one invitee (paste nostr:npub or nostr:nprofile links)", "Scheduled call created and {{count}} invite(s) sent": "Scheduled call created and {{count}} invite(s) sent", "Join video call": "Join video call", + "Open link": "Open link", + "All tags": "All tags", "Scheduled video call": "Scheduled video call", "Video call": "Video call", "Schedule and send invite": "Schedule and send invite", diff --git a/src/i18n/locales/ru.ts b/src/i18n/locales/ru.ts index 2106369e..d14376e7 100644 --- a/src/i18n/locales/ru.ts +++ b/src/i18n/locales/ru.ts @@ -228,6 +228,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Add at least one invitee (paste nostr:npub or nostr:nprofile links)", "Scheduled call created and {{count}} invite(s) sent": "Scheduled call created and {{count}} invite(s) sent", "Join video call": "Join video call", + "Open link": "Open link", + "All tags": "All tags", "Scheduled video call": "Scheduled video call", "Video call": "Video call", "Schedule and send invite": "Schedule and send invite", diff --git a/src/i18n/locales/tr.ts b/src/i18n/locales/tr.ts index 4b357a7b..4fca24e5 100644 --- a/src/i18n/locales/tr.ts +++ b/src/i18n/locales/tr.ts @@ -228,6 +228,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Add at least one invitee (paste nostr:npub or nostr:nprofile links)", "Scheduled call created and {{count}} invite(s) sent": "Scheduled call created and {{count}} invite(s) sent", "Join video call": "Join video call", + "Open link": "Open link", + "All tags": "All tags", "Scheduled video call": "Scheduled video call", "Video call": "Video call", "Schedule and send invite": "Schedule and send invite", diff --git a/src/i18n/locales/zh.ts b/src/i18n/locales/zh.ts index cfc42a40..c03082b2 100644 --- a/src/i18n/locales/zh.ts +++ b/src/i18n/locales/zh.ts @@ -228,6 +228,8 @@ export default { "Add at least one invitee (paste nostr:npub or nostr:nprofile links)": "Add at least one invitee (paste nostr:npub or nostr:nprofile links)", "Scheduled call created and {{count}} invite(s) sent": "Scheduled call created and {{count}} invite(s) sent", "Join video call": "Join video call", + "Open link": "Open link", + "All tags": "All tags", "Scheduled video call": "Scheduled video call", "Video call": "Video call", "Schedule and send invite": "Schedule and send invite", diff --git a/src/lib/calendar-event.ts b/src/lib/calendar-event.ts index 3134822e..07f1b029 100644 --- a/src/lib/calendar-event.ts +++ b/src/lib/calendar-event.ts @@ -15,7 +15,21 @@ export interface CalendarEventMeta { /** Date-based: YYYY-MM-DD (exclusive end). Time-based: undefined. */ endDate: string isDateBased: boolean + /** First `r` tag with an http(s) URL (join / registration link). */ joinUrl: string + /** Same as {@link joinUrl}; every http(s) `r` value. */ + rUrl: string + rUrls: string[] + /** `location` tag (venue / address text). */ + location: string + /** `d` tag (replaceable identifier). */ + d: string + /** `g` tag (geohash). */ + geo: string + /** `start_tzid` (IANA zone). */ + startTzid: string + /** `end_tzid` (IANA zone). */ + endTzid: string topics: string[] } @@ -25,9 +39,17 @@ export function getCalendarEventMeta(event: Event): CalendarEventMeta { const image = event.tags.find(tagNameEquals('image'))?.[1] ?? '' const startStr = event.tags.find(tagNameEquals('start'))?.[1] const endStr = event.tags.find(tagNameEquals('end'))?.[1] - const location = event.tags.find(tagNameEquals('location'))?.[1] - const rTag = event.tags.find(tagNameEquals('r'))?.[1] - const joinUrl = rTag || location || '' + const location = event.tags.find(tagNameEquals('location'))?.[1] ?? '' + const d = event.tags.find(tagNameEquals('d'))?.[1] ?? '' + const geo = event.tags.find(tagNameEquals('g'))?.[1] ?? '' + const startTzid = event.tags.find(tagNameEquals('start_tzid'))?.[1] ?? '' + const endTzid = event.tags.find(tagNameEquals('end_tzid'))?.[1] ?? '' + const rUrls = event.tags + .filter(tagNameEquals('r')) + .map((t) => t[1]?.trim()) + .filter((u): u is string => !!u && (u.startsWith('http://') || u.startsWith('https://'))) + const rUrl = rUrls[0] ?? '' + const joinUrl = rUrl const topics = event.tags.filter(tagNameEquals('t')).map((t) => t[1]?.trim()).filter(Boolean) const isDateBased = event.kind === ExtendedKind.CALENDAR_EVENT_DATE if (isDateBased) { @@ -41,6 +63,13 @@ export function getCalendarEventMeta(event: Event): CalendarEventMeta { endDate: endStr ?? '', isDateBased: true, joinUrl, + rUrl, + rUrls, + location, + d, + geo, + startTzid, + endTzid, topics } } @@ -56,6 +85,13 @@ export function getCalendarEventMeta(event: Event): CalendarEventMeta { endDate: '', isDateBased: false, joinUrl, + rUrl, + rUrls, + location, + d, + geo, + startTzid, + endTzid, topics } } diff --git a/src/pages/primary/CalendarPrimaryPage.tsx b/src/pages/primary/CalendarPrimaryPage.tsx index 006d3361..ce6f06c7 100644 --- a/src/pages/primary/CalendarPrimaryPage.tsx +++ b/src/pages/primary/CalendarPrimaryPage.tsx @@ -19,11 +19,12 @@ import { useNostr } from '@/providers/NostrProvider' import { useScreenSize } from '@/providers/ScreenSizeProvider' import client from '@/services/client.service' import indexedDb from '@/services/indexed-db.service' +import storage from '@/services/local-storage.service' import { CALENDAR_EVENT_KINDS, ExtendedKind } from '@/constants' import { TPageRef } from '@/types' import { RefreshButton } from '@/components/RefreshButton' import { CalendarDays, ChevronLeft, ChevronRight } from 'lucide-react' -import { type Event } from 'nostr-tools' +import { type Event as NostrEvent } from 'nostr-tools' import { forwardRef, useCallback, @@ -50,8 +51,8 @@ export type CalendarPrimaryPageProps = { weekOffset?: number } -function dedupeCalendarEvents(events: Event[]): Event[] { - const map = new Map() +function dedupeCalendarEvents(events: NostrEvent[]): NostrEvent[] { + const map = new Map() for (const e of events) { const k = replaceableEventDedupeKey(e) const prev = map.get(k) @@ -85,9 +86,22 @@ const CalendarPrimaryPage = forwardRef(funct const { navigateToNote } = useSmartNoteNavigation() const { push } = useSecondaryPage() const { isSmallScreen } = useScreenSize() + const [panelMode, setPanelMode] = useState<'single' | 'double'>(() => storage.getPanelMode()) const layoutRef = useRef(null) const [refreshKey, setRefreshKey] = useState(0) + useEffect(() => { + const onPanelMode = (ev: Event) => { + const d = (ev as CustomEvent<{ mode: 'single' | 'double' }>).detail?.mode + if (d === 'single' || d === 'double') setPanelMode(d) + } + window.addEventListener('panelModeChanged', onPanelMode) + return () => window.removeEventListener('panelModeChanged', onPanelMode) + }, []) + + /** Month grid is unreadable in the narrow primary column of double-pane; use the same vertical layout as mobile. */ + const useVerticalMonthCalendar = isSmallScreen || panelMode === 'double' + const [activeWeekOffset, setActiveWeekOffset] = useState(weekOffsetProp) useEffect(() => { setActiveWeekOffset(weekOffsetProp) @@ -108,7 +122,7 @@ const CalendarPrimaryPage = forwardRef(funct setViewMonth(d.getMonth()) }, [highlightBounds.weekStartMs]) - const [rawEvents, setRawEvents] = useState([]) + const [rawEvents, setRawEvents] = useState([]) const [loading, setLoading] = useState(false) const relayUrls = useMemo(() => { @@ -193,7 +207,7 @@ const CalendarPrimaryPage = forwardRef(funct ) if (cancelled) return - const fromFollowing: Event[] = [] + const fromFollowing: NostrEvent[] = [] if (followAuthorsKey) { const authorList = followAuthorsKey.split('|').filter(Boolean).slice(0, FOLLOWING_CALENDAR_AUTHORS_CAP) for (let i = 0; i < authorList.length; i += FOLLOWING_CALENDAR_AUTHORS_CHUNK) { @@ -369,7 +383,7 @@ const CalendarPrimaryPage = forwardRef(funct

    {t('sidebarCalendarLoading')}

    ) : null} - {isSmallScreen ? ( + {useVerticalMonthCalendar ? (
    {Array.from({ length: daysInMonth(viewYear, viewMonth) }, (_, idx) => { const day = idx + 1 @@ -401,17 +415,27 @@ const CalendarPrimaryPage = forwardRef(funct {list.slice(0, 4).map((ev) => { const meta = getCalendarEventMeta(ev) const title = meta.title?.trim() || t('calendarPageUntitledEvent') + const cover = meta.image?.trim() return (
  • ) @@ -471,18 +495,28 @@ const CalendarPrimaryPage = forwardRef(funct {list.slice(0, 4).map((ev) => { const meta = getCalendarEventMeta(ev) const title = meta.title?.trim() || t('calendarPageUntitledEvent') + const cover = meta.image?.trim() return (
  • ) diff --git a/src/pages/secondary/CalendarDayEventsPage/index.tsx b/src/pages/secondary/CalendarDayEventsPage/index.tsx index 23b93070..11a6800b 100644 --- a/src/pages/secondary/CalendarDayEventsPage/index.tsx +++ b/src/pages/secondary/CalendarDayEventsPage/index.tsx @@ -75,17 +75,29 @@ const CalendarDayEventsPage = forwardRef { const meta = getCalendarEventMeta(ev) const label = meta.title?.trim() || t('calendarPageUntitledEvent') + const cover = meta.image?.trim() return (
  • )