import Location from '../../components/Location.vue'; import { Badge } from '../../components/ui/badge'; import { Button } from '../../components/ui/button'; import { Tooltip, TooltipContent, TooltipTrigger, TooltipWrapper } from '../../components/ui/tooltip'; import { ArrowUpDown, Ban, BellOff, Check, Link, MessageCircle, Reply, Tag, Trash2, X } from 'lucide-vue-next'; import { storeToRefs } from 'pinia'; import { checkCanInvite, formatDateFilter } from '../../shared/utils'; import { i18n } from '../../plugin'; import { useGameStore, useGroupStore, useLocationStore, useUiStore, useUserStore, useWorldStore } from '../../stores'; import Emoji from '../../components/Emoji.vue'; const { t } = i18n.global; const isGroupId = (id) => typeof id === 'string' && id.startsWith('grp_'); export const createColumns = ({ getNotificationCreatedAt, getNotificationCreatedAtTs, openNotificationLink, showFullscreenImageDialog, getSmallThumbnailUrl, acceptFriendRequestNotification, showSendInviteResponseDialog, showSendInviteRequestResponseDialog, acceptRequestInvite, sendNotificationResponse, hideNotification, hideNotificationPrompt, deleteNotificationLog, deleteNotificationLogPrompt }) => { const { showUserDialog, showSendBoopDialog } = useUserStore(); const { showWorldDialog } = useWorldStore(); const { showGroupDialog } = useGroupStore(); const { shiftHeld } = storeToRefs(useUiStore()); const { currentUser } = storeToRefs(useUserStore()); const { lastLocation } = storeToRefs(useLocationStore()); const { isGameRunning } = storeToRefs(useGameStore()); const canInvite = () => { const location = lastLocation.value?.location; return ( Boolean(location) && isGameRunning.value && checkCanInvite(location) ); }; const getResponseIcon = (response, notificationType) => { if (response?.type === 'link') { return Link; } switch (response?.icon) { case 'check': return Check; case 'cancel': return X; case 'ban': return Ban; case 'bell-slash': return BellOff; case 'reply': return notificationType === 'boop' ? MessageCircle : Reply; default: return Tag; } }; return [ { accessorFn: (row) => getNotificationCreatedAtTs(row), id: 'created_at', size: 120, header: ({ column }) => ( ), sortingFn: (rowA, rowB, columnId) => { const a = rowA.getValue(columnId) ?? 0; const b = rowB.getValue(columnId) ?? 0; if (a !== b) { return a - b; } const aId = typeof rowA.original?.id === 'string' ? rowA.original.id : ''; const bId = typeof rowB.original?.id === 'string' ? rowB.original.id : ''; return aId.localeCompare(bId); }, cell: ({ row }) => { const createdAt = getNotificationCreatedAt(row.original); const shortText = formatDateFilter(createdAt, 'short'); const longText = formatDateFilter(createdAt, 'long'); return ( {shortText} {longText} ); } }, { accessorKey: 'type', size: 180, header: () => t('table.notification.type'), cell: ({ row }) => { const original = row.original; const label = t(`view.notification.filters.${original.type}`); if (original.type === 'invite') { return ( {label} ); } if ( original.type === 'group.queueReady' || original.type === 'instance.closed' ) { return ( showWorldDialog(original.location) } > {label} {original.location ? ( ) : null} ); } if (original.link) { return ( openNotificationLink(original.link) } > {label} {original.linkText} ); } return ( {label} ); } }, { accessorKey: 'senderUsername', meta: { class: 'overflow-hidden' }, size: 150, header: () => t('table.notification.user'), cell: ({ row }) => { const original = row.original; if ( original.senderUserId && !isGroupId(original.senderUserId) ) { return ( showUserDialog(original.senderUserId) } > {original.senderUsername} ); } if (original.link?.startsWith('user:')) { return ( openNotificationLink(original.link) } > {original.linkText || original.senderUsername} ); } if ( original.senderUsername && !isGroupId(original.senderUserId) ) { return ( {original.senderUsername} ); } return null; } }, { accessorKey: 'groupName', meta: { class: 'overflow-hidden' }, size: 150, header: () => t('table.notification.group'), cell: ({ row }) => { const original = row.original; const label = original.senderUsername || original.groupName || original.data?.groupName || original.details?.groupName || original.linkText; if ( original.senderUserId && (original.type === 'groupChange' || isGroupId(original.senderUserId)) ) { return ( showGroupDialog(original.senderUserId) } > {label} ); } if ( original.type === 'groupChange' && original.senderUsername ) { return ( {original.senderUsername} ); } if (original.link?.startsWith('group:')) { return ( openNotificationLink(original.link) } > {original.data?.groupName || label} ); } if (original.link?.startsWith('event:')) { return ( openNotificationLink(original.link) } > {original.data?.groupName || original.groupName || label} ); } if (original.data?.groupName) { return ( {original.data.groupName} ); } if (original.details?.groupName) { return ( {original.details.groupName} ); } if (original.groupName) { return ( {original.groupName} ); } return null; } }, { accessorKey: 'photo', size: 80, header: () => t('table.notification.photo'), cell: ({ row }) => { const original = row.original; if (original.type === 'boop') { const imageUrl = original.details?.imageUrl; if (!imageUrl || imageUrl.startsWith('default_')) { return null; } return ( showFullscreenImageDialog(imageUrl)} imageUrl={imageUrl} size={30} /> ); } if (original.details?.imageUrl) { return ( showFullscreenImageDialog( original.details.imageUrl ) } loading="lazy" /> ); } if (original.imageUrl) { return ( showFullscreenImageDialog(original.imageUrl) } loading="lazy" /> ); } return null; } }, { id: 'message', header: () => t('table.notification.message'), enableSorting: false, meta: { class: 'min-w-0 overflow-hidden', stretch: true }, minSize: 100, cell: ({ row }) => { const original = row.original; return (
{original.type === 'invite' && original.details ? (
) : null} {original.message && original.message !== `This is a generated invite to ${original.details?.worldName}` ? ( {original.message} ) : null} {!original.message && original.details?.inviteMessage ? ( {original.details.inviteMessage} ) : null} {!original.message && original.details?.requestMessage ? ( {original.details.requestMessage} ) : null} {!original.message && original.details?.responseMessage ? ( {original.details.responseMessage} ) : null}
); } }, { id: 'action', meta: { class: 'text-right' }, size: 120, minSize: 120, maxSize: 120, header: () => t('table.notification.action'), enableSorting: false, cell: ({ row }) => { const original = row.original; const hasResponses = Array.isArray(original.responses); const showDecline = original.type !== 'requestInviteResponse' && original.type !== 'inviteResponse' && original.type !== 'message' && original.type !== 'boop' && original.type !== 'groupChange' && !original.type?.includes('group.') && !original.type?.includes('moderation.') && !original.type?.includes('instance.'); const showDeleteLog = original.type !== 'friendRequest' && original.type !== 'ignoredFriendRequest' && !original.type?.includes('group.') && !original.type?.includes('moderation.'); return (
{original.senderUserId !== currentUser.value?.id && !original.$isExpired ? ( {original.type === 'friendRequest' ? ( {t( 'view.notification.actions.accept' )} ) : null} {original.type === 'invite' ? ( {t( 'view.notification.actions.decline_with_message' )} ) : null} {original.type === 'requestInvite' ? ( {canInvite() ? ( {t( 'view.notification.actions.invite' )} ) : null} {t( 'view.notification.actions.decline_with_message' )} ) : null} {hasResponses ? original.responses.map((response) => { const onClick = () => { if (response.type === 'link') { openNotificationLink( response.data ); return; } if ( response.icon === 'reply' && original.type === 'boop' ) { showSendBoopDialog( original.senderUserId ); return; } sendNotificationResponse( original.id, original.responses, response.type ); }; const ResponseIcon = getResponseIcon( response, original.type ); return ( {response.text} ); }) : null} {showDecline ? ( {t( 'view.notification.actions.decline' )} ) : null} {original.type === 'group.queueReady' ? ( {t( 'view.notification.actions.delete_log' )} ) : null} ) : null} {showDeleteLog ? ( {t( 'view.notification.actions.delete_log' )} ) : null}
); } }, { id: 'trailing', header: () => null, enableSorting: false, enableResizing: false, size: 5, cell: () => null } ]; };