vue-parley 4.9.2 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/README.md +26 -4
  2. package/dist/chat.css +412 -68
  3. package/dist/chunks/Call-DvVJ7IsY.mjs +1717 -0
  4. package/dist/chunks/Call-DvVJ7IsY.mjs.map +1 -0
  5. package/dist/chunks/Call-h9r4EZ5Y.cjs +1717 -0
  6. package/dist/chunks/Call-h9r4EZ5Y.cjs.map +1 -0
  7. package/dist/chunks/data-CsUe_T0I.cjs +1894 -0
  8. package/dist/chunks/data-CsUe_T0I.cjs.map +1 -0
  9. package/dist/chunks/data-VApcOLKg.mjs +1894 -0
  10. package/dist/chunks/data-VApcOLKg.mjs.map +1 -0
  11. package/dist/chunks/duotone-CZ2lLMty.cjs +95 -0
  12. package/dist/chunks/duotone-CZ2lLMty.cjs.map +1 -0
  13. package/dist/chunks/duotone-DWysXhVh.mjs +95 -0
  14. package/dist/chunks/duotone-DWysXhVh.mjs.map +1 -0
  15. package/dist/chunks/{index-CqkX2ds2.cjs → index-BSzP10Mk.cjs} +1211 -712
  16. package/dist/chunks/index-BSzP10Mk.cjs.map +1 -0
  17. package/dist/chunks/{index-BBr7KDrd.mjs → index-C5yf_PW0.mjs} +1231 -732
  18. package/dist/chunks/index-C5yf_PW0.mjs.map +1 -0
  19. package/dist/chunks/light-CewGh2Ah.cjs +95 -0
  20. package/dist/chunks/light-CewGh2Ah.cjs.map +1 -0
  21. package/dist/chunks/light-DtApNkwW.mjs +95 -0
  22. package/dist/chunks/light-DtApNkwW.mjs.map +1 -0
  23. package/dist/chunks/{session-DBA9iE_n.mjs → session-CKOlYafG.mjs} +391 -33
  24. package/dist/chunks/session-CKOlYafG.mjs.map +1 -0
  25. package/dist/chunks/{session-DAl8n0Eh.cjs → session-DhajXqvC.cjs} +391 -33
  26. package/dist/chunks/session-DhajXqvC.cjs.map +1 -0
  27. package/dist/chunks/thin-Ccq8qzb_.mjs +95 -0
  28. package/dist/chunks/thin-Ccq8qzb_.mjs.map +1 -0
  29. package/dist/chunks/thin-Dlw1Y57w.cjs +95 -0
  30. package/dist/chunks/thin-Dlw1Y57w.cjs.map +1 -0
  31. package/dist/index.cjs +3 -3
  32. package/dist/index.mjs +20 -20
  33. package/dist/types/app/components/call/Call.vue.d.ts +1 -2
  34. package/dist/types/app/components/call/Call.vue.d.ts.map +1 -1
  35. package/dist/types/app/components/call/CallIcon.vue.d.ts +4 -0
  36. package/dist/types/app/components/call/CallIcon.vue.d.ts.map +1 -1
  37. package/dist/types/app/components/call/CallParticipants.vue.d.ts +14 -0
  38. package/dist/types/app/components/call/CallParticipants.vue.d.ts.map +1 -0
  39. package/dist/types/app/components/call/CallTile.vue.d.ts +46 -0
  40. package/dist/types/app/components/call/CallTile.vue.d.ts.map +1 -0
  41. package/dist/types/app/components/call/tokens.d.ts +204 -0
  42. package/dist/types/app/components/call/tokens.d.ts.map +1 -0
  43. package/dist/types/app/components/chat/ChatInput.vue.d.ts.map +1 -1
  44. package/dist/types/app/components/chat/ChatPageBar.vue.d.ts.map +1 -1
  45. package/dist/types/app/components/chat/chat-input/InputAttachement.vue.d.ts.map +1 -1
  46. package/dist/types/app/components/chat/contact/ContactAvatar.vue.d.ts.map +1 -1
  47. package/dist/types/app/components/general/IconButton.vue.d.ts +1 -1
  48. package/dist/types/app/components/general/IconButton.vue.d.ts.map +1 -1
  49. package/dist/types/app/components/global/BEmojiPicker.vue.d.ts +11 -4
  50. package/dist/types/app/components/global/BEmojiPicker.vue.d.ts.map +1 -1
  51. package/dist/types/app/components/global/BIcon.vue.d.ts +1 -1
  52. package/dist/types/app/components/global/BIcon.vue.d.ts.map +1 -1
  53. package/dist/types/app/components/global/emoji/data.d.ts +13 -0
  54. package/dist/types/app/components/global/emoji/data.d.ts.map +1 -0
  55. package/dist/types/app/components/global/emoji/types.d.ts +12 -0
  56. package/dist/types/app/components/global/emoji/types.d.ts.map +1 -0
  57. package/dist/types/app/components/global/icons/bold.d.ts.map +1 -1
  58. package/dist/types/app/components/global/icons/duotone.d.ts.map +1 -1
  59. package/dist/types/app/components/global/icons/fill.d.ts.map +1 -1
  60. package/dist/types/app/components/global/icons/light.d.ts.map +1 -1
  61. package/dist/types/app/components/global/icons/regular.d.ts.map +1 -1
  62. package/dist/types/app/components/global/icons/thin.d.ts.map +1 -1
  63. package/dist/types/app/composables/call/limits.d.ts +18 -0
  64. package/dist/types/app/composables/call/limits.d.ts.map +1 -0
  65. package/dist/types/app/composables/call/peer.d.ts +14 -1
  66. package/dist/types/app/composables/call/peer.d.ts.map +1 -1
  67. package/dist/types/app/composables/call/peers.d.ts +22 -3
  68. package/dist/types/app/composables/call/peers.d.ts.map +1 -1
  69. package/dist/types/app/composables/call/session.d.ts +55 -7
  70. package/dist/types/app/composables/call/session.d.ts.map +1 -1
  71. package/dist/types/app/composables/call/signaling.d.ts +23 -6
  72. package/dist/types/app/composables/call/signaling.d.ts.map +1 -1
  73. package/dist/types/app/composables/call/useCallLayout.d.ts +38 -0
  74. package/dist/types/app/composables/call/useCallLayout.d.ts.map +1 -0
  75. package/dist/types/app/composables/call/useCallNotices.d.ts +23 -0
  76. package/dist/types/app/composables/call/useCallNotices.d.ts.map +1 -0
  77. package/dist/types/app/composables/call/useCallUi.d.ts +3 -0
  78. package/dist/types/app/composables/call/useCallUi.d.ts.map +1 -1
  79. package/dist/types/app/composables/chat/useChatRecording.d.ts +1 -1
  80. package/dist/types/app/composables/useCall.d.ts +12 -1
  81. package/dist/types/app/composables/useCall.d.ts.map +1 -1
  82. package/dist/types/app/composables/useHostI18n.d.ts +1 -1
  83. package/dist/types/app/composables/useHostI18n.d.ts.map +1 -1
  84. package/dist/types/app/index.d.ts +2 -2
  85. package/dist/types/app/index.d.ts.map +1 -1
  86. package/dist/types/app/stores/callStore.d.ts +207 -24
  87. package/dist/types/app/stores/callStore.d.ts.map +1 -1
  88. package/dist/types/app/types/index.d.ts +26 -1
  89. package/dist/types/app/types/index.d.ts.map +1 -1
  90. package/dist/types/app/utils/avatar.d.ts +25 -0
  91. package/dist/types/app/utils/avatar.d.ts.map +1 -0
  92. package/dist/types/i18n/locales/index.d.ts +146 -0
  93. package/dist/types/i18n/locales/index.d.ts.map +1 -1
  94. package/package.json +6 -4
  95. package/dist/chunks/Call-B8Po7lDD.mjs +0 -1155
  96. package/dist/chunks/Call-B8Po7lDD.mjs.map +0 -1
  97. package/dist/chunks/Call-Cz-Hk_YZ.cjs +0 -1155
  98. package/dist/chunks/Call-Cz-Hk_YZ.cjs.map +0 -1
  99. package/dist/chunks/duotone-DEZDBwbj.mjs +0 -90
  100. package/dist/chunks/duotone-DEZDBwbj.mjs.map +0 -1
  101. package/dist/chunks/duotone-Dx8FFD3-.cjs +0 -90
  102. package/dist/chunks/duotone-Dx8FFD3-.cjs.map +0 -1
  103. package/dist/chunks/index-BBr7KDrd.mjs.map +0 -1
  104. package/dist/chunks/index-CqkX2ds2.cjs.map +0 -1
  105. package/dist/chunks/light-BdqG_1xJ.mjs +0 -90
  106. package/dist/chunks/light-BdqG_1xJ.mjs.map +0 -1
  107. package/dist/chunks/light-DWwZlbLY.cjs +0 -90
  108. package/dist/chunks/light-DWwZlbLY.cjs.map +0 -1
  109. package/dist/chunks/session-DAl8n0Eh.cjs.map +0 -1
  110. package/dist/chunks/session-DBA9iE_n.mjs.map +0 -1
  111. package/dist/chunks/thin-BzrijWaM.cjs +0 -90
  112. package/dist/chunks/thin-BzrijWaM.cjs.map +0 -1
  113. package/dist/chunks/thin-CXKKNj_8.mjs +0 -90
  114. package/dist/chunks/thin-CXKKNj_8.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-BBr7KDrd.mjs","sources":["../../app/types/index.ts","../../app/composables/useAppToast.ts","../../app/composables/useHostI18n.ts","../../app/stores/profileStore.ts","../../i18n/locales/index.ts","../../app/stores/callStore.ts","../../app/stores/chatStore.ts","../../app/utils/compressVideo.ts","../../app/stores/messageStores.ts","../../app/stores/mediaStore.ts","../../app/assets/lib-images/chat/empty-state.webp","../../app/components/general/MediaImage.vue","../../app/components/general/NoDataDisplay.vue","../../app/composables/useLocalI18n.ts","../../app/components/global/icons/bold.ts","../../app/components/global/icons/fill.ts","../../app/components/global/icons/regular.ts","../../app/components/global/BIcon.vue","../../app/components/global/BVirtualVerticalList.vue","../../app/directives/loading.ts","../../app/utils/emojiParser.ts","../../app/components/general/SafeEmojiText.vue","../../app/components/chat/contact/ContactAvatar.vue","../../app/composables/useDate.ts","../../app/components/chat/contact/ChatContactDisplay.vue","../../app/components/chat/contact/ContactSkeleton.vue","../../app/components/general/IconButton.vue","../../app/components/chat/contact/ChatListSearch.vue","../../app/components/chat/contact/ChatList.vue","../../app/composables/useAppPermissions.ts","../../app/components/general/ResponsiveDialog.vue","../../app/components/chat/chat-input/PermissionPopup.vue","../../app/utils/format.ts","../../app/components/chat/profile/FileDisplay.vue","../../app/components/chat/ChatProfileOverview.vue","../../app/components/general/ConfirmModal.vue","../../app/utils/media.ts","../../app/components/general/MediaThumb.vue","../../app/components/chat/chat-bubbles/viewer/ViewerImage.vue","../../app/components/chat/chat-bubbles/viewer/ViewerVideo.vue","../../app/components/chat/chat-bubbles/MediaViewer.vue","../../app/components/chat/chat-bubbles/BubbleOptions.vue","../../app/components/general/LoadingStatus.vue","../../app/components/chat/chat-bubbles/VoiceDisplay.vue","../../app/components/chat/chat-bubbles/BubbleVideo.vue","../../app/components/general/FileFormatDisplay.vue","../../app/components/chat/chat-bubbles/FileDisplay.vue","../../app/components/chat/chat-bubbles/BubbleDivider.vue","../../app/components/chat/chat-bubbles/UploadProgressOverlay.vue","../../app/components/chat/chat-bubbles/BubbleMedia.vue","../../app/components/chat/chat-bubbles/BubbleSelectionMark.vue","../../app/components/chat/chat-bubbles/BubbleRequest.vue","../../app/components/chat/chat-bubbles/BubbleStatus.vue","../../app/components/chat/chat-bubbles/BubbleMeta.vue","../../app/components/chat/chat-bubbles/ReplyPreview.vue","../../app/composables/useLongPress.ts","../../app/components/chat/ChatBubble.vue","../../app/components/chat/messages/MessagesSkeleton.vue","../../app/components/chat/messages/FloatingDateHeader.vue","../../app/components/chat/messages/ScrollToBottomButton.vue","../../app/composables/useChatMessageList.ts","../../app/composables/useFlippedVirtualScroll.ts","../../app/components/chat/ChatMessages.vue","../../app/components/chat/ChatPageBar.vue","../../app/components/global/BEmojiPicker.vue","../../app/components/chat/chat-input/AttachementFileDisplay.vue","../../app/composables/useAttachmentPicker.ts","../../app/components/chat/chat-input/InputAttachement.vue","../../app/composables/chat/useChatRecording.ts","../../app/components/chat/chat-input/VideoRecordDisplay.vue","../../app/composables/useRichTextEditor.ts","../../app/components/chat/chat-input/InputActionBar.vue","../../app/components/chat/chat-input/RecordingStatus.vue","../../app/components/chat/chat-input/RecordButton.vue","../../app/composables/chat/useInputDraft.ts","../../app/components/chat/ChatInput.vue","../../app/components/chat/ChatView.vue","../../app/components/ChatPage.vue","../../app/provider/callProvider.ts","../../app/plugin.ts","../../app/index.ts"],"sourcesContent":["/**\n * A WebRTC signalling payload: an SDP offer/answer, an ICE candidate, or a request for the\n * initiator to renegotiate. The same shape simple-peer uses, so clients on the previous,\n * simple-peer based build still interoperate.\n */\nexport interface SignalData {\n type?: \"transceiverRequest\" | \"renegotiate\" | \"candidate\" | RTCSdpType;\n sdp?: string;\n candidate?: RTCIceCandidateInit;\n renegotiate?: boolean;\n transceiverRequest?: { kind: string; init?: RTCRtpTransceiverInit };\n}\n\nexport type ThemeMode = \"light\" | \"dark\";\n\nexport interface CallMember extends Contact {\n stream: MediaStream | null;\n isScreenSharing: boolean;\n isCameraOn: boolean;\n isSpeaking: boolean;\n isMuted: boolean;\n}\n\nexport type status = \"pending\" | \"approved\" | \"rejected\" | \"expired\";\nexport type ServicePresence = \"online\" | \"on-site\";\nexport type UserRoleKey = \"user\" | \"employee\" | \"business\" | \"support\";\nexport type StateKeys = \"\" | \"online\" | \"ended\" | \"active\";\nexport type MessageType = \"text\" | \"image\" | \"file\" | \"voice\" | \"video\";\n\n/** One photo or video of an album. */\nexport interface MediaItem {\n url: string;\n kind: \"image\" | \"video\";\n}\n\nexport interface Message {\n id: string;\n conversationId: string;\n date: Date;\n type: MessageType;\n text?: string;\n /** Photos of an album. A host that also sends videos uses `media` instead. */\n imageUrl?: string[];\n /**\n * The album's photos and videos, in order, on a message of type `image`. Takes precedence over\n * `imageUrl`, which senders still fill with just the photos. A round video note is `videoUrl`.\n */\n media?: MediaItem[];\n fileUrl?: string;\n fileName?: string;\n voiceUrl?: string;\n videoUrl?: string;\n isEdited: boolean;\n senderId: string;\n isSent: boolean;\n /** Set when the last send attempt failed, so the bubble can offer a retry. */\n isFailed?: boolean;\n isRead: boolean;\n repliedTo?: Message;\n request?: string;\n}\n\nexport interface Contact {\n id: string;\n name: string;\n lastName: string;\n isOnline: boolean;\n /** Omit when unknown; the header then hides the \"last seen\" line. */\n lastSeen?: Date;\n imageUrl: string;\n nationalCode?: string;\n phoneNumber?: string;\n isActive: boolean;\n birthDate: Date;\n lastMessage?: Message;\n /**\n * When the conversation last changed. The row shows it, and the lists sort by it, when there is\n * no `lastMessage`.\n */\n lastActivity?: Date;\n /**\n * A short label on the row that tells conversations with the same person apart, such as the\n * service it is about.\n */\n tag?: string;\n unreadCount?: number;\n serviceType?: \"video-call\" | \"voice-call\" | \"chat\";\n userType: UserRoleKey[];\n}\n\nexport interface ChatFilter {\n key: StateKeys;\n label: string;\n}\n\nexport interface ExtendedMessage extends Message {\n prevMessage?: Message;\n nextMessage?: Message;\n isFirstInDate: boolean;\n contact?: Contact;\n}\n\nexport interface ChatProvider {\n fetchContacts: () => Promise<Contact[]>;\n}\n\nexport type CallKind = \"voice-call\" | \"video-call\";\n\nexport type CallMessage =\n | {\n type: \"signal\";\n payload: {\n signal: SignalData & { sdp: string };\n from: string;\n to: string;\n name: string;\n };\n }\n | { type: \"join\"; payload: { from: string; name: string } }\n | {\n type: \"track_type\";\n payload: { from: string; types: { id: string; type: TrackType }[] };\n }\n | {\n type: \"call\";\n payload: {\n from: string;\n name: string;\n channel: string;\n avatar?: string;\n };\n }\n | {\n type: \"hangup\";\n payload: { from: string; channel: string; name?: string };\n };\n\nexport interface TurnConfig {\n urls: string[];\n username?: string;\n credential?: string;\n iceTransportPolicy?: \"relay\" | \"all\";\n}\n\nexport interface CallPublishOptions {\n retain?: boolean;\n}\n\nexport type Credential = {\n ttl: number;\n user: string;\n pass: string;\n urls: string[];\n};\n\nexport interface CallHandlers {\n credential: Credential;\n handleGenerateCred: () => Promise<void>;\n publisher: (json: string) => Promise<void>;\n subscriber: (\n callback: (message: CallMessageSchema) => Promise<void>,\n ) => Promise<number>;\n unSubscriber: (id: number) => Promise<void>;\n /**\n * \"relay\" (the default) sends media only through the TURN servers in `credential`. \"all\" also\n * allows direct connections, and works without TURN servers (e.g. on a LAN or in tests).\n */\n iceTransportPolicy?: RTCIceTransportPolicy;\n /** Logs signalling and peer events to the console. */\n debug?: boolean;\n}\n\nexport interface FetchContactsParams {\n page: number;\n pageSize: number;\n state: StateKeys;\n search?: string;\n}\n\nexport interface ContactsPage {\n data: Contact[];\n hasNextPage: boolean;\n}\n\nexport interface ChatHandlers {\n fetchConversations(params: FetchContactsParams): Promise<ContactsPage>;\n deleteConversation(id: string): Promise<void>;\n /** Optional; the \"end conversation\" action is only offered when provided. */\n endConversation?(id: string): Promise<void>;\n}\n\nexport interface MediaDownloadOptions {\n signal?: AbortSignal;\n onProgress?: (percent: number) => void;\n}\n\nexport interface MediaHandlers {\n download(url: string, opts?: MediaDownloadOptions): Promise<Blob>;\n getFileSize(url: string): Promise<number | null>;\n}\n\nexport interface UploadProgressEvent {\n uploaded: number;\n total: number;\n progress: number;\n}\n\nexport interface SendMessageOptions {\n onProgress?: (e: UploadProgressEvent) => void;\n}\n\nexport interface FetchMessagesParams {\n conversationId: string;\n page: number;\n pageSize: number;\n}\n\n/** Someone who has read one of the viewer's messages. */\nexport interface MessageReader {\n /** The reader's user id. */\n id: string;\n name: string;\n lastName?: string;\n imageUrl?: string;\n /**\n * When the reader last caught up on the conversation. That is when they read the newest message\n * they have seen, so for an older message it can be later than when they actually read it.\n */\n readAt?: Date;\n}\n\nexport interface MessagesHandlers {\n sendMessage(msg: Message, opts?: SendMessageOptions): Promise<Message>;\n editMessage(id: string, text: string): Promise<Message>;\n deleteMessages(ids: string[]): Promise<void>;\n fetchMessages(params: FetchMessagesParams): Promise<Message[]>;\n /**\n * Persists that the viewer has read a conversation, up to `lastMessageId` when one is loaded.\n * Called when a conversation opens and again as messages from others arrive while it is on\n * screen. Optional; without it read state stays local.\n */\n markRead?(conversationId: string, lastMessageId?: string): Promise<void>;\n /**\n * Who among the other participants has read one of the viewer's own messages. Optional; when\n * given, the message menu lists them (\"Seen by\").\n */\n fetchReaders?(message: Message): Promise<MessageReader[]>;\n}\n\nexport interface FetchProfileAttachmentsParams {\n conversationId: string;\n page: number;\n pageSize: number;\n}\n\nexport interface ProfileAttachmentsPage {\n data: string[];\n hasNextPage: boolean;\n}\n\nexport interface ProfileHandlers {\n fetchMedia(\n params: FetchProfileAttachmentsParams,\n ): Promise<ProfileAttachmentsPage>;\n fetchFiles(\n params: FetchProfileAttachmentsParams,\n ): Promise<ProfileAttachmentsPage>;\n}\n\n// A plain object rather than a `const enum`, which consumers compiling with isolatedModules or\n// erasableSyntaxOnly can't use from a .d.ts.\nexport const CallMessageType = {\n Signal: \"signal\",\n Join: \"join\",\n TrackType: \"track_type\",\n Call: \"call\",\n Hangup: \"hangup\",\n Presence: \"presence\",\n} as const;\nexport type CallMessageType = (typeof CallMessageType)[keyof typeof CallMessageType];\n\nexport type TrackType = \"webcam\" | \"screen\" | \"audio\" | \"webcam_audio\";\n\nexport type CallMessageSchema =\n | {\n type: typeof CallMessageType.Signal;\n payload: {\n signal: SignalData & { sdp: string };\n from: string;\n to: string;\n name: string;\n };\n }\n | {\n type: typeof CallMessageType.Join;\n payload: {\n from: string;\n name: string;\n /** The sender dropped its connection to everyone: discard yours to it and reconnect. */\n restart?: boolean;\n };\n }\n | {\n type: typeof CallMessageType.TrackType;\n payload: {\n from: string;\n types: { id: string; type: TrackType }[];\n };\n }\n | {\n type: typeof CallMessageType.Call;\n payload: {\n from: string;\n name: string;\n channel: string;\n avatar: string;\n };\n }\n | {\n type: typeof CallMessageType.Hangup;\n payload: {\n from: string;\n channel: string;\n };\n }\n | {\n /**\n * Sent by everyone in a call when they join and then every 15 seconds while they stay, so\n * members outside it can tell a call is running and join it (`callStore.observeCall`).\n */\n type: typeof CallMessageType.Presence;\n payload: {\n from: string;\n channel: string;\n /** Whether the sender started it as a video call rather than a voice call. */\n video: boolean;\n };\n };\n\nexport type { MenuOption } from \"./components/menu-options\";\n","import { useToast } from \"primevue/usetoast\";\n\n/** Rendered by `<Toast group=\"vue-parley\" />` in ChatView, so the host's own toasts stay apart. */\nexport const TOAST_GROUP = \"vue-parley\";\n\nconst SEVERITY = {\n success: \"success\",\n error: \"error\",\n warning: \"warn\",\n info: \"info\",\n} as const;\n\nexport const useAppToast = () => {\n const toast = useToast();\n\n const openToast = (\n message: string,\n type: keyof typeof SEVERITY = \"success\",\n ) => {\n toast.add({\n group: TOAST_GROUP,\n severity: SEVERITY[type],\n summary: message,\n life: 4000,\n });\n };\n\n return { openToast };\n};\n","import {\n computed,\n getCurrentInstance,\n inject,\n isRef,\n watch,\n type App,\n type ComputedRef,\n type InjectionKey,\n type Ref,\n} from \"vue\";\nimport { createI18n, type I18n } from \"vue-i18n\";\n\n// vue-i18n provides itself under a per-instance symbol, reachable only through the app. createChat()\n// re-provides it under this key so stores, which have no component, can find it too.\nconst hostI18nKey: InjectionKey<I18n> = Symbol(\"vue-chat:i18n\");\n\ntype I18nApp = App & { __VUE_I18N_SYMBOL__?: InjectionKey<I18n> };\n\nfunction injectFromApp(app: I18nApp): I18n | undefined {\n const symbol = app.__VUE_I18N_SYMBOL__;\n return symbol ? app.runWithContext(() => inject(symbol, undefined)) : undefined;\n}\n\nexport function provideHostI18n(app: App) {\n const i18n = injectFromApp(app);\n if (i18n) app.provide(hostI18nKey, i18n);\n}\n\nfunction injectHostI18n(): I18n {\n const instance = getCurrentInstance();\n const i18n =\n inject(hostI18nKey, undefined) ??\n // Stores configured through setHandlers() instead of createChat(), used from a component.\n (instance ? injectFromApp(instance.appContext.app) : undefined);\n if (!i18n) {\n throw new Error(\n \"[vue-chat] vue-i18n not found: install it, then createChat(), before using the chat\",\n );\n }\n return i18n;\n}\n\nfunction read(value: string | Ref<string> | undefined): string | undefined {\n return isRef(value) ? value.value : value;\n}\n\n/**\n * The host's current locale. Unlike useI18n(), works in a store as well as a component, so a\n * store can be created anywhere (a Nuxt plugin, a route guard), not only in a component's setup.\n */\nexport function useHostLocale(): ComputedRef<string> {\n const global = injectHostI18n().global as unknown as { locale: string | Ref<string> };\n return computed(() => read(global.locale) ?? \"en\");\n}\n\n/**\n * Translations for a store: `messages` on their own, following the host's locale. A component\n * uses useLocalI18n() instead, which scopes them to the component.\n */\nexport function useStoreI18n(messages: Record<string, any>): { t: (key: string) => string } {\n const host = injectHostI18n().global as unknown as {\n locale: string | Ref<string>;\n fallbackLocale: string | Ref<string>;\n };\n const locale = useHostLocale();\n const { global } = createI18n({\n legacy: false,\n locale: locale.value,\n fallbackLocale: read(host.fallbackLocale) ?? \"en\",\n messages,\n });\n watch(locale, (value) => (global.locale.value = value));\n return { t: (key) => global.t(key) };\n}\n","import { ProfileAttachmentsPage, ProfileHandlers } from \"~/types\";\nimport { defineStore } from \"pinia\";\n\nconst DEFAULT_PAGE_SIZE = 20;\n\nexport const useProfileStore = defineStore(\"profile-store\", () => {\n let handlers: ProfileHandlers;\n\n function setHandlers(val: ProfileHandlers) {\n handlers = val;\n }\n\n const userId = ref<string>(\"\");\n const userName = ref<string>(\"\");\n const userAvatar = ref<Blob | undefined>(undefined);\n const mediaMap = ref<Record<string, string[]>>({});\n const filesMap = ref<Record<string, string[]>>({});\n const mediaPage = ref<Record<string, number>>({});\n const filesPage = ref<Record<string, number>>({});\n const mediaHasNextPage = ref<Record<string, boolean>>({});\n const filesHasNextPage = ref<Record<string, boolean>>({});\n const pageSize = ref(DEFAULT_PAGE_SIZE);\n const mediaLoading = ref(false);\n const filesLoading = ref(false);\n /** Bumped by `reset`, so a page started for the previous user is dropped when it lands. */\n let generation = 0;\n\n const fetchMedia = async (\n conversationId: string,\n page: number = 1,\n size: number = pageSize.value,\n ) => {\n if (mediaLoading.value) return;\n if (page > 1 && !mediaHasNextPage.value[conversationId]) return;\n const started = generation;\n mediaLoading.value = true;\n try {\n const batch: ProfileAttachmentsPage = await handlers.fetchMedia({\n conversationId,\n page,\n pageSize: size,\n });\n if (started !== generation) return;\n const existing = mediaMap.value[conversationId] ?? [];\n mediaMap.value[conversationId] =\n page === 1 ? batch.data : [...existing, ...batch.data];\n mediaPage.value[conversationId] = page;\n mediaHasNextPage.value[conversationId] = batch.hasNextPage;\n } finally {\n if (started === generation) mediaLoading.value = false;\n }\n };\n\n const fetchFiles = async (\n conversationId: string,\n page: number = 1,\n size: number = pageSize.value,\n ) => {\n if (filesLoading.value) return;\n if (page > 1 && !filesHasNextPage.value[conversationId]) return;\n const started = generation;\n filesLoading.value = true;\n try {\n const batch: ProfileAttachmentsPage = await handlers.fetchFiles({\n conversationId,\n page,\n pageSize: size,\n });\n if (started !== generation) return;\n const existing = filesMap.value[conversationId] ?? [];\n filesMap.value[conversationId] =\n page === 1 ? batch.data : [...existing, ...batch.data];\n filesPage.value[conversationId] = page;\n filesHasNextPage.value[conversationId] = batch.hasNextPage;\n } finally {\n if (started === generation) filesLoading.value = false;\n }\n };\n\n /**\n * Forgets the signed-in user and every conversation's media and files, for a host whose user\n * changes. The handlers stay. A page still loading for the previous user is dropped.\n */\n const reset = () => {\n generation++;\n userId.value = \"\";\n userName.value = \"\";\n userAvatar.value = undefined;\n mediaMap.value = {};\n filesMap.value = {};\n mediaPage.value = {};\n filesPage.value = {};\n mediaHasNextPage.value = {};\n filesHasNextPage.value = {};\n mediaLoading.value = false;\n filesLoading.value = false;\n };\n\n const clear = (conversationId: string) => {\n delete mediaMap.value[conversationId];\n delete filesMap.value[conversationId];\n delete mediaPage.value[conversationId];\n delete filesPage.value[conversationId];\n delete mediaHasNextPage.value[conversationId];\n delete filesHasNextPage.value[conversationId];\n };\n\n return {\n reset,\n setHandlers,\n fetchMedia,\n fetchFiles,\n clear,\n mediaMap,\n filesMap,\n mediaPage,\n filesPage,\n mediaHasNextPage,\n userId,\n userName,\n userAvatar,\n filesHasNextPage,\n mediaLoading,\n filesLoading,\n pageSize,\n };\n});\n","import generalEn from \"./en/general.json\";\nimport chatEn from \"./en/chat.json\";\nimport profileEn from \"./en/profile.json\";\nimport calendarEn from \"./en/calendar.json\";\nimport validationEn from \"./en/validation.json\";\n\nimport generalFa from \"./fa/general.json\";\nimport chatFa from \"./fa/chat.json\";\nimport profileFa from \"./fa/profile.json\";\nimport calendarFa from \"./fa/calendar.json\";\nimport validationFa from \"./fa/validation.json\";\nimport authFa from \"./fa/auth.json\";\n\nimport componentsGeneralEn from \"./en/components/general.json\";\nimport componentsGeneralFa from \"./fa/components/general.json\";\n\nimport bModalEn from \"./en/components/BModal.json\";\nimport boardColorPickerEn from \"./en/components/BoardColorPicker.json\";\nimport bubbleOptionsEn from \"./en/components/BubbleOptions.json\";\nimport callPageOverlayEn from \"./en/components/CallPageOverlay.json\";\nimport callPaintBoardEn from \"./en/components/CallPaintBoard.json\";\nimport chatBubbleEn from \"./en/components/ChatBubble.json\";\nimport chatContactDisplayEn from \"./en/components/ChatContactDisplay.json\";\nimport chatInputEn from \"./en/components/ChatInput.json\";\nimport chatListEn from \"./en/components/ChatList.json\";\nimport chatListSearchEn from \"./en/components/ChatListSearch.json\";\nimport chatMessagesEn from \"./en/components/ChatMessages.json\";\nimport chatPageEn from \"./en/components/ChatPage.json\";\nimport chatPageBarEn from \"./en/components/ChatPageBar.json\";\nimport chatProfileOverviewEn from \"./en/components/ChatProfileOverview.json\";\nimport chatViewEn from \"./en/components/ChatView.json\";\nimport inputAttachementEn from \"./en/components/InputAttachement.json\";\nimport mediaViewerEn from \"./en/components/MediaViewer.json\";\nimport permissionPopupEn from \"./en/components/PermissionPopup.json\";\nimport chatBubblesFileDisplayEn from \"./en/components/chat-bubbles_FileDisplay.json\";\nimport profileFileDisplayEn from \"./en/components/profile_FileDisplay.json\";\n\nimport bModalFa from \"./fa/components/BModal.json\";\nimport boardColorPickerFa from \"./fa/components/BoardColorPicker.json\";\nimport bubbleOptionsFa from \"./fa/components/BubbleOptions.json\";\nimport callPageOverlayFa from \"./fa/components/CallPageOverlay.json\";\nimport callPaintBoardFa from \"./fa/components/CallPaintBoard.json\";\nimport chatBubbleFa from \"./fa/components/ChatBubble.json\";\nimport chatContactDisplayFa from \"./fa/components/ChatContactDisplay.json\";\nimport chatInputFa from \"./fa/components/ChatInput.json\";\nimport chatListFa from \"./fa/components/ChatList.json\";\nimport chatListSearchFa from \"./fa/components/ChatListSearch.json\";\nimport chatMessagesFa from \"./fa/components/ChatMessages.json\";\nimport chatPageFa from \"./fa/components/ChatPage.json\";\nimport chatPageBarFa from \"./fa/components/ChatPageBar.json\";\nimport chatProfileOverviewFa from \"./fa/components/ChatProfileOverview.json\";\nimport chatViewFa from \"./fa/components/ChatView.json\";\nimport inputAttachementFa from \"./fa/components/InputAttachement.json\";\nimport mediaViewerFa from \"./fa/components/MediaViewer.json\";\nimport permissionPopupFa from \"./fa/components/PermissionPopup.json\";\nimport chatBubblesFileDisplayFa from \"./fa/components/chat-bubbles_FileDisplay.json\";\nimport profileFileDisplayFa from \"./fa/components/profile_FileDisplay.json\";\n\nexport const general = {\n en: generalEn,\n fa: generalFa,\n};\n\nexport const chat = {\n en: { ...general.en, ...chatEn },\n fa: { ...general.fa, ...chatFa },\n};\n\nexport const profile = {\n en: { ...general.en, ...profileEn },\n fa: { ...general.fa, ...profileFa },\n};\n\nexport const calendar = {\n en: { ...general.en, ...calendarEn },\n fa: { ...general.fa, ...calendarFa },\n};\n\nexport const validation = {\n en: { ...general.en, ...validationEn },\n fa: { ...general.fa, ...validationFa },\n};\n\nexport const auth = {\n en: { ...general.en },\n fa: { ...general.fa, ...authFa },\n};\n\nexport const componentsGeneral = {\n en: componentsGeneralEn,\n fa: componentsGeneralFa,\n};\n\nexport const bModal = {\n en: { ...componentsGeneral.en, ...bModalEn },\n fa: { ...componentsGeneral.fa, ...bModalFa },\n};\n\nexport const boardColorPicker = {\n en: { ...componentsGeneral.en, ...boardColorPickerEn },\n fa: { ...componentsGeneral.fa, ...boardColorPickerFa },\n};\n\nexport const bubbleOptions = {\n en: { ...componentsGeneral.en, ...bubbleOptionsEn },\n fa: { ...componentsGeneral.fa, ...bubbleOptionsFa },\n};\n\nexport const callPageOverlay = {\n en: { ...componentsGeneral.en, ...callPageOverlayEn },\n fa: { ...componentsGeneral.fa, ...callPageOverlayFa },\n};\n\nexport const callPaintBoard = {\n en: { ...componentsGeneral.en, ...callPaintBoardEn },\n fa: { ...componentsGeneral.fa, ...callPaintBoardFa },\n};\n\nexport const chatBubble = {\n en: { ...componentsGeneral.en, ...chatBubbleEn },\n fa: { ...componentsGeneral.fa, ...chatBubbleFa },\n};\n\nexport const chatContactDisplay = {\n en: { ...componentsGeneral.en, ...chatContactDisplayEn },\n fa: { ...componentsGeneral.fa, ...chatContactDisplayFa },\n};\n\nexport const chatInput = {\n en: { ...componentsGeneral.en, ...chatInputEn },\n fa: { ...componentsGeneral.fa, ...chatInputFa },\n};\n\nexport const chatList = {\n en: { ...componentsGeneral.en, ...chatListEn },\n fa: { ...componentsGeneral.fa, ...chatListFa },\n};\n\nexport const chatListSearch = {\n en: { ...componentsGeneral.en, ...chatListSearchEn },\n fa: { ...componentsGeneral.fa, ...chatListSearchFa },\n};\n\nexport const chatMessages = {\n en: { ...componentsGeneral.en, ...chatMessagesEn },\n fa: { ...componentsGeneral.fa, ...chatMessagesFa },\n};\n\nexport const chatPage = {\n en: { ...componentsGeneral.en, ...chatPageEn },\n fa: { ...componentsGeneral.fa, ...chatPageFa },\n};\n\nexport const chatPageBar = {\n en: { ...componentsGeneral.en, ...chatPageBarEn },\n fa: { ...componentsGeneral.fa, ...chatPageBarFa },\n};\n\nexport const chatProfileOverview = {\n en: { ...componentsGeneral.en, ...chatProfileOverviewEn },\n fa: { ...componentsGeneral.fa, ...chatProfileOverviewFa },\n};\n\nexport const chatView = {\n en: { ...componentsGeneral.en, ...chatViewEn },\n fa: { ...componentsGeneral.fa, ...chatViewFa },\n};\n\nexport const inputAttachement = {\n en: { ...componentsGeneral.en, ...inputAttachementEn },\n fa: { ...componentsGeneral.fa, ...inputAttachementFa },\n};\n\nexport const permissionPopup = {\n en: { ...componentsGeneral.en, ...permissionPopupEn },\n fa: { ...componentsGeneral.fa, ...permissionPopupFa },\n};\n\nexport const mediaViewer = {\n en: { ...componentsGeneral.en, ...mediaViewerEn },\n fa: { ...componentsGeneral.fa, ...mediaViewerFa },\n};\n\nexport const chatBubblesFileDisplay = {\n en: { ...componentsGeneral.en, ...chatBubblesFileDisplayEn },\n fa: { ...componentsGeneral.fa, ...chatBubblesFileDisplayFa },\n};\n\nexport const profileFileDisplay = {\n en: { ...componentsGeneral.en, ...profileFileDisplayEn },\n fa: { ...componentsGeneral.fa, ...profileFileDisplayFa },\n};\n","import { defineStore, acceptHMRUpdate } from \"pinia\";\nimport { markRaw, ref, shallowRef } from \"vue\";\nimport { CallMessageType, type CallHandlers, type CallMessageSchema } from \"~/types\";\nimport type { CallSession } from \"~/composables/call/session\";\nimport { useAppToast } from \"~/composables/useAppToast\";\nimport { useStoreI18n } from \"~/composables/useHostI18n\";\nimport { useProfileStore } from \"./profileStore\";\nimport { chat } from \"@i18n/locales\";\n\nexport const useCallStore = defineStore(\"call-modal\", () => {\n const { t } = useStoreI18n(chat);\n const { openToast } = useAppToast();\n const profileStore = useProfileStore();\n\n let handlers: CallHandlers | null = null;\n function setHandlers(val: CallHandlers) {\n handlers = val;\n }\n\n /**\n * The running call. Lives here, not in a component, so it survives the call view unmounting.\n * Null until its code has loaded: calling is fetched on first use.\n */\n const session = shallowRef<CallSession | null>(null);\n /** Bumped on every start/end, so a slow load can tell it was overtaken. */\n let attempt = 0;\n\n const timerInterval = ref<ReturnType<typeof setInterval> | null>(null);\n const channelId = ref<string | null>(null);\n const startTime = ref<number | null>(null);\n const isMinimized = ref(false);\n const isActive = ref(false);\n const elapsedTime = ref(0);\n\n const stopTimer = () => {\n if (timerInterval.value) clearInterval(timerInterval.value);\n timerInterval.value = null;\n startTime.value = null;\n };\n\n const startTimer = () => {\n stopTimer();\n startTime.value = Date.now();\n timerInterval.value = setInterval(() => {\n elapsedTime.value = Math.floor(\n (Date.now() - (startTime.value || 0)) / 1000,\n );\n }, 1000);\n };\n\n /** Starts a call in conversation `id`; `video: false` joins with the camera off. */\n const startCall = (id: string, { video = true }: { video?: boolean } = {}) => {\n // One call at a time; asking again just brings the running one back into view.\n if (isActive.value) {\n isMinimized.value = false;\n return;\n }\n if (!handlers) {\n throw new Error(\n \"[vue-chat] No call handlers: pass `call` to createChat() or use provideCallHandlers()\",\n );\n }\n\n const callHandlers = handlers;\n const current = ++attempt;\n startTimer();\n channelId.value = id;\n isActive.value = true;\n isMinimized.value = false;\n\n void import(\"~/composables/call/session\").then(({ createCallSession }) => {\n if (current !== attempt) return; // ended or restarted while loading\n const call = createCallSession({\n handlers: callHandlers,\n channel: id,\n self: {\n id: profileStore.userId,\n name: () => profileStore.userName ?? \"\",\n avatar: () => profileStore.userAvatar,\n },\n notify: (key) => openToast(t(key), \"error\"),\n video,\n });\n // Streams and connections inside must not be made deeply reactive.\n session.value = markRaw(call);\n void call.start();\n });\n };\n\n const endCall = () => {\n attempt++;\n session.value?.end();\n session.value = null;\n stopTimer();\n isActive.value = false;\n isMinimized.value = false;\n elapsedTime.value = 0;\n channelId.value = null;\n };\n\n const minimize = () => {\n isMinimized.value = true;\n };\n\n const maximize = () => {\n isMinimized.value = false;\n };\n\n /**\n * Calls running in conversations, as heard from their signalling: channel → the signalling id\n * of each participant → when they count as gone unless heard from again.\n */\n const ongoing = ref<Record<string, Record<string, { until: number; video?: boolean }>>>({});\n let sweepTimer: ReturnType<typeof setInterval> | undefined;\n\n const sweep = () => {\n const now = Date.now();\n for (const [channel, members] of Object.entries(ongoing.value)) {\n for (const [from, member] of Object.entries(members)) {\n if (member.until <= now) delete members[from];\n }\n if (!Object.keys(members).length) delete ongoing.value[channel];\n }\n if (!Object.keys(ongoing.value).length) {\n clearInterval(sweepTimer);\n sweepTimer = undefined;\n }\n };\n\n /**\n * Feeds the store a call message heard on a conversation's channel, so the header can offer to\n * join a call others are in. Hosts call it for every call message on every conversation the\n * user belongs to, not only the open one. `channel` defaults to the payload's own (`join`,\n * `signal` and `track_type` carry none). The user's own messages are ignored.\n */\n const observeCall = (\n message: CallMessageSchema,\n channel = \"channel\" in message.payload ? message.payload.channel : undefined,\n ) => {\n // Signalling ids are `<user id>:<suffix>`; `<user>:declined` is a ring turned down rather than\n // someone leaving, and `<user>:ring` a host's ring sent before the caller's session is up.\n const from = message.payload.from;\n const [user, suffix] = from.split(\":\");\n if (!channel || !user || user === profileStore.userId || suffix === \"declined\") return;\n\n if (message.type === CallMessageType.Hangup) {\n const members = ongoing.value[channel];\n if (!members) return;\n delete members[from];\n delete members[`${user}:ring`];\n if (!Object.keys(members).length) delete ongoing.value[channel];\n return;\n }\n\n const members = (ongoing.value[channel] ??= {});\n // Three missed presence beats. A message other than presence also counts, for clients that\n // send none.\n const until = Date.now() + 45_000;\n const video = message.type === CallMessageType.Presence ? message.payload.video : members[from]?.video;\n members[from] = { until, video };\n sweepTimer ??= setInterval(sweep, 5_000);\n };\n\n /** The call others are in on conversation `id`, if any: whether it is a video call. */\n const ongoingCall = (id: string | null | undefined) => {\n const members = id ? ongoing.value[id] : undefined;\n if (!members || !Object.keys(members).length) return null;\n return { video: Object.values(members).some((m) => m.video) };\n };\n\n /** Ends a running call and forgets the calls heard of elsewhere, for the next signed-in user. */\n const reset = () => {\n endCall();\n clearInterval(sweepTimer);\n sweepTimer = undefined;\n ongoing.value = {};\n };\n\n return {\n session,\n isActive,\n isMinimized,\n elapsedTime,\n channelId,\n setHandlers,\n startCall,\n endCall,\n minimize,\n maximize,\n observeCall,\n ongoingCall,\n reset,\n };\n});\n\nif (import.meta.hot) {\n import.meta.hot.accept(acceptHMRUpdate(useCallStore, import.meta.hot));\n}\n","import { ChatHandlers, Contact, StateKeys, UserRoleKey } from \"~/types\";\nimport { defineStore } from \"pinia\";\nimport { shallowReadonly } from \"vue\";\n\nconst FILTERS: StateKeys[] = [\"\", \"online\", \"ended\", \"active\"];\n\ninterface ListState {\n /** Contact ids in the order the server returned them. */\n ids: string[];\n loading: boolean;\n /** A page-1 load (first load, search, filter), as opposed to loading more. */\n refreshing: boolean;\n page: number;\n hasNextPage: boolean;\n /** The search the list was loaded with; its next pages and a return to its tab keep it. */\n search: string;\n}\n\n/** One conversation list as `conversationStates` exposes it. */\nexport interface ConversationListView {\n /** Read-only: add contacts with `addContact`, change them with `updateContact`. */\n data: readonly Contact[];\n loading: boolean;\n refreshing?: boolean;\n page: number;\n hasNextPage: boolean;\n search: string;\n}\n\nconst lastActivityOf = (contact: Contact) => {\n const date = contact.lastMessage?.date ?? contact.lastActivity;\n return date ? new Date(date).getTime() : 0;\n};\n\nconst byLastMessage = (a: Contact, b: Contact) => lastActivityOf(b) - lastActivityOf(a);\n\nexport const useChatStore = defineStore(\"chat\", () => {\n const { height: windowHeight } = useWindowSize();\n let handlers: ChatHandlers;\n const calls = ref<\n { channel: string; name: string; avatar?: string; from: string }[]\n >([]);\n\n // `handlers` is not reactive, so the UI reads this flag instead.\n const canEndConversation = ref(false);\n\n function setHandlers(val: ChatHandlers) {\n handlers = val;\n canEndConversation.value = !!val.endConversation;\n }\n\n const chatsPerPage = computed(() => {\n const h = windowHeight.value || 800;\n return Math.floor((h - 138) / 76) + 1;\n });\n\n /** @deprecated Host-specific; kept for compatibility. */\n const chosenRole = ref<UserRoleKey>(\"user\");\n /** @deprecated Host-specific; kept for compatibility. */\n const currentUserBirthDate = ref<Date | null>(null);\n const activeConversationId = ref<string | null>(null);\n const profileViewOpen = ref(false);\n const typingByConversation = ref<Record<string, string | null>>({});\n\n // --- Normalised conversations: each contact stored once, lists hold ids ---\n const contactsById = ref<Record<string, Contact>>({});\n const emptyList = (): ListState => ({\n ids: [],\n loading: false,\n refreshing: false,\n page: 0,\n hasNextPage: true,\n search: \"\",\n });\n const lists = ref<Record<StateKeys, ListState>>({\n \"\": emptyList(),\n online: emptyList(),\n ended: emptyList(),\n active: emptyList(),\n });\n\n const contactsOf = (list: ListState) =>\n list.ids.map((id) => contactsById.value[id]).filter((c): c is Contact => !!c);\n\n /**\n * Each list with its contacts resolved; the shape hosts already read. The lists are read-only\n * (writing to them warns in development), since they are rebuilt from `contactsById`.\n */\n const conversationStates = computed(\n () =>\n Object.fromEntries(\n FILTERS.map((key) => {\n const list = lists.value[key];\n return [\n key,\n {\n data: shallowReadonly(contactsOf(list)),\n loading: list.loading,\n refreshing: list.refreshing,\n page: list.page,\n hasNextPage: list.hasNextPage,\n search: list.search,\n },\n ];\n }),\n ) as Record<StateKeys, ConversationListView>,\n );\n\n /** Each list sorted newest-first, recomputed only when its contacts change. */\n const displayedContacts = computed(\n () =>\n Object.fromEntries(\n FILTERS.map((key) => [key, [...conversationStates.value[key].data].sort(byLastMessage)]),\n ) as Record<StateKeys, Contact[]>,\n );\n\n const getDisplayedContacts = (filter: StateKeys): Contact[] =>\n displayedContacts.value[filter];\n\n const getContactById = (id: string): Contact | null =>\n contactsById.value[id] ?? null;\n\n /**\n * Adds a contact the lists haven't fetched (e.g. a conversation opened from a link) to the top\n * of a list, or refreshes it if it is already known.\n */\n const addContact = (contact: Contact, filter: StateKeys = \"\") => {\n contactsById.value[contact.id] = contact;\n const list = lists.value[filter];\n if (!list.ids.includes(contact.id)) list.ids.unshift(contact.id);\n };\n\n /** Changes a contact everywhere it is listed. */\n const updateContact = (id: string, updates: Partial<Contact>) => {\n const contact = contactsById.value[id];\n if (contact) Object.assign(contact, updates);\n };\n\n const setSelectedChat = (id: string | null) => {\n activeConversationId.value = id;\n profileViewOpen.value = false;\n };\n\n const openProfile = () => {\n profileViewOpen.value = true;\n };\n\n const closeProfile = () => {\n profileViewOpen.value = false;\n };\n\n const queued: Partial<Record<StateKeys, string>> = {};\n /** Bumped by `reset`, so a load started for the previous user cannot land in the next one's lists. */\n let generation = 0;\n\n const fetchConversations = async (\n filterState: StateKeys = \"\",\n page = 1,\n search = \"\",\n ) => {\n const list = lists.value[filterState];\n\n if (list.loading) {\n // A new search or filter must not be dropped because a load is in flight; run the\n // latest one when it finishes. Loading more while busy is safely ignored.\n if (page === 1) queued[filterState] = search;\n return;\n }\n const started = generation;\n list.loading = true;\n list.refreshing = page === 1;\n try {\n const result = await handlers.fetchConversations({\n pageSize: chatsPerPage.value,\n state: filterState,\n search,\n page,\n });\n if (started !== generation) return;\n\n // The newest copy of a contact wins, whichever list it came in with.\n for (const contact of result.data) contactsById.value[contact.id] = contact;\n const ids = result.data.map((c) => c.id);\n list.ids = page === 1 ? ids : [...list.ids, ...ids.filter((id) => !list.ids.includes(id))];\n list.page = page;\n list.hasNextPage = result.hasNextPage;\n list.search = search;\n } finally {\n list.loading = false;\n list.refreshing = false;\n // After a reset `list` is detached and the queue belongs to the next user.\n const next = started === generation ? queued[filterState] : undefined;\n if (next !== undefined) {\n delete queued[filterState];\n void fetchConversations(filterState, 1, next);\n }\n }\n };\n\n const loadNextPage = async (filter: StateKeys) => {\n const list = lists.value[filter];\n if (list.hasNextPage && !list.loading) {\n await fetchConversations(filter, list.page + 1, list.search);\n }\n };\n\n const endConversation = async (id: string) => {\n if (!handlers.endConversation) return;\n await handlers.endConversation(id);\n updateContact(id, { isActive: false });\n };\n\n const deleteConversation = async (id: string) => {\n const contact = contactsById.value[id];\n // Where it was listed, to put it back if the server refuses.\n const positions = FILTERS.map((key) => [key, lists.value[key].ids.indexOf(id)] as const)\n .filter(([, index]) => index !== -1);\n\n for (const [key] of positions)\n lists.value[key].ids = lists.value[key].ids.filter((x) => x !== id);\n delete contactsById.value[id];\n\n const wasActive = activeConversationId.value === id;\n if (wasActive) {\n activeConversationId.value = null;\n profileViewOpen.value = false;\n }\n delete typingByConversation.value[id];\n\n try {\n await handlers.deleteConversation(id);\n } catch (error) {\n if (contact) contactsById.value[id] = contact;\n for (const [key, index] of positions) lists.value[key].ids.splice(index, 0, id);\n if (wasActive) activeConversationId.value = id;\n throw error;\n }\n };\n\n const unreadCount = computed(\n () =>\n Object.values(contactsById.value).filter(\n (c) => c.lastMessage && c.lastMessage.isRead === false,\n ).length,\n );\n\n /**\n * Forgets every conversation, for a host whose signed-in user changes (sign-out, switching\n * accounts) while the app keeps running. The handlers stay: they belong to the host, not the\n * user. A load still in flight for the previous user is dropped when it lands, and a list\n * mounted afterwards loads again since it starts out empty.\n */\n const reset = () => {\n generation++;\n for (const key of Object.keys(queued) as StateKeys[]) delete queued[key];\n contactsById.value = {};\n lists.value = Object.fromEntries(FILTERS.map((key) => [key, emptyList()])) as Record<StateKeys, ListState>;\n activeConversationId.value = null;\n profileViewOpen.value = false;\n typingByConversation.value = {};\n calls.value = [];\n };\n\n return {\n chosenRole,\n currentUserBirthDate,\n conversationStates,\n activeConversationId,\n profileViewOpen,\n typingByConversation,\n chatsPerPage,\n unreadCount,\n setHandlers,\n setSelectedChat,\n openProfile,\n closeProfile,\n deleteConversation,\n canEndConversation,\n endConversation,\n fetchConversations,\n loadNextPage,\n getContactById,\n getDisplayedContacts,\n updateContact,\n addContact,\n calls,\n reset,\n };\n});\n","/**\n * Re-encodes a video in the browser (WebCodecs, through mediabunny) to a smaller MP4: the long side\n * capped at 1280 px, at most 30 fps, medium quality. mediabunny is loaded on first use, so chats\n * that never send a video never download it.\n *\n * Resolves to `null` when the video should go out as it is: the browser can't encode, the file is\n * small already, a track would be lost, or the result isn't meaningfully smaller. Rejects only when\n * `signal` aborts.\n */\n\nconst MAX_SIDE = 1280;\nconst MAX_FPS = 30;\n// Below this a re-encode saves too little to be worth the wait.\nconst MIN_BYTES = 1024 * 1024;\n// The result must save at least this share of the original, or the original is sent.\nconst MIN_SAVING = 0.1;\n\nexport interface CompressVideoOptions {\n /** 0 to 1. */\n onProgress?: (progress: number) => void;\n signal?: AbortSignal;\n}\n\nexport const canCompressVideo = () =>\n typeof VideoEncoder !== \"undefined\" && typeof VideoDecoder !== \"undefined\";\n\nexport async function compressVideo(\n file: File,\n { onProgress, signal }: CompressVideoOptions = {},\n): Promise<File | null> {\n if (!canCompressVideo() || file.size < MIN_BYTES) return null;\n signal?.throwIfAborted();\n\n const mb = await import(\"mediabunny\");\n const input = new mb.Input({ source: new mb.BlobSource(file), formats: mb.ALL_FORMATS });\n\n try {\n const track = await input.getPrimaryVideoTrack();\n if (!track) return null;\n\n const [displayWidth, displayHeight] = await Promise.all([\n track.getDisplayWidth(),\n track.getDisplayHeight(),\n ]);\n const scale = Math.min(1, MAX_SIDE / Math.max(displayWidth, displayHeight));\n // Encoders want even dimensions.\n const even = (n: number) => Math.max(2, Math.round((n * scale) / 2) * 2);\n const width = even(displayWidth);\n const height = even(displayHeight);\n\n const codec = await mb.getFirstEncodableVideoCodec([\"avc\", \"vp9\", \"av1\", \"hevc\"], {\n width,\n height,\n quality: mb.QUALITY_MEDIUM,\n });\n if (!codec) return null;\n\n // Phones record at 60 fps; only ever resample down, never add frames.\n const { averagePacketRate } = await track.computePacketStats(90);\n const frameRate = averagePacketRate > MAX_FPS + 2 ? MAX_FPS : undefined;\n\n signal?.throwIfAborted();\n\n const output = new mb.Output({\n format: new mb.Mp4OutputFormat({ fastStart: \"in-memory\" }),\n target: new mb.BufferTarget(),\n });\n const conversion = await mb.Conversion.init({\n input,\n output,\n tracks: \"primary\",\n showWarnings: false,\n video: {\n width,\n height,\n fit: \"fill\",\n frameRate,\n codec,\n quality: mb.QUALITY_MEDIUM,\n forceTranscode: true,\n },\n // Copied when MP4 can carry it as it is, re-encoded otherwise.\n audio: { quality: mb.QUALITY_MEDIUM },\n });\n\n // A silent or missing picture is worse than a big file.\n if (!conversion.isValid || conversion.discardedTracks.length) return null;\n\n const abort = () => void conversion.cancel();\n signal?.addEventListener(\"abort\", abort, { once: true });\n if (onProgress) conversion.onProgress = (progress) => onProgress(progress);\n\n try {\n await conversion.execute();\n } finally {\n signal?.removeEventListener(\"abort\", abort);\n }\n\n const buffer = output.target.buffer;\n if (!buffer || buffer.byteLength > file.size * (1 - MIN_SAVING)) return null;\n\n const name = file.name.replace(/\\.[^.]*$/, \"\") + \".mp4\";\n return new File([buffer], name, { type: \"video/mp4\", lastModified: file.lastModified });\n } catch (error) {\n signal?.throwIfAborted();\n // An unreadable container or a failing encoder: send the original.\n console.warn(\"[vue-parley] video compression failed, sending the original\", error);\n return null;\n } finally {\n input.dispose();\n }\n}\n","import {\n ExtendedMessage,\n Message,\n MessagesHandlers,\n MessageReader,\n UploadProgressEvent,\n} from \"~/types\";\nimport { useAppToast } from \"~/composables/useAppToast\";\nimport { useStoreI18n } from \"~/composables/useHostI18n\";\nimport { useProfileStore } from \"./profileStore\";\nimport { useChatStore } from \"./chatStore\";\nimport { chat } from \"@i18n/locales\";\nimport { canCompressVideo, compressVideo } from \"~/utils/compressVideo\";\nimport { defineStore } from \"pinia\";\n\n// Messages compress one after another, so two albums never share the encoder.\nlet compressionQueue: Promise<unknown> = Promise.resolve();\n// A sent video's object URL → its compressed copy's, kept until the send goes through so a retry\n// doesn't compress it again.\nconst compressedUrls = new Map<string, string>();\n\nexport const useMessagesStore = defineStore(\"messages-store\", () => {\n const { t } = useStoreI18n(chat);\n const { openToast } = useAppToast();\n const chatStore = useChatStore();\n const profileStore = useProfileStore();\n const currentUserId = computed(() => profileStore.userId);\n\n let handlers: MessagesHandlers;\n\n function setHandlers(val: MessagesHandlers) {\n handlers = val;\n }\n\n const isOptionMenuOpen = ref(false);\n const isSelectMode = ref(false);\n const selectedMessages = ref<Map<string, ExtendedMessage>>(new Map());\n const uploadProgress = ref<Map<string, UploadProgressEvent>>(new Map());\n /** 0–100 per message while its videos are compressed, before the upload starts. */\n const compressionProgress = ref<Map<string, number>>(new Map());\n const replyingTo = ref<ExtendedMessage | null>(null);\n\n // Where the user left each thread, as a distance from its newest message. Not reactive: only\n // the message list reads it, when a conversation opens again.\n const scrollPositions = new Map<string, number>();\n\n // Unsent text per conversation, so switching chats never loses what was being typed.\n const drafts = ref<Record<string, string>>({});\n const setDraft = (conversationId: string, text: string) => {\n if (text.trim()) drafts.value[conversationId] = text;\n else delete drafts.value[conversationId];\n };\n\n const messagesMap = ref<Record<string, Message[]>>({});\n // Per conversation, so a fetch still running for one chat never swallows another's.\n const messagesLoadingMap = ref<Record<string, boolean>>({});\n const messagesLoading = computed(() =>\n Object.values(messagesLoadingMap.value).some(Boolean),\n );\n const messagesPageSize = ref(20);\n const messagesPage = ref<Record<string, number>>({});\n const messagesHasNextPage = ref<Record<string, boolean>>({});\n\n const selectedArray = computed(() =>\n Array.from(selectedMessages.value.values()),\n );\n\n const editWindowHours = ref(6);\n\n const canEdit = computed(() => {\n if (selectedMessages.value.size !== 1) return false;\n const msg = selectedArray.value[0];\n if (!msg) return false;\n const isMine = msg.senderId === currentUserId.value;\n const hoursPassed =\n (Date.now() - new Date(msg.date).getTime()) / (1000 * 60 * 60);\n return isMine && hoursPassed < editWindowHours.value;\n });\n\n const canDelete = computed(() => {\n if (selectedMessages.value.size === 0) return false;\n return selectedArray.value.every((msg) => {\n const isMine = msg.senderId === currentUserId.value;\n const hoursPassed =\n (Date.now() - new Date(msg.date).getTime()) / (1000 * 60 * 60);\n return isMine && hoursPassed < editWindowHours.value;\n });\n });\n\n const clearSelection = () => {\n isSelectMode.value = false;\n selectedMessages.value.clear();\n };\n\n const startSelectMode = (message: ExtendedMessage) => {\n isSelectMode.value = true;\n const newMap = new Map();\n newMap.set(message.id, message);\n selectedMessages.value = newMap;\n };\n\n const toggleSelection = (message: ExtendedMessage) => {\n const newMap = new Map(selectedMessages.value);\n if (newMap.has(message.id)) {\n newMap.delete(message.id);\n if (newMap.size === 0) isSelectMode.value = false;\n } else {\n newMap.set(message.id, message);\n }\n selectedMessages.value = newMap;\n };\n\n const triggerEdit = (message: ExtendedMessage) => {\n editingMessage.value = message;\n editBus.emit(message);\n };\n\n const copyMessageText = () => {\n // Only what was written: no sender, time or placeholder for photos, voice or files.\n const textToCopy = selectedArray.value\n .map((msg) => msg.text?.trim())\n .filter(Boolean)\n .join(\"\\n\\n\");\n if (!textToCopy) return clearActions();\n\n navigator.clipboard.writeText(textToCopy).then(() => {\n openToast(t(\"chat.copiedMessage\"), \"success\");\n });\n clearActions();\n };\n\n const triggerDelete = async (specificIds?: string[]) => {\n const targets = specificIds?.length\n ? specificIds\n : selectedArray.value.map((m) => m.id);\n if (targets.length === 0) return;\n\n // Only asks for confirmation; `confirmDelete` runs once the user accepts.\n deleteBus.emit(targets);\n clearActions();\n };\n\n const confirmDelete = async (targets: string[]) => {\n if (targets.length === 0) return;\n targets.forEach((id) => processingActions.value.set(id, \"cancel-request\"));\n\n try {\n await handlers.deleteMessages(targets);\n } finally {\n targets.forEach((id) => processingActions.value.delete(id));\n }\n };\n\n const processingActions = ref(new Map<string, string>());\n\n const isActionBusy = (messageId: string, actionKey: string) =>\n processingActions.value.get(messageId) === actionKey;\n\n const editingMessage = ref<ExtendedMessage | null>(null);\n\n const deleteBus = useEventBus<string[]>(\"chat-delete\");\n const sendBus = useEventBus<Message[]>(\"chat-send\");\n const editBus = useEventBus<ExtendedMessage>(\"edit-message\");\n const updateBus = useEventBus<{ id: string; updates: Partial<Message> }>(\n \"chat-update\",\n );\n\n const canReply = computed(() => selectedMessages.value.size <= 1);\n\n const clearActions = () => {\n clearSelection();\n replyingTo.value = null;\n editingMessage.value = null;\n };\n\n const handleRemoteAction = async (\n messageId: string,\n actionKey: string,\n apiCall: () => Promise<void>,\n ) => {\n processingActions.value.set(messageId, actionKey);\n try {\n await apiCall();\n } finally {\n processingActions.value.delete(messageId);\n }\n };\n\n /**\n * Patches one message in its own conversation. Keyed by the message's conversation rather\n * than the open one, so a send that settles after the user switched chats still lands.\n * When `updates.id` swaps a temp id for one the thread already holds (the realtime event\n * beat the send response), the temp copy is dropped instead of leaving a duplicate.\n */\n const patchMessage = (\n conversationId: string,\n id: string,\n updates: Partial<Message>,\n ) => {\n const list = messagesMap.value[conversationId];\n if (!list) return;\n const index = list.findIndex((m) => m.id === id);\n if (index === -1) return;\n\n if (updates.id && updates.id !== id && list.some((m) => m.id === updates.id)) {\n messagesMap.value[conversationId] = list.filter((_, i) => i !== index);\n return;\n }\n\n messagesMap.value[conversationId] = [\n ...list.slice(0, index),\n { ...list[index]!, ...updates },\n ...list.slice(index + 1),\n ];\n };\n\n /** Puts messages back after a failed delete, in date order. */\n const restoreMessages = (conversationId: string, restored: Message[]) => {\n const list = messagesMap.value[conversationId];\n if (!list || restored.length === 0) return;\n const present = new Set(list.map((m) => m.id));\n const merged = [...list, ...restored.filter((m) => !present.has(m.id))].sort(\n (a, b) => new Date(a.date).getTime() - new Date(b.date).getTime(),\n );\n messagesMap.value[conversationId] = merged;\n const last = merged[merged.length - 1];\n if (last) updateLastMessage(conversationId, last);\n };\n\n const markAsRead = (conversationId: string) => {\n const last = chatStore.getContactById(conversationId)?.lastMessage;\n // On the viewer's own message `isRead` means someone else read it, which opening the chat\n // says nothing about.\n const incoming = last && last.senderId !== profileStore.userId;\n chatStore.updateContact(conversationId, {\n unreadCount: 0,\n ...(incoming && { lastMessage: { ...last, isRead: true } }),\n });\n\n // The newest message that has reached the server; a send still in flight has no id yet.\n const newest = [...(messagesMap.value[conversationId] ?? [])]\n .reverse()\n .find((m) => m.isSent && !m.id.startsWith(\"tmp-\"));\n handlers.markRead?.(conversationId, newest?.id ?? last?.id).catch((error) =>\n console.error(\"[chat] failed to mark conversation as read\", error),\n );\n };\n\n /**\n * Marks the viewer's own messages in a conversation as read by someone, up to and including\n * `messageId`, for a host that learns another participant caught up (a read receipt). Messages\n * are compared by their place in the loaded thread, so `messageId` has to be one of them: the\n * newest loaded message the reader has reached.\n */\n const markSeenUpTo = (conversationId: string, messageId: string) => {\n const list = messagesMap.value[conversationId];\n const index = list?.findIndex((m) => m.id === messageId) ?? -1;\n if (!list || index === -1) return;\n\n const me = profileStore.userId;\n const seen = (m: Message, i: number) => i <= index && m.senderId === me && m.isSent && !m.isRead;\n if (list.some(seen))\n messagesMap.value[conversationId] = list.map((m, i) => (seen(m, i) ? { ...m, isRead: true } : m));\n\n const last = chatStore.getContactById(conversationId)?.lastMessage;\n if (last && last.senderId === me && !last.isRead && list.slice(0, index + 1).some((m) => m.id === last.id))\n chatStore.updateContact(conversationId, { lastMessage: { ...last, isRead: true } });\n };\n\n const canListReaders = () => !!handlers?.fetchReaders;\n\n /** Who has read one of the viewer's messages; empty when the host does not say. */\n const fetchReaders = (message: Message): Promise<MessageReader[]> =>\n handlers?.fetchReaders?.(message) ?? Promise.resolve([]);\n\n const updateLastMessage = (conversationId: string, message: Message) => {\n chatStore.updateContact(conversationId, { lastMessage: { ...message } });\n };\n\n const patchLastMessage = (\n conversationId: string,\n messageId: string,\n updates: Partial<Message>,\n ) => {\n const last = chatStore.getContactById(conversationId)?.lastMessage;\n if (last?.id === messageId)\n chatStore.updateContact(conversationId, { lastMessage: { ...last, ...updates } });\n };\n\n const sendMessage = async (messages: Message[]) => {\n const tempMessages = messages.map((m) => ({\n ...m,\n id: `tmp-${crypto.randomUUID()}`,\n isSent: false,\n }));\n\n sendBus.emit(tempMessages);\n\n if (tempMessages.length > 0) {\n const latest = tempMessages[tempMessages.length - 1]!;\n updateLastMessage(latest.conversationId, latest);\n }\n\n await Promise.all(tempMessages.map(deliver));\n };\n\n const applyUpdate = (\n conversationId: string,\n id: string,\n updates: Partial<Message>,\n ) => {\n patchMessage(conversationId, id, updates);\n patchLastMessage(conversationId, id, updates);\n updateBus.emit({ id, updates });\n };\n\n /**\n * The album as it should leave the device: each video swapped for a smaller MP4 copy where one\n * comes out smaller. The bubble keeps showing what was picked.\n */\n const compressMedia = async (message: Message): Promise<Message> => {\n const videos = (message.media ?? []).filter((item) => item.kind === \"video\");\n if (message.type !== \"image\" || !videos.length || !canCompressVideo()) return message;\n\n const { id } = message;\n compressionProgress.value.set(id, 0);\n const run = compressionQueue.then(async () => {\n for (const [index, item] of videos.entries()) {\n if (compressedUrls.has(item.url)) continue;\n const report = (p: number) =>\n compressionProgress.value.set(id, Math.round(((index + p) / videos.length) * 100));\n report(0);\n try {\n const blob = await fetch(item.url).then((r) => r.blob());\n const smaller = await compressVideo(new File([blob], \"video\", { type: blob.type }), {\n onProgress: report,\n });\n if (smaller) compressedUrls.set(item.url, URL.createObjectURL(smaller));\n } catch (error) {\n console.warn(\"[vue-parley] video compression failed, sending the original\", error);\n }\n }\n });\n compressionQueue = run;\n await run;\n compressionProgress.value.delete(id);\n\n return {\n ...message,\n media: message.media!.map((item) => ({\n ...item,\n url: compressedUrls.get(item.url) ?? item.url,\n })),\n };\n };\n\n const releaseCompressed = (message: Message) =>\n message.media?.forEach((item) => {\n const url = compressedUrls.get(item.url);\n if (!url) return;\n URL.revokeObjectURL(url);\n compressedUrls.delete(item.url);\n });\n\n const deliver = async (tempMsg: Message) => {\n const { conversationId } = tempMsg;\n const tracksProgress = tempMsg.type !== \"text\";\n try {\n const outgoing = await compressMedia(tempMsg);\n // The bubble moves straight from compressing to uploading, before the first upload event.\n if (outgoing !== tempMsg)\n uploadProgress.value.set(tempMsg.id, { progress: 0, uploaded: 0, total: 0 });\n const canonical = await handlers.sendMessage(outgoing, {\n onProgress: tracksProgress\n ? (e) => {\n if (e.progress >= 100) {\n uploadProgress.value.delete(tempMsg.id);\n } else {\n uploadProgress.value.set(tempMsg.id, {\n progress: e.progress,\n uploaded: e.uploaded,\n total: e.total,\n });\n }\n }\n : undefined,\n });\n\n uploadProgress.value.delete(tempMsg.id);\n releaseCompressed(tempMsg);\n applyUpdate(conversationId, tempMsg.id, {\n id: canonical.id,\n isSent: true,\n isFailed: false,\n });\n } catch {\n uploadProgress.value.delete(tempMsg.id);\n applyUpdate(conversationId, tempMsg.id, { isSent: false, isFailed: true });\n }\n };\n\n /** Re-sends a message whose last attempt failed, keeping its place in the thread. */\n const retryMessage = async (message: Message) => {\n // The bubble hands over its enriched copy; send the stored one.\n const stored = messagesMap.value[message.conversationId]?.find(\n (m) => m.id === message.id,\n );\n if (!stored?.isFailed || !stored.id.startsWith(\"tmp-\")) return;\n applyUpdate(stored.conversationId, stored.id, { isFailed: false });\n await deliver({ ...stored, isFailed: false });\n };\n\n const saveEditMessage = async (id: string, text: string) => {\n const original = editingMessage.value;\n const conversationId = original?.conversationId;\n clearActions();\n if (!conversationId) return;\n\n applyUpdate(conversationId, id, { text, isSent: false });\n\n try {\n await handlers.editMessage(id, text);\n applyUpdate(conversationId, id, { isSent: true, isEdited: true });\n } catch {\n // Put the old text back: the edit never reached the server, and an unsent edit has no retry.\n applyUpdate(conversationId, id, { text: original.text, isSent: true });\n openToast(t(\"chat.editFailed\"), \"error\");\n }\n };\n\n /**\n * A fresh newest page laid over the thread already loaded, as when a conversation is opened\n * again. The page replaces the stretch it covers (so edits and deletions there show), older\n * pages the user scrolled back through stay, and sends still in flight or failed keep their\n * place. Older pages are dropped only when the page is the whole thread or no longer meets\n * them (more arrived meanwhile than a page holds), which would leave a gap.\n */\n const mergeNewest = (existing: Message[], batch: Message[], pageSize: number) => {\n const isPending = (m: Message) => m.id.startsWith(\"tmp-\");\n const inBatch = new Set(batch.map((m) => m.id));\n const settled = existing.filter((m) => !isPending(m));\n const pending = existing.filter((m) => isPending(m) && !inBatch.has(m.id));\n\n const oldest = batch[0];\n const meets = settled.some((m) => inBatch.has(m.id));\n const cut = oldest ? new Date(oldest.date).getTime() : 0;\n const older =\n oldest && batch.length === pageSize && meets\n ? settled.filter((m) => !inBatch.has(m.id) && new Date(m.date).getTime() < cut)\n : [];\n\n const time = (m: Message) => new Date(m.date).getTime();\n // A stable sort: only the pending sends move, to where their date puts them.\n const list = [...older, ...batch, ...pending].sort((a, b) => time(a) - time(b));\n return { list, keptOlder: older.length > 0 };\n };\n\n const fetchMessages = async (\n conversationId: string,\n page: number = 1,\n pageSize: number = messagesPageSize.value,\n ) => {\n if (messagesLoadingMap.value[conversationId]) return;\n const started = generation;\n messagesLoadingMap.value[conversationId] = true;\n try {\n const batch = await handlers.fetchMessages({\n conversationId,\n page,\n pageSize,\n });\n if (started !== generation) return;\n\n const existing = messagesMap.value[conversationId] ?? [];\n\n if (page === 1) {\n const { list, keptOlder } = mergeNewest(existing, batch, pageSize);\n messagesMap.value[conversationId] = list;\n // Older pages still loaded keep their place, so loading more carries on from them.\n if (!keptOlder) {\n messagesPage.value[conversationId] = 1;\n messagesHasNextPage.value[conversationId] = batch.length === pageSize;\n }\n return;\n }\n\n // Pages count back from the newest message, so each one sent or received shifts them: an\n // older page can repeat messages already shown.\n const known = new Set(existing.map((m) => m.id));\n messagesMap.value[conversationId] = [...batch.filter((m) => !known.has(m.id)), ...existing];\n messagesPage.value[conversationId] = page;\n messagesHasNextPage.value[conversationId] = batch.length === pageSize;\n } finally {\n if (started === generation) delete messagesLoadingMap.value[conversationId];\n }\n };\n\n /** Bumped by `reset`, so a load started for the previous user cannot land in the next one's threads. */\n let generation = 0;\n\n /**\n * Forgets every thread, draft and pending action, for a host whose signed-in user changes. The\n * handlers stay. A send or load still in flight settles into nothing.\n */\n const reset = () => {\n generation++;\n clearActions();\n isOptionMenuOpen.value = false;\n drafts.value = {};\n scrollPositions.clear();\n messagesMap.value = {};\n messagesLoadingMap.value = {};\n messagesPage.value = {};\n messagesHasNextPage.value = {};\n uploadProgress.value = new Map();\n processingActions.value = new Map();\n };\n\n return {\n reset,\n isOptionMenuOpen,\n isSelectMode,\n selectedMessages,\n replyingTo,\n selectedArray,\n editWindowHours,\n canEdit,\n canDelete,\n clearSelection,\n startSelectMode,\n setHandlers,\n toggleSelection,\n triggerEdit,\n copyMessageText,\n triggerDelete,\n confirmDelete,\n editingMessage,\n canReply,\n deleteBus,\n sendBus,\n updateBus,\n drafts,\n scrollPositions,\n setDraft,\n sendMessage,\n retryMessage,\n patchMessage,\n restoreMessages,\n saveEditMessage,\n fetchMessages,\n markAsRead,\n markSeenUpTo,\n canListReaders,\n fetchReaders,\n updateLastMessage,\n patchLastMessage,\n messagesMap,\n messagesLoading,\n messagesLoadingMap,\n messagesPage,\n messagesPageSize,\n messagesHasNextPage,\n clearActions,\n editBus,\n processingActions,\n isActionBusy,\n handleRemoteAction,\n uploadProgress,\n compressionProgress,\n };\n});\n","import { MediaDownloadOptions, MediaHandlers } from \"~/types\";\nimport { defineStore } from \"pinia\";\n\nconst DB_NAME = \"ChatFileCache\";\n// v2 stores { blob, size, usedAt } so the cache can be kept under a size limit.\nconst DB_VERSION = 2;\nconst STORE_NAME = \"files\";\n/** Least recently used files are dropped beyond this. */\nconst MAX_CACHE_BYTES = 200 * 1024 * 1024;\n\ninterface CacheEntry {\n blob: Blob;\n size: number;\n usedAt: number;\n}\n\nconst request = <T>(req: IDBRequest<T>) =>\n new Promise<T>((resolve, reject) => {\n req.onsuccess = () => resolve(req.result);\n req.onerror = () => reject(req.error);\n });\n\n// One connection for the page, opened on first use.\nlet dbPromise: Promise<IDBDatabase> | null = null;\nconst getDB = () =>\n (dbPromise ??= new Promise<IDBDatabase>((resolve, reject) => {\n const open = indexedDB.open(DB_NAME, DB_VERSION);\n open.onupgradeneeded = () => {\n const db = open.result;\n // v1 stored bare blobs with no sizes; start over rather than guess.\n if (db.objectStoreNames.contains(STORE_NAME)) db.deleteObjectStore(STORE_NAME);\n db.createObjectStore(STORE_NAME);\n };\n open.onsuccess = () => resolve(open.result);\n open.onerror = () => {\n dbPromise = null;\n reject(open.error);\n };\n }));\n\n/** Deletes least recently used entries until the cache fits in MAX_CACHE_BYTES. */\nasync function evict(db: IDBDatabase) {\n const store = db.transaction(STORE_NAME, \"readwrite\").objectStore(STORE_NAME);\n const [keys, entries] = await Promise.all([\n request(store.getAllKeys()),\n request(store.getAll() as IDBRequest<CacheEntry[]>),\n ]);\n let total = entries.reduce((sum, e) => sum + (e?.size ?? 0), 0);\n if (total <= MAX_CACHE_BYTES) return;\n\n const byAge = keys\n .map((key, i) => ({ key, entry: entries[i]! }))\n .sort((a, b) => a.entry.usedAt - b.entry.usedAt);\n for (const { key, entry } of byAge) {\n if (total <= MAX_CACHE_BYTES) break;\n store.delete(key);\n total -= entry.size;\n }\n}\n\nexport const useMediaStore = defineStore(\"media\", () => {\n let handlers: MediaHandlers;\n\n function setHandlers(val: MediaHandlers) {\n handlers = val;\n }\n\n const getCachedBlob = async (url: string): Promise<Blob | null> => {\n try {\n const db = await getDB();\n const store = db.transaction(STORE_NAME, \"readwrite\").objectStore(STORE_NAME);\n const entry = (await request(store.get(url))) as CacheEntry | undefined;\n if (!entry) return null;\n // Mark as recently used, so eviction keeps it.\n store.put({ ...entry, usedAt: Date.now() }, url);\n return entry.blob;\n } catch {\n return null;\n }\n };\n\n const putCachedBlob = async (url: string, blob: Blob): Promise<void> => {\n try {\n const db = await getDB();\n const entry: CacheEntry = { blob, size: blob.size, usedAt: Date.now() };\n await request(\n db.transaction(STORE_NAME, \"readwrite\").objectStore(STORE_NAME).put(entry, url),\n );\n await evict(db);\n } catch {\n // cache is best-effort; ignore write failures\n }\n };\n\n const fetchFileSize = (url: string): Promise<number | null> =>\n handlers.getFileSize(url);\n\n const download = async (\n url: string,\n opts?: MediaDownloadOptions,\n ): Promise<Blob> => {\n const cached = await getCachedBlob(url);\n if (cached) {\n opts?.onProgress?.(100);\n return cached;\n }\n const started = generation;\n const blob = await handlers.download(url, opts);\n if (started === generation) await putCachedBlob(url, blob);\n return blob;\n };\n\n /** Bumped by `clearCache`, so a download started before it is not cached after it. */\n let generation = 0;\n\n /**\n * Empties the downloaded-file cache, for a host whose signed-in user changes: it holds the\n * previous user's files, which must not outlive their session on a shared device.\n */\n const clearCache = async (): Promise<void> => {\n generation++;\n try {\n const db = await getDB();\n await request(db.transaction(STORE_NAME, \"readwrite\").objectStore(STORE_NAME).clear());\n } catch {\n // Nothing cached, or IndexedDB unavailable (private mode): nothing to clear.\n }\n };\n\n return {\n clearCache,\n setHandlers,\n fetchFileSize,\n getCachedBlob,\n download,\n };\n});\n","export default \"data:image/webp;base64,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\"","<script setup lang=\"ts\">\n/** An image that shows a PrimeVue Skeleton until it loads, then fades in. Sized by its class. */\nimport { ref, watch } from \"vue\";\nimport Skeleton from \"primevue/skeleton\";\n\nconst props = withDefaults(\n defineProps<{\n src?: string;\n alt?: string;\n fit?: \"cover\" | \"contain\";\n /** Skip the skeleton, e.g. for decorative images that load from the bundle. */\n noLoading?: boolean;\n }>(),\n { src: \"\", alt: \"\", fit: \"cover\", noLoading: false },\n);\n\nconst loaded = ref(false);\nwatch(\n () => props.src,\n () => (loaded.value = false),\n);\n</script>\n\n<template>\n <div class=\"relative overflow-hidden\">\n <div v-if=\"!loaded && !noLoading\" class=\"absolute inset-0\">\n <Skeleton width=\"100%\" height=\"100%\" border-radius=\"0\" />\n </div>\n <img\n v-if=\"src\"\n :key=\"src\"\n :src=\"src\"\n :alt=\"alt\"\n draggable=\"false\"\n class=\"block size-full select-none transition-opacity duration-300\"\n :class=\"[\n fit === 'cover' ? 'object-cover' : 'object-contain',\n loaded || noLoading ? 'opacity-100' : 'opacity-0',\n ]\"\n @load=\"loaded = true\"\n @error=\"loaded = true\"\n />\n <div v-if=\"$slots.default\" class=\"absolute inset-0\">\n <slot />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport MediaImage from \"./MediaImage.vue\";\n\ndefineProps<{\n imagePath?: string;\n title?: string;\n}>();\n</script>\n<template>\n <div class=\"w-full h-full flex flex-col items-center justify-center gap-y-5\">\n <div class=\"h-50 w-50\">\n <MediaImage :src=\"imagePath\" fit=\"contain\" no-loading class=\"size-full\" />\n </div>\n <div class=\"select-none text-label-sm text-center text-chat-muted\">\n {{ title }}\n </div>\n </div>\n</template>\n","import { useI18n } from \"vue-i18n\";\nimport { computed } from \"vue\";\n\nfunction mergeLocaleObjects(objects: Record<string, any>[]) {\n return objects.reduce<Record<string, any>>((result, obj) => {\n for (const [key, value] of Object.entries(obj)) {\n result[key] = {\n ...(result[key] || {}),\n ...value,\n };\n }\n\n return result;\n }, {});\n}\n\nexport default function useLocalI18n(...messages: Record<string, any>[]) {\n return useI18n({\n useScope: \"local\",\n inheritLocale: true,\n messages: mergeLocaleObjects(messages),\n });\n}\n\nexport function useDirection() {\n const { locale } = useI18n();\n\n const dir = computed<\"rtl\" | \"ltr\">(() => {\n const currentLocale = locale.value;\n\n if (currentLocale.startsWith(\"fa\") || currentLocale.startsWith(\"ar\")) {\n return \"rtl\";\n }\n\n return \"ltr\";\n });\n\n return {\n dir,\n };\n}\n","// Generated by scripts/generate-icons.mjs from @phosphor-icons/vue; do not edit.\nexport default {\n ArrowBendUpLeft: \"<g><path d=\\\"M236,200a12,12,0,0,1-24,0,84.09,84.09,0,0,0-84-84H61l27.52,27.51a12,12,0,0,1-17,17l-48-48a12,12,0,0,1,0-17l48-48a12,12,0,0,1,17,17L61,92h67A108.12,108.12,0,0,1,236,200Z\\\"></path></g>\",\n ArrowDown: \"<g><path d=\\\"M208.49,152.49l-72,72a12,12,0,0,1-17,0l-72-72a12,12,0,0,1,17-17L116,187V40a12,12,0,0,1,24,0V187l51.51-51.52a12,12,0,0,1,17,17Z\\\"></path></g>\",\n ArrowLeft: \"<g><path d=\\\"M228,128a12,12,0,0,1-12,12H69l51.52,51.51a12,12,0,0,1-17,17l-72-72a12,12,0,0,1,0-17l72-72a12,12,0,0,1,17,17L69,116H216A12,12,0,0,1,228,128Z\\\"></path></g>\",\n ArrowRight: \"<g><path d=\\\"M224.49,136.49l-72,72a12,12,0,0,1-17-17L187,140H40a12,12,0,0,1,0-24H187L135.51,64.48a12,12,0,0,1,17-17l72,72A12,12,0,0,1,224.49,136.49Z\\\"></path></g>\",\n ArrowUUpLeft: \"<g><path d=\\\"M236,144a68.07,68.07,0,0,1-68,68H80a12,12,0,0,1,0-24h88a44,44,0,0,0,0-88H61l27.52,27.51a12,12,0,0,1-17,17l-48-48a12,12,0,0,1,0-17l48-48a12,12,0,1,1,17,17L61,76H168A68.08,68.08,0,0,1,236,144Z\\\"></path></g>\",\n ArrowUUpRight: \"<g><path d=\\\"M167.51,127.51,195,100H88a44,44,0,0,0,0,88h88a12,12,0,0,1,0,24H88A68,68,0,0,1,88,76H195L167.51,48.49a12,12,0,1,1,17-17l48,48a12,12,0,0,1,0,17l-48,48a12,12,0,0,1-17-17Z\\\"></path></g>\",\n ArrowsClockwise: \"<g><path d=\\\"M228,48V96a12,12,0,0,1-12,12H168a12,12,0,0,1,0-24h19l-7.8-7.8a75.55,75.55,0,0,0-53.32-22.26h-.43A75.49,75.49,0,0,0,72.39,75.57,12,12,0,1,1,55.61,58.41a99.38,99.38,0,0,1,69.87-28.47H126A99.42,99.42,0,0,1,196.2,59.23L204,67V48a12,12,0,0,1,24,0ZM183.61,180.43a75.49,75.49,0,0,1-53.09,21.63h-.43A75.55,75.55,0,0,1,76.77,179.8L69,172H88a12,12,0,0,0,0-24H40a12,12,0,0,0-12,12v48a12,12,0,0,0,24,0V189l7.8,7.8A99.42,99.42,0,0,0,130,226.06h.56a99.38,99.38,0,0,0,69.87-28.47,12,12,0,0,0-16.78-17.16Z\\\"></path></g>\",\n ArrowsInSimple: \"<g><path d=\\\"M216.49,56.48,177,96h19a12,12,0,0,1,0,24H148a12,12,0,0,1-12-12V60a12,12,0,0,1,24,0V79l39.51-39.52a12,12,0,0,1,17,17ZM108,136H60a12,12,0,0,0,0,24H79L39.51,199.51a12,12,0,0,0,17,17L96,177v19a12,12,0,0,0,24,0V148A12,12,0,0,0,108,136Z\\\"></path></g>\",\n Buildings: \"<g><path d=\\\"M240,204H228V96a20,20,0,0,0-20-20H172V32a20,20,0,0,0-28.45-18.12l-104,48.54A20.06,20.06,0,0,0,28,80.55V204H16a12,12,0,0,0,0,24H240a12,12,0,0,0,0-24ZM204,100V204H172V100ZM52,83.09,148,38.3V204H52ZM132,112v12a12,12,0,0,1-24,0V112a12,12,0,0,1,24,0Zm-40,0v12a12,12,0,0,1-24,0V112a12,12,0,0,1,24,0Zm0,52v12a12,12,0,0,1-24,0V164a12,12,0,0,1,24,0Zm40,0v12a12,12,0,0,1-24,0V164a12,12,0,0,1,24,0Z\\\"></path></g>\",\n Cake: \"<g><path d=\\\"M236,112a28,28,0,0,0-28-28H140V81.94A36.07,36.07,0,0,0,164,48c0-31.06-29.38-46.11-30.63-46.73a12,12,0,0,0-10.74,0C121.38,1.89,92,16.94,92,48a36.07,36.07,0,0,0,24,33.94V84H48a28,28,0,0,0-28,28v23.33a44.7,44.7,0,0,0,8,25.49V200a28,28,0,0,0,28,28H200a28,28,0,0,0,28-28V160.82a44.7,44.7,0,0,0,8-25.49ZM124,29.93a42.49,42.49,0,0,1,4-3.57,41.26,41.26,0,0,1,4,3.57c5.33,5.52,8,11.6,8,18.07a12,12,0,0,1-24,0C116,41.53,118.71,35.45,124,29.93ZM44,112a4,4,0,0,1,4-4H208a4,4,0,0,1,4,4v23.33c0,11.1-8.72,20.37-19.43,20.66A20,20,0,0,1,172,136a12,12,0,0,0-24,0,20,20,0,0,1-40,0,12,12,0,0,0-24,0,20,20,0,0,1-20.57,20C52.72,155.7,44,146.43,44,135.33Zm156,92H56a4,4,0,0,1-4-4V178.29A42.65,42.65,0,0,0,62.77,180a43.68,43.68,0,0,0,31.91-12.44c.46-.44.9-.9,1.33-1.35a44,44,0,0,0,64,0c.43.45.87.91,1.33,1.35A43.66,43.66,0,0,0,192,180l1.25,0A42.65,42.65,0,0,0,204,178.29V200A4,4,0,0,1,200,204Z\\\"></path></g>\",\n Camera: \"<g><path d=\\\"M208,52H182.42L170,33.34A12,12,0,0,0,160,28H96a12,12,0,0,0-10,5.34L73.57,52H48A28,28,0,0,0,20,80V192a28,28,0,0,0,28,28H208a28,28,0,0,0,28-28V80A28,28,0,0,0,208,52Zm4,140a4,4,0,0,1-4,4H48a4,4,0,0,1-4-4V80a4,4,0,0,1,4-4H80a12,12,0,0,0,10-5.34L102.42,52h51.15L166,70.66A12,12,0,0,0,176,76h32a4,4,0,0,1,4,4ZM128,84a48,48,0,1,0,48,48A48.05,48.05,0,0,0,128,84Zm0,72a24,24,0,1,1,24-24A24,24,0,0,1,128,156Z\\\"></path></g>\",\n CaretDown: \"<g><path d=\\\"M216.49,104.49l-80,80a12,12,0,0,1-17,0l-80-80a12,12,0,0,1,17-17L128,159l71.51-71.52a12,12,0,0,1,17,17Z\\\"></path></g>\",\n CaretLeft: \"<g><path d=\\\"M168.49,199.51a12,12,0,0,1-17,17l-80-80a12,12,0,0,1,0-17l80-80a12,12,0,0,1,17,17L97,128Z\\\"></path></g>\",\n CaretRight: \"<g><path d=\\\"M184.49,136.49l-80,80a12,12,0,0,1-17-17L159,128,87.51,56.49a12,12,0,1,1,17-17l80,80A12,12,0,0,1,184.49,136.49Z\\\"></path></g>\",\n CaretUp: \"<g><path d=\\\"M216.49,168.49a12,12,0,0,1-17,0L128,97,56.49,168.49a12,12,0,0,1-17-17l80-80a12,12,0,0,1,17,0l80,80A12,12,0,0,1,216.49,168.49Z\\\"></path></g>\",\n ChatCircleDots: \"<g><path d=\\\"M120,128a16,16,0,1,1-16-16A16,16,0,0,1,120,128Zm32-16a16,16,0,1,0,16,16A16,16,0,0,0,152,112Zm84,16A108,108,0,0,1,78.77,224.15L46.34,235A20,20,0,0,1,21,209.66l10.81-32.43A108,108,0,1,1,236,128Zm-24,0A84,84,0,1,0,55.27,170.06a12,12,0,0,1,1,9.81l-9.93,29.79,29.79-9.93a12.1,12.1,0,0,1,3.8-.62,12,12,0,0,1,6,1.62A84,84,0,0,0,212,128Z\\\"></path></g>\",\n Check: \"<g><path d=\\\"M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z\\\"></path></g>\",\n CheckCircle: \"<g><path d=\\\"M176.49,95.51a12,12,0,0,1,0,17l-56,56a12,12,0,0,1-17,0l-24-24a12,12,0,1,1,17-17L112,143l47.51-47.52A12,12,0,0,1,176.49,95.51ZM236,128A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Z\\\"></path></g>\",\n Checks: \"<g><path d=\\\"M152.41,88.56l-89.6,88a12,12,0,0,1-16.82,0L7.59,138.85a12,12,0,0,1,16.82-17.13l30,29.46,81.19-79.74a12,12,0,0,1,16.82,17.12Zm96.15-17a12,12,0,0,0-17-.15L150.4,151.18l-7.88-7.74a12,12,0,0,0-16.82,17.12l16.29,16a12,12,0,0,0,16.82,0l89.6-88A12,12,0,0,0,248.56,71.59Z\\\"></path></g>\",\n CircleNotch: \"<g><path d=\\\"M236,128a108,108,0,0,1-216,0c0-42.52,24.73-81.34,63-98.9A12,12,0,1,1,93,50.91C63.24,64.57,44,94.83,44,128a84,84,0,0,0,168,0c0-33.17-19.24-63.43-49-77.09A12,12,0,1,1,173,29.1C211.27,46.66,236,85.48,236,128Z\\\"></path></g>\",\n Clock: \"<g><path d=\\\"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Zm68-84a12,12,0,0,1-12,12H128a12,12,0,0,1-12-12V72a12,12,0,0,1,24,0v44h44A12,12,0,0,1,196,128Z\\\"></path></g>\",\n Copy: \"<g><path d=\\\"M216,28H88A12,12,0,0,0,76,40V76H40A12,12,0,0,0,28,88V216a12,12,0,0,0,12,12H168a12,12,0,0,0,12-12V180h36a12,12,0,0,0,12-12V40A12,12,0,0,0,216,28ZM156,204H52V100H156Zm48-48H180V88a12,12,0,0,0-12-12H100V52H204Z\\\"></path></g>\",\n CornersIn: \"<g><path d=\\\"M148,96V48a12,12,0,0,1,24,0V84h36a12,12,0,0,1,0,24H160A12,12,0,0,1,148,96ZM96,148H48a12,12,0,0,0,0,24H84v36a12,12,0,0,0,24,0V160A12,12,0,0,0,96,148Zm112,0H160a12,12,0,0,0-12,12v48a12,12,0,0,0,24,0V172h36a12,12,0,0,0,0-24ZM96,36A12,12,0,0,0,84,48V84H48a12,12,0,0,0,0,24H96a12,12,0,0,0,12-12V48A12,12,0,0,0,96,36Z\\\"></path></g>\",\n DotsThreeVertical: \"<g><path d=\\\"M112,60a16,16,0,1,1,16,16A16,16,0,0,1,112,60Zm16,52a16,16,0,1,0,16,16A16,16,0,0,0,128,112Zm0,68a16,16,0,1,0,16,16A16,16,0,0,0,128,180Z\\\"></path></g>\",\n DownloadSimple: \"<g><path d=\\\"M228,144v64a12,12,0,0,1-12,12H40a12,12,0,0,1-12-12V144a12,12,0,0,1,24,0v52H204V144a12,12,0,0,1,24,0Zm-108.49,8.49a12,12,0,0,0,17,0l40-40a12,12,0,0,0-17-17L140,115V32a12,12,0,0,0-24,0v83L96.49,95.51a12,12,0,0,0-17,17Z\\\"></path></g>\",\n Eraser: \"<g><path d=\\\"M216,204H141l86.84-86.84a28,28,0,0,0,0-39.6L186.43,36.19a28,28,0,0,0-39.6,0L28.19,154.82a28,28,0,0,0,0,39.6l30.06,30.07A12,12,0,0,0,66.74,228H216a12,12,0,0,0,0-24ZM163.8,53.16a4,4,0,0,1,5.66,0l41.38,41.38a4,4,0,0,1,0,5.65L160,151l-47-47ZM71.71,204,45.16,177.45a4,4,0,0,1,0-5.65L96,121l47,47-36,36Z\\\"></path></g>\",\n File: \"<g><path d=\\\"M216.49,79.52l-56-56A12,12,0,0,0,152,20H56A20,20,0,0,0,36,40V216a20,20,0,0,0,20,20H200a20,20,0,0,0,20-20V88A12,12,0,0,0,216.49,79.52ZM160,57l23,23H160ZM60,212V44h76V92a12,12,0,0,0,12,12h48V212Z\\\"></path></g>\",\n FileText: \"<g><path d=\\\"M216.49,79.52l-56-56A12,12,0,0,0,152,20H56A20,20,0,0,0,36,40V216a20,20,0,0,0,20,20H200a20,20,0,0,0,20-20V88A12,12,0,0,0,216.49,79.52ZM160,57l23,23H160ZM60,212V44h76V92a12,12,0,0,0,12,12h48V212Zm112-80a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,132Zm0,40a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,172Z\\\"></path></g>\",\n Files: \"<g><path d=\\\"M220.49,59.51l-40-40A12,12,0,0,0,172,16H92A20,20,0,0,0,72,36V56H56A20,20,0,0,0,36,76V216a20,20,0,0,0,20,20H164a20,20,0,0,0,20-20V196h20a20,20,0,0,0,20-20V68A12,12,0,0,0,220.49,59.51ZM160,212H60V80h67l33,33Zm40-40H184V108a12,12,0,0,0-3.51-8.49l-40-40A12,12,0,0,0,132,56H96V40h71l33,33Zm-56-28a12,12,0,0,1-12,12H88a12,12,0,0,1,0-24h44A12,12,0,0,1,144,144Zm0,40a12,12,0,0,1-12,12H88a12,12,0,0,1,0-24h44A12,12,0,0,1,144,184Z\\\"></path></g>\",\n FilmStrip: \"<g><path d=\\\"M216,36H40A20,20,0,0,0,20,56V200a20,20,0,0,0,20,20H216a20,20,0,0,0,20-20V56A20,20,0,0,0,216,36ZM44,100h72v56H44Zm96-24V60h24V76Zm-24,0H92V60h24Zm0,104v16H92V180Zm24,0h24v16H140Zm0-24V100h72v56Zm72-80H188V60h24ZM68,60V76H44V60ZM44,180H68v16H44Zm144,16V180h24v16Z\\\"></path></g>\",\n Flag: \"<g><path d=\\\"M40.14,46.88A12,12,0,0,0,36,56V224a12,12,0,0,0,24,0V181.72c22.84-17.12,42.1-9.12,70.68,5,16.23,8,34.74,17.2,54.8,17.2,14.72,0,30.28-4.94,46.38-18.88A12,12,0,0,0,236,176V56a12,12,0,0,0-19.86-9.07c-24.71,21.41-44.53,13.31-74.82-1.68C113.19,31.27,78.17,13.94,40.14,46.88ZM212,170.26c-22.84,17.13-42.1,9.11-70.68-5C118.16,153.76,90.33,140,60,153.87V61.69c22.84-17.12,42.1-9.12,70.68,5,16.23,8,34.74,17.2,54.8,17.2A63,63,0,0,0,212,78.08Z\\\"></path></g>\",\n FrameCorners: \"<g><path d=\\\"M140,88a12,12,0,0,1,12-12h32a12,12,0,0,1,12,12v32a12,12,0,0,1-24,0V100H152A12,12,0,0,1,140,88ZM72,180h32a12,12,0,0,0,0-24H84V136a12,12,0,0,0-24,0v32A12,12,0,0,0,72,180ZM236,56V200a20,20,0,0,1-20,20H40a20,20,0,0,1-20-20V56A20,20,0,0,1,40,36H216A20,20,0,0,1,236,56Zm-24,4H44V196H212Z\\\"></path></g>\",\n Hamburger: \"<g><path d=\\\"M227.9,152.72l-39.7,14.44-35.74-14.3a12,12,0,0,0-8.92,0L108,167.08,72.46,152.86a12,12,0,0,0-8.56-.14l-44,16a12,12,0,0,0,8.2,22.56l8.12-2.95A44.06,44.06,0,0,0,80,228h96a44.05,44.05,0,0,0,44-44v-2.87l16.1-5.85a12,12,0,0,0-8.2-22.56ZM176,204H80a20,20,0,0,1-20-20v-4.32l7.8-2.84,35.74,14.3a12,12,0,0,0,8.92,0L148,176.92l35.54,14.22a12,12,0,0,0,8.56.14l2.89-1.06A20,20,0,0,1,176,204ZM12,128a12,12,0,0,1,12-12H232a12,12,0,0,1,0,24H24A12,12,0,0,1,12,128Zm36.2-24H207.8a20.36,20.36,0,0,0,16.38-8.29,19.59,19.59,0,0,0,2.88-17.65C216.12,43.88,175.39,20,128,20S39.89,43.87,28.94,78.05A19.56,19.56,0,0,0,31.82,95.7,20.32,20.32,0,0,0,48.2,104ZM128,44c33.7,0,63.61,14.85,74,36H54C64.4,58.85,94.31,44,128,44Z\\\"></path></g>\",\n IdentificationCard: \"<g><path d=\\\"M148,108a12,12,0,0,1,12-12h28a12,12,0,0,1,0,24H160A12,12,0,0,1,148,108Zm40,28H168a12,12,0,0,0,0,24h20a12,12,0,0,0,0-24Zm48-80V200a20,20,0,0,1-20,20H40a20,20,0,0,1-20-20V56A20,20,0,0,1,40,36H216A20,20,0,0,1,236,56Zm-24,4H44V196H212ZM58.28,159.37A43.82,43.82,0,0,1,71.53,142a36,36,0,1,1,56.94,0,43.84,43.84,0,0,1,13.26,17.37,12,12,0,0,1-22.15,9.26C116.48,161.19,108.42,156,100,156s-16.47,5.2-19.59,12.63a12,12,0,1,1-22.13-9.26ZM88,120a12,12,0,1,0,12-12A12,12,0,0,0,88,120Z\\\"></path></g>\",\n Image: \"<g><path d=\\\"M144,96a16,16,0,1,1,16,16A16,16,0,0,1,144,96Zm92-40V200a20,20,0,0,1-20,20H40a20,20,0,0,1-20-20V56A20,20,0,0,1,40,36H216A20,20,0,0,1,236,56ZM44,60v79.72l33.86-33.86a20,20,0,0,1,28.28,0L147.31,147l17.18-17.17a20,20,0,0,1,28.28,0L212,149.09V60Zm0,136H162.34L92,125.66l-48,48Zm168,0V183l-33.37-33.37L164.28,164l32,32Z\\\"></path></g>\",\n Images: \"<g><path d=\\\"M160,88a16,16,0,1,1,16,16A16,16,0,0,1,160,88Zm76-32V160a20,20,0,0,1-20,20H204v20a20,20,0,0,1-20,20H40a20,20,0,0,1-20-20V88A20,20,0,0,1,40,68H60V56A20,20,0,0,1,80,36H216A20,20,0,0,1,236,56ZM180,180H80a20,20,0,0,1-20-20V92H44V196H180Zm-21.66-24L124,121.66,89.66,156ZM212,60H84v67.72l25.86-25.86a20,20,0,0,1,28.28,0L192.28,156H212Z\\\"></path></g>\",\n Info: \"<g><path d=\\\"M108,84a16,16,0,1,1,16,16A16,16,0,0,1,108,84Zm128,44A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Zm-72,36.68V132a20,20,0,0,0-20-20,12,12,0,0,0-4,23.32V168a20,20,0,0,0,20,20,12,12,0,0,0,4-23.32Z\\\"></path></g>\",\n Lightbulb: \"<g><path d=\\\"M180,232a12,12,0,0,1-12,12H88a12,12,0,0,1,0-24h80A12,12,0,0,1,180,232Zm40-128a91.51,91.51,0,0,1-35.17,72.35A12.26,12.26,0,0,0,180,186v2a20,20,0,0,1-20,20H96a20,20,0,0,1-20-20v-2a12,12,0,0,0-4.7-9.51A91.57,91.57,0,0,1,36,104.52C35.73,54.69,76,13.2,125.79,12A92,92,0,0,1,220,104Zm-24,0a68,68,0,0,0-69.65-68C89.56,36.88,59.8,67.55,60,104.38a67.71,67.71,0,0,0,26.1,53.19A35.87,35.87,0,0,1,100,184h56.1A36.13,36.13,0,0,1,170,157.49,67.68,67.68,0,0,0,196,104Zm-20.07-5.32a48.5,48.5,0,0,0-31.91-40,12,12,0,0,0-8,22.62,24.31,24.31,0,0,1,16.09,20,12,12,0,0,0,23.86-2.64Z\\\"></path></g>\",\n Lightning: \"<g><path d=\\\"M219.71,117.38a12,12,0,0,0-7.25-8.52L161.28,88.39l10.59-70.61a12,12,0,0,0-20.64-10l-112,120a12,12,0,0,0,4.31,19.33l51.18,20.47L84.13,238.22a12,12,0,0,0,20.64,10l112-120A12,12,0,0,0,219.71,117.38ZM113.6,203.55l6.27-41.77a12,12,0,0,0-7.41-12.92L68.74,131.37,142.4,52.45l-6.27,41.77a12,12,0,0,0,7.41,12.92l43.72,17.49Z\\\"></path></g>\",\n LightningSlash: \"<g><path d=\\\"M56.88,31.93A12,12,0,1,0,39.12,48.07L75.9,88.52,39.23,127.81a12,12,0,0,0,4.31,19.33l51.18,20.47L84.13,238.22a12,12,0,0,0,20.64,10l58.9-63.11,35.45,39a12,12,0,0,0,17.76-16.14ZM113.6,203.55l6.27-41.77a12,12,0,0,0-7.41-12.92L68.74,131.37l23.35-25,55.38,60.92ZM111.41,68.06a12,12,0,0,1-.59-17L151.23,7.81a12,12,0,0,1,20.64,10L161.28,88.39l51.18,20.47a12,12,0,0,1,4.31,19.33l-16.82,18a12,12,0,0,1-17.55-16.38l4.86-5.21-43.72-17.49a12,12,0,0,1-7.41-12.92l6.27-41.77-14,15A12,12,0,0,1,111.41,68.06Z\\\"></path></g>\",\n LockKey: \"<g><path d=\\\"M208,76H180V56A52,52,0,0,0,76,56V76H48A20,20,0,0,0,28,96V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V96A20,20,0,0,0,208,76ZM100,56a28,28,0,0,1,56,0V76H100ZM204,204H52V100H204Zm-76-92a32,32,0,0,0-12,61.66V180a12,12,0,0,0,24,0v-6.34A32,32,0,0,0,128,112Zm0,24a8,8,0,1,1-8,8A8,8,0,0,1,128,136Z\\\"></path></g>\",\n MagnifyingGlass: \"<g><path d=\\\"M232.49,215.51,185,168a92.12,92.12,0,1,0-17,17l47.53,47.54a12,12,0,0,0,17-17ZM44,112a68,68,0,1,1,68,68A68.07,68.07,0,0,1,44,112Z\\\"></path></g>\",\n Microphone: \"<g><path d=\\\"M128,180a52.06,52.06,0,0,0,52-52V64A52,52,0,0,0,76,64v64A52.06,52.06,0,0,0,128,180ZM100,64a28,28,0,0,1,56,0v64a28,28,0,0,1-56,0Zm40,155.22V240a12,12,0,0,1-24,0V219.22A92.14,92.14,0,0,1,36,128a12,12,0,0,1,24,0,68,68,0,0,0,136,0,12,12,0,0,1,24,0A92.14,92.14,0,0,1,140,219.22Z\\\"></path></g>\",\n MicrophoneSlash: \"<g><path d=\\\"M56.88,39.93A12,12,0,1,0,39.12,56.07L76,96.64V128a52,52,0,0,0,72.11,48l11.26,12.39A67.34,67.34,0,0,1,128,196a68.07,68.07,0,0,1-68-68,12,12,0,0,0-24,0,92.14,92.14,0,0,0,80,91.22V240a12,12,0,0,0,24,0V219.23a90.39,90.39,0,0,0,35.92-12.68l23.2,25.52a12,12,0,0,0,17.76-16.14ZM128,156a28,28,0,0,1-28-28v-5l29.9,32.89C129.27,156,128.64,156,128,156Zm63-2.42A67.63,67.63,0,0,0,196,128a12,12,0,0,1,24,0,91.48,91.48,0,0,1-6.74,34.61,12,12,0,0,1-22.23-9ZM85.7,33.75A52,52,0,0,1,180,64v56.54a12,12,0,0,1-24,0V64a28,28,0,0,0-50.79-16.28,12,12,0,0,1-19.51-14Z\\\"></path></g>\",\n Monitor: \"<g><path d=\\\"M208,36H48A28,28,0,0,0,20,64V176a28,28,0,0,0,28,28H208a28,28,0,0,0,28-28V64A28,28,0,0,0,208,36Zm4,140a4,4,0,0,1-4,4H48a4,4,0,0,1-4-4V64a4,4,0,0,1,4-4H208a4,4,0,0,1,4,4Zm-40,52a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,228Z\\\"></path></g>\",\n MonitorArrowUp: \"<g><path d=\\\"M208,36H48A28,28,0,0,0,20,64V176a28,28,0,0,0,28,28H208a28,28,0,0,0,28-28V64A28,28,0,0,0,208,36Zm4,140a4,4,0,0,1-4,4H48a4,4,0,0,1-4-4V64a4,4,0,0,1,4-4H208a4,4,0,0,1,4,4Zm-40,52a12,12,0,0,1-12,12H96a12,12,0,0,1,0-24h64A12,12,0,0,1,172,228ZM160.49,103.51a12,12,0,0,1-17,17L140,117v35a12,12,0,0,1-24,0V117l-3.51,3.52a12,12,0,0,1-17-17l24-24a12,12,0,0,1,17,0Z\\\"></path></g>\",\n Moon: \"<g><path d=\\\"M236.37,139.4a12,12,0,0,0-12-3A84.07,84.07,0,0,1,119.6,31.59a12,12,0,0,0-15-15A108.86,108.86,0,0,0,49.69,55.07,108,108,0,0,0,136,228a107.09,107.09,0,0,0,64.93-21.69,108.86,108.86,0,0,0,38.44-54.94A12,12,0,0,0,236.37,139.4Zm-49.88,47.74A84,84,0,0,1,68.86,69.51,84.93,84.93,0,0,1,92.27,48.29Q92,52.13,92,56A108.12,108.12,0,0,0,200,164q3.87,0,7.71-.27A84.79,84.79,0,0,1,186.49,187.14Z\\\"></path></g>\",\n MusicNotes: \"<g><path d=\\\"M215.38,14.54a12,12,0,0,0-10.29-2.18l-128,32A12,12,0,0,0,68,56V159.35A40,40,0,1,0,92,196V113.37l104-26v40A40,40,0,1,0,220,164V24A12,12,0,0,0,215.38,14.54ZM52,212a16,16,0,1,1,16-16A16,16,0,0,1,52,212ZM92,88.63V65.37l104-26V62.63ZM180,180a16,16,0,1,1,16-16A16,16,0,0,1,180,180Z\\\"></path></g>\",\n Palette: \"<g><path d=\\\"M203.57,51A107.9,107.9,0,0,0,20,128c0,44.72,27.6,82.25,72,97.94A36,36,0,0,0,140,192a12,12,0,0,1,12-12h46.21a35.79,35.79,0,0,0,35.1-28A108.6,108.6,0,0,0,236,127.09,107.23,107.23,0,0,0,203.57,51Zm6.34,95.67a11.91,11.91,0,0,1-11.7,9.3H152a36,36,0,0,0-36,36,12,12,0,0,1-16,11.3c-16.65-5.88-30.65-15.76-40.48-28.56A76,76,0,0,1,44,128a84,84,0,0,1,83.13-84H128a84.35,84.35,0,0,1,84,83.29A84.72,84.72,0,0,1,209.91,146.71ZM144,76a16,16,0,1,1-16-16A16,16,0,0,1,144,76Zm-44,24A16,16,0,1,1,84,84,16,16,0,0,1,100,100Zm0,56a16,16,0,1,1-16-16A16,16,0,0,1,100,156Zm88-56a16,16,0,1,1-16-16A16,16,0,0,1,188,100Z\\\"></path></g>\",\n PaperPlaneTilt: \"<g><path d=\\\"M230.14,25.86a20,20,0,0,0-19.57-5.11l-.22.07L18.44,79a20,20,0,0,0-3.06,37.25L99,157l40.71,83.65a19.81,19.81,0,0,0,18,11.38c.57,0,1.15,0,1.73-.07A19.82,19.82,0,0,0,177,237.56L235.18,45.65a1.42,1.42,0,0,0,.07-.22A20,20,0,0,0,230.14,25.86ZM156.91,221.07l-34.37-70.64,46-45.95a12,12,0,0,0-17-17l-46,46L34.93,99.09,210,46Z\\\"></path></g>\",\n Paperclip: \"<g><path d=\\\"M212.48,136.49l-82.06,82a60,60,0,0,1-84.85-84.88l98.16-97.89a40,40,0,0,1,56.56,56.59l-.17.16-95.8,92.22a12,12,0,1,1-16.64-17.3l95.71-92.12a16,16,0,0,0-22.7-22.56L62.53,150.57a36,36,0,0,0,50.93,50.91l82.06-82a12,12,0,0,1,17,17Z\\\"></path></g>\",\n Pause: \"<g><path d=\\\"M200,28H160a20,20,0,0,0-20,20V208a20,20,0,0,0,20,20h40a20,20,0,0,0,20-20V48A20,20,0,0,0,200,28Zm-4,176H164V52h32ZM96,28H56A20,20,0,0,0,36,48V208a20,20,0,0,0,20,20H96a20,20,0,0,0,20-20V48A20,20,0,0,0,96,28ZM92,204H60V52H92Z\\\"></path></g>\",\n PauseCircle: \"<g><path d=\\\"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212ZM116,96v64a12,12,0,0,1-24,0V96a12,12,0,0,1,24,0Zm48,0v64a12,12,0,0,1-24,0V96a12,12,0,0,1,24,0Z\\\"></path></g>\",\n PawPrint: \"<g><path d=\\\"M236,108a24,24,0,1,1-24-24A24,24,0,0,1,236,108ZM68,108a24,24,0,1,0-24,24A24,24,0,0,0,68,108ZM92,84A24,24,0,1,0,68,60,24,24,0,0,0,92,84Zm72,0a24,24,0,1,0-24-24A24,24,0,0,0,164,84Zm48,100a44,44,0,0,1-61.1,40.55,60.15,60.15,0,0,0-45.8,0A44,44,0,0,1,67,145.34,31.33,31.33,0,0,0,81.91,126.6a48,48,0,0,1,92.18,0A31.34,31.34,0,0,0,189,145.34,44,44,0,0,1,212,184Zm-24,0a20,20,0,0,0-10.49-17.6l-.1-.06a55.22,55.22,0,0,1-26.37-33,24,24,0,0,0-46.08,0,55.21,55.21,0,0,1-26.37,33.05l-.1.06A20,20,0,0,0,88,204a19.77,19.77,0,0,0,7.8-1.58l.13,0a84,84,0,0,1,64.14,0l.13,0A19.77,19.77,0,0,0,168,204,20,20,0,0,0,188,184Z\\\"></path></g>\",\n PencilLine: \"<g><path d=\\\"M230.15,70.54,185.46,25.86a20,20,0,0,0-28.28,0L33.86,149.17A19.86,19.86,0,0,0,28,163.31V208a20,20,0,0,0,20,20H216a12,12,0,0,0,0-24H125L230.15,98.83A20,20,0,0,0,230.15,70.54ZM136,81l11,11L76,163,65,152ZM52,204V173l15.52,15.51h0L83,204Zm52-13L93,180l71-71,11,11Zm88-88L153,64l18.34-18.34,39,39Z\\\"></path></g>\",\n PencilSimpleLine: \"<g><path d=\\\"M230.15,70.54,185.46,25.86a20,20,0,0,0-28.28,0L33.86,149.17A19.86,19.86,0,0,0,28,163.31V208a20,20,0,0,0,20,20H216a12,12,0,0,0,0-24H125L230.15,98.83A20,20,0,0,0,230.15,70.54ZM91,204H52V165l84-84,39,39ZM192,103,153,64l18.34-18.34,39,39Z\\\"></path></g>\",\n Phone: \"<g><path d=\\\"M224,154.8l-47.09-21.11-.18-.08a19.94,19.94,0,0,0-19,1.75,13.08,13.08,0,0,0-1.12.84l-22.31,19c-13-7.05-26.43-20.37-33.49-33.21l19.06-22.66a11.76,11.76,0,0,0,.85-1.15,20,20,0,0,0,1.66-18.83,1.42,1.42,0,0,1-.08-.18L101.2,32A20.06,20.06,0,0,0,80.42,20.15,60.27,60.27,0,0,0,28,80c0,81.61,66.39,148,148,148a60.27,60.27,0,0,0,59.85-52.42A20.06,20.06,0,0,0,224,154.8ZM176,204A124.15,124.15,0,0,1,52,80,36.29,36.29,0,0,1,80.48,44.46l18.82,42L80.14,109.28a12,12,0,0,0-.86,1.16A20,20,0,0,0,78,130.08c9.42,19.28,28.83,38.56,48.31,48A20,20,0,0,0,146,176.63a11.63,11.63,0,0,0,1.11-.85l22.43-19.07,42,18.81A36.29,36.29,0,0,1,176,204Z\\\"></path></g>\",\n PhoneCall: \"<g><path d=\\\"M140.41,44.9a12,12,0,0,1,14.69-8.49,90.12,90.12,0,0,1,64.49,64.49,12,12,0,1,1-23.18,6.2A66.42,66.42,0,0,0,148.9,59.59,12,12,0,0,1,140.41,44.9Zm87.44,138.68A60.27,60.27,0,0,1,168,236C86.39,236,20,169.61,20,88A60.27,60.27,0,0,1,72.42,28.15,20.05,20.05,0,0,1,93.2,40l21.11,47.13a1.42,1.42,0,0,0,.08.18,20,20,0,0,1-1.66,18.83,10.67,10.67,0,0,1-.85,1.15L92.82,130c7.06,12.84,20.5,26.16,33.49,33.21l22.31-19a13.08,13.08,0,0,1,1.12-.84,19.91,19.91,0,0,1,19-1.74l.18.08L216,162.8A20.06,20.06,0,0,1,227.85,183.58Zm-24.31-.06-42-18.81-22.43,19.07a11.63,11.63,0,0,1-1.11.85A20,20,0,0,1,118.31,186c-19.48-9.4-38.89-28.68-48.31-48a20,20,0,0,1,1.28-19.64,10.75,10.75,0,0,1,.86-1.15L91.3,94.49l-18.82-42A36.29,36.29,0,0,0,44,88,124.15,124.15,0,0,0,168,212,36.29,36.29,0,0,0,203.54,183.52ZM137.63,97.47a32,32,0,0,1,20.9,20.9,12,12,0,0,0,11.44,8.4,12.22,12.22,0,0,0,3.61-.55,12,12,0,0,0,7.84-15,56,56,0,0,0-36.59-36.59,12,12,0,1,0-7.2,22.89Z\\\"></path></g>\",\n PhoneX: \"<g><path d=\\\"M143.52,95.51,159,80,143.52,64.48a12,12,0,1,1,17-17L176,63l15.52-15.52a12,12,0,0,1,17,17L193,80l15.52,15.51a12,12,0,1,1-17,17L176,97l-15.51,15.51a12,12,0,1,1-17-17Zm84.33,88.07A60.27,60.27,0,0,1,168,236C86.39,236,20,169.61,20,88A60.27,60.27,0,0,1,72.42,28.15,20.06,20.06,0,0,1,93.2,40l21.11,47.13a1.42,1.42,0,0,0,.08.18,20,20,0,0,1-1.66,18.83,11.76,11.76,0,0,1-.85,1.15L92.82,130c7.06,12.84,20.5,26.16,33.49,33.21l22.31-19a13.08,13.08,0,0,1,1.12-.84,19.94,19.94,0,0,1,19-1.75l.18.08L216,162.8A20.06,20.06,0,0,1,227.85,183.58Zm-24.31-.06-42-18.81-22.43,19.07a11.63,11.63,0,0,1-1.11.85A20,20,0,0,1,118.31,186c-19.48-9.4-38.89-28.68-48.31-48a20,20,0,0,1,1.28-19.64,12,12,0,0,1,.86-1.16L91.3,94.49l-18.82-42A36.29,36.29,0,0,0,44,88,124.15,124.15,0,0,0,168,212,36.29,36.29,0,0,0,203.54,183.52Z\\\"></path></g>\",\n Play: \"<g><path d=\\\"M234.49,111.07,90.41,22.94A20,20,0,0,0,60,39.87V216.13a20,20,0,0,0,30.41,16.93l144.08-88.13a19.82,19.82,0,0,0,0-33.86ZM84,208.85V47.15L216.16,128Z\\\"></path></g>\",\n PlayCircle: \"<g><path d=\\\"M176,128a12,12,0,0,1-5.17,9.87l-52,36A12,12,0,0,1,100,164V92a12,12,0,0,1,18.83-9.87l52,36A12,12,0,0,1,176,128Zm60,0A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Z\\\"></path></g>\",\n Plus: \"<g><path d=\\\"M228,128a12,12,0,0,1-12,12H140v76a12,12,0,0,1-24,0V140H40a12,12,0,0,1,0-24h76V40a12,12,0,0,1,24,0v76h76A12,12,0,0,1,228,128Z\\\"></path></g>\",\n Resize: \"<g><path d=\\\"M136,108H48a12,12,0,0,0-12,12v88a12,12,0,0,0,12,12h88a12,12,0,0,0,12-12V120A12,12,0,0,0,136,108Zm-12,88H60V132h64Zm96-8v12a20,20,0,0,1-20,20H180a12,12,0,0,1,0-24h16v-8a12,12,0,0,1,24,0Zm0-72v24a12,12,0,0,1-24,0V116a12,12,0,0,1,24,0Zm0-60V72a12,12,0,0,1-24,0V60H184a12,12,0,0,1,0-24h16A20,20,0,0,1,220,56Zm-68-8a12,12,0,0,1-12,12H116a12,12,0,0,1,0-24h24A12,12,0,0,1,152,48ZM36,76V56A20,20,0,0,1,56,36H68a12,12,0,0,1,0,24H60V76a12,12,0,0,1-24,0Z\\\"></path></g>\",\n SidebarSimple: \"<g><path d=\\\"M216,36H40A20,20,0,0,0,20,56V200a20,20,0,0,0,20,20H216a20,20,0,0,0,20-20V56A20,20,0,0,0,216,36ZM44,60H76V196H44ZM212,196H100V60H212Z\\\"></path></g>\",\n Smiley: \"<g><path d=\\\"M178.39,158c-11,19.06-29.39,30-50.39,30s-39.36-10.93-50.39-30a12,12,0,0,1,20.78-12c3.89,6.73,12.91,18,29.61,18s25.72-11.28,29.61-18a12,12,0,1,1,20.78,12ZM236,128A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128ZM92,124a16,16,0,1,0-16-16A16,16,0,0,0,92,124Zm72-32a16,16,0,1,0,16,16A16,16,0,0,0,164,92Z\\\"></path></g>\",\n SoccerBall: \"<g><path d=\\\"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm71.88,151.42h-24L166.1,158l11.3-32.94L193.15,120l18.6,14.26A83.42,83.42,0,0,1,199.88,171.42ZM44.25,134.21,62.85,120l15.75,5.11L89.9,158l-9.75,13.42h-24A83.42,83.42,0,0,1,44.25,134.21ZM111.85,148l-9.54-27.77L128,102.56l25.69,17.67L144.15,148Zm80.66-73.73-6.78,22.85-15.81,5.14L140,81.69V65.46l21.22-14.59A84.27,84.27,0,0,1,192.51,74.27ZM94.78,50.87,116,65.46V81.69L86.08,102.26,70.27,97.12,63.49,74.27A84.27,84.27,0,0,1,94.78,50.87Zm13.58,158.79-8.62-24.37L109.39,172h37.22l9.65,13.29-8.62,24.37a83.59,83.59,0,0,1-39.28,0Z\\\"></path></g>\",\n SpeakerHigh: \"<g><path d=\\\"M157.27,21.22a12,12,0,0,0-12.64,1.31L75.88,76H32A20,20,0,0,0,12,96v64a20,20,0,0,0,20,20H75.88l68.75,53.47A12,12,0,0,0,164,224V32A12,12,0,0,0,157.27,21.22ZM36,100H68v56H36Zm104,99.46L92,162.13V93.87l48-37.33ZM212,128a44,44,0,0,1-11,29.11,12,12,0,1,1-18-15.88,20,20,0,0,0,0-26.43,12,12,0,0,1,18-15.86A43.94,43.94,0,0,1,212,128Zm40,0a83.87,83.87,0,0,1-21.39,56,12,12,0,0,1-17.89-16,60,60,0,0,0,0-80,12,12,0,1,1,17.88-16A83.87,83.87,0,0,1,252,128Z\\\"></path></g>\",\n SpeakerSlash: \"<g><path d=\\\"M56.88,31.93A12,12,0,1,0,39.12,48.07L64.51,76H32A20,20,0,0,0,12,96v64a20,20,0,0,0,20,20H75.88l68.75,53.47A12,12,0,0,0,164,224V185.44l35.12,38.63a12,12,0,0,0,17.76-16.14ZM36,100H68v56H36Zm104,99.46L92,162.13V106.24L140,159Zm-31-134a12,12,0,0,1,2.11-16.84l33.51-26.07A12,12,0,0,1,164,32V94.94a12,12,0,0,1-24,0V56.54l-14.15,11A12,12,0,0,1,109,65.44Zm74,49.35a12,12,0,0,1,18-15.85,44,44,0,0,1,5.55,50.21,12,12,0,0,1-21-11.55A19.67,19.67,0,0,0,188,128,20,20,0,0,0,183,114.79ZM252,128a84.18,84.18,0,0,1-19.11,53.35,12,12,0,1,1-18.53-15.25A60,60,0,0,0,212.73,88a12,12,0,1,1,17.88-16A83.87,83.87,0,0,1,252,128Z\\\"></path></g>\",\n Subtitles: \"<g><path d=\\\"M224,44H32A20,20,0,0,0,12,64V192a20,20,0,0,0,20,20H224a20,20,0,0,0,20-20V64A20,20,0,0,0,224,44Zm-4,144H36V68H220ZM48,128a12,12,0,0,1,12-12H76a12,12,0,0,1,0,24H60A12,12,0,0,1,48,128Zm56,0a12,12,0,0,1,12-12h80a12,12,0,0,1,0,24H116A12,12,0,0,1,104,128ZM48,164a12,12,0,0,1,12-12h80a12,12,0,0,1,0,24H60A12,12,0,0,1,48,164Zm160,0a12,12,0,0,1-12,12H180a12,12,0,0,1,0-24h16A12,12,0,0,1,208,164Z\\\"></path></g>\",\n SunDim: \"<g><path d=\\\"M116,36V32a12,12,0,0,1,24,0v4a12,12,0,0,1-24,0Zm80,92a68,68,0,1,1-68-68A68.07,68.07,0,0,1,196,128Zm-24,0a44,44,0,1,0-44,44A44.05,44.05,0,0,0,172,128ZM51.51,68.49a12,12,0,1,0,17-17l-4-4a12,12,0,0,0-17,17Zm0,119-4,4a12,12,0,0,0,17,17l4-4a12,12,0,1,0-17-17ZM196,72a12,12,0,0,0,8.49-3.51l4-4a12,12,0,0,0-17-17l-4,4A12,12,0,0,0,196,72Zm8.49,115.51a12,12,0,0,0-17,17l4,4a12,12,0,0,0,17-17ZM48,128a12,12,0,0,0-12-12H32a12,12,0,0,0,0,24h4A12,12,0,0,0,48,128Zm80,80a12,12,0,0,0-12,12v4a12,12,0,0,0,24,0v-4A12,12,0,0,0,128,208Zm96-92h-4a12,12,0,0,0,0,24h4a12,12,0,0,0,0-24Z\\\"></path></g>\",\n Trash: \"<g><path d=\\\"M216,48H180V36A28,28,0,0,0,152,8H104A28,28,0,0,0,76,36V48H40a12,12,0,0,0,0,24h4V208a20,20,0,0,0,20,20H192a20,20,0,0,0,20-20V72h4a12,12,0,0,0,0-24ZM100,36a4,4,0,0,1,4-4h48a4,4,0,0,1,4,4V48H100Zm88,168H68V72H188ZM116,104v64a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Zm48,0v64a12,12,0,0,1-24,0V104a12,12,0,0,1,24,0Z\\\"></path></g>\",\n TrayArrowDown: \"<g><path d=\\\"M208,28H48A20,20,0,0,0,28,48V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V48A20,20,0,0,0,208,28Zm-4,24v92H179.31a19.86,19.86,0,0,0-14.14,5.86L147,168H109L90.83,149.86A19.86,19.86,0,0,0,76.69,144H52V52ZM52,204V168H75l18.14,18.14A19.86,19.86,0,0,0,107.31,192h41.38a19.86,19.86,0,0,0,14.14-5.86L181,168h23v36Zm35.51-87.51a12,12,0,0,1,17-17L116,111V76a12,12,0,0,1,24,0v35l11.51-11.52a12,12,0,0,1,17,17l-32,32a12,12,0,0,1-17,0Z\\\"></path></g>\",\n UploadSimple: \"<g><path d=\\\"M228,144v64a12,12,0,0,1-12,12H40a12,12,0,0,1-12-12V144a12,12,0,0,1,24,0v52H204V144a12,12,0,0,1,24,0ZM96.49,80.49,116,61v83a12,12,0,0,0,24,0V61l19.51,19.52a12,12,0,1,0,17-17l-40-40a12,12,0,0,0-17,0l-40,40a12,12,0,1,0,17,17Z\\\"></path></g>\",\n Users: \"<g><path d=\\\"M125.18,156.94a64,64,0,1,0-82.36,0,100.23,100.23,0,0,0-39.49,32,12,12,0,0,0,19.35,14.2,76,76,0,0,1,122.64,0,12,12,0,0,0,19.36-14.2A100.33,100.33,0,0,0,125.18,156.94ZM44,108a40,40,0,1,1,40,40A40,40,0,0,1,44,108Zm206.1,97.67a12,12,0,0,1-16.78-2.57A76.31,76.31,0,0,0,172,172a12,12,0,0,1,0-24,40,40,0,1,0-10.3-78.67,12,12,0,1,1-6.16-23.19,64,64,0,0,1,57.64,110.8,100.23,100.23,0,0,1,39.49,32A12,12,0,0,1,250.1,205.67Z\\\"></path></g>\",\n Video: \"<g><path d=\\\"M216,36H40A20,20,0,0,0,20,56V160a20,20,0,0,0,20,20H216a20,20,0,0,0,20-20V56A20,20,0,0,0,216,36Zm-4,120H44V60H212Zm24,52a12,12,0,0,1-12,12H32a12,12,0,0,1,0-24H224A12,12,0,0,1,236,208ZM104,128V88a12,12,0,0,1,18.36-10.18l32,20a12,12,0,0,1,0,20.36l-32,20A12,12,0,0,1,104,128Z\\\"></path></g>\",\n VideoCamera: \"<g><path d=\\\"M249.45,69.31a12,12,0,0,0-12.51,1L212,88.43V72a20,20,0,0,0-20-20H32A20,20,0,0,0,12,72V184a20,20,0,0,0,20,20H192a20,20,0,0,0,20-20V167.57l24.94,18.14A12,12,0,0,0,256,176V80A12,12,0,0,0,249.45,69.31ZM188,180H36V76H188Zm44-27.57-20-14.54V118.11l20-14.54Z\\\"></path></g>\",\n VideoCameraSlash: \"<g><path d=\\\"M249.45,69.31a12,12,0,0,0-12.51,1L212,88.43V72a20,20,0,0,0-20-20H123.88a12,12,0,0,0,0,24H188v68a12,12,0,0,0,4.46,9.33c.15.13.31.25.48.38l44,32A12,12,0,0,0,256,176V80A12,12,0,0,0,249.45,69.31ZM232,152.43l-20-14.54V118.11l20-14.54ZM56.88,31.93A12,12,0,1,0,39.12,48.07L42.69,52H32A20,20,0,0,0,12,72V184a20,20,0,0,0,20,20H180.87l18.25,20.07a12,12,0,0,0,17.76-16.14ZM36,180V76H64.51l94.55,104Z\\\"></path></g>\",\n Warning: \"<g><path d=\\\"M240.26,186.1,152.81,34.23h0a28.74,28.74,0,0,0-49.62,0L15.74,186.1a27.45,27.45,0,0,0,0,27.71A28.31,28.31,0,0,0,40.55,228h174.9a28.31,28.31,0,0,0,24.79-14.19A27.45,27.45,0,0,0,240.26,186.1Zm-20.8,15.7a4.46,4.46,0,0,1-4,2.2H40.55a4.46,4.46,0,0,1-4-2.2,3.56,3.56,0,0,1,0-3.73L124,46.2a4.77,4.77,0,0,1,8,0l87.44,151.87A3.56,3.56,0,0,1,219.46,201.8ZM116,136V104a12,12,0,0,1,24,0v32a12,12,0,0,1-24,0Zm28,40a16,16,0,1,1-16-16A16,16,0,0,1,144,176Z\\\"></path></g>\",\n WarningCircle: \"<g><path d=\\\"M128,20A108,108,0,1,0,236,128,108.12,108.12,0,0,0,128,20Zm0,192a84,84,0,1,1,84-84A84.09,84.09,0,0,1,128,212Zm-12-80V80a12,12,0,0,1,24,0v52a12,12,0,0,1-24,0Zm28,40a16,16,0,1,1-16-16A16,16,0,0,1,144,172Z\\\"></path></g>\",\n WarningOctagon: \"<g><path d=\\\"M116,132V80a12,12,0,0,1,24,0v52a12,12,0,0,1-24,0ZM236,91.55v72.9a19.86,19.86,0,0,1-5.86,14.14l-51.55,51.55A19.85,19.85,0,0,1,164.45,236H91.55a19.85,19.85,0,0,1-14.14-5.86L25.86,178.59A19.86,19.86,0,0,1,20,164.45V91.55a19.86,19.86,0,0,1,5.86-14.14L77.41,25.86A19.85,19.85,0,0,1,91.55,20h72.9a19.85,19.85,0,0,1,14.14,5.86l51.55,51.55A19.86,19.86,0,0,1,236,91.55Zm-24,1.66L162.79,44H93.21L44,93.21v69.58L93.21,212h69.58L212,162.79ZM128,156a16,16,0,1,0,16,16A16,16,0,0,0,128,156Z\\\"></path></g>\",\n Waveform: \"<g><path d=\\\"M60,96v64a12,12,0,0,1-24,0V96a12,12,0,0,1,24,0ZM88,20A12,12,0,0,0,76,32V224a12,12,0,0,0,24,0V32A12,12,0,0,0,88,20Zm40,32a12,12,0,0,0-12,12V192a12,12,0,0,0,24,0V64A12,12,0,0,0,128,52Zm40,32a12,12,0,0,0-12,12v64a12,12,0,0,0,24,0V96A12,12,0,0,0,168,84Zm40-16a12,12,0,0,0-12,12v96a12,12,0,0,0,24,0V80A12,12,0,0,0,208,68Z\\\"></path></g>\",\n X: \"<g><path d=\\\"M208.49,191.51a12,12,0,0,1-17,17L128,145,64.49,208.49a12,12,0,0,1-17-17L111,128,47.51,64.49a12,12,0,0,1,17-17L128,111l63.51-63.52a12,12,0,0,1,17,17L145,128Z\\\"></path></g>\",\n XCircle: \"<g><path d=\\\"M168.49,104.49,145,128l23.52,23.51a12,12,0,0,1-17,17L128,145l-23.51,23.52a12,12,0,0,1-17-17L111,128,87.51,104.49a12,12,0,0,1,17-17L128,111l23.51-23.52a12,12,0,0,1,17,17ZM236,128A108,108,0,1,1,128,20,108.12,108.12,0,0,1,236,128Zm-24,0a84,84,0,1,0-84,84A84.09,84.09,0,0,0,212,128Z\\\"></path></g>\",\n XSquare: \"<g><path d=\\\"M208,28H48A20,20,0,0,0,28,48V208a20,20,0,0,0,20,20H208a20,20,0,0,0,20-20V48A20,20,0,0,0,208,28Zm-4,176H52V52H204ZM87.51,151.51,111,128,87.51,104.49a12,12,0,0,1,17-17L128,111l23.51-23.52a12,12,0,0,1,17,17L145,128l23.52,23.51a12,12,0,0,1-17,17L128,145l-23.51,23.52a12,12,0,0,1-17-17Z\\\"></path></g>\",\n} as Record<string, string>;\n","// Generated by scripts/generate-icons.mjs from @phosphor-icons/vue; do not edit.\nexport default {\n ArrowBendUpLeft: \"<g><path d=\\\"M232,200a8,8,0,0,1-16,0,88.1,88.1,0,0,0-88-88H88v40a8,8,0,0,1-13.66,5.66l-48-48a8,8,0,0,1,0-11.32l48-48A8,8,0,0,1,88,56V96h40A104.11,104.11,0,0,1,232,200Z\\\"></path></g>\",\n ArrowDown: \"<g><path d=\\\"M205.66,149.66l-72,72a8,8,0,0,1-11.32,0l-72-72A8,8,0,0,1,56,136h64V40a8,8,0,0,1,16,0v96h64a8,8,0,0,1,5.66,13.66Z\\\"></path></g>\",\n ArrowLeft: \"<g><path d=\\\"M224,128a8,8,0,0,1-8,8H120v64a8,8,0,0,1-13.66,5.66l-72-72a8,8,0,0,1,0-11.32l72-72A8,8,0,0,1,120,56v64h96A8,8,0,0,1,224,128Z\\\"></path></g>\",\n ArrowRight: \"<g><path d=\\\"M221.66,133.66l-72,72A8,8,0,0,1,136,200V136H40a8,8,0,0,1,0-16h96V56a8,8,0,0,1,13.66-5.66l72,72A8,8,0,0,1,221.66,133.66Z\\\"></path></g>\",\n ArrowUUpLeft: \"<g><path d=\\\"M232,144a64.07,64.07,0,0,1-64,64H80a8,8,0,0,1,0-16h88a48,48,0,0,0,0-96H88v40a8,8,0,0,1-13.66,5.66l-48-48a8,8,0,0,1,0-11.32l48-48A8,8,0,0,1,88,40V80h80A64.07,64.07,0,0,1,232,144Z\\\"></path></g>\",\n ArrowUUpRight: \"<g><path d=\\\"M168,136V96H88a48,48,0,0,0,0,96h88a8,8,0,0,1,0,16H88A64,64,0,0,1,88,80h80V40a8,8,0,0,1,13.66-5.66l48,48a8,8,0,0,1,0,11.32l-48,48A8,8,0,0,1,168,136Z\\\"></path></g>\",\n ArrowsClockwise: \"<g><path d=\\\"M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1-5.66-13.66L180.65,72a79.48,79.48,0,0,0-54.72-22.09h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27,96,96,0,0,1,192,60.7l18.36-18.36A8,8,0,0,1,224,48ZM186.41,183.29A80,80,0,0,1,75.35,184l18.31-18.31A8,8,0,0,0,88,152H40a8,8,0,0,0-8,8v48a8,8,0,0,0,13.66,5.66L64,195.3a95.42,95.42,0,0,0,66,26.76h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z\\\"></path></g>\",\n ArrowsInSimple: \"<g><path d=\\\"M120,144v48a8,8,0,0,1-13.66,5.66L88,179.31,53.66,213.66a8,8,0,0,1-11.32-11.32L76.69,168,58.34,149.66A8,8,0,0,1,64,136h48A8,8,0,0,1,120,144ZM213.66,42.34a8,8,0,0,0-11.32,0L168,76.69,149.66,58.34A8,8,0,0,0,136,64v48a8,8,0,0,0,8,8h48a8,8,0,0,0,5.66-13.66L179.31,88l34.35-34.34A8,8,0,0,0,213.66,42.34Z\\\"></path></g>\",\n Buildings: \"<g><path d=\\\"M239.73,208H224V96a16,16,0,0,0-16-16H164a4,4,0,0,0-4,4V208H144V32.41a16.43,16.43,0,0,0-6.16-13,16,16,0,0,0-18.72-.69L39.12,72A16,16,0,0,0,32,85.34V208H16.27A8.18,8.18,0,0,0,8,215.47,8,8,0,0,0,16,224H240a8,8,0,0,0,8-8.53A8.18,8.18,0,0,0,239.73,208ZM76,184a8,8,0,0,1-8.53,8A8.18,8.18,0,0,1,60,183.72V168.27A8.19,8.19,0,0,1,67.47,160,8,8,0,0,1,76,168Zm0-56a8,8,0,0,1-8.53,8A8.19,8.19,0,0,1,60,127.72V112.27A8.19,8.19,0,0,1,67.47,104,8,8,0,0,1,76,112Zm40,56a8,8,0,0,1-8.53,8,8.18,8.18,0,0,1-7.47-8.26V168.27a8.19,8.19,0,0,1,7.47-8.26,8,8,0,0,1,8.53,8Zm0-56a8,8,0,0,1-8.53,8,8.19,8.19,0,0,1-7.47-8.26V112.27a8.19,8.19,0,0,1,7.47-8.26,8,8,0,0,1,8.53,8Z\\\"></path></g>\",\n Cake: \"<g><path d=\\\"M208,88H136V79a32.06,32.06,0,0,0,24-31c0-28-26.44-45.91-27.56-46.66a8,8,0,0,0-8.88,0C122.44,2.09,96,20,96,48a32.06,32.06,0,0,0,24,31v9H48a24,24,0,0,0-24,24v23.33a40.84,40.84,0,0,0,8,24.24V200a24,24,0,0,0,24,24H200a24,24,0,0,0,24-24V159.57a40.84,40.84,0,0,0,8-24.24V112A24,24,0,0,0,208,88ZM112,48c0-13.57,10-24.46,16-29.79,6,5.33,16,16.22,16,29.79a16,16,0,0,1-32,0Zm104,87.33c0,13.25-10.46,24.31-23.32,24.66A24,24,0,0,1,168,136a8,8,0,0,0-16,0,24,24,0,0,1-48,0,8,8,0,0,0-16,0,24,24,0,0,1-24.68,24C50.46,159.64,40,148.58,40,135.33V112a8,8,0,0,1,8-8H208a8,8,0,0,1,8,8Z\\\"></path></g>\",\n Camera: \"<g><path d=\\\"M208,56H180.28L166.65,35.56A8,8,0,0,0,160,32H96a8,8,0,0,0-6.65,3.56L75.71,56H48A24,24,0,0,0,24,80V192a24,24,0,0,0,24,24H208a24,24,0,0,0,24-24V80A24,24,0,0,0,208,56Zm-44,76a36,36,0,1,1-36-36A36,36,0,0,1,164,132Z\\\"></path></g>\",\n CaretDown: \"<g><path d=\\\"M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,48,88H208a8,8,0,0,1,5.66,13.66Z\\\"></path></g>\",\n CaretLeft: \"<g><path d=\\\"M168,48V208a8,8,0,0,1-13.66,5.66l-80-80a8,8,0,0,1,0-11.32l80-80A8,8,0,0,1,168,48Z\\\"></path></g>\",\n CaretRight: \"<g><path d=\\\"M181.66,133.66l-80,80A8,8,0,0,1,88,208V48a8,8,0,0,1,13.66-5.66l80,80A8,8,0,0,1,181.66,133.66Z\\\"></path></g>\",\n CaretUp: \"<g><path d=\\\"M215.39,163.06A8,8,0,0,1,208,168H48a8,8,0,0,1-5.66-13.66l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,215.39,163.06Z\\\"></path></g>\",\n ChatCircleDots: \"<g><path d=\\\"M128,24A104,104,0,0,0,36.18,176.88L24.83,210.93a16,16,0,0,0,20.24,20.24l34.05-11.35A104,104,0,1,0,128,24ZM84,140a12,12,0,1,1,12-12A12,12,0,0,1,84,140Zm44,0a12,12,0,1,1,12-12A12,12,0,0,1,128,140Zm44,0a12,12,0,1,1,12-12A12,12,0,0,1,172,140Z\\\"></path></g>\",\n Check: \"<g><path d=\\\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM205.66,85.66l-96,96a8,8,0,0,1-11.32,0l-40-40a8,8,0,0,1,11.32-11.32L104,164.69l90.34-90.35a8,8,0,0,1,11.32,11.32Z\\\"></path></g>\",\n CheckCircle: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm45.66,85.66-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35a8,8,0,0,1,11.32,11.32Z\\\"></path></g>\",\n Checks: \"<g><path d=\\\"M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48ZM72,168a8,8,0,0,1-5.66-2.34l-24-24a8,8,0,0,1,11.32-11.32L72,148.69l58.34-58.35a8,8,0,0,1,11.32,11.32l-64,64A8,8,0,0,1,72,168Zm141.66-66.34-64,64a8,8,0,0,1-11.32,0l-16-16a8,8,0,0,1,11.32-11.32L144,148.69l58.34-58.35a8,8,0,0,1,11.32,11.32Z\\\"></path></g>\",\n CircleNotch: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,176A72,72,0,0,1,92,65.64a8,8,0,0,1,8,13.85,56,56,0,1,0,56,0,8,8,0,0,1,8-13.85A72,72,0,0,1,128,200Z\\\"></path></g>\",\n Clock: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm56,112H128a8,8,0,0,1-8-8V72a8,8,0,0,1,16,0v48h48a8,8,0,0,1,0,16Z\\\"></path></g>\",\n Copy: \"<g><path d=\\\"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32Zm-8,128H176V88a8,8,0,0,0-8-8H96V48H208Z\\\"></path></g>\",\n CornersIn: \"<g><path d=\\\"M152,96V48a8,8,0,0,1,13.66-5.66l48,48A8,8,0,0,1,208,104H160A8,8,0,0,1,152,96ZM96,152H48a8,8,0,0,0-5.66,13.66l48,48A8,8,0,0,0,104,208V160A8,8,0,0,0,96,152ZM99.06,40.61a8,8,0,0,0-8.72,1.73l-48,48A8,8,0,0,0,48,104H96a8,8,0,0,0,8-8V48A8,8,0,0,0,99.06,40.61ZM208,152H160a8,8,0,0,0-8,8v48a8,8,0,0,0,13.66,5.66l48-48A8,8,0,0,0,208,152Z\\\"></path></g>\",\n DotsThreeVertical: \"<g><path d=\\\"M160,16H96A16,16,0,0,0,80,32V224a16,16,0,0,0,16,16h64a16,16,0,0,0,16-16V32A16,16,0,0,0,160,16ZM128,208a12,12,0,1,1,12-12A12,12,0,0,1,128,208Zm0-68a12,12,0,1,1,12-12A12,12,0,0,1,128,140Zm0-68a12,12,0,1,1,12-12A12,12,0,0,1,128,72Z\\\"></path></g>\",\n DownloadSimple: \"<g><path d=\\\"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0Zm-101.66,5.66a8,8,0,0,0,11.32,0l40-40A8,8,0,0,0,168,96H136V32a8,8,0,0,0-16,0V96H88a8,8,0,0,0-5.66,13.66Z\\\"></path></g>\",\n Eraser: \"<g><path d=\\\"M225,80.4,183.6,39a24,24,0,0,0-33.94,0L31,157.66a24,24,0,0,0,0,33.94l30.06,30.06A8,8,0,0,0,66.74,224H216a8,8,0,0,0,0-16h-84.7L225,114.34A24,24,0,0,0,225,80.4ZM213.67,103,160,156.69,107.31,104,161,50.34a8,8,0,0,1,11.32,0l41.38,41.38a8,8,0,0,1,0,11.31Z\\\"></path></g>\",\n File: \"<g><path d=\\\"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM152,88V44l44,44Z\\\"></path></g>\",\n FileText: \"<g><path d=\\\"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,176H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Zm0-32H96a8,8,0,0,1,0-16h64a8,8,0,0,1,0,16Zm-8-56V44l44,44Z\\\"></path></g>\",\n Files: \"<g><path d=\\\"M213.66,66.34l-40-40A8,8,0,0,0,168,24H88A16,16,0,0,0,72,40V56H56A16,16,0,0,0,40,72V216a16,16,0,0,0,16,16H168a16,16,0,0,0,16-16V200h16a16,16,0,0,0,16-16V72A8,8,0,0,0,213.66,66.34ZM136,192H88a8,8,0,0,1,0-16h48a8,8,0,0,1,0,16Zm0-32H88a8,8,0,0,1,0-16h48a8,8,0,0,1,0,16Zm64,24H184V104a8,8,0,0,0-2.34-5.66l-40-40A8,8,0,0,0,136,56H88V40h76.69L200,75.31Z\\\"></path></g>\",\n FilmStrip: \"<g><path d=\\\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM184,56h32V72H184ZM72,200H40V184H72ZM72,72H40V56H72Zm48,128H88V184h32Zm0-128H88V56h32Zm48,128H136V184h32Zm0-128H136V56h32Zm48,128H184V184h32v16Z\\\"></path></g>\",\n Flag: \"<g><path d=\\\"M232,56V176a8,8,0,0,1-2.76,6c-15.28,13.23-29.89,18-43.82,18-18.91,0-36.57-8.74-53-16.85C105.87,170,82.79,158.61,56,179.77V224a8,8,0,0,1-16,0V56a8,8,0,0,1,2.77-6h0c36-31.18,68.31-15.21,96.79-1.12C167,62.46,190.79,74.2,218.76,50A8,8,0,0,1,232,56Z\\\"></path></g>\",\n FrameCorners: \"<g><path d=\\\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM88,192H56a8,8,0,0,1-8-8V152a8,8,0,0,1,16,0v24H88a8,8,0,0,1,0,16Zm120-88a8,8,0,0,1-16,0V80H168a8,8,0,0,1,0-16h32a8,8,0,0,1,8,8Z\\\"></path></g>\",\n Hamburger: \"<g><path d=\\\"M35.58,98.06a16,16,0,0,1-3.23-13.44C39.78,49.5,80,24,128,24s88.22,25.5,95.65,60.62A16,16,0,0,1,207.93,104H48.07A16,16,0,0,1,35.58,98.06Zm193.68,54.42-41.13,15L151,152.57a8,8,0,0,0-5.94,0l-37,14.81L71,152.57a8,8,0,0,0-5.7-.09l-44,16a8,8,0,0,0,5.47,15L40,178.69V184a40,40,0,0,0,40,40h96a40,40,0,0,0,40-40v-9.67l18.73-6.81a8,8,0,1,0-5.47-15ZM24,136H232a8,8,0,0,0,0-16H24a8,8,0,0,0,0,16Z\\\"></path></g>\",\n IdentificationCard: \"<g><path d=\\\"M112,120a16,16,0,1,1-16-16A16,16,0,0,1,112,120ZM232,56V200a16,16,0,0,1-16,16H40a16,16,0,0,1-16-16V56A16,16,0,0,1,40,40H216A16,16,0,0,1,232,56ZM135.75,166a39.76,39.76,0,0,0-17.19-23.34,32,32,0,1,0-45.12,0A39.84,39.84,0,0,0,56.25,166a8,8,0,0,0,15.5,4c2.64-10.25,13.06-18,24.25-18s21.62,7.73,24.25,18a8,8,0,1,0,15.5-4ZM200,144a8,8,0,0,0-8-8H152a8,8,0,0,0,0,16h40A8,8,0,0,0,200,144Zm0-32a8,8,0,0,0-8-8H152a8,8,0,0,0,0,16h40A8,8,0,0,0,200,112Z\\\"></path></g>\",\n Image: \"<g><path d=\\\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM156,88a12,12,0,1,1-12,12A12,12,0,0,1,156,88Zm60,112H40V160.69l46.34-46.35a8,8,0,0,1,11.32,0h0L165,181.66a8,8,0,0,0,11.32-11.32l-17.66-17.65L173,138.34a8,8,0,0,1,11.31,0L216,170.07V200Z\\\"></path></g>\",\n Images: \"<g><path d=\\\"M216,40H72A16,16,0,0,0,56,56V72H40A16,16,0,0,0,24,88V200a16,16,0,0,0,16,16H184a16,16,0,0,0,16-16V184h16a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM172,72a12,12,0,1,1-12,12A12,12,0,0,1,172,72Zm12,128H40V88H56v80a16,16,0,0,0,16,16H184Zm32-32H72V120.69l30.34-30.35a8,8,0,0,1,11.32,0L163.31,140,189,114.34a8,8,0,0,1,11.31,0L216,130.07V168Z\\\"></path></g>\",\n Info: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm-4,48a12,12,0,1,1-12,12A12,12,0,0,1,124,72Zm12,112a16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40a8,8,0,0,1,0,16Z\\\"></path></g>\",\n Lightbulb: \"<g><path d=\\\"M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-32.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z\\\"></path></g>\",\n Lightning: \"<g><path d=\\\"M213.85,125.46l-112,120a8,8,0,0,1-13.69-7l14.66-73.33L45.19,143.49a8,8,0,0,1-3-13l112-120a8,8,0,0,1,13.69,7L153.18,90.9l57.63,21.61a8,8,0,0,1,3,12.95Z\\\"></path></g>\",\n LightningSlash: \"<g><path d=\\\"M105.72,67.81a4,4,0,0,1,0-5.42l48.39-51.85a8,8,0,0,1,13.7,7L153.18,90.9l57.43,21.53a8.24,8.24,0,0,1,4.22,3.4,8,8,0,0,1-1,9.63l-25.27,27.07a4,4,0,0,1-5.88,0Zm27.76,54.32L53.92,34.62A8,8,0,1,0,42.08,45.38L81.34,88.56l-39,41.83A8.15,8.15,0,0,0,40,135.31a8,8,0,0,0,5.16,8.18l57.63,21.61L88.16,238.43a8,8,0,0,0,13.69,7l61.86-66.28,38.37,42.2a8,8,0,1,0,11.84-10.76Z\\\"></path></g>\",\n LockKey: \"<g><path d=\\\"M208,80H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80Zm-72,78.63V184a8,8,0,0,1-16,0V158.63a24,24,0,1,1,16,0ZM160,80H96V56a32,32,0,0,1,64,0Z\\\"></path></g>\",\n MagnifyingGlass: \"<g><path d=\\\"M168,112a56,56,0,1,1-56-56A56,56,0,0,1,168,112Zm61.66,117.66a8,8,0,0,1-11.32,0l-50.06-50.07a88,88,0,1,1,11.32-11.31l50.06,50.06A8,8,0,0,1,229.66,229.66ZM112,184a72,72,0,1,0-72-72A72.08,72.08,0,0,0,112,184Z\\\"></path></g>\",\n Microphone: \"<g><path d=\\\"M80,128V64a48,48,0,0,1,96,0v64a48,48,0,0,1-96,0Zm128,0a8,8,0,0,0-16,0,64,64,0,0,1-128,0,8,8,0,0,0-16,0,80.11,80.11,0,0,0,72,79.6V240a8,8,0,0,0,16,0V207.6A80.11,80.11,0,0,0,208,128Z\\\"></path></g>\",\n MicrophoneSlash: \"<g><path d=\\\"M213.38,229.92a8,8,0,0,1-11.3-.54l-30.92-34A78.83,78.83,0,0,1,136,207.59V240a8,8,0,0,1-16,0V207.6A80.11,80.11,0,0,1,48,128a8,8,0,0,1,16,0,64.07,64.07,0,0,0,64,64,63.41,63.41,0,0,0,32.21-8.68l-11.1-12.2A48,48,0,0,1,80,128V95.09L42.08,53.38A8,8,0,0,1,53.92,42.62l160,176A8,8,0,0,1,213.38,229.92Zm-24.19-63.13a7.88,7.88,0,0,0,3.51.82,8,8,0,0,0,7.19-4.49A79.16,79.16,0,0,0,208,128a8,8,0,0,0-16,0,63.32,63.32,0,0,1-6.48,28.09A8,8,0,0,0,189.19,166.79Zm-27.33-29.22A8,8,0,0,0,175.74,133a49.49,49.49,0,0,0,.26-5V64A48,48,0,0,0,84,44.87a8,8,0,0,0,1.41,8.57Z\\\"></path></g>\",\n Monitor: \"<g><path d=\\\"M232,64V176a24,24,0,0,1-24,24H48a24,24,0,0,1-24-24V64A24,24,0,0,1,48,40H208A24,24,0,0,1,232,64ZM160,216H96a8,8,0,0,0,0,16h64a8,8,0,0,0,0-16Z\\\"></path></g>\",\n MonitorArrowUp: \"<g><path d=\\\"M168,224a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,224ZM232,64V176a24,24,0,0,1-24,24H48a24,24,0,0,1-24-24V64A24,24,0,0,1,48,40H208A24,24,0,0,1,232,64Zm-74.34,42.34-24-24a8,8,0,0,0-11.32,0l-24,24a8,8,0,0,0,11.32,11.32L120,107.31V152a8,8,0,0,0,16,0V107.31l10.34,10.35a8,8,0,0,0,11.32-11.32Z\\\"></path></g>\",\n Moon: \"<g><path d=\\\"M235.54,150.21a104.84,104.84,0,0,1-37,52.91A104,104,0,0,1,32,120,103.09,103.09,0,0,1,52.88,57.48a104.84,104.84,0,0,1,52.91-37,8,8,0,0,1,10,10,88.08,88.08,0,0,0,109.8,109.8,8,8,0,0,1,10,10Z\\\"></path></g>\",\n MusicNotes: \"<g><path d=\\\"M212.92,17.71a7.89,7.89,0,0,0-6.86-1.46l-128,32A8,8,0,0,0,72,56V166.1A36,36,0,1,0,88,196V102.25l112-28V134.1A36,36,0,1,0,216,164V24A8,8,0,0,0,212.92,17.71Z\\\"></path></g>\",\n Palette: \"<g><path d=\\\"M200.77,53.89A103.27,103.27,0,0,0,128,24h-1.07A104,104,0,0,0,24,128c0,43,26.58,79.06,69.36,94.17A32,32,0,0,0,136,192a16,16,0,0,1,16-16h46.21a31.81,31.81,0,0,0,31.2-24.88,104.43,104.43,0,0,0,2.59-24A103.28,103.28,0,0,0,200.77,53.89ZM84,168a12,12,0,1,1,12-12A12,12,0,0,1,84,168Zm0-56a12,12,0,1,1,12-12A12,12,0,0,1,84,112Zm44-24a12,12,0,1,1,12-12A12,12,0,0,1,128,88Zm44,24a12,12,0,1,1,12-12A12,12,0,0,1,172,112Z\\\"></path></g>\",\n PaperPlaneTilt: \"<g><path d=\\\"M231.4,44.34s0,.1,0,.15l-58.2,191.94a15.88,15.88,0,0,1-14,11.51q-.69.06-1.38.06a15.86,15.86,0,0,1-14.42-9.15L107,164.15a4,4,0,0,1,.77-4.58l57.92-57.92a8,8,0,0,0-11.31-11.31L96.43,148.26a4,4,0,0,1-4.58.77L17.08,112.64a16,16,0,0,1,2.49-29.8l191.94-58.2.15,0A16,16,0,0,1,231.4,44.34Z\\\"></path></g>\",\n Paperclip: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm37.66,50.34a8,8,0,0,0-11.32,0L87.09,143A24,24,0,1,0,121,177l49.32-50.32a8,8,0,1,1,11.42,11.2l-49.37,50.38a40,40,0,1,1-56.62-56.51L143,63.09A24,24,0,1,1,177,97L109.71,165.6a8,8,0,1,1-11.42-11.2L165.6,85.71a8,8,0,0,0,.06-11.37Z\\\"></path></g>\",\n Pause: \"<g><path d=\\\"M216,48V208a16,16,0,0,1-16,16H160a16,16,0,0,1-16-16V48a16,16,0,0,1,16-16h40A16,16,0,0,1,216,48ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Z\\\"></path></g>\",\n PauseCircle: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.13,104.13,0,0,0,128,24ZM112,160a8,8,0,0,1-16,0V96a8,8,0,0,1,16,0Zm48,0a8,8,0,0,1-16,0V96a8,8,0,0,1,16,0Z\\\"></path></g>\",\n PawPrint: \"<g><path d=\\\"M240,108a28,28,0,1,1-28-28A28,28,0,0,1,240,108ZM72,108a28,28,0,1,0-28,28A28,28,0,0,0,72,108ZM92,88A28,28,0,1,0,64,60,28,28,0,0,0,92,88Zm72,0a28,28,0,1,0-28-28A28,28,0,0,0,164,88Zm23.12,60.86a35.3,35.3,0,0,1-16.87-21.14,44,44,0,0,0-84.5,0A35.25,35.25,0,0,1,69,148.82,40,40,0,0,0,88,224a39.48,39.48,0,0,0,15.52-3.13,64.09,64.09,0,0,1,48.87,0,40,40,0,0,0,34.73-72Z\\\"></path></g>\",\n PencilLine: \"<g><path d=\\\"M227.32,73.37,182.63,28.69a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H216a8,8,0,0,0,0-16H115.32l112-112A16,16,0,0,0,227.32,73.37ZM79.32,188l90.34-90.34,16.69,16.68L96,204.69Zm79-101.66h0L68,176.69,51.31,160l90.35-90.34ZM48,179.31,76.69,208H48Z\\\"></path></g>\",\n PencilSimpleLine: \"<g><path d=\\\"M227.32,73.37,182.63,28.69a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H216a8,8,0,0,0,0-16H115.32l112-112A16,16,0,0,0,227.32,73.37ZM192,108.69,147.32,64l24-24L216,84.69Z\\\"></path></g>\",\n Phone: \"<g><path d=\\\"M231.88,175.08A56.26,56.26,0,0,1,176,224C96.6,224,32,159.4,32,80A56.26,56.26,0,0,1,80.92,24.12a16,16,0,0,1,16.62,9.52l21.12,47.15,0,.12A16,16,0,0,1,117.39,96c-.18.27-.37.52-.57.77L96,121.45c7.49,15.22,23.41,31,38.83,38.51l24.34-20.71a8.12,8.12,0,0,1,.75-.56,16,16,0,0,1,15.17-1.4l.13.06,47.11,21.11A16,16,0,0,1,231.88,175.08Z\\\"></path></g>\",\n PhoneCall: \"<g><path d=\\\"M144.27,45.93a8,8,0,0,1,9.8-5.66,86.22,86.22,0,0,1,61.66,61.66,8,8,0,0,1-5.66,9.8A8.23,8.23,0,0,1,208,112a8,8,0,0,1-7.73-5.93,70.35,70.35,0,0,0-50.33-50.34A8,8,0,0,1,144.27,45.93Zm-2.33,41.8c13.79,3.68,22.65,12.55,26.33,26.34A8,8,0,0,0,176,120a8.23,8.23,0,0,0,2.07-.27,8,8,0,0,0,5.66-9.8c-5.12-19.16-18.5-32.54-37.66-37.66a8,8,0,1,0-4.13,15.46Zm72.43,78.73-47.11-21.11-.13-.06a16,16,0,0,0-15.17,1.4,8.12,8.12,0,0,0-.75.56L126.87,168c-15.42-7.49-31.34-23.29-38.83-38.51l20.78-24.71c.2-.25.39-.5.57-.77a16,16,0,0,0,1.32-15.06l0-.12L89.54,41.64a16,16,0,0,0-16.62-9.52A56.26,56.26,0,0,0,24,88c0,79.4,64.6,144,144,144a56.26,56.26,0,0,0,55.88-48.92A16,16,0,0,0,214.37,166.46Z\\\"></path></g>\",\n PhoneX: \"<g><path d=\\\"M146.34,98.34,164.69,80,146.34,61.66a8,8,0,0,1,11.32-11.32L176,68.69l18.34-18.35a8,8,0,0,1,11.32,11.32L187.32,80l18.34,18.34a8,8,0,0,1-11.32,11.32L176,91.31l-18.34,18.35a8,8,0,0,1-11.32-11.32Zm68,68.12-47.11-21.11-.13-.06a16,16,0,0,0-15.17,1.4,8.12,8.12,0,0,0-.75.56L126.87,168c-15.42-7.49-31.34-23.29-38.83-38.51l20.78-24.71c.2-.25.39-.5.57-.77a16,16,0,0,0,1.32-15.06l0-.12L89.54,41.64a16,16,0,0,0-16.62-9.52A56.26,56.26,0,0,0,24,88c0,79.4,64.6,144,144,144a56.26,56.26,0,0,0,55.88-48.92A16,16,0,0,0,214.37,166.46Z\\\"></path></g>\",\n Play: \"<g><path d=\\\"M240,128a15.74,15.74,0,0,1-7.6,13.51L88.32,229.65a16,16,0,0,1-16.2.3A15.86,15.86,0,0,1,64,216.13V39.87a15.86,15.86,0,0,1,8.12-13.82,16,16,0,0,1,16.2.3L232.4,114.49A15.74,15.74,0,0,1,240,128Z\\\"></path></g>\",\n PlayCircle: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm40.55,110.58-52,36A8,8,0,0,1,104,164V92a8,8,0,0,1,12.55-6.58l52,36a8,8,0,0,1,0,13.16Z\\\"></path></g>\",\n Plus: \"<g><path d=\\\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM184,136H136v48a8,8,0,0,1-16,0V136H72a8,8,0,0,1,0-16h48V72a8,8,0,0,1,16,0v48h48a8,8,0,0,1,0,16Z\\\"></path></g>\",\n Resize: \"<g><path d=\\\"M144,120v88a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V120a8,8,0,0,1,8-8h88A8,8,0,0,1,144,120Zm64,56a8,8,0,0,0-8,8v16H176a8,8,0,0,0,0,16h24a16,16,0,0,0,16-16V184A8,8,0,0,0,208,176Zm0-72a8,8,0,0,0-8,8v32a8,8,0,0,0,16,0V112A8,8,0,0,0,208,104Zm-8-64H184a8,8,0,0,0,0,16h16V72a8,8,0,0,0,16,0V56A16,16,0,0,0,200,40Zm-56,0H112a8,8,0,0,0,0,16h32a8,8,0,0,0,0-16ZM48,88a8,8,0,0,0,8-8V56H72a8,8,0,0,0,0-16H56A16,16,0,0,0,40,56V80A8,8,0,0,0,48,88Z\\\"></path></g>\",\n SidebarSimple: \"<g><path d=\\\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,160H88V56H216V200Z\\\"></path></g>\",\n Smiley: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24ZM92,96a12,12,0,1,1-12,12A12,12,0,0,1,92,96Zm82.92,60c-10.29,17.79-27.39,28-46.92,28s-36.63-10.2-46.92-28a8,8,0,1,1,13.84-8c7.47,12.91,19.21,20,33.08,20s25.61-7.1,33.08-20a8,8,0,1,1,13.84,8ZM164,120a12,12,0,1,1,12-12A12,12,0,0,1,164,120Z\\\"></path></g>\",\n SoccerBall: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm8,39.38,24.79-17.05a88.41,88.41,0,0,1,36.18,27l-8,26.94c-.2,0-.41.1-.61.17l-22.82,7.41a7.59,7.59,0,0,0-1,.4L136,88.62c0-.2,0-.41,0-.62V64C136,63.79,136,63.58,136,63.38ZM95.24,46.33,120,63.38c0,.2,0,.41,0,.62V88c0,.21,0,.42,0,.62L91.44,108.29a7.59,7.59,0,0,0-1-.4l-22.82-7.41c-.2-.07-.41-.12-.61-.17l-8-26.94A88.41,88.41,0,0,1,95.24,46.33Zm-13,129.09H53.9a87.4,87.4,0,0,1-13.79-43.07l22-16.88a5.77,5.77,0,0,0,.58.22l22.83,7.42a7.83,7.83,0,0,0,.93.22l10.79,31.42c-.15.18-.3.36-.44.55L82.7,174.71A7.8,7.8,0,0,0,82.24,175.42ZM150.69,213a88.16,88.16,0,0,1-45.38,0L95.25,184.6c.13-.16.27-.31.39-.48l14.11-19.42a7.66,7.66,0,0,0,.46-.7h35.58a7.66,7.66,0,0,0,.46.7l14.11,19.42c.12.17.26.32.39.48Zm23.07-37.61a7.8,7.8,0,0,0-.46-.71L159.19,155.3c-.14-.19-.29-.37-.44-.55l10.79-31.42a7.83,7.83,0,0,0,.93-.22l22.83-7.42a5.77,5.77,0,0,0,.58-.22l22,16.88a87.4,87.4,0,0,1-13.79,43.07Z\\\"></path></g>\",\n SpeakerHigh: \"<g><path d=\\\"M160,32.25V223.69a8.29,8.29,0,0,1-3.91,7.18,8,8,0,0,1-9-.56l-65.57-51A4,4,0,0,1,80,176.16V79.84a4,4,0,0,1,1.55-3.15l65.57-51a8,8,0,0,1,10,.16A8.27,8.27,0,0,1,160,32.25ZM60,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H60a4,4,0,0,0,4-4V84A4,4,0,0,0,60,80Zm126.77,20.84a8,8,0,0,0-.72,11.3,24,24,0,0,1,0,31.72,8,8,0,1,0,12,10.58,40,40,0,0,0,0-52.88A8,8,0,0,0,186.74,100.84Zm40.89-26.17a8,8,0,1,0-11.92,10.66,64,64,0,0,1,0,85.34,8,8,0,1,0,11.92,10.66,80,80,0,0,0,0-106.66Z\\\"></path></g>\",\n SpeakerSlash: \"<g><path d=\\\"M213.92,210.62a8,8,0,1,1-11.84,10.76L160,175.09v48.6a8.29,8.29,0,0,1-3.91,7.18,8,8,0,0,1-9-.56l-65.55-51A4,4,0,0,1,80,176.18V87.09L42.08,45.38A8,8,0,1,1,53.92,34.62Zm-27.21-55.46a8,8,0,0,0,11.29-.7,40,40,0,0,0,0-52.88,8,8,0,1,0-12,10.57,24,24,0,0,1,0,31.72A8,8,0,0,0,186.71,155.16Zm40.92-80.49a8,8,0,1,0-11.92,10.66,64,64,0,0,1,0,85.34,8,8,0,1,0,11.92,10.66,80,80,0,0,0,0-106.66ZM153,119.87a4,4,0,0,0,7-2.7V32.25a8.27,8.27,0,0,0-2.88-6.4,8,8,0,0,0-10-.16L103.83,59.33a4,4,0,0,0-.5,5.85ZM60,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H60a4,4,0,0,0,4-4V84A4,4,0,0,0,60,80Z\\\"></path></g>\",\n Subtitles: \"<g><path d=\\\"M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48ZM56,128H72a8,8,0,0,1,0,16H56a8,8,0,0,1,0-16Zm96,48H56a8,8,0,0,1,0-16h96a8,8,0,0,1,0,16Zm48,0H184a8,8,0,0,1,0-16h16a8,8,0,0,1,0,16Zm0-32H104a8,8,0,0,1,0-16h96a8,8,0,0,1,0,16Z\\\"></path></g>\",\n SunDim: \"<g><path d=\\\"M120,40V32a8,8,0,0,1,16,0v8a8,8,0,0,1-16,0Zm8,24a64,64,0,1,0,64,64A64.07,64.07,0,0,0,128,64ZM58.34,69.66A8,8,0,0,0,69.66,58.34l-8-8A8,8,0,0,0,50.34,61.66Zm0,116.68-8,8a8,8,0,0,0,11.32,11.32l8-8a8,8,0,0,0-11.32-11.32ZM192,72a8,8,0,0,0,5.66-2.34l8-8a8,8,0,0,0-11.32-11.32l-8,8A8,8,0,0,0,192,72Zm5.66,114.34a8,8,0,0,0-11.32,11.32l8,8a8,8,0,0,0,11.32-11.32ZM40,120H32a8,8,0,0,0,0,16h8a8,8,0,0,0,0-16Zm88,88a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,128,208Zm96-88h-8a8,8,0,0,0,0,16h8a8,8,0,0,0,0-16Z\\\"></path></g>\",\n Trash: \"<g><path d=\\\"M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM112,168a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm0-120H96V40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8Z\\\"></path></g>\",\n TrayArrowDown: \"<g><path d=\\\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM90.34,114.34a8,8,0,0,1,11.32,0L120,132.69V72a8,8,0,0,1,16,0v60.69l18.34-18.35a8,8,0,0,1,11.32,11.32l-32,32a8,8,0,0,1-11.32,0l-32-32A8,8,0,0,1,90.34,114.34ZM208,208H48V168H76.69L96,187.32A15.89,15.89,0,0,0,107.31,192h41.38A15.86,15.86,0,0,0,160,187.31L179.31,168H208v40Z\\\"></path></g>\",\n UploadSimple: \"<g><path d=\\\"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0ZM88,80h32v64a8,8,0,0,0,16,0V80h32a8,8,0,0,0,5.66-13.66l-40-40a8,8,0,0,0-11.32,0l-40,40A8,8,0,0,0,88,80Z\\\"></path></g>\",\n Users: \"<g><path d=\\\"M164.47,195.63a8,8,0,0,1-6.7,12.37H10.23a8,8,0,0,1-6.7-12.37,95.83,95.83,0,0,1,47.22-37.71,60,60,0,1,1,66.5,0A95.83,95.83,0,0,1,164.47,195.63Zm87.91-.15a95.87,95.87,0,0,0-47.13-37.56A60,60,0,0,0,144.7,54.59a4,4,0,0,0-1.33,6A75.83,75.83,0,0,1,147,150.53a4,4,0,0,0,1.07,5.53,112.32,112.32,0,0,1,29.85,30.83,23.92,23.92,0,0,1,3.65,16.47,4,4,0,0,0,3.95,4.64h60.3a8,8,0,0,0,7.73-5.93A8.22,8.22,0,0,0,252.38,195.48Z\\\"></path></g>\",\n Video: \"<g><path d=\\\"M232,208a8,8,0,0,1-8,8H32a8,8,0,0,1,0-16H224A8,8,0,0,1,232,208Zm0-152V168a16,16,0,0,1-16,16H40a16,16,0,0,1-16-16V56A16,16,0,0,1,40,40H216A16,16,0,0,1,232,56Zm-68,56a8,8,0,0,0-3.41-6.55l-40-28A8,8,0,0,0,108,84v56a8,8,0,0,0,12.59,6.55l40-28A8,8,0,0,0,164,112Z\\\"></path></g>\",\n VideoCamera: \"<g><path d=\\\"M192,72V184a16,16,0,0,1-16,16H32a16,16,0,0,1-16-16V72A16,16,0,0,1,32,56H176A16,16,0,0,1,192,72Zm58,.25a8.23,8.23,0,0,0-6.63,1.22L209.78,95.86A4,4,0,0,0,208,99.19v57.62a4,4,0,0,0,1.78,3.33l33.78,22.52a8,8,0,0,0,8.58.19,8.33,8.33,0,0,0,3.86-7.17V80A8,8,0,0,0,250,72.25Z\\\"></path></g>\",\n VideoCameraSlash: \"<g><path d=\\\"M256,80.23v95.45a8.33,8.33,0,0,1-3.86,7.17,8,8,0,0,1-8.58-.19l-33.78-22.52a4,4,0,0,1-1.78-3.33V99.19a4,4,0,0,1,1.78-3.32l33.78-22.53a8,8,0,0,1,9.73.66A8.23,8.23,0,0,1,256,80.23ZM53.92,34.62A8,8,0,1,0,42.08,45.38L51.73,56H32A16,16,0,0,0,16,72V184a16,16,0,0,0,16,16H182.64l19.44,21.38a8,8,0,1,0,11.84-10.76ZM185,155.07a4,4,0,0,0,7-2.7V72a16,16,0,0,0-16-16H104a4,4,0,0,0-3,6.69Z\\\"></path></g>\",\n Warning: \"<g><path d=\\\"M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM120,104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm8,88a12,12,0,1,1,12-12A12,12,0,0,1,128,192Z\\\"></path></g>\",\n WarningCircle: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm-8,56a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm8,104a12,12,0,1,1,12-12A12,12,0,0,1,128,184Z\\\"></path></g>\",\n WarningOctagon: \"<g><path d=\\\"M227.31,80.23,175.77,28.69A16.13,16.13,0,0,0,164.45,24H91.55a16.13,16.13,0,0,0-11.32,4.69L28.69,80.23A16.13,16.13,0,0,0,24,91.55v72.9a16.13,16.13,0,0,0,4.69,11.32l51.54,51.54A16.13,16.13,0,0,0,91.55,232h72.9a16.13,16.13,0,0,0,11.32-4.69l51.54-51.54A16.13,16.13,0,0,0,232,164.45V91.55A16.13,16.13,0,0,0,227.31,80.23ZM120,80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm8,104a12,12,0,1,1,12-12A12,12,0,0,1,128,184Z\\\"></path></g>\",\n Waveform: \"<g><path d=\\\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM72,152a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm32,32a8,8,0,0,1-16,0V72a8,8,0,0,1,16,0Zm32-16a8,8,0,0,1-16,0V88a8,8,0,0,1,16,0Zm32-16a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm32,8a8,8,0,0,1-16,0V96a8,8,0,0,1,16,0Z\\\"></path></g>\",\n X: \"<g><path d=\\\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM181.66,170.34a8,8,0,0,1-11.32,11.32L128,139.31,85.66,181.66a8,8,0,0,1-11.32-11.32L116.69,128,74.34,85.66A8,8,0,0,1,85.66,74.34L128,116.69l42.34-42.35a8,8,0,0,1,11.32,11.32L139.31,128Z\\\"></path></g>\",\n XCircle: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm37.66,130.34a8,8,0,0,1-11.32,11.32L128,139.31l-26.34,26.35a8,8,0,0,1-11.32-11.32L116.69,128,90.34,101.66a8,8,0,0,1,11.32-11.32L128,116.69l26.34-26.35a8,8,0,0,1,11.32,11.32L139.31,128Z\\\"></path></g>\",\n XSquare: \"<g><path d=\\\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM165.66,154.34a8,8,0,0,1-11.32,11.32L128,139.31l-26.34,26.35a8,8,0,0,1-11.32-11.32L116.69,128,90.34,101.66a8,8,0,0,1,11.32-11.32L128,116.69l26.34-26.35a8,8,0,0,1,11.32,11.32L139.31,128Z\\\"></path></g>\",\n} as Record<string, string>;\n","// Generated by scripts/generate-icons.mjs from @phosphor-icons/vue; do not edit.\nexport default {\n ArrowBendUpLeft: \"<g><path d=\\\"M232,200a8,8,0,0,1-16,0,88.1,88.1,0,0,0-88-88H51.31l34.35,34.34a8,8,0,0,1-11.32,11.32l-48-48a8,8,0,0,1,0-11.32l48-48A8,8,0,0,1,85.66,61.66L51.31,96H128A104.11,104.11,0,0,1,232,200Z\\\"></path></g>\",\n ArrowDown: \"<g><path d=\\\"M205.66,149.66l-72,72a8,8,0,0,1-11.32,0l-72-72a8,8,0,0,1,11.32-11.32L120,196.69V40a8,8,0,0,1,16,0V196.69l58.34-58.35a8,8,0,0,1,11.32,11.32Z\\\"></path></g>\",\n ArrowLeft: \"<g><path d=\\\"M224,128a8,8,0,0,1-8,8H59.31l58.35,58.34a8,8,0,0,1-11.32,11.32l-72-72a8,8,0,0,1,0-11.32l72-72a8,8,0,0,1,11.32,11.32L59.31,120H216A8,8,0,0,1,224,128Z\\\"></path></g>\",\n ArrowRight: \"<g><path d=\\\"M221.66,133.66l-72,72a8,8,0,0,1-11.32-11.32L196.69,136H40a8,8,0,0,1,0-16H196.69L138.34,61.66a8,8,0,0,1,11.32-11.32l72,72A8,8,0,0,1,221.66,133.66Z\\\"></path></g>\",\n ArrowUUpLeft: \"<g><path d=\\\"M232,144a64.07,64.07,0,0,1-64,64H80a8,8,0,0,1,0-16h88a48,48,0,0,0,0-96H51.31l34.35,34.34a8,8,0,0,1-11.32,11.32l-48-48a8,8,0,0,1,0-11.32l48-48A8,8,0,0,1,85.66,45.66L51.31,80H168A64.07,64.07,0,0,1,232,144Z\\\"></path></g>\",\n ArrowUUpRight: \"<g><path d=\\\"M170.34,130.34,204.69,96H88a48,48,0,0,0,0,96h88a8,8,0,0,1,0,16H88A64,64,0,0,1,88,80H204.69L170.34,45.66a8,8,0,0,1,11.32-11.32l48,48a8,8,0,0,1,0,11.32l-48,48a8,8,0,0,1-11.32-11.32Z\\\"></path></g>\",\n ArrowsClockwise: \"<g><path d=\\\"M224,48V96a8,8,0,0,1-8,8H168a8,8,0,0,1,0-16h28.69L182.06,73.37a79.56,79.56,0,0,0-56.13-23.43h-.45A79.52,79.52,0,0,0,69.59,72.71,8,8,0,0,1,58.41,61.27a96,96,0,0,1,135,.79L208,76.69V48a8,8,0,0,1,16,0ZM186.41,183.29a80,80,0,0,1-112.47-.66L59.31,168H88a8,8,0,0,0,0-16H40a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V179.31l14.63,14.63A95.43,95.43,0,0,0,130,222.06h.53a95.36,95.36,0,0,0,67.07-27.33,8,8,0,0,0-11.18-11.44Z\\\"></path></g>\",\n ArrowsInSimple: \"<g><path d=\\\"M213.66,53.66,163.31,104H192a8,8,0,0,1,0,16H144a8,8,0,0,1-8-8V64a8,8,0,0,1,16,0V92.69l50.34-50.35a8,8,0,0,1,11.32,11.32ZM112,136H64a8,8,0,0,0,0,16H92.69L42.34,202.34a8,8,0,0,0,11.32,11.32L104,163.31V192a8,8,0,0,0,16,0V144A8,8,0,0,0,112,136Z\\\"></path></g>\",\n Buildings: \"<g><path d=\\\"M240,208H224V96a16,16,0,0,0-16-16H144V32a16,16,0,0,0-24.88-13.32L39.12,72A16,16,0,0,0,32,85.34V208H16a8,8,0,0,0,0,16H240a8,8,0,0,0,0-16ZM208,96V208H144V96ZM48,85.34,128,32V208H48ZM112,112v16a8,8,0,0,1-16,0V112a8,8,0,1,1,16,0Zm-32,0v16a8,8,0,0,1-16,0V112a8,8,0,1,1,16,0Zm0,56v16a8,8,0,0,1-16,0V168a8,8,0,0,1,16,0Zm32,0v16a8,8,0,0,1-16,0V168a8,8,0,0,1,16,0Z\\\"></path></g>\",\n Cake: \"<g><path d=\\\"M232,112a24,24,0,0,0-24-24H136V79a32.06,32.06,0,0,0,24-31c0-28-26.44-45.91-27.56-46.66a8,8,0,0,0-8.88,0C122.44,2.09,96,20,96,48a32.06,32.06,0,0,0,24,31v9H48a24,24,0,0,0-24,24v23.33a40.84,40.84,0,0,0,8,24.24V200a24,24,0,0,0,24,24H200a24,24,0,0,0,24-24V159.57a40.84,40.84,0,0,0,8-24.24ZM112,48c0-13.57,10-24.46,16-29.79,6,5.33,16,16.22,16,29.79a16,16,0,0,1-32,0ZM40,112a8,8,0,0,1,8-8H208a8,8,0,0,1,8,8v23.33c0,13.25-10.46,24.31-23.32,24.66A24,24,0,0,1,168,136a8,8,0,0,0-16,0,24,24,0,0,1-48,0,8,8,0,0,0-16,0,24,24,0,0,1-24.68,24C50.46,159.64,40,148.58,40,135.33Zm160,96H56a8,8,0,0,1-8-8V172.56A38.77,38.77,0,0,0,62.88,176a39.69,39.69,0,0,0,29-11.31A40.36,40.36,0,0,0,96,160a40,40,0,0,0,64,0,40.36,40.36,0,0,0,4.13,4.67A39.67,39.67,0,0,0,192,176c.38,0,.76,0,1.14,0A38.77,38.77,0,0,0,208,172.56V200A8,8,0,0,1,200,208Z\\\"></path></g>\",\n Camera: \"<g><path d=\\\"M208,56H180.28L166.65,35.56A8,8,0,0,0,160,32H96a8,8,0,0,0-6.65,3.56L75.71,56H48A24,24,0,0,0,24,80V192a24,24,0,0,0,24,24H208a24,24,0,0,0,24-24V80A24,24,0,0,0,208,56Zm8,136a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V80a8,8,0,0,1,8-8H80a8,8,0,0,0,6.66-3.56L100.28,48h55.43l13.63,20.44A8,8,0,0,0,176,72h32a8,8,0,0,1,8,8ZM128,88a44,44,0,1,0,44,44A44.05,44.05,0,0,0,128,88Zm0,72a28,28,0,1,1,28-28A28,28,0,0,1,128,160Z\\\"></path></g>\",\n CaretDown: \"<g><path d=\\\"M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z\\\"></path></g>\",\n CaretLeft: \"<g><path d=\\\"M165.66,202.34a8,8,0,0,1-11.32,11.32l-80-80a8,8,0,0,1,0-11.32l80-80a8,8,0,0,1,11.32,11.32L91.31,128Z\\\"></path></g>\",\n CaretRight: \"<g><path d=\\\"M181.66,133.66l-80,80a8,8,0,0,1-11.32-11.32L164.69,128,90.34,53.66a8,8,0,0,1,11.32-11.32l80,80A8,8,0,0,1,181.66,133.66Z\\\"></path></g>\",\n CaretUp: \"<g><path d=\\\"M213.66,165.66a8,8,0,0,1-11.32,0L128,91.31,53.66,165.66a8,8,0,0,1-11.32-11.32l80-80a8,8,0,0,1,11.32,0l80,80A8,8,0,0,1,213.66,165.66Z\\\"></path></g>\",\n ChatCircleDots: \"<g><path d=\\\"M140,128a12,12,0,1,1-12-12A12,12,0,0,1,140,128ZM84,116a12,12,0,1,0,12,12A12,12,0,0,0,84,116Zm88,0a12,12,0,1,0,12,12A12,12,0,0,0,172,116Zm60,12A104,104,0,0,1,79.12,219.82L45.07,231.17a16,16,0,0,1-20.24-20.24l11.35-34.05A104,104,0,1,1,232,128Zm-16,0A88,88,0,1,0,51.81,172.06a8,8,0,0,1,.66,6.54L40,216,77.4,203.53a7.85,7.85,0,0,1,2.53-.42,8,8,0,0,1,4,1.08A88,88,0,0,0,216,128Z\\\"></path></g>\",\n Check: \"<g><path d=\\\"M229.66,77.66l-128,128a8,8,0,0,1-11.32,0l-56-56a8,8,0,0,1,11.32-11.32L96,188.69,218.34,66.34a8,8,0,0,1,11.32,11.32Z\\\"></path></g>\",\n CheckCircle: \"<g><path d=\\\"M173.66,98.34a8,8,0,0,1,0,11.32l-56,56a8,8,0,0,1-11.32,0l-24-24a8,8,0,0,1,11.32-11.32L112,148.69l50.34-50.35A8,8,0,0,1,173.66,98.34ZM232,128A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z\\\"></path></g>\",\n Checks: \"<g><path d=\\\"M149.61,85.71l-89.6,88a8,8,0,0,1-11.22,0L10.39,136a8,8,0,1,1,11.22-11.41L54.4,156.79l84-82.5a8,8,0,1,1,11.22,11.42Zm96.1-11.32a8,8,0,0,0-11.32-.1l-84,82.5-18.83-18.5a8,8,0,0,0-11.21,11.42l24.43,24a8,8,0,0,0,11.22,0l89.6-88A8,8,0,0,0,245.71,74.39Z\\\"></path></g>\",\n CircleNotch: \"<g><path d=\\\"M232,128a104,104,0,0,1-208,0c0-41,23.81-78.36,60.66-95.27a8,8,0,0,1,6.68,14.54C60.15,61.59,40,93.27,40,128a88,88,0,0,0,176,0c0-34.73-20.15-66.41-51.34-80.73a8,8,0,0,1,6.68-14.54C208.19,49.64,232,87,232,128Z\\\"></path></g>\",\n Clock: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm64-88a8,8,0,0,1-8,8H128a8,8,0,0,1-8-8V72a8,8,0,0,1,16,0v48h48A8,8,0,0,1,192,128Z\\\"></path></g>\",\n Copy: \"<g><path d=\\\"M216,32H88a8,8,0,0,0-8,8V80H40a8,8,0,0,0-8,8V216a8,8,0,0,0,8,8H168a8,8,0,0,0,8-8V176h40a8,8,0,0,0,8-8V40A8,8,0,0,0,216,32ZM160,208H48V96H160Zm48-48H176V88a8,8,0,0,0-8-8H96V48H208Z\\\"></path></g>\",\n CornersIn: \"<g><path d=\\\"M152,96V48a8,8,0,0,1,16,0V88h40a8,8,0,0,1,0,16H160A8,8,0,0,1,152,96ZM96,152H48a8,8,0,0,0,0,16H88v40a8,8,0,0,0,16,0V160A8,8,0,0,0,96,152Zm112,0H160a8,8,0,0,0-8,8v48a8,8,0,0,0,16,0V168h40a8,8,0,0,0,0-16ZM96,40a8,8,0,0,0-8,8V88H48a8,8,0,0,0,0,16H96a8,8,0,0,0,8-8V48A8,8,0,0,0,96,40Z\\\"></path></g>\",\n DotsThreeVertical: \"<g><path d=\\\"M140,128a12,12,0,1,1-12-12A12,12,0,0,1,140,128ZM128,72a12,12,0,1,0-12-12A12,12,0,0,0,128,72Zm0,112a12,12,0,1,0,12,12A12,12,0,0,0,128,184Z\\\"></path></g>\",\n DownloadSimple: \"<g><path d=\\\"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0Zm-101.66,5.66a8,8,0,0,0,11.32,0l40-40a8,8,0,0,0-11.32-11.32L136,124.69V32a8,8,0,0,0-16,0v92.69L93.66,98.34a8,8,0,0,0-11.32,11.32Z\\\"></path></g>\",\n Eraser: \"<g><path d=\\\"M225,80.4,183.6,39a24,24,0,0,0-33.94,0L31,157.66a24,24,0,0,0,0,33.94l30.06,30.06A8,8,0,0,0,66.74,224H216a8,8,0,0,0,0-16h-84.7L225,114.34A24,24,0,0,0,225,80.4ZM108.68,208H70.05L42.33,180.28a8,8,0,0,1,0-11.31L96,115.31,148.69,168Zm105-105L160,156.69,107.31,104,161,50.34a8,8,0,0,1,11.32,0l41.38,41.38a8,8,0,0,1,0,11.31Z\\\"></path></g>\",\n File: \"<g><path d=\\\"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Z\\\"></path></g>\",\n FileText: \"<g><path d=\\\"M213.66,82.34l-56-56A8,8,0,0,0,152,24H56A16,16,0,0,0,40,40V216a16,16,0,0,0,16,16H200a16,16,0,0,0,16-16V88A8,8,0,0,0,213.66,82.34ZM160,51.31,188.69,80H160ZM200,216H56V40h88V88a8,8,0,0,0,8,8h48V216Zm-32-80a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,136Zm0,32a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,168Z\\\"></path></g>\",\n Files: \"<g><path d=\\\"M213.66,66.34l-40-40A8,8,0,0,0,168,24H88A16,16,0,0,0,72,40V56H56A16,16,0,0,0,40,72V216a16,16,0,0,0,16,16H168a16,16,0,0,0,16-16V200h16a16,16,0,0,0,16-16V72A8,8,0,0,0,213.66,66.34ZM168,216H56V72h76.69L168,107.31v84.53c0,.06,0,.11,0,.16s0,.1,0,.16V216Zm32-32H184V104a8,8,0,0,0-2.34-5.66l-40-40A8,8,0,0,0,136,56H88V40h76.69L200,75.31Zm-56-32a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h48A8,8,0,0,1,144,152Zm0,32a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h48A8,8,0,0,1,144,184Z\\\"></path></g>\",\n FilmStrip: \"<g><path d=\\\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM40,88h80v80H40Zm96-16V56h32V72Zm-16,0H88V56h32Zm0,112v16H88V184Zm16,0h32v16H136Zm0-16V88h80v80Zm80-96H184V56h32ZM72,56V72H40V56ZM40,184H72v16H40Zm176,16H184V184h32v16Z\\\"></path></g>\",\n Flag: \"<g><path d=\\\"M42.76,50A8,8,0,0,0,40,56V224a8,8,0,0,0,16,0V179.77c26.79-21.16,49.87-9.75,76.45,3.41,16.4,8.11,34.06,16.85,53,16.85,13.93,0,28.54-4.75,43.82-18a8,8,0,0,0,2.76-6V56A8,8,0,0,0,218.76,50c-28,24.23-51.72,12.49-79.21-1.12C111.07,34.76,78.78,18.79,42.76,50ZM216,172.25c-26.79,21.16-49.87,9.74-76.45-3.41-25-12.35-52.81-26.13-83.55-8.4V59.79c26.79-21.16,49.87-9.75,76.45,3.4,25,12.35,52.82,26.13,83.55,8.4Z\\\"></path></g>\",\n FrameCorners: \"<g><path d=\\\"M200,80v32a8,8,0,0,1-16,0V88H160a8,8,0,0,1,0-16h32A8,8,0,0,1,200,80ZM96,168H72V144a8,8,0,0,0-16,0v32a8,8,0,0,0,8,8H96a8,8,0,0,0,0-16ZM232,56V200a16,16,0,0,1-16,16H40a16,16,0,0,1-16-16V56A16,16,0,0,1,40,40H216A16,16,0,0,1,232,56ZM216,200V56H40V200H216Z\\\"></path></g>\",\n Hamburger: \"<g><path d=\\\"M48.07,104H207.93a16,16,0,0,0,15.72-19.38C216.22,49.5,176,24,128,24S39.78,49.5,32.35,84.62A16,16,0,0,0,48.07,104ZM128,40c39.82,0,74.21,20.61,79.93,48H48.07L48,87.93C53.79,60.61,88.18,40,128,40ZM229.26,152.48l-41.13,15L151,152.57a8,8,0,0,0-5.94,0l-37,14.81L71,152.57a8,8,0,0,0-5.7-.09l-44,16a8,8,0,0,0,5.47,15L40,178.69V184a40,40,0,0,0,40,40h96a40,40,0,0,0,40-40v-9.67l18.73-6.81a8,8,0,1,0-5.47-15ZM200,184a24,24,0,0,1-24,24H80a24,24,0,0,1-24-24V172.88l11.87-4.32L105,183.43a8,8,0,0,0,5.94,0l37-14.81,37,14.81a8,8,0,0,0,5.7.09l9.27-3.37ZM16,128a8,8,0,0,1,8-8H232a8,8,0,0,1,0,16H24A8,8,0,0,1,16,128Z\\\"></path></g>\",\n IdentificationCard: \"<g><path d=\\\"M200,112a8,8,0,0,1-8,8H152a8,8,0,0,1,0-16h40A8,8,0,0,1,200,112Zm-8,24H152a8,8,0,0,0,0,16h40a8,8,0,0,0,0-16Zm40-80V200a16,16,0,0,1-16,16H40a16,16,0,0,1-16-16V56A16,16,0,0,1,40,40H216A16,16,0,0,1,232,56ZM216,200V56H40V200H216Zm-80.26-34a8,8,0,1,1-15.5,4c-2.63-10.26-13.06-18-24.25-18s-21.61,7.74-24.25,18a8,8,0,1,1-15.5-4,39.84,39.84,0,0,1,17.19-23.34,32,32,0,1,1,45.12,0A39.76,39.76,0,0,1,135.75,166ZM96,136a16,16,0,1,0-16-16A16,16,0,0,0,96,136Z\\\"></path></g>\",\n Image: \"<g><path d=\\\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,16V158.75l-26.07-26.06a16,16,0,0,0-22.63,0l-20,20-44-44a16,16,0,0,0-22.62,0L40,149.37V56ZM40,172l52-52,80,80H40Zm176,28H194.63l-36-36,20-20L216,181.38V200ZM144,100a12,12,0,1,1,12,12A12,12,0,0,1,144,100Z\\\"></path></g>\",\n Images: \"<g><path d=\\\"M216,40H72A16,16,0,0,0,56,56V72H40A16,16,0,0,0,24,88V200a16,16,0,0,0,16,16H184a16,16,0,0,0,16-16V184h16a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM72,56H216v62.75l-10.07-10.06a16,16,0,0,0-22.63,0l-20,20-44-44a16,16,0,0,0-22.62,0L72,109.37ZM184,200H40V88H56v80a16,16,0,0,0,16,16H184Zm32-32H72V132l36-36,49.66,49.66a8,8,0,0,0,11.31,0L194.63,120,216,141.38V168ZM160,84a12,12,0,1,1,12,12A12,12,0,0,1,160,84Z\\\"></path></g>\",\n Info: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm16-40a8,8,0,0,1-8,8,16,16,0,0,1-16-16V128a8,8,0,0,1,0-16,16,16,0,0,1,16,16v40A8,8,0,0,1,144,176ZM112,84a12,12,0,1,1,12,12A12,12,0,0,1,112,84Z\\\"></path></g>\",\n Lightbulb: \"<g><path d=\\\"M176,232a8,8,0,0,1-8,8H88a8,8,0,0,1,0-16h80A8,8,0,0,1,176,232Zm40-128a87.55,87.55,0,0,1-33.64,69.21A16.24,16.24,0,0,0,176,186v6a16,16,0,0,1-16,16H96a16,16,0,0,1-16-16v-6a16,16,0,0,0-6.23-12.66A87.59,87.59,0,0,1,40,104.49C39.74,56.83,78.26,17.14,125.88,16A88,88,0,0,1,216,104Zm-16,0a72,72,0,0,0-73.74-72c-39,.92-70.47,33.39-70.26,72.39a71.65,71.65,0,0,0,27.64,56.3A32,32,0,0,1,96,186v6h64v-6a32.15,32.15,0,0,1,12.47-25.35A71.65,71.65,0,0,0,200,104Zm-16.11-9.34a57.6,57.6,0,0,0-46.56-46.55,8,8,0,0,0-2.66,15.78c16.57,2.79,30.63,16.85,33.44,33.45A8,8,0,0,0,176,104a9,9,0,0,0,1.35-.11A8,8,0,0,0,183.89,94.66Z\\\"></path></g>\",\n Lightning: \"<g><path d=\\\"M215.79,118.17a8,8,0,0,0-5-5.66L153.18,90.9l14.66-73.33a8,8,0,0,0-13.69-7l-112,120a8,8,0,0,0,3,13l57.63,21.61L88.16,238.43a8,8,0,0,0,13.69,7l112-120A8,8,0,0,0,215.79,118.17ZM109.37,214l10.47-52.38a8,8,0,0,0-5-9.06L62,132.71l84.62-90.66L136.16,94.43a8,8,0,0,0,5,9.06l52.8,19.8Z\\\"></path></g>\",\n LightningSlash: \"<g><path d=\\\"M53.92,34.62A8,8,0,1,0,42.08,45.38L81.33,88.56l-39.18,42a8,8,0,0,0,3,13l57.63,21.61L88.16,238.43a8,8,0,0,0,13.69,7l61.86-66.28,38.37,42.2a8,8,0,1,0,11.84-10.76ZM109.37,214l10.47-52.38a8,8,0,0,0-5-9.06L62,132.71l30.12-32.27,60.78,66.86ZM108.66,71a8,8,0,0,1-.39-11.31l45.88-49.16a8,8,0,0,1,13.69,7L153.18,90.9l57.63,21.61a8,8,0,0,1,3,12.95l-22.3,23.89a8,8,0,0,1-11.7-10.91L194,123.29l-52.8-19.8a8,8,0,0,1-5-9.06l10.47-52.38L120,70.62A8,8,0,0,1,108.66,71Z\\\"></path></g>\",\n LockKey: \"<g><path d=\\\"M128,112a28,28,0,0,0-8,54.83V184a8,8,0,0,0,16,0V166.83A28,28,0,0,0,128,112Zm0,40a12,12,0,1,1,12-12A12,12,0,0,1,128,152Zm80-72H176V56a48,48,0,0,0-96,0V80H48A16,16,0,0,0,32,96V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V96A16,16,0,0,0,208,80ZM96,56a32,32,0,0,1,64,0V80H96ZM208,208H48V96H208V208Z\\\"></path></g>\",\n MagnifyingGlass: \"<g><path d=\\\"M229.66,218.34l-50.07-50.06a88.11,88.11,0,1,0-11.31,11.31l50.06,50.07a8,8,0,0,0,11.32-11.32ZM40,112a72,72,0,1,1,72,72A72.08,72.08,0,0,1,40,112Z\\\"></path></g>\",\n Microphone: \"<g><path d=\\\"M128,176a48.05,48.05,0,0,0,48-48V64a48,48,0,0,0-96,0v64A48.05,48.05,0,0,0,128,176ZM96,64a32,32,0,0,1,64,0v64a32,32,0,0,1-64,0Zm40,143.6V240a8,8,0,0,1-16,0V207.6A80.11,80.11,0,0,1,48,128a8,8,0,0,1,16,0,64,64,0,0,0,128,0,8,8,0,0,1,16,0A80.11,80.11,0,0,1,136,207.6Z\\\"></path></g>\",\n MicrophoneSlash: \"<g><path d=\\\"M213.92,218.62l-160-176A8,8,0,0,0,42.08,53.38L80,95.09V128a48,48,0,0,0,69.11,43.12l11.1,12.2A63.41,63.41,0,0,1,128,192a64.07,64.07,0,0,1-64-64,8,8,0,0,0-16,0,80.11,80.11,0,0,0,72,79.6V240a8,8,0,0,0,16,0V207.59a78.83,78.83,0,0,0,35.16-12.22l30.92,34a8,8,0,1,0,11.84-10.76ZM128,160a32,32,0,0,1-32-32V112.69l41.66,45.82A32,32,0,0,1,128,160Zm57.52-3.91A63.32,63.32,0,0,0,192,128a8,8,0,0,1,16,0,79.16,79.16,0,0,1-8.11,35.12,8,8,0,0,1-7.19,4.49,7.88,7.88,0,0,1-3.51-.82A8,8,0,0,1,185.52,156.09ZM84,44.87A48,48,0,0,1,176,64v64a49.19,49.19,0,0,1-.26,5,8,8,0,0,1-8,7.17,8.13,8.13,0,0,1-.84,0,8,8,0,0,1-7.12-8.79c.11-1.1.17-2.24.17-3.36V64A32,32,0,0,0,98.64,51.25,8,8,0,1,1,84,44.87Z\\\"></path></g>\",\n Monitor: \"<g><path d=\\\"M208,40H48A24,24,0,0,0,24,64V176a24,24,0,0,0,24,24H208a24,24,0,0,0,24-24V64A24,24,0,0,0,208,40Zm8,136a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V64a8,8,0,0,1,8-8H208a8,8,0,0,1,8,8Zm-48,48a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,224Z\\\"></path></g>\",\n MonitorArrowUp: \"<g><path d=\\\"M208,40H48A24,24,0,0,0,24,64V176a24,24,0,0,0,24,24H208a24,24,0,0,0,24-24V64A24,24,0,0,0,208,40Zm8,136a8,8,0,0,1-8,8H48a8,8,0,0,1-8-8V64a8,8,0,0,1,8-8H208a8,8,0,0,1,8,8Zm-48,48a8,8,0,0,1-8,8H96a8,8,0,0,1,0-16h64A8,8,0,0,1,168,224ZM157.66,106.34a8,8,0,0,1-11.32,11.32L136,107.31V152a8,8,0,0,1-16,0V107.31l-10.34,10.35a8,8,0,0,1-11.32-11.32l24-24a8,8,0,0,1,11.32,0Z\\\"></path></g>\",\n Moon: \"<g><path d=\\\"M233.54,142.23a8,8,0,0,0-8-2,88.08,88.08,0,0,1-109.8-109.8,8,8,0,0,0-10-10,104.84,104.84,0,0,0-52.91,37A104,104,0,0,0,136,224a103.09,103.09,0,0,0,62.52-20.88,104.84,104.84,0,0,0,37-52.91A8,8,0,0,0,233.54,142.23ZM188.9,190.34A88,88,0,0,1,65.66,67.11a89,89,0,0,1,31.4-26A106,106,0,0,0,96,56,104.11,104.11,0,0,0,200,160a106,106,0,0,0,14.92-1.06A89,89,0,0,1,188.9,190.34Z\\\"></path></g>\",\n MusicNotes: \"<g><path d=\\\"M212.92,17.69a8,8,0,0,0-6.86-1.45l-128,32A8,8,0,0,0,72,56V166.08A36,36,0,1,0,88,196V110.25l112-28v51.83A36,36,0,1,0,216,164V24A8,8,0,0,0,212.92,17.69ZM52,216a20,20,0,1,1,20-20A20,20,0,0,1,52,216ZM88,93.75V62.25l112-28v31.5ZM180,184a20,20,0,1,1,20-20A20,20,0,0,1,180,184Z\\\"></path></g>\",\n Palette: \"<g><path d=\\\"M200.77,53.89A103.27,103.27,0,0,0,128,24h-1.07A104,104,0,0,0,24,128c0,43,26.58,79.06,69.36,94.17A32,32,0,0,0,136,192a16,16,0,0,1,16-16h46.21a31.81,31.81,0,0,0,31.2-24.88,104.43,104.43,0,0,0,2.59-24A103.28,103.28,0,0,0,200.77,53.89Zm13,93.71A15.89,15.89,0,0,1,198.21,160H152a32,32,0,0,0-32,32,16,16,0,0,1-21.31,15.07C62.49,194.3,40,164,40,128a88,88,0,0,1,87.09-88h.9a88.35,88.35,0,0,1,88,87.25A88.86,88.86,0,0,1,213.81,147.6ZM140,76a12,12,0,1,1-12-12A12,12,0,0,1,140,76ZM96,100A12,12,0,1,1,84,88,12,12,0,0,1,96,100Zm0,56a12,12,0,1,1-12-12A12,12,0,0,1,96,156Zm88-56a12,12,0,1,1-12-12A12,12,0,0,1,184,100Z\\\"></path></g>\",\n PaperPlaneTilt: \"<g><path d=\\\"M227.32,28.68a16,16,0,0,0-15.66-4.08l-.15,0L19.57,82.84a16,16,0,0,0-2.49,29.8L102,154l41.3,84.87A15.86,15.86,0,0,0,157.74,248q.69,0,1.38-.06a15.88,15.88,0,0,0,14-11.51l58.2-191.94c0-.05,0-.1,0-.15A16,16,0,0,0,227.32,28.68ZM157.83,231.85l-.05.14,0-.07-40.06-82.3,48-48a8,8,0,0,0-11.31-11.31l-48,48L24.08,98.25l-.07,0,.14,0L216,40Z\\\"></path></g>\",\n Paperclip: \"<g><path d=\\\"M209.66,122.34a8,8,0,0,1,0,11.32l-82.05,82a56,56,0,0,1-79.2-79.21L147.67,35.73a40,40,0,1,1,56.61,56.55L105,193A24,24,0,1,1,71,159L154.3,74.38A8,8,0,1,1,165.7,85.6L82.39,170.31a8,8,0,1,0,11.27,11.36L192.93,81A24,24,0,1,0,159,47L59.76,147.68a40,40,0,1,0,56.53,56.62l82.06-82A8,8,0,0,1,209.66,122.34Z\\\"></path></g>\",\n Pause: \"<g><path d=\\\"M200,32H160a16,16,0,0,0-16,16V208a16,16,0,0,0,16,16h40a16,16,0,0,0,16-16V48A16,16,0,0,0,200,32Zm0,176H160V48h40ZM96,32H56A16,16,0,0,0,40,48V208a16,16,0,0,0,16,16H96a16,16,0,0,0,16-16V48A16,16,0,0,0,96,32Zm0,176H56V48H96Z\\\"></path></g>\",\n PauseCircle: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216ZM112,96v64a8,8,0,0,1-16,0V96a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V96a8,8,0,0,1,16,0Z\\\"></path></g>\",\n PawPrint: \"<g><path d=\\\"M212,80a28,28,0,1,0,28,28A28,28,0,0,0,212,80Zm0,40a12,12,0,1,1,12-12A12,12,0,0,1,212,120ZM72,108a28,28,0,1,0-28,28A28,28,0,0,0,72,108ZM44,120a12,12,0,1,1,12-12A12,12,0,0,1,44,120ZM92,88A28,28,0,1,0,64,60,28,28,0,0,0,92,88Zm0-40A12,12,0,1,1,80,60,12,12,0,0,1,92,48Zm72,40a28,28,0,1,0-28-28A28,28,0,0,0,164,88Zm0-40a12,12,0,1,1-12,12A12,12,0,0,1,164,48Zm23.12,100.86a35.3,35.3,0,0,1-16.87-21.14,44,44,0,0,0-84.5,0A35.25,35.25,0,0,1,69,148.82,40,40,0,0,0,88,224a39.48,39.48,0,0,0,15.52-3.13,64.09,64.09,0,0,1,48.87,0,40,40,0,0,0,34.73-72ZM168,208a24,24,0,0,1-9.45-1.93,80.14,80.14,0,0,0-61.19,0,24,24,0,0,1-20.71-43.26,51.22,51.22,0,0,0,24.46-30.67,28,28,0,0,1,53.78,0,51.27,51.27,0,0,0,24.53,30.71A24,24,0,0,1,168,208Z\\\"></path></g>\",\n PencilLine: \"<g><path d=\\\"M227.32,73.37,182.63,28.69a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H216a8,8,0,0,0,0-16H115.32l112-112A16,16,0,0,0,227.32,73.37ZM136,75.31,152.69,92,68,176.69,51.31,160ZM48,208V179.31L76.69,208Zm48-3.31L79.32,188,164,103.31,180.69,120Zm96-96L147.32,64l24-24L216,84.69Z\\\"></path></g>\",\n PencilSimpleLine: \"<g><path d=\\\"M227.32,73.37,182.63,28.69a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H216a8,8,0,0,0,0-16H115.32l112-112A16,16,0,0,0,227.32,73.37ZM92.69,208H48V163.31l88-88L180.69,120ZM192,108.69,147.32,64l24-24L216,84.69Z\\\"></path></g>\",\n Phone: \"<g><path d=\\\"M222.37,158.46l-47.11-21.11-.13-.06a16,16,0,0,0-15.17,1.4,8.12,8.12,0,0,0-.75.56L134.87,160c-15.42-7.49-31.34-23.29-38.83-38.51l20.78-24.71c.2-.25.39-.5.57-.77a16,16,0,0,0,1.32-15.06l0-.12L97.54,33.64a16,16,0,0,0-16.62-9.52A56.26,56.26,0,0,0,32,80c0,79.4,64.6,144,144,144a56.26,56.26,0,0,0,55.88-48.92A16,16,0,0,0,222.37,158.46ZM176,208A128.14,128.14,0,0,1,48,80,40.2,40.2,0,0,1,82.87,40a.61.61,0,0,0,0,.12l21,47L83.2,111.86a6.13,6.13,0,0,0-.57.77,16,16,0,0,0-1,15.7c9.06,18.53,27.73,37.06,46.46,46.11a16,16,0,0,0,15.75-1.14,8.44,8.44,0,0,0,.74-.56L168.89,152l47,21.05h0s.08,0,.11,0A40.21,40.21,0,0,1,176,208Z\\\"></path></g>\",\n PhoneCall: \"<g><path d=\\\"M144.27,45.93a8,8,0,0,1,9.8-5.66,86.22,86.22,0,0,1,61.66,61.66,8,8,0,0,1-5.66,9.8A8.23,8.23,0,0,1,208,112a8,8,0,0,1-7.73-5.94,70.35,70.35,0,0,0-50.33-50.33A8,8,0,0,1,144.27,45.93Zm-2.33,41.8c13.79,3.68,22.65,12.54,26.33,26.33A8,8,0,0,0,176,120a8.23,8.23,0,0,0,2.07-.27,8,8,0,0,0,5.66-9.8c-5.12-19.16-18.5-32.54-37.66-37.66a8,8,0,1,0-4.13,15.46Zm81.94,95.35A56.26,56.26,0,0,1,168,232C88.6,232,24,167.4,24,88A56.26,56.26,0,0,1,72.92,32.12a16,16,0,0,1,16.62,9.52l21.12,47.15,0,.12A16,16,0,0,1,109.39,104c-.18.27-.37.52-.57.77L88,129.45c7.49,15.22,23.41,31,38.83,38.51l24.34-20.71a8.12,8.12,0,0,1,.75-.56,16,16,0,0,1,15.17-1.4l.13.06,47.11,21.11A16,16,0,0,1,223.88,183.08Zm-15.88-2s-.07,0-.11,0h0l-47-21.05-24.35,20.71a8.44,8.44,0,0,1-.74.56,16,16,0,0,1-15.75,1.14c-18.73-9.05-37.4-27.58-46.46-46.11a16,16,0,0,1,1-15.7,6.13,6.13,0,0,1,.57-.77L96,95.15l-21-47a.61.61,0,0,1,0-.12A40.2,40.2,0,0,0,40,88,128.14,128.14,0,0,0,168,216,40.21,40.21,0,0,0,208,181.07Z\\\"></path></g>\",\n PhoneX: \"<g><path d=\\\"M146.34,98.34,164.69,80,146.34,61.66a8,8,0,0,1,11.32-11.32L176,68.69l18.34-18.35a8,8,0,0,1,11.32,11.32L187.32,80l18.34,18.34a8,8,0,0,1-11.32,11.32L176,91.31l-18.34,18.35a8,8,0,0,1-11.32-11.32Zm77.54,84.74A56.26,56.26,0,0,1,168,232C88.6,232,24,167.4,24,88A56.26,56.26,0,0,1,72.92,32.12a16,16,0,0,1,16.62,9.52l21.12,47.15,0,.12A16,16,0,0,1,109.39,104c-.18.27-.37.52-.57.77L88,129.45c7.49,15.22,23.41,31,38.83,38.51l24.34-20.71a8.12,8.12,0,0,1,.75-.56,16,16,0,0,1,15.17-1.4l.13.06,47.11,21.11A16,16,0,0,1,223.88,183.08Zm-15.88-2s-.07,0-.11,0h0l-47-21.05-24.35,20.71a8.44,8.44,0,0,1-.74.56,16,16,0,0,1-15.75,1.14c-18.73-9.05-37.4-27.58-46.46-46.11a16,16,0,0,1,1-15.7,6.13,6.13,0,0,1,.57-.77L96,95.15l-21-47a.61.61,0,0,1,0-.12A40.2,40.2,0,0,0,40,88,128.14,128.14,0,0,0,168,216,40.21,40.21,0,0,0,208,181.07Z\\\"></path></g>\",\n Play: \"<g><path d=\\\"M232.4,114.49,88.32,26.35a16,16,0,0,0-16.2-.3A15.86,15.86,0,0,0,64,39.87V216.13A15.94,15.94,0,0,0,80,232a16.07,16.07,0,0,0,8.36-2.35L232.4,141.51a15.81,15.81,0,0,0,0-27ZM80,215.94V40l143.83,88Z\\\"></path></g>\",\n PlayCircle: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm48.24-94.78-64-40A8,8,0,0,0,100,88v80a8,8,0,0,0,12.24,6.78l64-40a8,8,0,0,0,0-13.56ZM116,153.57V102.43L156.91,128Z\\\"></path></g>\",\n Plus: \"<g><path d=\\\"M224,128a8,8,0,0,1-8,8H136v80a8,8,0,0,1-16,0V136H40a8,8,0,0,1,0-16h80V40a8,8,0,0,1,16,0v80h80A8,8,0,0,1,224,128Z\\\"></path></g>\",\n Resize: \"<g><path d=\\\"M136,112H48a8,8,0,0,0-8,8v88a8,8,0,0,0,8,8h88a8,8,0,0,0,8-8V120A8,8,0,0,0,136,112Zm-8,88H56V128h72Zm88-16v16a16,16,0,0,1-16,16H176a8,8,0,0,1,0-16h24V184a8,8,0,0,1,16,0Zm0-72v32a8,8,0,0,1-16,0V112a8,8,0,0,1,16,0Zm0-56V72a8,8,0,0,1-16,0V56H184a8,8,0,0,1,0-16h16A16,16,0,0,1,216,56Zm-64-8a8,8,0,0,1-8,8H112a8,8,0,0,1,0-16h32A8,8,0,0,1,152,48ZM40,80V56A16,16,0,0,1,56,40H72a8,8,0,0,1,0,16H56V80a8,8,0,0,1-16,0Z\\\"></path></g>\",\n SidebarSimple: \"<g><path d=\\\"M216,40H40A16,16,0,0,0,24,56V200a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40ZM40,56H80V200H40ZM216,200H96V56H216V200Z\\\"></path></g>\",\n Smiley: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216ZM80,108a12,12,0,1,1,12,12A12,12,0,0,1,80,108Zm96,0a12,12,0,1,1-12-12A12,12,0,0,1,176,108Zm-1.07,48c-10.29,17.79-27.4,28-46.93,28s-36.63-10.2-46.92-28a8,8,0,1,1,13.84-8c7.47,12.91,19.21,20,33.08,20s25.61-7.1,33.07-20a8,8,0,0,1,13.86,8Z\\\"></path></g>\",\n SoccerBall: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm76.52,147.42H170.9l-9.26-12.76,12.63-36.78,15-4.89,26.24,20.13A87.38,87.38,0,0,1,204.52,171.42Zm-164-34.3L66.71,117l15,4.89,12.63,36.78L85.1,171.42H51.48A87.38,87.38,0,0,1,40.47,137.12Zm10-50.64,5.51,18.6L40.71,116.77A87.33,87.33,0,0,1,50.43,86.48ZM109,152,97.54,118.65,128,97.71l30.46,20.94L147,152Zm91.07-46.92,5.51-18.6a87.33,87.33,0,0,1,9.72,30.29Zm-6.2-35.38-9.51,32.08-15.07,4.89L136,83.79V68.21l29.09-20A88.58,88.58,0,0,1,193.86,69.7ZM146.07,41.87,128,54.29,109.93,41.87a88.24,88.24,0,0,1,36.14,0ZM90.91,48.21l29.09,20V83.79L86.72,106.67l-15.07-4.89L62.14,69.7A88.58,88.58,0,0,1,90.91,48.21ZM63.15,187.42H83.52l7.17,20.27A88.4,88.4,0,0,1,63.15,187.42ZM110,214.13,98.12,180.71,107.35,168h41.3l9.23,12.71-11.83,33.42a88,88,0,0,1-36.1,0Zm55.36-6.44,7.17-20.27h20.37A88.4,88.4,0,0,1,165.31,207.69Z\\\"></path></g>\",\n SpeakerHigh: \"<g><path d=\\\"M155.51,24.81a8,8,0,0,0-8.42.88L77.25,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V32A8,8,0,0,0,155.51,24.81ZM32,96H72v64H32ZM144,207.64,88,164.09V91.91l56-43.55Zm54-106.08a40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.58,24,24,0,0,0,0-31.72,8,8,0,0,1,12-10.58ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z\\\"></path></g>\",\n SpeakerSlash: \"<g><path d=\\\"M53.92,34.62A8,8,0,1,0,42.08,45.38L73.55,80H32A16,16,0,0,0,16,96v64a16,16,0,0,0,16,16H77.25l69.84,54.31A8,8,0,0,0,160,224V175.09l42.08,46.29a8,8,0,1,0,11.84-10.76ZM32,96H72v64H32ZM144,207.64,88,164.09V95.89l56,61.6Zm42-63.77a24,24,0,0,0,0-31.72,8,8,0,1,1,12-10.57,40,40,0,0,1,0,52.88,8,8,0,0,1-12-10.59Zm-80.16-76a8,8,0,0,1,1.4-11.23l39.85-31A8,8,0,0,1,160,32v74.83a8,8,0,0,1-16,0V48.36l-26.94,21A8,8,0,0,1,105.84,67.91ZM248,128a79.9,79.9,0,0,1-20.37,53.34,8,8,0,0,1-11.92-10.67,64,64,0,0,0,0-85.33,8,8,0,1,1,11.92-10.67A79.83,79.83,0,0,1,248,128Z\\\"></path></g>\",\n Subtitles: \"<g><path d=\\\"M224,48H32A16,16,0,0,0,16,64V192a16,16,0,0,0,16,16H224a16,16,0,0,0,16-16V64A16,16,0,0,0,224,48Zm0,144H32V64H224V192ZM48,136a8,8,0,0,1,8-8H72a8,8,0,0,1,0,16H56A8,8,0,0,1,48,136Zm160,0a8,8,0,0,1-8,8H104a8,8,0,0,1,0-16h96A8,8,0,0,1,208,136Zm-48,32a8,8,0,0,1-8,8H56a8,8,0,0,1,0-16h96A8,8,0,0,1,160,168Zm48,0a8,8,0,0,1-8,8H184a8,8,0,0,1,0-16h16A8,8,0,0,1,208,168Z\\\"></path></g>\",\n SunDim: \"<g><path d=\\\"M120,40V32a8,8,0,0,1,16,0v8a8,8,0,0,1-16,0Zm72,88a64,64,0,1,1-64-64A64.07,64.07,0,0,1,192,128Zm-16,0a48,48,0,1,0-48,48A48.05,48.05,0,0,0,176,128ZM58.34,69.66A8,8,0,0,0,69.66,58.34l-8-8A8,8,0,0,0,50.34,61.66Zm0,116.68-8,8a8,8,0,0,0,11.32,11.32l8-8a8,8,0,0,0-11.32-11.32ZM192,72a8,8,0,0,0,5.66-2.34l8-8a8,8,0,0,0-11.32-11.32l-8,8A8,8,0,0,0,192,72Zm5.66,114.34a8,8,0,0,0-11.32,11.32l8,8a8,8,0,0,0,11.32-11.32ZM40,120H32a8,8,0,0,0,0,16h8a8,8,0,0,0,0-16Zm88,88a8,8,0,0,0-8,8v8a8,8,0,0,0,16,0v-8A8,8,0,0,0,128,208Zm96-88h-8a8,8,0,0,0,0,16h8a8,8,0,0,0,0-16Z\\\"></path></g>\",\n Trash: \"<g><path d=\\\"M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z\\\"></path></g>\",\n TrayArrowDown: \"<g><path d=\\\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm0,16V152h-28.7A15.86,15.86,0,0,0,168,156.69L148.69,176H107.31L88,156.69A15.86,15.86,0,0,0,76.69,152H48V48Zm0,160H48V168H76.69L96,187.31A15.86,15.86,0,0,0,107.31,192h41.38A15.86,15.86,0,0,0,160,187.31L179.31,168H208v40ZM90.34,125.66a8,8,0,0,1,11.32-11.32L120,132.69V72a8,8,0,0,1,16,0v60.69l18.34-18.35a8,8,0,0,1,11.32,11.32l-32,32a8,8,0,0,1-11.32,0Z\\\"></path></g>\",\n UploadSimple: \"<g><path d=\\\"M224,144v64a8,8,0,0,1-8,8H40a8,8,0,0,1-8-8V144a8,8,0,0,1,16,0v56H208V144a8,8,0,0,1,16,0ZM93.66,77.66,120,51.31V144a8,8,0,0,0,16,0V51.31l26.34,26.35a8,8,0,0,0,11.32-11.32l-40-40a8,8,0,0,0-11.32,0l-40,40A8,8,0,0,0,93.66,77.66Z\\\"></path></g>\",\n Users: \"<g><path d=\\\"M117.25,157.92a60,60,0,1,0-66.5,0A95.83,95.83,0,0,0,3.53,195.63a8,8,0,1,0,13.4,8.74,80,80,0,0,1,134.14,0,8,8,0,0,0,13.4-8.74A95.83,95.83,0,0,0,117.25,157.92ZM40,108a44,44,0,1,1,44,44A44.05,44.05,0,0,1,40,108Zm210.14,98.7a8,8,0,0,1-11.07-2.33A79.83,79.83,0,0,0,172,168a8,8,0,0,1,0-16,44,44,0,1,0-16.34-84.87,8,8,0,1,1-5.94-14.85,60,60,0,0,1,55.53,105.64,95.83,95.83,0,0,1,47.22,37.71A8,8,0,0,1,250.14,206.7Z\\\"></path></g>\",\n Video: \"<g><path d=\\\"M164.44,105.34l-48-32A8,8,0,0,0,104,80v64a8,8,0,0,0,12.44,6.66l48-32a8,8,0,0,0,0-13.32ZM120,129.05V95l25.58,17ZM216,40H40A16,16,0,0,0,24,56V168a16,16,0,0,0,16,16H216a16,16,0,0,0,16-16V56A16,16,0,0,0,216,40Zm0,128H40V56H216V168Zm16,40a8,8,0,0,1-8,8H32a8,8,0,0,1,0-16H224A8,8,0,0,1,232,208Z\\\"></path></g>\",\n VideoCamera: \"<g><path d=\\\"M251.77,73a8,8,0,0,0-8.21.39L208,97.05V72a16,16,0,0,0-16-16H32A16,16,0,0,0,16,72V184a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V159l35.56,23.71A8,8,0,0,0,248,184a8,8,0,0,0,8-8V80A8,8,0,0,0,251.77,73ZM192,184H32V72H192V184Zm48-22.95-32-21.33V116.28L240,95Z\\\"></path></g>\",\n VideoCameraSlash: \"<g><path d=\\\"M251.77,73a8,8,0,0,0-8.21.39L208,97.05V72a16,16,0,0,0-16-16H113.06a8,8,0,0,0,0,16H192v87.63a8,8,0,0,0,16,0V159l35.56,23.71A8,8,0,0,0,248,184a8,8,0,0,0,8-8V80A8,8,0,0,0,251.77,73ZM240,161.05l-32-21.33V116.28L240,95ZM53.92,34.62A8,8,0,1,0,42.08,45.38L51.73,56H32A16,16,0,0,0,16,72V184a16,16,0,0,0,16,16H182.64l19.44,21.38a8,8,0,1,0,11.84-10.76ZM32,184V72H66.28L168.1,184Z\\\"></path></g>\",\n Warning: \"<g><path d=\\\"M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM222.93,203.8a8.5,8.5,0,0,1-7.48,4.2H40.55a8.5,8.5,0,0,1-7.48-4.2,7.59,7.59,0,0,1,0-7.72L120.52,44.21a8.75,8.75,0,0,1,15,0l87.45,151.87A7.59,7.59,0,0,1,222.93,203.8ZM120,144V104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,180Z\\\"></path></g>\",\n WarningCircle: \"<g><path d=\\\"M128,24A104,104,0,1,0,232,128,104.11,104.11,0,0,0,128,24Zm0,192a88,88,0,1,1,88-88A88.1,88.1,0,0,1,128,216Zm-8-80V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0Zm20,36a12,12,0,1,1-12-12A12,12,0,0,1,140,172Z\\\"></path></g>\",\n WarningOctagon: \"<g><path d=\\\"M120,136V80a8,8,0,0,1,16,0v56a8,8,0,0,1-16,0ZM232,91.55v72.9a15.86,15.86,0,0,1-4.69,11.31l-51.55,51.55A15.86,15.86,0,0,1,164.45,232H91.55a15.86,15.86,0,0,1-11.31-4.69L28.69,175.76A15.86,15.86,0,0,1,24,164.45V91.55a15.86,15.86,0,0,1,4.69-11.31L80.24,28.69A15.86,15.86,0,0,1,91.55,24h72.9a15.86,15.86,0,0,1,11.31,4.69l51.55,51.55A15.86,15.86,0,0,1,232,91.55Zm-16,0L164.45,40H91.55L40,91.55v72.9L91.55,216h72.9L216,164.45ZM128,160a12,12,0,1,0,12,12A12,12,0,0,0,128,160Z\\\"></path></g>\",\n Waveform: \"<g><path d=\\\"M56,96v64a8,8,0,0,1-16,0V96a8,8,0,0,1,16,0ZM88,24a8,8,0,0,0-8,8V224a8,8,0,0,0,16,0V32A8,8,0,0,0,88,24Zm40,32a8,8,0,0,0-8,8V192a8,8,0,0,0,16,0V64A8,8,0,0,0,128,56Zm40,32a8,8,0,0,0-8,8v64a8,8,0,0,0,16,0V96A8,8,0,0,0,168,88Zm40-16a8,8,0,0,0-8,8v96a8,8,0,0,0,16,0V80A8,8,0,0,0,208,72Z\\\"></path></g>\",\n X: \"<g><path d=\\\"M205.66,194.34a8,8,0,0,1-11.32,11.32L128,139.31,61.66,205.66a8,8,0,0,1-11.32-11.32L116.69,128,50.34,61.66A8,8,0,0,1,61.66,50.34L128,116.69l66.34-66.35a8,8,0,0,1,11.32,11.32L139.31,128Z\\\"></path></g>\",\n XCircle: \"<g><path d=\\\"M165.66,101.66,139.31,128l26.35,26.34a8,8,0,0,1-11.32,11.32L128,139.31l-26.34,26.35a8,8,0,0,1-11.32-11.32L116.69,128,90.34,101.66a8,8,0,0,1,11.32-11.32L128,116.69l26.34-26.35a8,8,0,0,1,11.32,11.32ZM232,128A104,104,0,1,1,128,24,104.11,104.11,0,0,1,232,128Zm-16,0a88,88,0,1,0-88,88A88.1,88.1,0,0,0,216,128Z\\\"></path></g>\",\n XSquare: \"<g><path d=\\\"M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm0,176H48V48H208V208ZM165.66,101.66,139.31,128l26.35,26.34a8,8,0,0,1-11.32,11.32L128,139.31l-26.34,26.35a8,8,0,0,1-11.32-11.32L116.69,128,90.34,101.66a8,8,0,0,1,11.32-11.32L128,116.69l26.34-26.35a8,8,0,0,1,11.32,11.32Z\\\"></path></g>\",\n} as Record<string, string>;\n","<script lang=\"ts\">\nimport { computed, shallowReactive, useAttrs, watchEffect } from \"vue\";\n\nimport bold from \"./icons/bold\";\nimport fill from \"./icons/fill\";\nimport regular from \"./icons/regular\";\n\ntype Weight = \"thin\" | \"light\" | \"regular\" | \"bold\" | \"fill\" | \"duotone\";\n\n/*\n * The icons are Phosphor's SVG markup, generated per weight by\n * scripts/generate-icons.mjs, instead of @phosphor-icons/vue's components:\n * each of those carries all six weights, ~105 KB brotli for the 84 icons here.\n * The chat itself uses regular, bold and fill (~23 KB); the other three load\n * the first time something asks for them, shared by every BIcon.\n */\nconst weights = shallowReactive<Partial<Record<Weight, Record<string, string>>>>({\n regular,\n bold,\n fill,\n});\n\nconst lazyWeights: Partial<Record<Weight, () => Promise<{ default: Record<string, string> }>>> = {\n thin: () => import(\"./icons/thin\"),\n light: () => import(\"./icons/light\"),\n duotone: () => import(\"./icons/duotone\"),\n};\n\nconst loading = new Set<Weight>();\n\nfunction loadWeight(weight: Weight) {\n const load = lazyWeights[weight];\n if (weights[weight] || loading.has(weight) || !load) return;\n loading.add(weight);\n void load().then((module) => {\n weights[weight] = module.default;\n });\n}\n\nfunction normalizeIconName(icon: string): string {\n // Strip a \"Ph\"/\"ph\" prefix (case-insensitive), then capitalize: \"phX\", \"PhX\" and \"x\" are all \"X\".\n const withoutPrefix = /^ph/i.test(icon) ? icon.slice(2) : icon;\n return withoutPrefix.charAt(0).toUpperCase() + withoutPrefix.slice(1);\n}\n</script>\n\n<script setup lang=\"ts\">\nconst props = withDefaults(\n defineProps<{\n icon: string;\n weight?: Weight;\n size?: string | number;\n color?: string;\n mirrored?: boolean;\n }>(),\n {\n weight: \"regular\",\n size: \"1em\",\n color: \"currentColor\",\n mirrored: false,\n },\n);\n\nconst attrs = useAttrs();\n\n// Filter out 'class' to handle it separately and avoid duplication\nconst filteredAttrs = computed(() => {\n const { class: _, ...rest } = attrs;\n return rest;\n});\n\nwatchEffect(() => loadWeight(props.weight));\n\nconst markup = computed(() =>\n props.icon ? weights[props.weight]?.[normalizeIconName(props.icon)] : undefined,\n);\n</script>\n\n<template>\n <svg\n v-if=\"markup\"\n xmlns=\"http://www.w3.org/2000/svg\"\n viewBox=\"0 0 256 256\"\n :width=\"size\"\n :height=\"size\"\n :fill=\"color\"\n :transform=\"mirrored ? 'scale(-1, 1)' : undefined\"\n v-bind=\"filteredAttrs\"\n :class=\"['inline-block fill-current transition-all duration-200']\"\n v-html=\"markup\"\n />\n <span v-else v-bind=\"filteredAttrs\" :class=\"['inline-block fill-current transition-all duration-200']\" />\n</template>\n","<template>\n <div\n ref=\"parentRef\"\n class=\"h-full w-full overflow-y-auto\"\n :class=\"[scrollbar ? 'chat-scrollbar' : 'hide-scrollbar']\"\n >\n <div\n :style=\"{\n height: `${virtualizer.getTotalSize()}px`,\n width: '100%',\n position: 'relative',\n }\"\n >\n <div\n v-for=\"virtualRow in virtualizer.getVirtualItems()\"\n :key=\"virtualRow.index\"\n :data-index=\"virtualRow.index\"\n :ref=\"(el) => virtualizer.measureElement(el as HTMLElement)\"\n :style=\"{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n transform: `translateY(${virtualRow.start}px)`,\n }\"\n >\n <slot\n name=\"item\"\n :item=\"items[virtualRow.index]\"\n :index=\"virtualRow.index\"\n />\n </div>\n </div>\n\n <div\n v-show=\"pagination && hasNextPage\"\n ref=\"sentinelRef\"\n class=\"flex min-h-13 w-full flex-col justify-center\"\n >\n <slot v-if=\"hasNextPage\" name=\"loader\">\n <Skeleton height=\"2.75rem\" border-radius=\"0.75rem\" />\n </slot>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\" generic=\"T extends Record<string, any>\">\nimport { ref, onMounted, onUnmounted } from \"vue\";\nimport { useVirtualizer } from \"@tanstack/vue-virtual\";\nimport Skeleton from \"primevue/skeleton\";\n\nconst props = withDefaults(\n defineProps<{\n items: T[];\n loading: boolean;\n hasNextPage: boolean;\n scrollbar?: boolean;\n pagination?: boolean;\n }>(),\n {\n scrollbar: false,\n pagination: true,\n },\n);\n\nconst emit = defineEmits<{\n \"load-more\": [];\n}>();\n\nconst parentRef = ref<HTMLElement | null>(null);\nconst sentinelRef = ref<HTMLElement | null>(null);\nlet observer: IntersectionObserver | null = null;\n\nconst virtualizer = useVirtualizer({\n get count() {\n return props.items.length;\n },\n getScrollElement: () => parentRef.value,\n // Internal default guess. TanStack will correct this instantly upon rendering.\n estimateSize: () => 45,\n overscan: 10,\n});\n\ndefineExpose<{\n resetScroll: () => void;\n}>({\n resetScroll: () => {\n if (parentRef.value) {\n parentRef.value.scrollTop = 0;\n }\n },\n});\n\n// Auto-trigger load-more when reaching the bottom\nonMounted(() => {\n if (!sentinelRef.value) return;\n\n observer = new IntersectionObserver(\n ([entry]) => {\n if (\n entry.isIntersecting &&\n props.hasNextPage &&\n !props.loading &&\n props.pagination\n ) {\n emit(\"load-more\");\n }\n },\n { threshold: 0.1 },\n );\n\n observer.observe(sentinelRef.value);\n});\n\nonUnmounted(() => {\n observer?.disconnect();\n});\n</script>\n","import type { Directive, DirectiveBinding } from \"vue\";\n\n// 1. The visual skeleton properties (No transitions here)\nconst coreClasses = [\n \"!text-transparent\",\n \"!bg-surface-variant-2\",\n \"dark:!bg-surface-variant-2\",\n \"!animate-pulse\",\n \"!rounded\",\n \"!pointer-events-none\",\n \"!select-none\",\n \"[&>*]:!opacity-0\",\n \"will-change-[opacity,background-color]\",\n];\n\n// 2. The transition properties (Applied AFTER initial load)\nconst transitionClasses = [\"!transition-all\", \"!duration-300\", \"!ease-in-out\"];\n\nconst loadingDirective: Directive & {\n getSSRProps?: (binding: DirectiveBinding) => Record<string, string>;\n} = {\n getSSRProps(binding: DirectiveBinding): Record<string, string> {\n if (binding.value) {\n return {\n class: coreClasses.join(\" \"),\n \"aria-busy\": \"true\",\n \"aria-hidden\": \"true\",\n };\n }\n return {};\n },\n // Runs BEFORE the element is added to the DOM\n beforeMount(el: HTMLElement, binding: DirectiveBinding) {\n if (binding.value) {\n // Instantly apply the skeleton visual without any delay/fade\n el.classList.add(...coreClasses);\n el.setAttribute(\"aria-busy\", \"true\");\n el.setAttribute(\"aria-hidden\", \"true\");\n }\n },\n\n // Runs AFTER the element is fully drawn on the screen\n mounted(el: HTMLElement) {\n void el.offsetHeight;\n // Wait for the browser to finish the initial paint,\n // then silently add the transition classes so future changes fade smoothly.\n requestAnimationFrame(() => {\n el.classList.add(...transitionClasses);\n });\n },\n\n // Runs when your `isLoading` boolean changes\n updated(el: HTMLElement, binding: DirectiveBinding) {\n if (binding.value !== binding.oldValue) {\n if (binding.value) {\n requestAnimationFrame(() => {\n el.classList.add(...coreClasses);\n el.setAttribute(\"aria-busy\", \"true\");\n el.setAttribute(\"aria-hidden\", \"true\");\n });\n } else {\n requestAnimationFrame(() => {\n el.classList.remove(...coreClasses);\n el.removeAttribute(\"aria-busy\");\n el.removeAttribute(\"aria-hidden\");\n });\n }\n }\n },\n};\n\nexport default loadingDirective;\n","export function parseEmojiArray(text: string | undefined) {\n if (!text) return [];\n\n // Safely split text by visual characters\n const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' });\n const graphemes = Array.from(segmenter.segment(text)).map(s => s.segment);\n\n const emojiRegex = /\\p{Extended_Pictographic}|\\p{Regional_Indicator}/u;\n const result: Array<{ type: 'text' | 'emoji'; content: string }> = [];\n let currentText = '';\n\n for (const grapheme of graphemes) {\n if (emojiRegex.test(grapheme)) {\n if (currentText) {\n result.push({ type: 'text', content: currentText });\n currentText = '';\n }\n result.push({ type: 'emoji', content: grapheme });\n } else {\n currentText += grapheme;\n }\n }\n\n if (currentText) {\n result.push({ type: 'text', content: currentText });\n }\n\n return result;\n}","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { parseEmojiArray } from \"~/utils/emojiParser\";\n\nconst props = withDefaults(\n defineProps<{\n text?: string;\n truncate?: boolean;\n }>(),\n {\n text: \"\",\n truncate: false,\n },\n);\n\nconst parsedText = computed(() => parseEmojiArray(props.text));\n</script>\n\n<template>\n <component\n :is=\"truncate ? 'div' : 'span'\"\n :class=\"[\n truncate\n ? 'line-clamp-1 overflow-hidden text-ellipsis break-all w-full'\n : 'inline whitespace-pre-wrap break-words',\n ]\"\n >\n <template v-for=\"(chunk, index) in parsedText\" :key=\"index\">\n <span\n v-if=\"chunk.type === 'emoji'\"\n class=\"emoji-glyph inline-block h-5 w-5 leading-5 text-xl align-middle select-text\"\n >{{ chunk.content }}</span>\n <span v-else>{{ chunk.content }}</span>\n </template>\n </component>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport Avatar from \"primevue/avatar\";\nimport type { Contact } from \"~/types\";\n\nconst props = withDefaults(\n defineProps<{\n // Only what an avatar draws, so a message's reader can use it as well as a contact.\n contact: Pick<Contact, \"name\" | \"lastName\" | \"imageUrl\"> & Partial<Pick<Contact, \"isOnline\">>;\n showOnline?: boolean;\n }>(),\n { showOnline: true },\n);\n\nconst image = computed(() => props.contact.imageUrl?.trim() || undefined);\n\nconst initials = computed(() => {\n const first = props.contact?.name?.trim() || \"\";\n const last = props.contact?.lastName?.trim() || \"\";\n\n if (!first && !last) return \"\";\n\n const firstInitial = first.charAt(0);\n const lastInitial = last.charAt(0);\n\n const isRTL = /[؀-ۿ]/.test(firstInitial);\n\n if (isRTL) {\n return lastInitial ? `${firstInitial} ${lastInitial}` : firstInitial;\n } else {\n return (firstInitial + lastInitial).toUpperCase();\n }\n});\n</script>\n<template>\n <div class=\"relative z-10 size-full\">\n <Avatar\n :image=\"image\"\n :label=\"image ? undefined : initials\"\n shape=\"circle\"\n class=\"size-full! bg-chat-primary/10! text-sm! font-semibold text-chat-primary! select-none\"\n :pt=\"{ image: { draggable: false } }\"\n />\n <div\n v-if=\"contact.isOnline && showOnline\"\n class=\"absolute end-0 bottom-0 size-3 rounded-full border-2 border-chat-background bg-chat-primary\"\n ></div>\n </div>\n</template>\n","import { useHostLocale } from \"./useHostI18n\";\n\nexport const useDate = () => {\n const locale = useHostLocale();\n\n const getLang = (): string => {\n const current = locale.value;\n if (current.includes(\"fa\")) return \"fa\";\n if (current.includes(\"ar\")) return \"ar\";\n return \"en\";\n };\n\n const parseDate = (dateInput: string | Date): Date => {\n return typeof dateInput === \"string\" ? new Date(dateInput) : dateInput;\n };\n\n const formatTime = (dateInput: string | Date): string => {\n const date = parseDate(dateInput);\n const lang = getLang();\n return new Intl.DateTimeFormat(lang, {\n hour: \"2-digit\",\n minute: \"2-digit\",\n hour12: false,\n }).format(date);\n };\n\n const formatRelativeDate = (dateInput: string | Date): string => {\n const date = parseDate(dateInput);\n const lang = getLang();\n const now = new Date();\n\n const rtf = new Intl.RelativeTimeFormat(lang, { numeric: \"auto\" });\n\n const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);\n\n if (diffInSeconds < 3600) {\n const mins = Math.max(Math.floor(diffInSeconds / 60), 1);\n return rtf.format(-mins, \"minute\");\n }\n\n if (diffInSeconds < 86400) {\n const hrs = Math.floor(diffInSeconds / 3600);\n return rtf.format(-hrs, \"hour\");\n }\n\n const startOfToday = new Date(\n now.getFullYear(),\n now.getMonth(),\n now.getDate(),\n );\n const startOfDate = new Date(\n date.getFullYear(),\n date.getMonth(),\n date.getDate(),\n );\n const diffInDays = Math.floor(\n (startOfToday.getTime() - startOfDate.getTime()) / 86400000,\n );\n\n if (diffInDays === 1) {\n return rtf.format(-1, \"day\");\n }\n\n const calendarLang = lang === \"fa\" ? \"fa-IR-u-ca-persian\" : lang;\n\n const isCurrentYear =\n lang === \"fa\"\n ? new Intl.DateTimeFormat(\"en-US-u-ca-persian\", {\n year: \"numeric\",\n }).format(now) ===\n new Intl.DateTimeFormat(\"en-US-u-ca-persian\", {\n year: \"numeric\",\n }).format(date)\n : now.getFullYear() === date.getFullYear();\n\n if (isCurrentYear) {\n return new Intl.DateTimeFormat(calendarLang, {\n day: \"numeric\",\n month: \"long\",\n }).format(date);\n } else {\n return new Intl.DateTimeFormat(calendarLang, {\n day: \"numeric\",\n month: \"long\",\n year: \"numeric\",\n }).format(date);\n }\n };\n\n const formatDateShort = (dateInput: string | Date): string => {\n const date = parseDate(dateInput);\n const lang = getLang();\n const now = new Date();\n\n const calendarLang = lang === \"fa\" ? \"fa-IR-u-ca-persian\" : lang;\n\n const isCurrentYear =\n lang === \"fa\"\n ? new Intl.DateTimeFormat(\"en-US-u-ca-persian\", {\n year: \"numeric\",\n }).format(now) ===\n new Intl.DateTimeFormat(\"en-US-u-ca-persian\", {\n year: \"numeric\",\n }).format(date)\n : now.getFullYear() === date.getFullYear();\n\n return new Intl.DateTimeFormat(calendarLang, {\n day: \"numeric\",\n month: \"long\",\n year: isCurrentYear ? undefined : \"numeric\",\n }).format(date);\n };\n\n const getYearsPassed = (date: Date): number => {\n const today = new Date();\n let years = today.getFullYear() - date.getFullYear();\n const monthDiff = today.getMonth() - date.getMonth();\n\n if (\n monthDiff < 0 ||\n (monthDiff === 0 && today.getDate() < date.getDate())\n ) {\n years--;\n }\n return years;\n };\n\n return {\n formatRelativeDate,\n getYearsPassed,\n formatDateShort,\n formatTime,\n };\n};\n","<script setup lang=\"ts\">\n/**\n * One conversation row: who and when on the first line; then the conversation's tag (what tells\n * two conversations with the same person apart), the last message or the draft, and the unread\n * count. The row is a button, so it is reached with Tab and opened with Enter or Space.\n */\nimport Badge from \"primevue/badge\";\nimport Button from \"primevue/button\";\nimport Tag from \"primevue/tag\";\nimport vLoading from \"~/directives/loading\";\nimport SafeEmojiText from \"~/components/general/SafeEmojiText.vue\";\nimport { useProfileStore } from \"~/stores/profileStore.js\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { useChatStore } from \"~/stores/chatStore.js\";\nimport { useMessagesStore } from \"~/stores/messageStores.js\";\nimport { chatContactDisplay } from \"@i18n/locales\";\nimport ContactAvatar from \"./ContactAvatar.vue\";\nimport { useDate } from \"~/composables/useDate\";\nimport type { Contact } from \"~/types\";\nimport { computed } from \"vue\";\n\nconst props = defineProps<{\n contact: Contact;\n loading?: boolean;\n}>();\n\nconst { t } = useLocalI18n(chatContactDisplay);\nconst chatStore = useChatStore();\nconst messagesStore = useMessagesStore();\nconst profileStore = useProfileStore();\nconst currentUserId = computed(() => profileStore.userId);\n\nconst isActive = computed(\n () => chatStore.activeConversationId === props.contact.id,\n);\n\nconst isLoading = computed(() => props.loading);\nconst unreadCount = computed(() => props.contact.unreadCount ?? 0);\nconst hasUnread = computed(() => unreadCount.value > 0 && !isLoading.value);\nconst fullName = computed(() =>\n `${props.contact.name} ${props.contact.lastName}`.trim(),\n);\n\nconst openChat = () => {\n chatStore.setSelectedChat(props.contact.id);\n};\n\n// The open chat shows its draft in the input already.\nconst draft = computed(() =>\n isActive.value ? \"\" : (messagesStore.drafts[props.contact.id] ?? \"\"),\n);\n\nconst isFromMe = computed(\n () => props.contact.lastMessage?.senderId === currentUserId.value,\n);\n\nconst lastMessageIcon = computed(() => {\n const msg = props.contact.lastMessage;\n if (!msg || !isFromMe.value) return { color: \"\", icon: \"\", label: \"\" };\n\n if (msg.isFailed)\n return { color: \"fill-error\", icon: \"PhWarningCircle\", label: t(\"status.failed\") };\n if (!msg.isSent)\n return { color: \"fill-chat-on-background/30\", icon: \"PhClock\", label: t(\"status.sending\") };\n if (!msg.isRead)\n return { color: \"fill-chat-muted\", icon: \"PhCheck\", label: t(\"status.sent\") };\n return { color: \"fill-chat-primary\", icon: \"PhChecks\", label: t(\"status.seen\") };\n});\n\nconst attachmentIcon = computed(() => {\n const msg = props.contact.lastMessage;\n if (!msg) return null;\n\n if (msg.request) return \"PhSubtitles\";\n\n const icons: Record<string, string> = {\n image: \"PhImage\",\n file: \"PhFile\",\n voice: \"PhMicrophone\",\n video: \"PhVideo\",\n };\n\n if (msg.type !== \"text\") {\n return icons[msg.type] || null;\n }\n\n return null;\n});\n\nconst { formatTime, formatDateShort } = useDate();\n\n/** Today's activity shows its time; older activity its date. */\nconst lastMessageTime = computed(() => {\n const date = props.contact.lastMessage?.date ?? props.contact.lastActivity;\n if (!date) return \"\";\n return new Date(date).toDateString() === new Date().toDateString()\n ? formatTime(date)\n : formatDateShort(date);\n});\n\nconst lastMessageText = computed(() => {\n const msg = props.contact.lastMessage;\n if (!msg) return \"\";\n\n if (msg.text) return msg.text;\n if (msg.request) return t(\"attachementTypes.request\");\n if (msg.type !== \"text\") return t(`attachementTypes.${msg.type}`);\n return \"\";\n});\n\nconst lastMessageColor = computed(() => {\n const msg = props.contact.lastMessage;\n if (!msg) return \"text-chat-muted\";\n\n if ((!msg.text && msg.type !== \"text\") || msg.request)\n return \"text-chat-primary font-medium\";\n\n if (unreadCount.value > 0)\n return \"text-chat-on-background font-medium\";\n\n return \"text-chat-muted\";\n});\n\n// With nothing for the second line, the name centres on the avatar instead of sitting over a gap.\nconst hasDetails = computed(\n () => !!(props.contact.tag || draft.value || props.contact.lastMessage || hasUnread.value),\n);\n\nconst unreadLabel = computed(() =>\n unreadCount.value > 99 ? \"+99\" : String(unreadCount.value),\n);\n\n/** Everything the row shows, in reading order, as the button's accessible name. */\nconst accessibleName = computed(() =>\n [\n fullName.value,\n props.contact.tag,\n lastMessageTime.value,\n draft.value ? `${t(\"draft\")}: ${draft.value}` : lastMessageText.value,\n lastMessageIcon.value.label,\n hasUnread.value ? t(\"unread\", { count: unreadLabel.value }) : \"\",\n ]\n .filter(Boolean)\n .join(\"، \"),\n);\n</script>\n<template>\n <Button\n unstyled\n data-testid=\"chat-contact\"\n :data-contact-id=\"contact.id\"\n :aria-current=\"isActive ? 'true' : undefined\"\n :aria-label=\"accessibleName\"\n :class=\"[isActive ? 'bg-chat-surface' : 'bg-chat-surface/0 hover:bg-chat-surface/50']\"\n class=\"flex h-19 w-full cursor-pointer items-center gap-x-3 rounded-xl p-2.5 text-start transition-colors duration-200 ease-in-out focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-chat-primary motion-reduce:transition-none\"\n @click=\"openChat\"\n >\n <span v-loading=\"isLoading\" class=\"relative block size-12 shrink-0\">\n <ContactAvatar :contact=\"contact\" />\n </span>\n\n <span class=\"flex min-w-0 flex-1 flex-col gap-y-1 select-none\">\n <span class=\"flex w-full items-baseline justify-between gap-x-2\">\n <span\n v-loading=\"isLoading\"\n :class=\"hasUnread ? 'font-bold' : 'font-semibold'\"\n class=\"min-w-20 truncate text-label-md text-chat-on-background\"\n >\n {{ fullName }}\n </span>\n <span\n v-if=\"lastMessageTime\"\n v-loading=\"isLoading\"\n :class=\"hasUnread ? 'font-semibold text-chat-primary' : 'text-chat-muted'\"\n class=\"shrink-0 text-[11px]\"\n >\n {{ lastMessageTime }}\n </span>\n </span>\n\n <span v-if=\"hasDetails\" class=\"flex w-full items-center gap-x-1.5\">\n <Tag\n v-if=\"contact.tag && !isLoading\"\n severity=\"secondary\"\n :value=\"contact.tag\"\n data-testid=\"chat-contact-tag\"\n :pt=\"{\n root: {\n class:\n 'max-w-24 shrink-0 rounded-md! px-1.5! py-0! bg-chat-on-background/6! text-chat-muted!',\n },\n label: { class: 'truncate text-[11px]! font-semibold! leading-5!' },\n }\"\n />\n\n <span class=\"flex min-w-0 flex-1 items-center gap-x-1\">\n <template v-if=\"draft\">\n <span class=\"shrink-0 text-body-sm text-error\">{{ t(\"draft\") }}:</span>\n <SafeEmojiText truncate :text=\"draft\" class=\"min-w-0 text-body-sm text-chat-muted\" />\n </template>\n\n <template v-else-if=\"contact.lastMessage && !isLoading\">\n <BIcon\n v-if=\"lastMessageIcon.icon\"\n :icon=\"lastMessageIcon.icon\"\n :class=\"lastMessageIcon.color\"\n class=\"size-4 shrink-0\"\n />\n <BIcon\n v-if=\"attachmentIcon\"\n weight=\"bold\"\n :icon=\"attachmentIcon\"\n class=\"size-4 shrink-0 fill-chat-primary\"\n />\n <span\n dir=\"auto\"\n :class=\"['min-w-0 truncate text-body-sm transition-colors', lastMessageColor]\"\n >\n <SafeEmojiText truncate :text=\"lastMessageText\" />\n </span>\n </template>\n </span>\n\n <Badge\n v-if=\"hasUnread\"\n dir=\"ltr\"\n :value=\"unreadLabel\"\n class=\"ms-1 shrink-0\"\n />\n </span>\n </span>\n </Button>\n</template>\n","<script setup lang=\"ts\">\n/** A placeholder conversation row, the size and shape of ChatContactDisplay, for loading more. */\nimport Skeleton from \"primevue/skeleton\";\n</script>\n\n<template>\n <div\n class=\"vue-chat flex h-19 w-full items-center gap-x-3 p-2.5\"\n aria-hidden=\"true\"\n >\n <Skeleton shape=\"circle\" size=\"3rem\" class=\"shrink-0\" />\n <div class=\"flex flex-1 flex-col gap-y-2.5 overflow-hidden\">\n <div class=\"flex items-center justify-between\">\n <Skeleton width=\"7rem\" height=\"0.875rem\" />\n <Skeleton width=\"2rem\" height=\"0.625rem\" />\n </div>\n <Skeleton width=\"60%\" height=\"0.75rem\" />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * An icon-only PrimeVue Button showing a Phosphor icon. Defaults to a round, text, secondary\n * button; any Button prop (severity, variant, size, loading, disabled...) and listener passes\n * through and overrides those defaults.\n */\nimport Button from \"primevue/button\";\nimport BIcon from \"~/components/global/BIcon.vue\";\n\ndefineOptions({ inheritAttrs: false });\n\nwithDefaults(\n defineProps<{\n icon: string;\n /** Accessible name; the button has no visible text. */\n label: string;\n weight?: \"thin\" | \"light\" | \"regular\" | \"bold\" | \"fill\" | \"duotone\";\n iconClass?: string;\n }>(),\n { weight: \"regular\", iconClass: \"size-5\" },\n);\n</script>\n\n<template>\n <Button rounded text severity=\"secondary\" v-bind=\"$attrs\" :aria-label=\"label\">\n <template #icon>\n <BIcon :icon=\"icon\" :weight=\"weight\" :class=\"iconClass\" />\n </template>\n </Button>\n</template>\n","<script setup lang=\"ts\">\n/**\n * The list's header: its title over a search field that is always there, so finding a\n * conversation is one step rather than two. The clear button only shows once there is a query.\n */\nimport { ref, type ComponentPublicInstance } from \"vue\";\nimport IconField from \"primevue/iconfield\";\nimport InputIcon from \"primevue/inputicon\";\nimport InputText from \"primevue/inputtext\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatListSearch } from \"@i18n/locales\";\nconst model = defineModel<string>({ default: \"\" });\n\nconst { t } = useLocalI18n(chatListSearch);\nconst inputRef = ref<ComponentPublicInstance | null>(null);\n\nconst clear = () => {\n model.value = \"\";\n (inputRef.value?.$el as HTMLInputElement | undefined)?.focus();\n};\n</script>\n<template>\n <div\n class=\"flex w-full flex-col gap-y-3 border-b border-b-chat-outline-variant px-4 pt-4 pb-3 md:pt-5\"\n >\n <h2 class=\"m-0 truncate text-label-lg text-chat-on-background select-none\">\n {{ t(\"title\") }}\n </h2>\n\n <div class=\"relative w-full\">\n <IconField class=\"w-full\">\n <InputIcon class=\"flex! items-center text-chat-muted\">\n <BIcon icon=\"PhMagnifyingGlass\" class=\"size-4.5\" />\n </InputIcon>\n <InputText\n ref=\"inputRef\"\n v-model=\"model\"\n type=\"search\"\n autocomplete=\"off\"\n data-testid=\"chat-search\"\n :placeholder=\"t('placeholder')\"\n :aria-label=\"t('search')\"\n class=\"h-11! w-full rounded-xl! pe-11! [&::-webkit-search-cancel-button]:hidden\"\n />\n </IconField>\n <IconButton\n v-if=\"model\"\n icon=\"PhX\"\n icon-class=\"size-4\"\n :label=\"t('clear')\"\n data-testid=\"chat-search-clear\"\n size=\"small\"\n class=\"absolute! end-1 top-1/2 size-9! -translate-y-1/2\"\n @click=\"clear\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { ref, computed, watch, onMounted, onBeforeUnmount } from \"vue\";\nimport SelectButton from \"primevue/selectbutton\";\nimport NoData from \"~/assets/lib-images/chat/empty-state.webp\";\nimport Button from \"primevue/button\";\nimport NoDataDisplay from \"~/components/general/NoDataDisplay.vue\";\nimport type { ChatFilter, StateKeys } from \"~/types\";\nimport ChatContactDisplay from \"./ChatContactDisplay.vue\";\nimport ContactSkeleton from \"./ContactSkeleton.vue\";\nimport { useChatStore } from \"~/stores/chatStore.js\";\nimport ChatListSearch from \"./ChatListSearch.vue\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { chatList } from \"@i18n/locales\";\nconst { t } = useLocalI18n(chatList);\nconst { dir } = useDirection();\nconst chatStore = useChatStore();\n\nconst activeFilter = ref<StateKeys>(\"\");\nconst searchText = ref(\"\");\nconst listRef = ref<HTMLElement | null>(null);\n\nlet searchTimeout: ReturnType<typeof setTimeout> | null = null;\n\nconst currentState = computed(\n () => chatStore.conversationStates[activeFilter.value],\n);\n\nconst chats = computed(() =>\n chatStore.getDisplayedContacts(activeFilter.value),\n);\n\nconst query = computed(() => searchText.value.trim());\n\nconst clearSearch = () => {\n searchText.value = \"\";\n};\n\nconst filters = computed<ChatFilter[]>(() => [\n { key: \"active\", label: t(\"filters.active\") },\n { key: \"ended\", label: t(\"filters.ended\") },\n]);\n\nconst setFilter = (type: StateKeys) => {\n if (activeFilter.value === type) return;\n activeFilter.value = type;\n};\n\n// Handle Filter Changes\nwatch(activeFilter, (newFilter) => {\n // 1. Scroll to top\n const scrollEl = listRef.value;\n if (scrollEl) scrollEl.scrollTop = 0;\n\n // 2. Fetch if the tab is empty or was loaded for another search\n const state = chatStore.conversationStates[newFilter];\n if (state.data.length === 0 || state.search !== query.value) {\n chatStore.fetchConversations(newFilter, 1, query.value);\n }\n});\n\n// Handle Search with Debounce\nwatch(query, (newQuery) => {\n if (searchTimeout) clearTimeout(searchTimeout);\n\n searchTimeout = setTimeout(() => {\n chatStore.fetchConversations(activeFilter.value, 1, newQuery);\n\n const scrollEl = listRef.value;\n if (scrollEl) scrollEl.scrollTop = 0;\n }, 500);\n});\n\nonMounted(() => {\n if (chatStore.conversationStates[activeFilter.value].data.length === 0) {\n chatStore.fetchConversations(activeFilter.value, 1);\n }\n});\n\n// Cleanup timeout to prevent memory leaks or state updates on unmounted components\nonBeforeUnmount(() => {\n if (searchTimeout) clearTimeout(searchTimeout);\n});\n</script>\n\n<template>\n <div\n :dir=\"dir\"\n class=\"vue-chat flex h-full w-full flex-col overflow-hidden border border-chat-outline-variant bg-chat-background\"\n >\n <ChatListSearch v-model=\"searchText\" class=\"shrink-0\" />\n\n <div class=\"flex w-full flex-1 flex-col overflow-hidden\">\n <div class=\"flex w-full shrink-0 items-center px-4 pt-3 pb-1\">\n <SelectButton\n :model-value=\"activeFilter || null\"\n :options=\"filters\"\n option-label=\"label\"\n option-value=\"key\"\n :aria-label=\"t('filters.label')\"\n class=\"w-full\"\n :pt=\"{ pcToggleButton: { root: { class: 'flex-1 h-9!' } } }\"\n @update:model-value=\"(key) => setFilter(key ?? '')\"\n />\n </div>\n\n <div\n v-if=\"currentState.loading || chats.length > 0\"\n class=\"relative w-full flex-1 overflow-hidden px-2.5 pt-2.5\"\n >\n <BVirtualVerticalList\n ref=\"listRef\"\n :items=\"chats\"\n :loading=\"currentState.loading\"\n :has-next-page=\"currentState.hasNextPage\"\n scrollbar\n class=\"h-full w-full\"\n @load-more=\"chatStore.loadNextPage(activeFilter)\"\n >\n <template #loader>\n <ContactSkeleton v-for=\"n in 2\" :key=\"n\" />\n </template>\n <template #item=\"{ item }\">\n <ChatContactDisplay\n :contact=\"item\"\n :loading=\"currentState.loading && (currentState.page === 0 || !!currentState.refreshing)\"\n />\n </template>\n </BVirtualVerticalList>\n </div>\n\n <div\n v-else-if=\"query\"\n role=\"status\"\n data-testid=\"chat-search-empty\"\n class=\"flex w-full flex-1 flex-col items-center justify-center gap-y-3 px-6 text-center\"\n >\n <span class=\"flex size-14 items-center justify-center rounded-full bg-chat-surface text-chat-muted\">\n <BIcon icon=\"PhMagnifyingGlass\" class=\"size-6.5\" />\n </span>\n <p class=\"m-0 text-label-md text-chat-on-background\">\n {{ t(\"noResults.title\", { query }) }}\n </p>\n <p class=\"m-0 text-body-sm text-chat-muted\">{{ t(\"noResults.hint\") }}</p>\n <Button\n :label=\"t('noResults.clear')\"\n severity=\"secondary\"\n variant=\"text\"\n size=\"small\"\n @click=\"clearSearch\"\n />\n </div>\n\n <div v-else class=\"flex w-full flex-1 items-center justify-center\">\n <NoDataDisplay :image-path=\"NoData\" :title=\"t('noMessages')\" />\n </div>\n </div>\n </div>\n</template>\n","// composables/useAppPermissions.ts\nimport { ref } from \"vue\";\nimport { useEventBus } from \"@vueuse/core\";\nexport type PopupState =\n | \"permission\"\n | \"mic-error\"\n | \"cam-error\"\n | \"mic-permission\"\n | \"cam-permission\"\n | \"screen-share-error\"\n | \"screen-share-permission\";\n\ninterface PermissionRequest {\n state: PopupState;\n resolve: (value: boolean) => void;\n}\n\nconst permissionBus = useEventBus<PermissionRequest>(\"global-permission-popup\");\nexport function useAppPermissions() {\n const checkMediaStatus = async () => {\n try {\n const mic = await navigator.permissions.query({\n name: \"microphone\" as PermissionName,\n });\n const cam = await navigator.permissions.query({\n name: \"camera\" as PermissionName,\n });\n return { mic: mic.state, cam: cam.state };\n } catch (err) {\n return { mic: \"unknown\", cam: \"unknown\" };\n }\n };\n\n // Requests BOTH at once as requested, with a fallback if hardware is missing\n const requestMediaAccess = async (need: \"audio\" | \"video\" | \"both\") => {\n try {\n // 1. Try the primary request\n const constraints: MediaStreamConstraints = {\n audio: need === \"audio\" || need === \"both\",\n video: need === \"video\" || need === \"both\",\n };\n\n const stream = await navigator.mediaDevices.getUserMedia(constraints);\n stream.getTracks().forEach((track) => track.stop());\n return { success: true };\n } catch (error: any) {\n // 2. DETECT MISSING HARDWARE (Mac Mini case)\n if (\n error.name === \"NotFoundError\" ||\n error.name === \"DevicesNotFoundError\"\n ) {\n console.warn(\"Hardware not found. Checking for partial success...\");\n\n // If they needed 'both' but only have one (or none), try a partial fallback\n if (need === \"both\") {\n try {\n // Try ONLY video if audio failed\n const vStream = await navigator.mediaDevices.getUserMedia({\n video: true,\n });\n vStream.getTracks().forEach((t) => t.stop());\n return { success: true, hardwareWarning: \"no-mic\" };\n } catch {\n return { success: false, error: \"no-hardware\" };\n }\n }\n return { success: false, error: \"no-hardware\" };\n }\n\n // 3. Handle explicit denials (NotAllowedError)\n return { success: false, error: error.name };\n }\n };\n\n const requestLocation = async (): Promise<GeolocationPosition> => {\n return new Promise((resolve, reject) => {\n if (!navigator.geolocation) return reject(\"Unsupported\");\n navigator.geolocation.getCurrentPosition(resolve, reject);\n });\n };\n\n const requestScreenShare = async (): Promise<boolean> => {\n return await requestWithPopup(\"screen-share-permission\");\n };\n\n const requestWithPopup = (state: PopupState) => {\n return new Promise<boolean>((resolve) => {\n permissionBus.emit({ state, resolve });\n });\n };\n\n const getNativeScreenShare = async (): Promise<MediaStream> => {\n return await navigator.mediaDevices.getDisplayMedia({\n video: true,\n audio: false,\n });\n };\n\n return {\n checkMediaStatus,\n requestMediaAccess,\n requestLocation,\n requestScreenShare,\n requestWithPopup,\n getNativeScreenShare,\n };\n}\n","<script setup lang=\"ts\">\n/**\n * A modal PrimeVue Dialog that is centred on wide screens and becomes a full-width bottom sheet\n * on phones. Dialog props, listeners and slots pass through.\n */\nimport Dialog from \"primevue/dialog\";\nimport { useSlots } from \"vue\";\nimport { useMediaQuery } from \"@vueuse/core\";\nimport { useDirection } from \"~/composables/useLocalI18n\";\n\ndefineOptions({ inheritAttrs: false });\n\nwithDefaults(defineProps<{ width?: string }>(), { width: \"30rem\" });\n\nconst visible = defineModel<boolean>(\"visible\", { default: false });\nconst slotNames: string[] = Object.keys(useSlots());\n\n// Tailwind's `md` breakpoint.\nconst isSheet = useMediaQuery(\"(max-width: 767.98px)\");\n// Teleported to <body>, so it takes the chat's direction here rather than the page's.\nconst { dir } = useDirection();\n</script>\n\n<template>\n <Dialog\n v-model:visible=\"visible\"\n modal\n :position=\"isSheet ? 'bottom' : 'center'\"\n :draggable=\"false\"\n :style=\"{ width }\"\n :breakpoints=\"{ '767.98px': '100vw' }\"\n :dir=\"dir\"\n v-bind=\"$attrs\"\n :class=\"['vue-chat', isSheet && 'm-0! rounded-b-none!']\"\n >\n <template v-for=\"name in slotNames\" #[name]=\"scope\">\n <slot :name=\"name\" v-bind=\"scope ?? {}\" />\n </template>\n </Dialog>\n</template>\n","<template>\n <ResponsiveDialog\n v-model:visible=\"visible\"\n :show-header=\"false\"\n width=\"30rem\"\n @hide=\"onHide\"\n >\n <div class=\"flex w-full items-center gap-x-2 pt-5 pb-3\">\n <BIcon\n :icon=\"popupIcon.icon\"\n weight=\"fill\"\n :class=\"[popupIcon.color]\"\n class=\"size-7\"\n />\n <div class=\"text-label-lg text-chat-on-background select-none\">\n {{ popupContent.title }}\n </div>\n </div>\n <p class=\"text-body-md text-chat-muted select-none\">\n {{ popupContent.description }}\n </p>\n <div class=\"flex w-full items-center gap-x-3 pt-5\">\n <Button\n :label=\"actionButtonText\"\n :loading=\"isLoading\"\n @click=\"handleAction\"\n />\n <Button\n severity=\"secondary\"\n outlined\n :label=\"t('permissions.notNow')\"\n @click=\"closePopup\"\n />\n </div>\n </ResponsiveDialog>\n</template>\n\n<script setup lang=\"ts\">\nimport {\n useAppPermissions,\n type PopupState,\n} from \"~/composables/useAppPermissions\";\nimport { ref, computed, onUnmounted } from \"vue\";\nimport Button from \"primevue/button\";\nimport ResponsiveDialog from \"~/components/general/ResponsiveDialog.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { permissionPopup } from \"@i18n/locales\";\nimport { useEventBus } from \"@vueuse/core\";\n\nconst { t } = useLocalI18n(permissionPopup);\nconst { requestMediaAccess, getNativeScreenShare } = useAppPermissions();\n\nconst visible = ref(false);\nconst popupMode = ref<PopupState>(\"mic-permission\");\nconst isLoading = ref(false);\nconst currentResolver = ref<((v: boolean) => void) | null>(null);\n\n// --- Event Bus ---\nconst bus = useEventBus<{ resolve: (v: boolean) => void; state: PopupState }>(\n \"global-permission-popup\",\n);\n\n// `bus.on(handler)` returns the cleanup function directly — not an object with an `off` property.\nconst offBus = bus.on((payload) => {\n currentResolver.value = payload.resolve;\n switchMode(payload.state);\n});\n\nonUnmounted(() => {\n offBus();\n});\n\n// --- Computed ---\nconst popupIcon = computed(() => ({\n icon: popupMode.value.endsWith(\"permission\")\n ? \"PhWarningCircle\"\n : \"PhWarningOctagon\",\n color: popupMode.value.endsWith(\"permission\")\n ? \"text-chat-primary\"\n : \"text-chat-error\",\n}));\n\nconst actionButtonText = computed(() =>\n popupMode.value.endsWith(\"permission\")\n ? t(\"permissions.allow\")\n : t(\"permissions.retry\"),\n);\n\nconst popupContent = computed(() => {\n switch (popupMode.value) {\n case \"permission\":\n return {\n title: t(\"permissions.permissionTitle\"),\n description: t(\"permissions.description\"),\n };\n case \"cam-error\":\n return {\n title: t(\"permissions.camError.title\"),\n description: t(\"permissions.camError.description\"),\n };\n case \"mic-error\":\n return {\n title: t(\"permissions.micError.title\"),\n description: t(\"permissions.micError.description\"),\n };\n case \"cam-permission\":\n return {\n title: t(\"permissions.cam.title\"),\n description: t(\"permissions.cam.description\"),\n };\n case \"mic-permission\":\n return {\n title: t(\"permissions.mic.title\"),\n description: t(\"permissions.mic.description\"),\n };\n case \"screen-share-error\":\n return {\n title: t(\"permissions.screenError.title\"),\n description: t(\"permissions.screenError.description\"),\n };\n case \"screen-share-permission\":\n return {\n title: t(\"permissions.screen.title\"),\n description: t(\"permissions.screen.description\"),\n };\n }\n});\n\n// --- Methods ---\nconst settle = (granted: boolean) => {\n currentResolver.value?.(granted);\n currentResolver.value = null;\n};\n\nlet switching = false;\n\n// Dismissing the dialog (Escape) refuses, like \"Not now\"; switching to another state does not.\nconst onHide = () => {\n if (!switching) settle(false);\n};\n\nconst switchMode = async (newMode: PopupState) => {\n switching = true;\n visible.value = false;\n\n // Let the closing dialog finish animating before it reopens with new content.\n await new Promise((resolve) => setTimeout(resolve, 300));\n\n popupMode.value = newMode;\n isLoading.value = false;\n visible.value = true;\n switching = false;\n};\n\nconst closePopup = () => {\n settle(false);\n visible.value = false;\n};\n\nconst handleAction = async () => {\n isLoading.value = true;\n let success = false;\n\n // --- 1. SCREEN SHARE FLOW (Standalone) ---\n if (popupMode.value === \"screen-share-permission\") {\n try {\n const stream = await getNativeScreenShare();\n if (stream) success = true;\n } catch (err: unknown) {\n console.error(\"Screen Share Error:\", (err as Error).name);\n success = false;\n }\n\n isLoading.value = false;\n if (success) {\n settle(true);\n visible.value = false;\n } else {\n // macOS often throws NotAllowedError if System Settings are off\n await switchMode(\"screen-share-error\");\n }\n return; // EXIT HERE so it doesn't run the Mic/Cam logic below\n }\n\n // --- 2. MIC / CAM FLOW ---\n let need: \"audio\" | \"video\" | \"both\" = \"audio\";\n if (popupMode.value.startsWith(\"cam\")) need = \"video\";\n if (popupMode.value === \"permission\") need = \"both\";\n\n const result = await requestMediaAccess(need);\n\n isLoading.value = false;\n if (result.success) {\n settle(true);\n visible.value = false;\n } else {\n // If hardware is missing (Mac Mini), show a specific error\n const errorMode =\n need === \"video\" || need === \"both\" ? \"cam-error\" : \"mic-error\";\n await switchMode(errorMode);\n }\n};\n\ndefineExpose<{\n open: (state: PopupState) => void;\n close: () => void;\n setLoading: (state: boolean) => void;\n}>({\n open: (state: PopupState) => {\n popupMode.value = state;\n isLoading.value = false;\n visible.value = true;\n },\n close: closePopup,\n setLoading: (state: boolean) => {\n isLoading.value = state;\n },\n});\n</script>\n","export const replaceDigitsByLocale = (\n value: string | number,\n locale: string = \"fa\",\n): string => {\n if (value === null || value === undefined) return \"\";\n const str = String(value);\n if (locale !== \"fa\") return str;\n const persianDigits = [\"۰\", \"۱\", \"۲\", \"۳\", \"۴\", \"۵\", \"۶\", \"۷\", \"۸\", \"۹\"];\n return str.replace(/\\d/g, (digit) => {\n return persianDigits[parseInt(digit)];\n });\n};\n\nexport const formatBytes = (bytes: number) => {\n if (bytes === 0) return \"0 KB\";\n const k = 1024;\n const sizes = [\"Bytes\", \"KB\", \"MB\", \"GB\"];\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + \" \" + sizes[i];\n};\n\nexport const formatDuration = (totalSeconds: number): string => {\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n\n const padded = (val: number) => val.toString().padStart(2, \"0\");\n\n if (hours > 0) {\n return `${padded(hours)}:${padded(minutes)}:${padded(seconds)}`;\n }\n\n return `${padded(minutes)}:${padded(seconds)}`;\n};\n","<script setup lang=\"ts\">\nimport vLoading from \"~/directives/loading\";\nimport { ref, computed, onMounted } from \"vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { profileFileDisplay } from \"@i18n/locales\";\nimport { formatBytes } from \"~/utils/format\";\nimport { useMediaStore } from \"~/stores/mediaStore\";\n\nconst props = withDefaults(\n defineProps<{\n url: string;\n loading?: boolean;\n }>(),\n {\n loading: true,\n },\n);\n\nconst { t } = useLocalI18n(profileFileDisplay);\nconst mediaStore = useMediaStore();\nconst fetchedSize = ref<number | null>(null);\nconst isLoading = computed(() => props.loading);\n\nconst fileName = computed(() => {\n try {\n const urlObj = new URL(props.url);\n const path = urlObj.pathname;\n return decodeURIComponent(path.split(\"/\").pop() || \"Unknown_File\");\n } catch {\n return \"File\";\n }\n});\n\nconst fileExt = computed(() => {\n const name = fileName.value;\n const lastDot = name.lastIndexOf(\".\");\n if (lastDot !== -1) {\n return name\n .substring(lastDot + 1)\n .toUpperCase()\n .substring(0, 4);\n }\n return \"FILE\";\n});\n\nconst formattedSize = computed(() => {\n // FIX: Check `!== null` instead of truthy. If the file size is exactly 0 bytes,\n // a truthy check would incorrectly show \"Calculating...\" forever.\n return fetchedSize.value !== null\n ? formatBytes(fetchedSize.value)\n : t(\"file.calculating\");\n});\n\nconst getFileSize = async () => {\n try {\n const size = await mediaStore.fetchFileSize(props.url);\n fetchedSize.value = size ?? 0;\n } catch (e) {\n console.warn(\"Could not fetch file size upfront:\", e);\n fetchedSize.value = 0; // Fallback\n }\n};\n\nonMounted(() => {\n getFileSize();\n});\n</script>\n\n<template>\n <div class=\"flex w-full select-none items-center gap-x-2\">\n <div class=\"flex min-w-0 flex-1 flex-col gap-y-0.5 text-left\">\n <div v-loading=\"isLoading\" class=\"truncate text-label-md text-chat-on-background\">\n {{ fileName }}\n </div>\n <div\n v-loading=\"isLoading\"\n dir=\"ltr\"\n class=\"text-body-sm text-chat-on-background/70\"\n >\n {{ formattedSize }}\n </div>\n </div>\n\n <div\n v-loading=\"isLoading\"\n class=\"relative shrink-0 cursor-pointer transition-transform active:scale-95\"\n >\n <BIcon\n icon=\"PhFile\"\n weight=\"fill\"\n class=\"h-10 w-10 fill-chat-surface-3\"\n />\n <div\n class=\"absolute bottom-2 right-0 flex items-center justify-center rounded-sm bg-chat-error px-1 py-0.5\"\n >\n <div\n class=\"text-center text-[7px] font-bold uppercase leading-none tracking-wide text-white\"\n >\n {{ fileExt }}\n </div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * The contact info panel beside the conversation: who it is, how to reach them, what they shared.\n * A header row lines up with the conversation header; then the person, their call actions, the\n * details the viewer may see, the shared media and files, and ending the conversation, set apart\n * at the foot because it cannot be undone.\n */\nimport Button from \"primevue/button\";\nimport Tab from \"primevue/tab\";\nimport TabList from \"primevue/tablist\";\nimport Tabs from \"primevue/tabs\";\nimport Tag from \"primevue/tag\";\nimport vLoading from \"~/directives/loading\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport MediaImage from \"~/components/general/MediaImage.vue\";\nimport { useProfileStore } from \"~/stores/profileStore.js\";\nimport ContactAvatar from \"./contact/ContactAvatar.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { useChatStore } from \"~/stores/chatStore.js\";\nimport { useCallStore } from \"~/stores/callStore.js\";\nimport { chatProfileOverview } from \"@i18n/locales\";\nimport FileDisplay from \"./profile/FileDisplay.vue\";\nimport { useDate } from \"~/composables/useDate.js\";\nimport { ref, computed, watch } from \"vue\";\nimport type { Contact } from \"~/types\";\n\nconst props = withDefaults(\n defineProps<{\n profile?: Contact | null;\n }>(),\n {\n profile: null,\n },\n);\n\nconst emit = defineEmits<{\n /** Asks to end the conversation; the parent confirms it first. */\n end: [];\n}>();\n\n// Enough to fill the panel on a tall screen; more load as the list scrolls.\nconst MEDIA_PER_PAGE = 48;\nconst FILES_PER_PAGE = 20;\nconst MEDIA_COLUMNS = 3;\n\nconst { getYearsPassed, formatRelativeDate } = useDate();\nconst callStore = useCallStore();\nconst chatStore = useChatStore();\nconst profileStore = useProfileStore();\nconst { t } = useLocalI18n(chatProfileOverview);\n\nconst conversationId = computed(() => chatStore.activeConversationId ?? \"\");\nconst isOpen = ref(false);\nconst localProfile = ref<Contact>();\nconst currentTab = ref<\"media\" | \"files\">(\"media\");\n\nconst mediaAttachements = computed<string[]>(\n () =>\n (conversationId.value && profileStore.mediaMap[conversationId.value]) || [],\n);\nconst fileAttachements = computed<string[]>(\n () =>\n (conversationId.value && profileStore.filesMap[conversationId.value]) || [],\n);\nconst isLoadingMedia = computed(() => profileStore.mediaLoading);\nconst isLoadingAttachements = computed(() => profileStore.filesLoading);\nconst hasMediaNextPage = computed(\n () =>\n (conversationId.value &&\n profileStore.mediaHasNextPage[conversationId.value]) ??\n false,\n);\nconst hasFileNextPage = computed(\n () =>\n (conversationId.value &&\n profileStore.filesHasNextPage[conversationId.value]) ??\n false,\n);\n\nconst isLoading = computed(() => props.profile === null);\nconst isInCall = computed(() => callStore.isActive);\nconst showPersonalInfo = computed(() => chatStore.chosenRole !== \"user\");\n\nconst fullName = computed(() =>\n `${localProfile.value?.name ?? \"\"} ${localProfile.value?.lastName ?? \"\"}`.trim(),\n);\n\n// The same rule as the conversation header: no calls once ended, none on a chat-only service,\n// and both when the host does not say.\nconst canVoiceCall = computed(\n () => !!localProfile.value?.isActive && localProfile.value.serviceType !== \"chat\",\n);\nconst canVideoCall = computed(\n () => canVoiceCall.value && localProfile.value?.serviceType !== \"voice-call\",\n);\nconst canEnd = computed(() => !!localProfile.value?.isActive && chatStore.canEndConversation);\n\n// Hosts without a birth date send the epoch, which would read as an age of fifty-odd.\nconst age = computed(() => {\n const birthDate = localProfile.value?.birthDate;\n if (!birthDate || new Date(birthDate).getTime() <= 0) return undefined;\n return getYearsPassed(new Date(birthDate));\n});\n\nconst details = computed(() =>\n [\n {\n key: \"age\",\n icon: \"PhCake\",\n label: t(\"info.age\"),\n value: age.value === undefined ? undefined : t(\"info.years\", { count: age.value }),\n show: true,\n },\n {\n key: \"nationalCode\",\n icon: \"PhIdentificationCard\",\n label: t(\"info.nationalCode\"),\n value: localProfile.value?.nationalCode,\n show: showPersonalInfo.value,\n },\n {\n key: \"phoneNumber\",\n icon: \"PhPhone\",\n label: t(\"info.phoneNumber\"),\n value: localProfile.value?.phoneNumber,\n show: showPersonalInfo.value,\n ltr: true,\n },\n {\n key: \"status\",\n icon: localProfile.value?.isActive ? \"PhChatCircleDots\" : \"PhLockKey\",\n label: t(\"info.status\"),\n value: localProfile.value\n ? localProfile.value.isActive\n ? t(\"status.active\")\n : t(\"status.ended\")\n : undefined,\n show: true,\n },\n ].filter((item) => item.show && item.value !== undefined && item.value !== \"\"),\n);\n\nconst mediaRows = computed(() => {\n const rows: string[][] = [];\n for (let i = 0; i < mediaAttachements.value.length; i += MEDIA_COLUMNS) {\n rows.push(mediaAttachements.value.slice(i, i + MEDIA_COLUMNS));\n }\n return rows;\n});\n\nconst hasShared = computed(\n () => mediaAttachements.value.length > 0 || fileAttachements.value.length > 0,\n);\nconst isLoadingShared = computed(\n () => (isLoadingMedia.value || isLoadingAttachements.value) && !hasShared.value,\n);\n\nconst fetchShared = (id: string) => {\n profileStore.fetchMedia(id, 1, MEDIA_PER_PAGE);\n profileStore.fetchFiles(id, 1, FILES_PER_PAGE);\n};\n\n// --- Watchers ---\nwatch(\n () => chatStore.profileViewOpen,\n (isProfileOpen) => {\n if (isProfileOpen) {\n if (props.profile) {\n localProfile.value = props.profile;\n }\n isOpen.value = true;\n if (conversationId.value) fetchShared(conversationId.value);\n } else {\n isOpen.value = false;\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.profile,\n (newVal) => {\n if (newVal) {\n localProfile.value = newVal;\n }\n },\n);\n\nwatch(\n () => conversationId.value,\n (newId, oldId) => {\n if (!newId || newId === oldId || !isOpen.value) return;\n fetchShared(newId);\n },\n);\n\n// Open on whichever kind the conversation has: files when it shared no media.\nwatch([mediaAttachements, fileAttachements], ([media, files]) => {\n if (currentTab.value === \"media\" && !media.length && files.length) currentTab.value = \"files\";\n});\n\n// --- Methods ---\nconst closeSidebar = () => {\n chatStore.closeProfile();\n};\n\nconst startCall = (video: boolean) => {\n if (chatStore.activeConversationId && props.profile) {\n callStore.startCall(chatStore.activeConversationId, { video });\n }\n};\n\nconst fetchMoreMedia = async () => {\n const id = conversationId.value;\n if (!id) return;\n const nextPage = (profileStore.mediaPage[id] ?? 0) + 1;\n await profileStore.fetchMedia(id, nextPage, MEDIA_PER_PAGE);\n};\n\nconst fetchMoreFiles = async () => {\n const id = conversationId.value;\n if (!id) return;\n const nextPage = (profileStore.filesPage[id] ?? 0) + 1;\n await profileStore.fetchFiles(id, nextPage, FILES_PER_PAGE);\n};\n</script>\n\n<template>\n <aside\n class=\"h-full shrink-0 overflow-hidden bg-chat-background transition-none md:transition-all md:duration-300 md:ease-in-out border-chat-outline-variant ltr:border-r rtl:border-l motion-reduce:transition-none\"\n :class=\"[isOpen ? 'w-dvw md:w-80' : 'w-0 border-none!']\"\n :aria-label=\"t('title')\"\n :aria-hidden=\"!isOpen\"\n :inert=\"!isOpen\"\n data-testid=\"chat-profile\"\n >\n <div class=\"flex h-full w-dvw flex-col md:w-80\">\n <!-- Lines up with the conversation header beside it. -->\n <div\n class=\"flex h-16 shrink-0 items-center justify-between gap-x-2 border-b border-b-chat-outline-variant px-4 md:h-20\"\n >\n <h2 class=\"m-0 truncate text-label-lg text-chat-on-background select-none\">\n {{ t(\"title\") }}\n </h2>\n <IconButton\n icon=\"PhX\"\n :label=\"t('actions.close')\"\n data-testid=\"chat-profile-close\"\n @click=\"closeSidebar\"\n />\n </div>\n\n <div class=\"flex min-h-0 flex-1 flex-col\">\n <div class=\"flex shrink-0 flex-col items-center gap-y-1.5 px-6 pt-6 pb-4 text-center\">\n <span v-loading=\"isLoading\" class=\"relative mb-1.5 block size-22 overflow-hidden rounded-full\">\n <ContactAvatar v-if=\"profile\" :contact=\"profile\" :show-online=\"false\" />\n </span>\n <p\n v-loading=\"isLoading\"\n class=\"m-0 min-w-24 max-w-full truncate text-title-md text-chat-on-background select-none\"\n >\n {{ fullName }}\n </p>\n <p v-if=\"!isLoading\" class=\"m-0 text-body-sm select-none\">\n <span v-if=\"localProfile?.isOnline\" class=\"font-medium text-chat-primary\">\n {{ t(\"online\") }}\n </span>\n <span v-else-if=\"localProfile?.lastSeen\" class=\"text-chat-muted\">\n {{ t(\"lastSeen\", { time: formatRelativeDate(localProfile.lastSeen) }) }}\n </span>\n </p>\n <Tag\n v-if=\"localProfile?.tag && !isLoading\"\n severity=\"secondary\"\n :value=\"localProfile.tag\"\n :pt=\"{\n root: { class: 'mt-1 rounded-md! px-2! py-0.5! bg-chat-on-background/6! text-chat-muted!' },\n label: { class: 'text-[12px]! font-semibold!' },\n }\"\n />\n </div>\n\n <div\n v-if=\"canVoiceCall || canVideoCall\"\n class=\"flex shrink-0 items-center justify-center gap-x-2 px-6 pb-4\"\n >\n <Button\n v-if=\"canVoiceCall\"\n :label=\"isInCall ? t('actions.returnToCall') : t('options.voiceCall')\"\n icon-pos=\"top\"\n severity=\"secondary\"\n variant=\"text\"\n data-testid=\"chat-profile-voice-call\"\n class=\"h-16 w-24 gap-y-1! rounded-xl! bg-chat-on-background/6! px-1! py-2! text-[12px]! text-chat-on-background! hover:bg-chat-on-background/10!\"\n @click=\"startCall(false)\"\n >\n <template #icon>\n <BIcon icon=\"PhPhone\" weight=\"fill\" class=\"size-5.5 text-chat-primary\" />\n </template>\n </Button>\n <Button\n v-if=\"canVideoCall\"\n :label=\"isInCall ? t('actions.returnToCall') : t('options.videoCall')\"\n icon-pos=\"top\"\n severity=\"secondary\"\n variant=\"text\"\n data-testid=\"chat-profile-video-call\"\n class=\"h-16 w-24 gap-y-1! rounded-xl! bg-chat-on-background/6! px-1! py-2! text-[12px]! text-chat-on-background! hover:bg-chat-on-background/10!\"\n @click=\"startCall(true)\"\n >\n <template #icon>\n <BIcon icon=\"PhVideoCamera\" weight=\"fill\" class=\"size-5.5 text-chat-primary\" />\n </template>\n </Button>\n </div>\n\n <dl\n v-if=\"details.length\"\n class=\"mx-4 mt-0 mb-4 shrink-0 divide-y divide-chat-outline-variant overflow-hidden rounded-xl border border-chat-outline-variant\"\n >\n <div\n v-for=\"item in details\"\n :key=\"item.key\"\n class=\"flex items-center justify-between gap-x-3 px-3.5 py-3 select-none\"\n >\n <dt class=\"flex min-w-0 items-center gap-x-2 text-body-sm text-chat-muted\">\n <BIcon :icon=\"item.icon\" class=\"size-4.5 shrink-0\" />\n <span class=\"truncate\">{{ item.label }}</span>\n </dt>\n <dd\n :dir=\"item.ltr ? 'ltr' : undefined\"\n class=\"m-0 truncate text-body-md font-medium text-chat-on-background\"\n >\n {{ item.value }}\n </dd>\n </div>\n </dl>\n\n <section\n :aria-label=\"t('info.shared')\"\n class=\"flex min-h-0 flex-1 flex-col border-t border-t-chat-outline-variant select-none\"\n >\n <Tabs v-model:value=\"currentTab\" class=\"shrink-0\">\n <TabList :pt=\"{ tabList: { class: 'bg-transparent!' } }\">\n <Tab value=\"media\" class=\"flex-1\">{{ t(\"info.media\") }}</Tab>\n <Tab value=\"files\" class=\"flex-1\">{{ t(\"info.files\") }}</Tab>\n </TabList>\n </Tabs>\n\n <div class=\"min-h-0 flex-1 px-4 pt-3\">\n <div v-if=\"isLoadingShared\" class=\"grid grid-cols-3 gap-2\" aria-hidden=\"true\">\n <div v-for=\"n in 6\" :key=\"n\" v-loading=\"true\" class=\"aspect-square rounded-xl\" />\n </div>\n\n <template v-else>\n <div v-show=\"currentTab === 'media'\" class=\"h-full\">\n <BVirtualVerticalList\n v-if=\"mediaAttachements.length\"\n :items=\"mediaRows\"\n :loading=\"isLoadingMedia\"\n :has-next-page=\"hasMediaNextPage\"\n class=\"h-full\"\n @load-more=\"fetchMoreMedia\"\n >\n <template #item=\"{ item: row }\">\n <div class=\"grid w-full grid-cols-3 gap-2 pb-2\">\n <div\n v-for=\"(media, idx) in row\"\n :key=\"idx\"\n class=\"aspect-square overflow-hidden rounded-xl bg-chat-surface\"\n >\n <MediaImage :src=\"media\" class=\"size-full\" />\n </div>\n </div>\n </template>\n </BVirtualVerticalList>\n <p\n v-else\n class=\"m-0 flex flex-col items-center gap-y-2 py-8 text-center text-body-sm text-chat-muted\"\n >\n <BIcon icon=\"PhImages\" class=\"size-7\" />\n {{ t(\"empty.media\") }}\n </p>\n </div>\n\n <div v-show=\"currentTab === 'files'\" class=\"h-full\">\n <BVirtualVerticalList\n v-if=\"fileAttachements.length\"\n :items=\"fileAttachements\"\n :loading=\"isLoadingAttachements\"\n :has-next-page=\"hasFileNextPage\"\n class=\"h-full\"\n @load-more=\"fetchMoreFiles\"\n >\n <template #item=\"{ item: file }\">\n <div class=\"pb-2\">\n <FileDisplay :url=\"file\" :loading=\"false\" />\n </div>\n </template>\n </BVirtualVerticalList>\n <p\n v-else\n class=\"m-0 flex flex-col items-center gap-y-2 py-8 text-center text-body-sm text-chat-muted\"\n >\n <BIcon icon=\"PhFiles\" class=\"size-7\" />\n {{ t(\"empty.files\") }}\n </p>\n </div>\n </template>\n </div>\n </section>\n\n <div v-if=\"canEnd\" class=\"shrink-0 border-t border-t-chat-outline-variant p-4\">\n <Button\n :label=\"t('options.end')\"\n severity=\"danger\"\n variant=\"outlined\"\n data-testid=\"chat-profile-end\"\n class=\"w-full\"\n @click=\"emit('end')\"\n >\n <template #icon>\n <BIcon icon=\"PhXSquare\" class=\"size-5\" />\n </template>\n </Button>\n </div>\n </div>\n </div>\n </aside>\n</template>\n","<template>\n <ResponsiveDialog\n v-model:visible=\"visible\"\n :show-header=\"false\"\n :closable=\"!loading\"\n :close-on-escape=\"!loading\"\n :dismissable-mask=\"!loading\"\n width=\"30rem\"\n @after-hide=\"emit('closed')\"\n >\n <div class=\"flex flex-col items-center pt-6 text-center\">\n <div\n class=\"flex size-16 items-center justify-center rounded-full\"\n :class=\"stateStyle.bg\"\n >\n <BIcon\n :icon=\"stateStyle.icon\"\n weight=\"fill\"\n class=\"size-8\"\n :class=\"stateStyle.text\"\n />\n </div>\n <div class=\"mt-4 flex w-full flex-col items-center gap-y-3 select-none\">\n <div v-if=\"title.trim()\" class=\"text-label-lg text-chat-on-background\">\n {{ title }}\n </div>\n <div v-if=\"text.trim()\" class=\"text-body-md text-chat-muted\">\n {{ text }}\n </div>\n </div>\n <div class=\"mt-8 flex w-full items-center gap-x-3\">\n <Button\n class=\"flex-1\"\n :label=\"hasAction ? actionText : t('confirm')\"\n :severity=\"hasAction ? stateStyle.severity : undefined\"\n :loading=\"loading\"\n @click=\"handleAction\"\n />\n <Button\n v-if=\"hasAction\"\n class=\"flex-1\"\n :label=\"t('cancel')\"\n severity=\"secondary\"\n outlined\n :disabled=\"loading\"\n @click=\"closeModal\"\n />\n </div>\n </div>\n </ResponsiveDialog>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed } from \"vue\";\nimport Button from \"primevue/button\";\nimport ResponsiveDialog from \"./ResponsiveDialog.vue\";\nimport type { ModalState } from \"~/types/components/modal\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { bModal } from \"@i18n/locales\";\n\nwithDefaults(\n defineProps<{\n /** Keeps the modal open, with the action button spinning, until cleared. */\n loading?: boolean;\n }>(),\n { loading: false },\n);\n\nconst emit = defineEmits<{\n cancel: [];\n action: [];\n closed: [];\n}>();\n\nconst { t } = useLocalI18n(bModal);\nconst visible = ref(false);\nconst state = ref<ModalState>(\"success\");\nconst text = ref(\"\");\nconst title = ref(\"\");\nconst hasAction = ref(false);\nconst actionText = ref(\"\");\n\nconst STATE_STYLES = {\n error: {\n icon: \"PhWarningOctagon\",\n severity: \"danger\",\n bg: \"bg-chat-error/10\",\n text: \"text-chat-error\",\n },\n warning: {\n icon: \"PhWarning\",\n severity: \"warn\",\n bg: \"bg-chat-warning/10\",\n text: \"text-chat-warning\",\n },\n success: {\n icon: \"PhCheckCircle\",\n severity: undefined,\n bg: \"bg-chat-success/10\",\n text: \"text-chat-success\",\n },\n} as const;\n\nconst stateStyle = computed(() => STATE_STYLES[state.value]);\n\nconst closeModal = () => {\n visible.value = false;\n};\n\nconst openModal = (\n modalTitle: string,\n description: string,\n color: ModalState,\n action: boolean = false,\n modalActionText?: string,\n) => {\n text.value = description;\n title.value = modalTitle;\n state.value = color;\n hasAction.value = action;\n actionText.value = modalActionText || t(\"confirm\");\n visible.value = true;\n};\n\nconst handleAction = () => {\n if (hasAction.value) {\n emit(\"action\");\n } else {\n closeModal();\n emit(\"cancel\");\n }\n};\n\ndefineExpose({ openModal, closeModal });\n</script>\n","import type { MediaItem, Message } from \"~/types\";\n\n/** A message's album: its `media`, or, from hosts that only send photos, its `imageUrl`. */\nexport const messageMedia = (message: Pick<Message, \"media\" | \"imageUrl\">): MediaItem[] =>\n message.media?.length\n ? message.media\n : (message.imageUrl ?? [])\n .filter((url) => url?.trim())\n .map((url) => ({ url, kind: \"image\" as const }));\n\n/** \"Video\" when every item of the album is a video, otherwise \"Photo\". */\nexport const albumKind = (items: MediaItem[]): MediaItem[\"kind\"] =>\n items.length > 0 && items.every((m) => m.kind === \"video\") ? \"video\" : \"image\";\n\n/** m:ss (or h:mm:ss) for a media duration in seconds. */\nexport const formatDuration = (seconds: number): string => {\n if (!Number.isFinite(seconds) || seconds < 0) return \"0:00\";\n const s = Math.floor(seconds % 60);\n const m = Math.floor(seconds / 60) % 60;\n const h = Math.floor(seconds / 3600);\n const ss = String(s).padStart(2, \"0\");\n return h ? `${h}:${String(m).padStart(2, \"0\")}:${ss}` : `${m}:${ss}`;\n};\n","<script setup lang=\"ts\">\n/**\n * A still of a photo or video, sized by its class: the photo itself, or a video's first frame with\n * a play badge and, once known, its length. Shows a PrimeVue Skeleton until the frame is ready.\n */\nimport { ref, watch } from \"vue\";\nimport Skeleton from \"primevue/skeleton\";\nimport type { MediaItem } from \"~/types\";\nimport MediaImage from \"./MediaImage.vue\";\nimport { formatDuration } from \"~/utils/media\";\n\nconst props = withDefaults(\n defineProps<{\n item: MediaItem;\n fit?: \"cover\" | \"contain\";\n /** Size of the play badge; \"none\" hides it. */\n badge?: \"sm\" | \"lg\" | \"none\";\n showDuration?: boolean;\n }>(),\n { fit: \"cover\", badge: \"lg\", showDuration: true },\n);\n\nconst loaded = ref(false);\nconst duration = ref<number | null>(null);\nwatch(\n () => props.item.url,\n () => {\n loaded.value = false;\n duration.value = null;\n },\n);\n\nconst onMetadata = (event: Event) => {\n const d = (event.target as HTMLVideoElement).duration;\n // Recordings without a duration in their header report Infinity until played through.\n duration.value = Number.isFinite(d) ? d : null;\n};\n</script>\n\n<template>\n <MediaImage v-if=\"item.kind === 'image'\" :src=\"item.url\" :fit=\"fit\" />\n\n <div v-else class=\"relative overflow-hidden bg-black\">\n <div v-if=\"!loaded\" class=\"absolute inset-0\">\n <Skeleton width=\"100%\" height=\"100%\" border-radius=\"0\" />\n </div>\n <!-- #t skips to a frame past the first, which is often black. -->\n <video\n :key=\"item.url\"\n :src=\"`${item.url}#t=0.1`\"\n preload=\"metadata\"\n muted\n playsinline\n disablepictureinpicture\n tabindex=\"-1\"\n aria-hidden=\"true\"\n class=\"pointer-events-none block size-full transition-opacity duration-300\"\n :class=\"[\n fit === 'cover' ? 'object-cover' : 'object-contain',\n loaded ? 'opacity-100' : 'opacity-0',\n ]\"\n @loadedmetadata=\"onMetadata\"\n @loadeddata=\"loaded = true\"\n @error=\"loaded = true\"\n />\n\n <div\n v-if=\"badge !== 'none'\"\n class=\"pointer-events-none absolute inset-0 flex items-center justify-center\"\n >\n <span\n class=\"flex items-center justify-center rounded-full bg-black/45 text-white backdrop-blur-sm\"\n :class=\"badge === 'lg' ? 'size-12' : 'size-6'\"\n >\n <BIcon\n icon=\"PhPlay\"\n weight=\"fill\"\n :class=\"badge === 'lg' ? 'size-5 ms-0.5' : 'size-3 ms-px'\"\n />\n </span>\n </div>\n\n <span\n v-if=\"showDuration && duration !== null\"\n class=\"pointer-events-none absolute start-1.5 top-1.5 rounded-full bg-black/55 px-1.5 py-0.5 text-[11px] leading-none text-white tabular-nums\"\n >\n {{ formatDuration(duration) }}\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * A photo in the media viewer, fitted to the stage, with zoom and pan: double-click or double-tap\n * zooms in on that point (and back out), the wheel or a pinch zooms around the pointer, and a drag\n * pans while zoomed in. At fit size a horizontal swipe asks for the neighbouring item instead.\n */\nimport { computed, reactive, ref } from \"vue\";\nimport ProgressSpinner from \"primevue/progressspinner\";\n\ndefineProps<{ src: string }>();\n\nconst emit = defineEmits<{\n swipe: [direction: \"left\" | \"right\"];\n zoomed: [zoomed: boolean];\n}>();\n\nconst MIN = 1;\nconst MAX = 5;\nconst DOUBLE_TAP_ZOOM = 2.5;\nconst DOUBLE_TAP_MS = 300;\nconst SWIPE_PX = 60;\n\nconst imageEl = ref<HTMLElement | null>(null);\nconst view = reactive({ scale: 1, x: 0, y: 0 });\nconst isZoomed = computed(() => view.scale > 1.01);\nconst animate = ref(false);\nconst loaded = ref(false);\n\nconst clamp = (v: number, lo: number, hi: number) => Math.min(hi, Math.max(lo, v));\n\n/** Keeps the photo covering the stage it has grown past, so it cannot be dragged off screen. */\nconst clampPan = () => {\n const el = imageEl.value;\n if (!el) return;\n const maxX = (el.offsetWidth * (view.scale - 1)) / 2;\n const maxY = (el.offsetHeight * (view.scale - 1)) / 2;\n view.x = clamp(view.x, -maxX, maxX);\n view.y = clamp(view.y, -maxY, maxY);\n};\n\n/** Scales to `next`, keeping the point under (clientX, clientY) where it is on screen. */\nconst zoomTo = (next: number, clientX: number, clientY: number) => {\n const el = imageEl.value;\n if (!el) return;\n const target = clamp(next, MIN, MAX);\n const rect = el.getBoundingClientRect();\n // Offset of the point from the photo's centre, in unscaled pixels.\n const px = (clientX - (rect.left + rect.width / 2)) / view.scale;\n const py = (clientY - (rect.top + rect.height / 2)) / view.scale;\n view.x += (view.scale - target) * px;\n view.y += (view.scale - target) * py;\n view.scale = target;\n if (target === MIN) {\n view.x = 0;\n view.y = 0;\n }\n clampPan();\n emit(\"zoomed\", isZoomed.value);\n};\n\nconst reset = () => {\n animate.value = true;\n view.scale = 1;\n view.x = 0;\n view.y = 0;\n emit(\"zoomed\", false);\n};\n\ndefineExpose({ reset, isZoomed });\n\nconst onWheel = (event: WheelEvent) => {\n animate.value = false;\n zoomTo(view.scale * Math.exp(-event.deltaY * 0.002), event.clientX, event.clientY);\n};\n\n// --- Pointers: pan, pinch, double tap and swipe share one set of listeners. ---\nconst pointers = new Map<number, { x: number; y: number }>();\nlet gesture: { x: number; y: number; moved: boolean } | null = null;\nlet pinch: { distance: number; scale: number } | null = null;\nlet lastTap = { time: 0, x: 0, y: 0 };\n\nconst distance = () => {\n const [a, b] = [...pointers.values()];\n return a && b ? Math.hypot(a.x - b.x, a.y - b.y) : 0;\n};\n\nconst onPointerDown = (event: PointerEvent) => {\n (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);\n pointers.set(event.pointerId, { x: event.clientX, y: event.clientY });\n animate.value = false;\n if (pointers.size === 1) {\n gesture = { x: event.clientX, y: event.clientY, moved: false };\n } else if (pointers.size === 2) {\n pinch = { distance: distance(), scale: view.scale };\n gesture = null;\n }\n};\n\nconst onPointerMove = (event: PointerEvent) => {\n const last = pointers.get(event.pointerId);\n if (!last) return;\n const dx = event.clientX - last.x;\n const dy = event.clientY - last.y;\n pointers.set(event.pointerId, { x: event.clientX, y: event.clientY });\n\n if (pinch && pointers.size === 2) {\n const [a, b] = [...pointers.values()];\n zoomTo(pinch.scale * (distance() / pinch.distance), (a!.x + b!.x) / 2, (a!.y + b!.y) / 2);\n return;\n }\n if (!gesture) return;\n if (Math.hypot(event.clientX - gesture.x, event.clientY - gesture.y) > 8) gesture.moved = true;\n if (isZoomed.value) {\n view.x += dx;\n view.y += dy;\n clampPan();\n }\n};\n\nconst onPointerUp = (event: PointerEvent) => {\n pointers.delete(event.pointerId);\n if (pointers.size < 2) pinch = null;\n if (!gesture || pointers.size > 0) return;\n const { x, y, moved } = gesture;\n gesture = null;\n\n if (!moved) {\n const now = event.timeStamp;\n const isDouble =\n now - lastTap.time < DOUBLE_TAP_MS &&\n Math.hypot(event.clientX - lastTap.x, event.clientY - lastTap.y) < 24;\n lastTap = isDouble ? { time: 0, x: 0, y: 0 } : { time: now, x: event.clientX, y: event.clientY };\n if (isDouble) {\n animate.value = true;\n if (isZoomed.value) reset();\n else zoomTo(DOUBLE_TAP_ZOOM, event.clientX, event.clientY);\n }\n return;\n }\n\n const dx = event.clientX - x;\n const dy = event.clientY - y;\n if (!isZoomed.value && Math.abs(dx) > SWIPE_PX && Math.abs(dx) > Math.abs(dy) * 1.5) {\n emit(\"swipe\", dx < 0 ? \"left\" : \"right\");\n }\n};\n</script>\n\n<template>\n <div\n class=\"relative flex size-full touch-none items-center justify-center overflow-hidden select-none\"\n :class=\"isZoomed ? 'cursor-grab active:cursor-grabbing' : 'cursor-zoom-in'\"\n data-testid=\"viewer-image\"\n :data-zoomed=\"String(isZoomed)\"\n @wheel.prevent=\"onWheel\"\n @pointerdown=\"onPointerDown\"\n @pointermove=\"onPointerMove\"\n @pointerup=\"onPointerUp\"\n @pointercancel=\"onPointerUp\"\n >\n <div\n ref=\"imageEl\"\n class=\"max-h-full max-w-full will-change-transform\"\n :class=\"animate && 'transition-transform duration-200 ease-out motion-reduce:transition-none'\"\n :style=\"{ transform: `translate(${view.x}px, ${view.y}px) scale(${view.scale})` }\"\n >\n <img\n :src=\"src\"\n alt=\"\"\n draggable=\"false\"\n class=\"block max-h-[calc(100dvh-10rem)] max-w-dvw object-contain transition-opacity duration-300 md:max-w-[calc(100dvw-9rem)]\"\n :class=\"loaded ? 'opacity-100' : 'opacity-0'\"\n @load=\"loaded = true\"\n @error=\"loaded = true\"\n />\n </div>\n <ProgressSpinner\n v-if=\"!loaded\"\n stroke-width=\"3\"\n class=\"absolute! size-10! [&_circle]:stroke-white!\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * A video in the media viewer, with PrimeVue controls: play/pause, a seek slider with the elapsed\n * and total time, mute and full screen. It starts playing when shown; a click on the picture\n * toggles playback and a horizontal swipe asks for the neighbouring item.\n */\nimport { onBeforeUnmount, onMounted, ref, useTemplateRef } from \"vue\";\nimport Slider from \"primevue/slider\";\nimport ProgressSpinner from \"primevue/progressspinner\";\nimport { useEventListener, useSwipe } from \"@vueuse/core\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { formatDuration } from \"~/utils/media\";\nimport { mediaViewer } from \"@i18n/locales\";\n\ndefineProps<{ src: string }>();\n\nconst emit = defineEmits<{ swipe: [direction: \"left\" | \"right\"] }>();\n\nconst { t } = useLocalI18n(mediaViewer);\n\nconst frame = useTemplateRef<HTMLElement>(\"frame\");\nconst video = useTemplateRef<HTMLVideoElement>(\"video\");\n\nconst isPlaying = ref(false);\nconst isMuted = ref(false);\nconst isFullscreen = ref(false);\nconst isWaiting = ref(true);\nconst failed = ref(false);\nconst current = ref(0);\nconst duration = ref(0);\n// While the slider is dragged, it drives the time rather than following playback.\nconst scrubbing = ref(false);\n\nconst togglePlay = () => {\n const el = video.value;\n if (!el) return;\n if (el.paused || el.ended) el.play().catch(() => {});\n else el.pause();\n};\n\nconst toggleMute = () => {\n if (video.value) video.value.muted = !video.value.muted;\n};\n\nconst toggleFullscreen = () => {\n if (document.fullscreenElement) document.exitFullscreen().catch(() => {});\n else frame.value?.requestFullscreen?.().catch(() => {});\n};\n\nconst seek = (value: number | number[]) => {\n const time = Array.isArray(value) ? value[0]! : value;\n current.value = time;\n if (video.value) video.value.currentTime = time;\n};\n\nconst onTimeUpdate = () => {\n if (!scrubbing.value && video.value) current.value = video.value.currentTime;\n};\n\nconst onMetadata = () => {\n const d = video.value?.duration ?? 0;\n // Recordings without a duration in their header report Infinity until played through.\n duration.value = Number.isFinite(d) ? d : 0;\n};\n\nuseEventListener(document, \"fullscreenchange\", () => {\n isFullscreen.value = !!document.fullscreenElement && document.fullscreenElement === frame.value;\n});\n\n// Space plays and pauses, unless a control that uses it has focus.\nuseEventListener(window, \"keydown\", (event: KeyboardEvent) => {\n if (event.key !== \" \" || event.defaultPrevented) return;\n const target = event.target as HTMLElement | null;\n if (target?.closest(\"button, [role='slider'], input, textarea\")) return;\n event.preventDefault();\n togglePlay();\n});\n\nuseSwipe(video, {\n onSwipeEnd: (_, direction) => {\n if (direction === \"left\" || direction === \"right\") emit(\"swipe\", direction);\n },\n});\n\nonMounted(() => {\n // Opened by a click, so sound is allowed; if the browser still refuses, it waits for play.\n video.value?.play().catch(() => {});\n});\n\nonBeforeUnmount(() => {\n if (document.fullscreenElement === frame.value) document.exitFullscreen().catch(() => {});\n});\n</script>\n\n<template>\n <div\n ref=\"frame\"\n class=\"relative flex size-full max-h-[calc(100dvh-10rem)] max-w-dvw flex-col items-center justify-center md:max-w-[calc(100dvw-9rem)]\"\n :class=\"isFullscreen && 'max-h-none! max-w-none! bg-black'\"\n data-testid=\"viewer-video\"\n :data-playing=\"String(isPlaying)\"\n >\n <div v-if=\"failed\" class=\"flex max-w-80 flex-col items-center gap-y-3 px-6 text-center text-white/80\">\n <BIcon icon=\"PhWarningCircle\" class=\"size-10\" />\n <p class=\"text-body-md\">{{ t(\"cantPlay\") }}</p>\n </div>\n\n <template v-else>\n <video\n ref=\"video\"\n :src=\"src\"\n playsinline\n preload=\"auto\"\n class=\"min-h-0 w-full flex-1 touch-pan-y object-contain\"\n @click=\"togglePlay\"\n @play=\"isPlaying = true\"\n @pause=\"isPlaying = false\"\n @ended=\"isPlaying = false\"\n @waiting=\"isWaiting = true\"\n @playing=\"isWaiting = false\"\n @canplay=\"isWaiting = false\"\n @loadedmetadata=\"onMetadata\"\n @durationchange=\"onMetadata\"\n @timeupdate=\"onTimeUpdate\"\n @volumechange=\"isMuted = !!video?.muted\"\n @error=\"failed = true\"\n />\n\n <ProgressSpinner\n v-if=\"isWaiting && !isPlaying\"\n stroke-width=\"3\"\n class=\"pointer-events-none absolute! top-1/2 left-1/2 size-12! -translate-1/2 [&_circle]:stroke-white!\"\n />\n\n <!-- Controls stay on the picture's reading-direction axis even in RTL, as players do. -->\n <div\n dir=\"ltr\"\n class=\"flex w-full shrink-0 items-center gap-x-1 px-2 py-2 text-white md:gap-x-2 md:px-3\"\n >\n <IconButton\n :icon=\"isPlaying ? 'PhPause' : 'PhPlay'\"\n :label=\"isPlaying ? t('actions.pause') : t('actions.play')\"\n weight=\"fill\"\n class=\"text-white! hover:bg-white/10!\"\n data-testid=\"viewer-play\"\n @click=\"togglePlay\"\n />\n <span class=\"w-10 shrink-0 text-end text-label-sm tabular-nums\">\n {{ formatDuration(current) }}\n </span>\n <Slider\n :model-value=\"current\"\n :min=\"0\"\n :max=\"duration || 1\"\n :step=\"0.1\"\n :disabled=\"!duration\"\n :aria-label=\"t('actions.seek')\"\n class=\"mx-2 flex-1\"\n :pt=\"{\n range: { class: 'bg-white!' },\n handle: { class: 'bg-white! before:bg-white!' },\n }\"\n :dt=\"{ track: { background: 'rgba(255,255,255,0.25)' } }\"\n @update:model-value=\"seek\"\n @slidestart=\"scrubbing = true\"\n @slideend=\"scrubbing = false\"\n />\n <span class=\"w-10 shrink-0 text-label-sm tabular-nums text-white/70\">\n {{ formatDuration(duration) }}\n </span>\n <IconButton\n :icon=\"isMuted ? 'PhSpeakerSlash' : 'PhSpeakerHigh'\"\n :label=\"isMuted ? t('actions.unmute') : t('actions.mute')\"\n class=\"text-white! hover:bg-white/10!\"\n @click=\"toggleMute\"\n />\n <IconButton\n :icon=\"isFullscreen ? 'PhCornersIn' : 'PhFrameCorners'\"\n :label=\"isFullscreen ? t('actions.exitFullscreen') : t('actions.fullscreen')\"\n class=\"hidden! text-white! hover:bg-white/10! md:inline-flex!\"\n @click=\"toggleFullscreen\"\n />\n </div>\n </template>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Full-screen viewer for a message's photos and videos, on PrimeVue's Galleria. A top bar carries\n * who sent it and when, the position in the album, download and close; round arrows (on wider\n * screens), swipes and the arrow keys move through the album; thumbnails run along the bottom.\n * Photos zoom and pan (ViewerImage); videos play with their own controls (ViewerVideo).\n */\nimport { computed, onUnmounted, ref, useTemplateRef, watch } from \"vue\";\nimport Galleria from \"primevue/galleria\";\nimport { useEventListener } from \"@vueuse/core\";\nimport type { MediaItem } from \"~/types\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport MediaThumb from \"~/components/general/MediaThumb.vue\";\nimport ViewerImage from \"./viewer/ViewerImage.vue\";\nimport ViewerVideo from \"./viewer/ViewerVideo.vue\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { useDate } from \"~/composables/useDate.js\";\nimport { useHostLocale } from \"~/composables/useHostI18n\";\nimport { useMediaStore } from \"~/stores/mediaStore\";\nimport { mediaViewer } from \"@i18n/locales\";\n\nconst props = defineProps<{\n items: MediaItem[];\n sender: string;\n date: Date;\n}>();\n\nconst mediaStore = useMediaStore();\nconst { t } = useLocalI18n(mediaViewer);\nconst { dir } = useDirection();\nconst { formatDateShort, formatTime } = useDate();\n\nconst isOpen = ref(false);\nconst activeIndex = ref(0);\nconst hasMany = computed(() => props.items.length > 1);\nconst active = computed(() => props.items[activeIndex.value]);\nconst sentOn = computed(() =>\n t(\"sentOn\", { day: formatDateShort(props.date), time: formatTime(props.date) }),\n);\nconst locale = useHostLocale();\nconst num = (n: number) => n.toLocaleString(locale.value);\n\nconst imageStage = useTemplateRef<InstanceType<typeof ViewerImage>>(\"imageStage\");\nconst zoomed = ref(false);\n\nwatch(\n () => props.items,\n (items) => {\n if (activeIndex.value >= items.length) activeIndex.value = 0;\n },\n);\nwatch(activeIndex, () => (zoomed.value = false));\n\nconst go = (step: number) => {\n const next = activeIndex.value + step;\n if (next >= 0 && next < props.items.length) activeIndex.value = next;\n};\n\n/** A swipe or arrow key toward the reading direction's end moves forward. */\nconst goToward = (direction: \"left\" | \"right\") =>\n go((direction === \"left\") === (dir.value !== \"rtl\") ? 1 : -1);\n\nuseEventListener(window, \"keydown\", (event: KeyboardEvent) => {\n if (!isOpen.value || event.defaultPrevented) return;\n if ((event.target as HTMLElement | null)?.closest(\"[role='slider']\")) return;\n if (event.key === \"ArrowLeft\") goToward(\"right\");\n else if (event.key === \"ArrowRight\") goToward(\"left\");\n else return;\n event.preventDefault();\n});\n\nconst download = async () => {\n const item = active.value;\n if (!item) return;\n try {\n const blob = await mediaStore.download(item.url);\n const href = URL.createObjectURL(blob);\n const link = document.createElement(\"a\");\n link.href = href;\n link.download =\n item.url.split(\"/\").pop()?.split(\"?\")[0] || (item.kind === \"video\" ? \"video.mp4\" : \"image.jpg\");\n document.body.appendChild(link);\n link.click();\n link.remove();\n URL.revokeObjectURL(href);\n } catch (error) {\n console.error(\"Failed to download media:\", error);\n }\n};\n\n// The browser's Back button closes the viewer instead of leaving the page.\nconst handlePopState = () => {\n isOpen.value = false;\n};\n\nwatch(isOpen, (open) => {\n if (open) {\n window.history.pushState({ viewerOpen: true }, \"\");\n window.addEventListener(\"popstate\", handlePopState);\n return;\n }\n window.removeEventListener(\"popstate\", handlePopState);\n if (window.history.state?.viewerOpen) window.history.back();\n});\n\nonUnmounted(() => {\n window.removeEventListener(\"popstate\", handlePopState);\n if (isOpen.value && window.history.state?.viewerOpen) window.history.back();\n});\n\ndefineExpose({\n open: (index: number) => {\n activeIndex.value = index;\n isOpen.value = true;\n },\n close: () => {\n isOpen.value = false;\n },\n download,\n});\n\nconst NAV =\n \"absolute! top-1/2! z-10 hidden! size-12! -translate-y-1/2 items-center justify-center rounded-full! bg-white/10! text-white! backdrop-blur-md transition-colors hover:bg-white/20! md:flex! disabled:invisible!\";\n\nconst pt = computed(() => ({\n mask: {\n class: \"vue-chat bg-black/95! backdrop-blur-sm\",\n \"data-testid\": \"image-viewer\",\n \"data-open\": String(isOpen.value),\n },\n root: { class: \"relative flex! h-dvh w-dvw flex-col border-0! rounded-none! bg-transparent!\" },\n closeButton: { class: \"hidden!\" },\n header: { class: \"absolute inset-x-0 top-0 z-20\" },\n content: { class: \"min-h-0 flex-1 bg-transparent!\" },\n itemsContainer: { class: \"h-full\" },\n items: { class: \"h-full\" },\n item: { class: \"h-full\" },\n prevButton: { class: `${NAV} start-6! end-auto! rtl:left-auto! rtl:right-6!`, \"aria-label\": t(\"actions.previous\") },\n nextButton: { class: `${NAV} end-6! start-auto! rtl:right-auto! rtl:left-6!`, \"aria-label\": t(\"actions.next\") },\n // Every thumbnail fits (albums hold at most 10), so they sit together instead of scrolling.\n // Phones go without: the counter and swiping cover it, and ten would not fit.\n thumbnails: { class: \"hidden! shrink-0 pb-3 md:block!\" },\n thumbnailContent: { class: \"justify-center bg-transparent! p-2!\" },\n thumbnailPrevButton: { class: \"hidden!\" },\n thumbnailNextButton: { class: \"hidden!\" },\n thumbnailsViewport: { class: \"w-auto! max-w-full grow-0!\" },\n // Galleria reverses the strip in RTL for its scrolling; ours never scrolls, so it reads naturally.\n thumbnailItems: { class: \"rtl:flex-row!\" },\n thumbnailItem: { class: \"flex-[0_0_auto]! opacity-100! p-1!\" },\n}));\n</script>\n\n<template>\n <Galleria\n v-model:visible=\"isOpen\"\n v-model:active-index=\"activeIndex\"\n :value=\"items\"\n full-screen\n :dir=\"dir\"\n :show-thumbnails=\"hasMany\"\n :show-item-navigators=\"hasMany\"\n :num-visible=\"items.length\"\n :pt=\"pt\"\n >\n <template #header>\n <div\n class=\"flex items-start justify-between gap-x-4 bg-linear-to-b from-black/70 to-transparent px-3 pt-[max(0.75rem,env(safe-area-inset-top))] pb-10 text-white md:px-5\"\n >\n <div class=\"min-w-0 ps-1\">\n <div class=\"truncate text-label-md\">{{ sender }}</div>\n <div class=\"truncate text-body-sm text-white/70\">{{ sentOn }}</div>\n </div>\n <div class=\"flex shrink-0 items-center gap-x-1\">\n <span\n v-if=\"hasMany\"\n data-testid=\"viewer-counter\"\n class=\"me-2 rounded-full bg-white/10 px-2.5 py-1 text-label-sm tabular-nums\"\n >\n {{ t(\"counter\", { current: num(activeIndex + 1), total: num(items.length) }) }}\n </span>\n <IconButton\n v-if=\"zoomed\"\n icon=\"PhCornersIn\"\n :label=\"t('actions.resetZoom')\"\n class=\"text-white! hover:bg-white/10!\"\n @click=\"imageStage?.reset()\"\n />\n <IconButton\n icon=\"PhDownloadSimple\"\n :label=\"t('actions.download')\"\n class=\"text-white! hover:bg-white/10!\"\n @click=\"download\"\n />\n <IconButton\n icon=\"PhX\"\n :label=\"t('actions.close')\"\n class=\"text-white! hover:bg-white/10!\"\n data-testid=\"viewer-close\"\n @click=\"isOpen = false\"\n />\n </div>\n </div>\n </template>\n\n <template #item=\"{ item }\">\n <div class=\"flex size-full items-center justify-center pt-16 pb-[env(safe-area-inset-bottom)] md:px-18 md:pb-0\">\n <ViewerImage\n v-if=\"item.kind === 'image'\"\n ref=\"imageStage\"\n :key=\"item.url\"\n :src=\"item.url\"\n @swipe=\"goToward\"\n @zoomed=\"zoomed = $event\"\n />\n <ViewerVideo v-else :key=\"item.url\" :src=\"item.url\" @swipe=\"goToward\" />\n </div>\n </template>\n\n <template #previousitemicon>\n <BIcon icon=\"PhCaretLeft\" class=\"size-6 rtl:-scale-x-100\" />\n </template>\n <template #nextitemicon>\n <BIcon icon=\"PhCaretLeft\" class=\"size-6 -scale-x-100 rtl:scale-x-100\" />\n </template>\n\n <template #thumbnail=\"{ item }\">\n <MediaThumb\n :item=\"item\"\n badge=\"sm\"\n :show-duration=\"false\"\n class=\"size-12 rounded-lg ring-offset-2 ring-offset-black transition md:size-14\"\n :class=\"item === active ? 'opacity-100 ring-2 ring-white' : 'opacity-50 hover:opacity-80'\"\n />\n </template>\n </Galleria>\n</template>\n","<script setup lang=\"ts\">\n/**\n * The message's action menu, opened at the pointer by a right click or long press. It is one\n * PrimeVue ContextMenu laid out as a card: a header with when the message was sent (and, on your\n * own, whether it was seen), a row of quick-action tiles, then the destructive action set apart.\n * The header is a disabled item, so arrow keys and typeahead skip it; the tiles and the delete row\n * are ordinary items in one wrapping list, so keyboard navigation still walks them in order.\n */\nimport { computed, ref } from \"vue\";\nimport ContextMenu from \"primevue/contextmenu\";\nimport Skeleton from \"primevue/skeleton\";\nimport type { MenuItem } from \"primevue/menuitem\";\nimport { useMessagesStore } from \"~/stores/messageStores\";\nimport type { ExtendedMessage, MessageReader } from \"~/types\";\nimport ContactAvatar from \"~/components/chat/contact/ContactAvatar.vue\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { useDate } from \"~/composables/useDate.js\";\nimport { bubbleOptions } from \"@i18n/locales\";\n\nconst props = defineProps<{\n message: ExtendedMessage;\n isMine: boolean;\n}>();\n\nconst { t } = useLocalI18n(bubbleOptions);\nconst { dir } = useDirection();\nconst { formatDateShort, formatTime } = useDate();\nconst messagesStore = useMessagesStore();\n\nconst menu = ref<InstanceType<typeof ContextMenu> | null>(null);\n\n// --- Who has read it (\"Seen by\"), on the viewer's own sent messages when the host can say ---\nconst readers = ref<MessageReader[]>([]);\nconst loadingReaders = ref(false);\nlet readersRequest = 0;\n\nconst canShowReaders = computed(\n () =>\n props.isMine &&\n props.message.isSent &&\n !props.message.id.startsWith(\"tmp-\") &&\n messagesStore.canListReaders(),\n);\n\n// Asked afresh on every open: someone may have read it since the menu was last shown.\nconst loadReaders = async () => {\n if (!canShowReaders.value) return;\n const request = ++readersRequest;\n loadingReaders.value = true;\n try {\n const found = await messagesStore.fetchReaders(props.message);\n if (request === readersRequest) readers.value = found;\n } catch (error) {\n console.error(\"[chat] failed to load who read the message\", error);\n if (request === readersRequest) readers.value = [];\n } finally {\n if (request === readersRequest) loadingReaders.value = false;\n }\n};\n\nconst readerName = (reader: MessageReader) => `${reader.name} ${reader.lastName ?? \"\"}`.trim();\nconst readerAvatar = (reader: MessageReader) => ({\n name: reader.name,\n lastName: reader.lastName ?? \"\",\n imageUrl: reader.imageUrl ?? \"\",\n});\n\n/** Opens at the pointer: a right click, or where a long press began. */\nconst openMenu = (event: MouseEvent | PointerEvent) => {\n messagesStore.isOptionMenuOpen = true;\n void loadReaders();\n menu.value?.show(event);\n};\n\nconst closeMenu = () => {\n menu.value?.hide();\n};\n\nconst onMenuClosed = () => {\n messagesStore.isOptionMenuOpen = false;\n};\n\ndefineExpose({ openMenu, closeMenu });\n\nconst showAsDeselect = computed(() => {\n return (\n messagesStore.isSelectMode &&\n messagesStore.selectedMessages.has(props.message.id)\n );\n});\n\nconst targetIds = () =>\n messagesStore.isSelectMode &&\n messagesStore.selectedMessages.has(props.message.id)\n ? messagesStore.selectedArray.map((m) => m.id)\n : [props.message.id];\n\nconst onDay = (value: Date | string) => {\n const date = new Date(value);\n const day =\n date.toDateString() === new Date().toDateString()\n ? t(\"meta.today\")\n : formatDateShort(date);\n return t(\"meta.sentOn\", { day, time: formatTime(date) });\n};\n\nconst sentOn = computed(() => onDay(props.message.date));\n\nconst isSeen = computed(() => props.message.isSent && props.message.isRead);\n\n// Tiles share the first row; anything else takes a full row. `class` lands on the item's <li>.\nconst TILE = \"flex-1 min-w-0\";\nconst ROW = \"basis-full\";\n\nconst items = computed<MenuItem[]>(() => [\n { key: \"meta\", meta: true, disabled: true, class: `${ROW} opacity-100!` },\n {\n // One reader is shown in place; several open a list of who and when.\n key: \"readers\",\n readers: true,\n visible: canShowReaders.value && (loadingReaders.value || readers.value.length > 0),\n disabled: loadingReaders.value || readers.value.length < 2,\n class: `${ROW} opacity-100!`,\n items:\n !loadingReaders.value && readers.value.length > 1\n ? readers.value.map((reader) => ({\n key: `reader-${reader.id}`,\n reader,\n disabled: true,\n class: \"opacity-100!\",\n }))\n : undefined,\n },\n {\n key: \"reply\",\n phIcon: \"PhArrowBendUpLeft\",\n label: t(\"messageOptions.reply\"),\n visible: props.message.isSent,\n class: TILE,\n command: () => {\n messagesStore.replyingTo = props.message;\n },\n },\n {\n key: \"copy\",\n phIcon: \"PhCopy\",\n label: t(\"messageOptions.copy\"),\n // Copy takes only text, so there is nothing to copy from a photo, voice note or file.\n visible: messagesStore.selectedArray.some((m) => m.text?.trim()),\n class: TILE,\n command: () => messagesStore.copyMessageText(),\n },\n {\n key: \"edit\",\n phIcon: \"PhPencilSimpleLine\",\n label: t(\"messageOptions.edit\"),\n visible: messagesStore.canEdit,\n class: TILE,\n command: () => messagesStore.triggerEdit(props.message),\n },\n {\n key: \"select\",\n phIcon: showAsDeselect.value ? \"PhXCircle\" : \"PhCheckCircle\",\n label: showAsDeselect.value\n ? t(\"messageOptions.deselect\")\n : t(\"messageOptions.select\"),\n class: TILE,\n command: () => {\n if (!messagesStore.isSelectMode) {\n messagesStore.startSelectMode(props.message);\n } else {\n messagesStore.toggleSelection(props.message);\n }\n },\n },\n {\n key: \"danger-separator\",\n separator: true,\n visible: messagesStore.canDelete,\n class: `${ROW} mx-2! my-1! border-chat-outline-variant!`,\n },\n {\n key: \"delete\",\n phIcon: \"PhTrash\",\n label: t(\"messageOptions.delete\"),\n visible: messagesStore.canDelete,\n danger: true,\n class: `${ROW} [&>div:hover]:bg-chat-error/10! [&.p-focus>div]:bg-chat-error/10!`,\n command: () => messagesStore.triggerDelete(targetIds()),\n },\n]);\n\nconst pt = {\n root: {\n class:\n \"w-72! rounded-2xl! border-chat-outline-variant/60! bg-chat-background/90! p-1.5! shadow-xl! backdrop-blur-md!\",\n },\n rootList: { class: \"flex-row! flex-wrap! gap-0.5! p-0!\" },\n // The readers list: a card like the menu itself, scrolling past a handful of people.\n submenu: {\n class:\n \"min-w-64! max-h-72! overflow-y-auto! rounded-2xl! border! border-chat-outline-variant/60! bg-chat-background/95! p-1.5! shadow-xl! backdrop-blur-md!\",\n },\n itemContent: { class: \"rounded-xl!\" },\n // Grows out of the pointer rather than just fading in.\n transition: {\n enterFromClass: \"opacity-0 scale-95\",\n enterActiveClass:\n \"transition duration-150 ease-out origin-top-left rtl:origin-top-right motion-reduce:transition-none\",\n leaveActiveClass: \"transition-opacity duration-100 ease-in motion-reduce:transition-none\",\n leaveToClass: \"opacity-0\",\n },\n};\n</script>\n<template>\n <ContextMenu\n ref=\"menu\"\n :model=\"items\"\n :pt=\"pt\"\n :dir=\"dir\"\n class=\"vue-chat\"\n @hide=\"onMenuClosed\"\n >\n <template #item=\"{ item, props: itemProps }\">\n <div\n v-if=\"item.meta\"\n class=\"flex select-none items-center justify-between gap-x-3 px-2.5 pt-1 pb-0.5 text-body-sm text-chat-muted\"\n >\n <span class=\"truncate\">{{ sentOn }}</span>\n <span\n v-if=\"isMine && message.isSent\"\n class=\"flex shrink-0 items-center gap-x-1\"\n :class=\"isSeen && 'text-chat-primary'\"\n >\n <BIcon :icon=\"isSeen ? 'PhChecks' : 'PhCheck'\" class=\"size-4\" />\n {{ isSeen ? t(\"meta.seen\") : t(\"meta.sent\") }}\n </span>\n </div>\n\n <a\n v-else-if=\"item.readers\"\n v-bind=\"itemProps.action\"\n data-testid=\"message-readers\"\n class=\"gap-x-2.5! px-2.5! py-2!\"\n >\n <template v-if=\"loadingReaders\">\n <Skeleton shape=\"circle\" size=\"1.75rem\" class=\"shrink-0\" />\n <Skeleton width=\"8rem\" height=\"0.75rem\" />\n </template>\n\n <template v-else-if=\"readers.length === 1\">\n <span class=\"size-7 shrink-0\">\n <ContactAvatar :contact=\"readerAvatar(readers[0]!)\" :show-online=\"false\" />\n </span>\n <span class=\"min-w-0 flex-1 truncate text-label-md text-chat-on-background\">\n {{ readerName(readers[0]!) }}\n </span>\n <span v-if=\"readers[0]!.readAt\" class=\"shrink-0 text-body-sm text-chat-muted\">\n {{ onDay(readers[0]!.readAt) }}\n </span>\n </template>\n\n <template v-else>\n <span class=\"flex shrink-0 -space-x-2 rtl:space-x-reverse\">\n <span\n v-for=\"reader in readers.slice(0, 3)\"\n :key=\"reader.id\"\n class=\"size-7 rounded-full ring-2 ring-chat-background\"\n >\n <ContactAvatar :contact=\"readerAvatar(reader)\" :show-online=\"false\" />\n </span>\n </span>\n <span class=\"min-w-0 flex-1 truncate text-label-md text-chat-on-background\">\n {{ t(\"readers.seenBy\", { count: readers.length }) }}\n </span>\n <BIcon icon=\"PhCaretRight\" class=\"size-4 shrink-0 text-chat-muted rtl:rotate-180\" />\n </template>\n </a>\n\n <div\n v-else-if=\"item.reader\"\n data-testid=\"message-reader\"\n class=\"flex select-none items-center gap-x-2.5 px-2 py-1.5\"\n >\n <span class=\"size-8 shrink-0\">\n <ContactAvatar :contact=\"readerAvatar(item.reader)\" :show-online=\"false\" />\n </span>\n <span class=\"flex min-w-0 flex-1 flex-col\">\n <span class=\"truncate text-label-md text-chat-on-background\">\n {{ readerName(item.reader) }}\n </span>\n <span v-if=\"item.reader.readAt\" class=\"text-body-sm text-chat-muted\">\n {{ onDay(item.reader.readAt) }}\n </span>\n </span>\n </div>\n\n <a\n v-else-if=\"!item.danger\"\n v-bind=\"itemProps.action\"\n class=\"flex-col! gap-y-1.5! px-1! py-2.5!\"\n >\n <span\n class=\"flex size-9 items-center justify-center rounded-full bg-chat-on-background/6\"\n >\n <BIcon :icon=\"item.phIcon\" class=\"size-5 text-chat-on-background\" />\n </span>\n <span\n v-bind=\"itemProps.label\"\n class=\"w-full truncate text-center text-label-sm leading-normal! text-chat-on-background\"\n >\n {{ item.label }}\n </span>\n </a>\n\n <a v-else v-bind=\"itemProps.action\" class=\"gap-x-3! px-2.5! py-2!\">\n <span\n class=\"flex size-9 items-center justify-center rounded-full bg-chat-error/10\"\n >\n <BIcon :icon=\"item.phIcon\" class=\"size-5 text-chat-error\" />\n </span>\n <span v-bind=\"itemProps.label\" class=\"text-label-md leading-normal! text-chat-error\">\n {{ item.label }}\n </span>\n </a>\n </template>\n </ContextMenu>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\nconst props = withDefaults(\n defineProps<{\n progress?: number;\n size?: number;\n strokeWidth?: number;\n isUploading?: boolean;\n isDownloading?: boolean;\n /** Replaces the upload/download icon. */\n icon?: string;\n }>(),\n {\n progress: 0,\n size: 40,\n strokeWidth: 2,\n isUploading: false,\n isDownloading: false,\n },\n);\n\n// SVG Geometry Calculations\nconst center = computed(() => props.size / 2);\n\n// Ensure the circle stays within the SVG box by subtracting half the stroke\nconst radius = computed(() => props.size / 2 - props.strokeWidth / 2);\n\n// Math for the progress ring\nconst circumference = computed(() => 2 * Math.PI * radius.value);\n\nconst dashOffset = computed(() => {\n return circumference.value - props.progress * circumference.value;\n});\n\n// Dynamic Icon Sizing (40% of container size)\nconst iconSize = computed(() => props.size * 0.4);\n</script>\n\n<template>\n <div\n class=\"relative shrink-0 group flex items-center justify-center\"\n :style=\"{ width: `${size}px`, height: `${size}px` }\"\n >\n <svg\n class=\"absolute inset-0 w-full h-full -rotate-90 pointer-events-none\"\n :viewBox=\"`0 0 ${size} ${size}`\"\n >\n <circle\n :cx=\"center\"\n :cy=\"center\"\n :r=\"radius\"\n class=\"stroke-chat-on-background/45\"\n :stroke-width=\"strokeWidth\"\n fill=\"none\"\n />\n <circle\n :cx=\"center\"\n :cy=\"center\"\n :r=\"radius\"\n class=\"stroke-chat-on-background transition-all duration-200 ease-linear\"\n :stroke-width=\"strokeWidth\"\n fill=\"none\"\n stroke-linecap=\"round\"\n :stroke-dasharray=\"circumference\"\n :stroke-dashoffset=\"dashOffset\"\n />\n </svg>\n\n <div class=\"flex items-center justify-center transition-colors\">\n <BIcon\n v-if=\"icon\"\n :icon=\"icon\"\n :style=\"{ width: `${iconSize}px`, height: `${iconSize}px` }\"\n class=\"fill-chat-on-background\"\n />\n <BIcon\n v-else-if=\"isUploading\"\n icon=\"PhUploadSimple\"\n :style=\"{ width: `${iconSize}px`, height: `${iconSize}px` }\"\n class=\"fill-chat-on-background\"\n />\n <BIcon\n v-else-if=\"isDownloading\"\n icon=\"PhX\"\n :style=\"{ width: `${iconSize}px`, height: `${iconSize}px` }\"\n class=\"fill-chat-on-background\"\n />\n <BIcon\n v-else\n icon=\"PhDownloadSimple\"\n :style=\"{ width: `${iconSize}px`, height: `${iconSize}px` }\"\n class=\"fill-chat-on-background\"\n />\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n// @ts-nocheck — grandfathered legacy chat-tree type errors; lift incrementally\nimport { computed, onBeforeUnmount, onMounted, ref } from \"vue\";\nimport Button from \"primevue/button\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport LoadingStatus from \"~/components/general/LoadingStatus.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatBubblesFileDisplay } from \"@i18n/locales\";\nimport { useMessagesStore } from \"~/stores/messageStores\";\nimport { useMediaStore } from \"~/stores/mediaStore\";\n\nconst props = withDefaults(\n defineProps<{\n url: string;\n messageId?: string;\n isSent?: boolean;\n }>(),\n {\n isSent: true,\n },\n);\n\nconst { t } = useLocalI18n(chatBubblesFileDisplay);\nconst messagesStore = useMessagesStore();\nconst mediaStore = useMediaStore();\nconst status = ref<\"idle\" | \"downloading\" | \"downloaded\">(\"idle\");\nconst downloadProgress = ref(0);\nconst playProgress = ref(0);\nconst isPlaying = ref(false);\nconst audioSrc = ref<string>(\"\");\n\nconst audioRef = ref<HTMLAudioElement | null>(null);\nlet abortController: AbortController | null = null;\n\nconst uploadData = computed(() =>\n props.messageId ? messagesStore.uploadProgress.get(props.messageId) : null,\n);\nconst isUploading = computed(() => !props.isSent && uploadData.value);\n\nconst displayProgress = computed(() => {\n if (isUploading.value && uploadData.value) {\n return uploadData.value.progress / 100;\n }\n if (status.value === \"downloading\") {\n return downloadProgress.value / 100;\n }\n return 0;\n});\n\nconst staticWaveform = [\n 20, 50, 90, 60, 30, 40, 80, 50, 30, 50, 80, 80, 90, 30, 60, 40, 70, 90, 40,\n 70, 40, 60, 20,\n];\n\nconst checkLocalExistence = async () => {\n try {\n const cached = await mediaStore.getCachedBlob(props.url);\n if (cached) {\n audioSrc.value = URL.createObjectURL(cached);\n status.value = \"downloaded\";\n }\n } catch (e) {\n console.warn(\"IDB check failed\", e);\n }\n};\n\nconst handleAction = async () => {\n if (isUploading.value) return;\n\n if (status.value === \"downloaded\" && audioRef.value) {\n if (isPlaying.value) {\n audioRef.value.pause();\n isPlaying.value = false;\n } else {\n audioRef.value\n .play()\n .then(() => {\n isPlaying.value = true;\n })\n .catch((err) => {\n console.warn(\n \"Cached blob invalid (likely mock data). Falling back to URL.\",\n err,\n );\n if (audioRef.value) {\n audioRef.value.src = props.url;\n audioRef.value.play().then(() => {\n isPlaying.value = true;\n });\n }\n });\n }\n return;\n }\n\n if (status.value === \"downloading\") {\n abortController?.abort();\n status.value = \"idle\";\n downloadProgress.value = 0;\n return;\n }\n\n status.value = \"downloading\";\n downloadProgress.value = 0;\n abortController = new AbortController();\n\n try {\n const blob = await mediaStore.download(props.url, {\n signal: abortController.signal,\n onProgress: (p) => {\n downloadProgress.value = p;\n },\n });\n audioSrc.value = URL.createObjectURL(blob);\n status.value = \"downloaded\";\n } catch (error: any) {\n if (error.name !== \"AbortError\")\n console.error(\"Voice download error:\", error);\n status.value = \"idle\";\n downloadProgress.value = 0;\n }\n};\n\nconst onTimeUpdate = () => {\n if (!audioRef.value) return;\n const current = audioRef.value.currentTime;\n const total = audioRef.value.duration;\n if (total) playProgress.value = (current / total) * 100;\n};\n\nconst onEnded = () => {\n isPlaying.value = false;\n playProgress.value = 0;\n};\n\nconst seekAudio = (e: MouseEvent) => {\n if (status.value !== \"downloaded\" || !audioRef.value || isUploading.value)\n return;\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n const clickPosition = Math.max(\n 0,\n Math.min(1, (e.clientX - rect.left) / rect.width),\n );\n const newTime = clickPosition * audioRef.value.duration;\n if (isFinite(newTime)) {\n audioRef.value.currentTime = newTime;\n playProgress.value = clickPosition * 100;\n }\n};\n\nonMounted(() => checkLocalExistence());\nonBeforeUnmount(() => {\n if (audioSrc.value) URL.revokeObjectURL(audioSrc.value);\n abortController?.abort();\n});\n</script>\n<template>\n <div class=\"w-55 p-2 flex items-center gap-x-2.5 select-none text-chat-on-background\">\n <div\n class=\"flex-1 h-7 relative flex items-center cursor-pointer overflow-hidden\"\n @click=\"seekAudio\"\n >\n <audio\n ref=\"audioRef\"\n :src=\"audioSrc\"\n @timeupdate=\"onTimeUpdate\"\n @ended=\"onEnded\"\n ></audio>\n\n <div\n class=\"absolute inset-0 flex items-center justify-between opacity-30\"\n >\n <div\n v-for=\"(h, idx) in staticWaveform\"\n :key=\"'base-' + idx\"\n :style=\"{ height: h + '%' }\"\n class=\"w-0.5 rounded-full bg-chat-on-background\"\n ></div>\n </div>\n\n <div\n class=\"absolute inset-0 flex items-center justify-between transition-all ease-linear\"\n :class=\"[isPlaying ? 'duration-100' : 'duration-75']\"\n :style=\"{ clipPath: `inset(0 ${100 - playProgress}% 0 0)` }\"\n >\n <div\n v-for=\"(h, idx) in staticWaveform\"\n :key=\"'active-' + idx\"\n :style=\"{ height: h + '%' }\"\n class=\"w-0.5 rounded-full bg-chat-on-background\"\n ></div>\n </div>\n </div>\n\n <IconButton\n v-if=\"status === 'downloaded' && !isUploading\"\n :icon=\"isPlaying ? 'PhPause' : 'PhPlay'\"\n :label=\"isPlaying ? t('actions.pause') : t('actions.play')\"\n weight=\"fill\"\n :text=\"false\"\n severity=\"contrast\"\n size=\"large\"\n class=\"shrink-0\"\n @click=\"handleAction\"\n />\n <Button\n v-else\n text\n rounded\n class=\"size-11! shrink-0 p-0!\"\n :aria-label=\"status === 'downloading' ? t('actions.cancelDownload') : t('actions.download')\"\n :disabled=\"isUploading\"\n @click=\"handleAction\"\n >\n <LoadingStatus\n :size=\"44\"\n :stroke-width=\"2.5\"\n :progress=\"displayProgress\"\n :is-uploading=\"isUploading\"\n :is-downloading=\"status === 'downloading'\"\n />\n </Button>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref, watch } from \"vue\";\nimport { useMessagesStore } from \"~/stores/messageStores\";\n\nconst props = withDefaults(\n defineProps<{\n videoUrl?: string;\n thumbnail?: string;\n mode?: \"playback\" | \"recording\";\n stream?: MediaStream | null;\n messageId?: string;\n isSent?: boolean;\n isPaused?: boolean;\n recordingTime?: number;\n maxDuration?: number;\n }>(),\n {\n videoUrl: \"\",\n thumbnail: \"\",\n mode: \"playback\",\n stream: null,\n isSent: true,\n isPaused: false,\n recordingTime: 0,\n maxDuration: 60,\n },\n);\n\nconst messagesStore = useMessagesStore();\nconst videoRef = ref<HTMLVideoElement | null>(null);\nconst isPlaying = ref(false);\nconst isLoaded = ref(false);\nconst progress = ref(0);\n\nconst uploadData = computed(() =>\n props.messageId ? messagesStore.uploadProgress.get(props.messageId) : null,\n);\nconst isUploading = computed(() => !props.isSent && uploadData.value);\n\nconst circumference = 2 * Math.PI * 113;\nconst dashOffset = computed(() => {\n if (isUploading.value && uploadData.value) {\n return circumference - (uploadData.value.progress / 100) * circumference;\n }\n\n if (props.mode === \"recording\") {\n const progressPercent = Math.min(\n (props.recordingTime / props.maxDuration) * 100,\n 100,\n );\n return circumference - (progressPercent / 100) * circumference;\n }\n\n return circumference - (progress.value / 100) * circumference;\n});\n\nconst togglePlay = () => {\n if (props.mode === \"recording\" || !videoRef.value || isUploading.value)\n return;\n\n if (isPlaying.value) {\n videoRef.value.pause();\n } else {\n videoRef.value.play();\n }\n};\n\nconst handleTimeUpdate = () => {\n if (!videoRef.value || props.mode === \"recording\" || isUploading.value)\n return;\n const current = videoRef.value.currentTime;\n const total = videoRef.value.duration;\n if (total) {\n progress.value = (current / total) * 100;\n }\n};\n\nconst handleEnded = () => {\n isPlaying.value = false;\n progress.value = 0;\n if (videoRef.value) videoRef.value.currentTime = 0;\n};\n\nconst handlePlay = () => {\n isPlaying.value = true;\n};\nconst handlePause = () => {\n isPlaying.value = false;\n};\n\nwatch(\n () => props.stream,\n (newStream) => {\n if (props.mode === \"recording\" && videoRef.value) {\n if (newStream) {\n videoRef.value.srcObject = newStream;\n videoRef.value.play();\n } else {\n videoRef.value.srcObject = null;\n }\n }\n },\n { immediate: true },\n);\n\nwatch(\n () => props.isPaused,\n (paused) => {\n if (\n props.mode === \"recording\" &&\n videoRef.value &&\n videoRef.value.srcObject\n ) {\n if (paused) {\n videoRef.value.pause();\n } else {\n videoRef.value.play();\n }\n }\n },\n);\n\nonBeforeUnmount(() => {\n if (videoRef.value) {\n videoRef.value.srcObject = null;\n }\n});\n</script>\n\n<template>\n <div\n class=\"relative w-60.5 h-60.5 p-2 shrink-0 group select-none flex items-center justify-center\"\n >\n <svg\n class=\"absolute w-57.5 h-57.5 -rotate-90 pointer-events-none z-20\"\n viewBox=\"0 0 230 230\"\n >\n <circle\n cx=\"115\"\n cy=\"115\"\n r=\"113\"\n :class=\"[\n isUploading ? 'stroke-white/30' : 'stroke-white dark:stroke-chat-background',\n ]\"\n stroke-width=\"4\"\n fill=\"none\"\n />\n\n <circle\n cx=\"115\"\n cy=\"115\"\n r=\"113\"\n class=\"stroke-chat-primary transition-all ease-linear\"\n :class=\"[isPlaying || isUploading ? 'duration-200' : 'duration-75']\"\n stroke-width=\"4\"\n fill=\"none\"\n stroke-linecap=\"round\"\n :stroke-dasharray=\"circumference\"\n :stroke-dashoffset=\"dashOffset\"\n />\n </svg>\n\n <div\n class=\"relative w-54.5 h-54.5 shrink-0 rounded-full overflow-hidden bg-[#1C1E22] z-10\"\n :class=\"[isUploading ? 'cursor-default' : 'cursor-pointer']\"\n @click=\"togglePlay\"\n >\n <video\n ref=\"videoRef\"\n :src=\"mode === 'playback' ? videoUrl : undefined\"\n :poster=\"thumbnail\"\n playsinline\n loop\n muted\n class=\"w-full h-full object-cover transition-opacity duration-300\"\n :class=\"[\n isLoaded || mode === 'recording' ? 'opacity-100' : 'opacity-0',\n ]\"\n @timeupdate=\"handleTimeUpdate\"\n @ended=\"handleEnded\"\n @play=\"handlePlay\"\n @pause=\"handlePause\"\n @loadeddata=\"isLoaded = true\"\n ></video>\n\n <div\n v-if=\"!isLoaded && mode === 'playback'\"\n class=\"absolute inset-0 flex items-center justify-center bg-chat-background\"\n ></div>\n\n <div\n v-if=\"mode === 'playback' && !isUploading\"\n class=\"absolute inset-0 flex items-center justify-center transition-all duration-300\"\n :class=\"[\n isPlaying ? 'bg-transparent opacity-0' : ' bg-black/30 opacity-100',\n ]\"\n >\n <BIcon\n :icon=\"isPlaying ? 'PhPause' : 'PhPlay'\"\n weight=\"light\"\n class=\"w-5 h-5 text-white transition-transform duration-300\"\n :class=\"[isPlaying ? 'scale-75' : 'scale-100 ml-1']\"\n />\n </div>\n\n <div\n v-if=\"isUploading\"\n class=\"absolute inset-0 flex items-center justify-center bg-black/40 z-20\"\n >\n <BIcon icon=\"PhUploadSimple\" class=\"w-6 h-6 text-white\" />\n </div>\n\n <div\n v-if=\"mode === 'recording'\"\n class=\"absolute top-4 left-1/2 -translate-x-1/2 flex items-center justify-center gap-x-1\"\n >\n <div class=\"w-2 h-2 rounded-full bg-chat-error animate-pulse\"></div>\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from \"vue\";\n\nconst props = withDefaults(\n defineProps<{\n width?: number | string;\n height?: number | string;\n label?: string;\n mainColor?: string;\n accentColor?: string;\n }>(),\n {\n width: 40,\n height: 40,\n label: \"\",\n mainColor: \"#FFFFFF\",\n accentColor: \"#F24E1E\",\n },\n);\n\nconst ASPECT_RATIO = 65 / 72;\n\nconst finalWidth = computed(() => {\n return Number(props.height) * ASPECT_RATIO;\n});\n\nconst finalHeight = computed(() => {\n return Number(props.width) / ASPECT_RATIO;\n});\n</script>\n<template>\n <div dir=\"ltr\" class=\"relative cursor-pointer\">\n <svg\n :width=\"finalWidth\"\n :height=\"finalHeight\"\n viewBox=\"0 0 65 72\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M47.564 4.21766C44.8552 1.51714 41.1812 0 37.3502 0H14.4444C6.467 0 0 6.4471 0 14.4V57.6C0 65.5529 6.467 72 14.4444 72H50.5556C58.533 72 65 65.5529 65 57.6V27.5647C65 23.7456 63.4782 20.0829 60.7693 17.3823L47.564 4.21766Z\"\n :fill=\"mainColor\"\n />\n\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M44 1C45.5315 1.7318 46.9413 2.75075 48.154 4.02411L61.1199 17.6383C61.1203 17.6387 61.1207 17.6392 61.1211 17.6396C62.3333 18.9127 63.3033 20.3924 64 22H52.8641C47.9686 22 44 17.833 44 12.6927V1Z\"\n :fill=\"accentColor\"\n />\n </svg>\n <div\n class=\"absolute right-0 top-1/2 rounded-sm px-1 py-0.5 flex items-center justify-center\"\n :style=\"{ backgroundColor: accentColor }\"\n >\n <div\n class=\"text-center text-white text-[7px] font-bold leading-none uppercase tracking-wide\"\n >\n {{ label }}\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport Button from \"primevue/button\";\nimport FileFormatDisplay from \"~/components/general/FileFormatDisplay.vue\";\nimport LoadingStatus from \"~/components/general/LoadingStatus.vue\";\nimport { useMessagesStore } from \"~/stores/messageStores\";\nimport { chatBubblesFileDisplay } from \"@i18n/locales\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { useMediaStore } from \"~/stores/mediaStore\";\nimport { computed, onMounted, ref } from \"vue\";\nimport { formatBytes } from \"~/utils/format\";\n\nconst props = withDefaults(\n defineProps<{\n messageId?: string;\n isMine?: boolean;\n isSent?: boolean;\n url: string;\n fileName?: string;\n }>(),\n {\n isMine: true,\n isSent: true,\n },\n);\n\nconst { t } = useLocalI18n(chatBubblesFileDisplay);\nconst messagesStore = useMessagesStore();\nconst mediaStore = useMediaStore();\n\nconst status = ref<\"idle\" | \"downloading\" | \"downloaded\">(\"idle\");\nconst progress = ref(0);\nconst fetchedSize = ref<number | null>(null);\nlet abortController: AbortController | null = null;\n\nconst uploadData = computed(() =>\n props.messageId ? messagesStore.uploadProgress.get(props.messageId) : null,\n);\nconst isUploading = computed(() => !props.isSent && !!uploadData.value);\n\nconst displayProgress = computed(() => {\n if (isUploading.value && uploadData.value) {\n return uploadData.value.progress / 100;\n }\n if (status.value === \"downloading\") {\n return progress.value / 100;\n }\n return 0;\n});\n\nconst checkLocalExistence = async () => {\n const cached = await mediaStore.getCachedBlob(props.url);\n if (cached) status.value = \"downloaded\";\n};\n\nconst fileName = computed(() => {\n if (props.fileName) return props.fileName;\n try {\n const urlObj = new URL(props.url);\n return decodeURIComponent(\n urlObj.pathname.split(\"/\").pop() || \"Unknown_File\",\n );\n } catch {\n return \"File\";\n }\n});\n\nconst actionLabel = computed(() => {\n if (status.value === \"downloading\") return t(\"actions.cancelDownload\");\n return t(\"actions.download\");\n});\n\nconst fileExt = computed(() => {\n const name = fileName.value;\n const lastDot = name.lastIndexOf(\".\");\n return lastDot !== -1\n ? name\n .substring(lastDot + 1)\n .toUpperCase()\n .substring(0, 4)\n : \"FILE\";\n});\n\nconst formattedSize = computed(() => {\n if (isUploading.value && uploadData.value) {\n const realTotal = fetchedSize.value || uploadData.value.total;\n const currentUploaded = (uploadData.value.progress / 100) * realTotal;\n return `${formatBytes(currentUploaded)} / ${formatBytes(realTotal)}`;\n }\n if (status.value === \"downloading\" && fetchedSize.value) {\n const downloaded = (progress.value / 100) * fetchedSize.value;\n return `${formatBytes(downloaded)} / ${formatBytes(fetchedSize.value)}`;\n }\n return fetchedSize.value\n ? formatBytes(fetchedSize.value)\n : t(\"file.calculating\");\n});\n\nconst getFileSize = async () => {\n if (props.url.startsWith(\"blob:\")) {\n try {\n const res = await fetch(props.url);\n const blob = await res.blob();\n fetchedSize.value = blob.size;\n } catch {\n fetchedSize.value = 0;\n }\n return;\n }\n try {\n const size = await mediaStore.fetchFileSize(props.url);\n fetchedSize.value = size ?? 0;\n } catch {\n fetchedSize.value = 0;\n }\n};\n\nconst toggleDownload = async () => {\n if (isUploading.value) return;\n\n if (status.value === \"downloaded\") {\n const fileBlob = await mediaStore.getCachedBlob(props.url);\n\n if (fileBlob) {\n const blobUrl = URL.createObjectURL(fileBlob);\n const a = document.createElement(\"a\");\n a.href = blobUrl;\n a.download = fileName.value;\n document.body.appendChild(a);\n a.click();\n document.body.removeChild(a);\n setTimeout(() => URL.revokeObjectURL(blobUrl), 1000);\n } else {\n status.value = \"idle\";\n toggleDownload();\n }\n return;\n }\n\n if (status.value === \"downloading\") {\n abortController?.abort();\n status.value = \"idle\";\n progress.value = 0;\n return;\n }\n\n status.value = \"downloading\";\n progress.value = 0;\n abortController = new AbortController();\n\n try {\n await mediaStore.download(props.url, {\n signal: abortController.signal,\n onProgress: (p) => {\n progress.value = p;\n },\n });\n status.value = \"downloaded\";\n } catch {\n status.value = \"idle\";\n progress.value = 0;\n }\n};\n\nonMounted(() => {\n getFileSize();\n checkLocalExistence();\n});\n</script>\n<template>\n <div class=\"px-3 flex gap-x-2 select-none items-center\">\n <div dir=\"ltr\" class=\"flex text-left flex-col gap-y-0.5 flex-1 min-w-0\">\n <div class=\"text-chat-on-background text-label-md truncate\">{{ fileName }}</div>\n <div class=\"w-20\">\n <div\n class=\"text-body-sm text-left text-chat-on-background/70 w-full line-clamp-1 text-ellipsis overflow-hidden\"\n >\n {{ formattedSize }}\n </div>\n </div>\n </div>\n <Button\n text\n rounded\n class=\"size-11! shrink-0 p-0!\"\n :aria-label=\"actionLabel\"\n :disabled=\"isUploading\"\n @click=\"toggleDownload\"\n >\n <FileFormatDisplay\n v-if=\"status === 'downloaded' && !isUploading\"\n :width=\"30\"\n :height=\"33\"\n :label=\"fileExt\"\n />\n <LoadingStatus\n v-else\n :progress=\"displayProgress\"\n :is-uploading=\"isUploading\"\n :is-downloading=\"status === 'downloading'\"\n />\n </Button>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** The pill above a message that starts a new day, or the first unread one. */\ndefineProps<{ label: string }>();\n</script>\n\n<template>\n <div class=\"py-5 w-full flex items-center justify-center\">\n <div\n class=\"rounded-full bg-on-surface/10 flex items-center justify-center px-4 py-0.5\"\n >\n <div class=\"text-on-surface select-none text-body-sm\">\n {{ label }}\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Dims media that is still on its way out and shows how far along it is: its videos being\n * compressed first, then the upload.\n */\nimport { computed } from \"vue\";\nimport LoadingStatus from \"~/components/general/LoadingStatus.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatBubble } from \"@i18n/locales\";\nimport { replaceDigitsByLocale } from \"~/utils/format\";\n\nconst props = withDefaults(\n defineProps<{\n /** 0–100, as UploadProgressEvent reports it. */\n progress: number;\n phase?: \"compress\" | \"upload\";\n size?: \"sm\" | \"lg\";\n }>(),\n { phase: \"upload\", size: \"lg\" },\n);\n\nconst { t, locale } = useLocalI18n(chatBubble);\n\nconst label = computed(() =>\n t(props.phase === \"compress\" ? \"sending.compressing\" : \"sending.uploading\", {\n progress: replaceDigitsByLocale(Math.round(props.progress), locale.value),\n }),\n);\n</script>\n\n<template>\n <div\n data-testid=\"upload-progress\"\n :data-phase=\"phase\"\n role=\"progressbar\"\n :aria-label=\"label\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n :aria-valuenow=\"Math.round(progress)\"\n class=\"absolute inset-0 flex flex-col items-center justify-center gap-y-2 bg-black/40\"\n >\n <div class=\"rounded-full bg-chat-background/85 p-0.5\">\n <LoadingStatus\n :progress=\"progress / 100\"\n :size=\"size === 'lg' ? 44 : 28\"\n :icon=\"phase === 'compress' ? 'PhArrowsInSimple' : undefined\"\n is-uploading\n />\n </div>\n <span\n v-if=\"size === 'lg'\"\n aria-hidden=\"true\"\n class=\"rounded-full bg-black/55 px-2 py-0.5 text-[11px] leading-4 text-white tabular-nums backdrop-blur-sm\"\n >\n {{ label }}\n </span>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * A message's photos and videos: one large tile, or a row of thumbnails with a \"+N\" tile when\n * there are more than fit. Videos show their first frame, a play badge and their length. Emits the\n * index to open in the viewer.\n */\nimport { computed } from \"vue\";\nimport Button from \"primevue/button\";\nimport type { MediaItem, UploadProgressEvent } from \"~/types\";\nimport UploadProgressOverlay from \"./UploadProgressOverlay.vue\";\nimport MediaThumb from \"~/components/general/MediaThumb.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatBubble } from \"@i18n/locales\";\n\nconst MAX_VISIBLE = 3;\n\nconst props = defineProps<{\n items: MediaItem[];\n isSent: boolean;\n upload?: UploadProgressEvent;\n /** 0–100 while its videos are compressed, before the upload. */\n compress?: number;\n}>();\n\nconst emit = defineEmits<{ preview: [index: number] }>();\n\nconst { t } = useLocalI18n(chatBubble);\n\nconst displayed = computed(() => props.items.slice(0, MAX_VISIBLE));\n// Compressing comes first, then the upload.\nconst sending = computed(() => {\n if (props.isSent) return null;\n if (props.compress !== undefined) return { phase: \"compress\" as const, progress: props.compress };\n if (props.upload) return { phase: \"upload\" as const, progress: props.upload.progress };\n return null;\n});\nconst label = (item: MediaItem) => t(`attachementTypes.${item.kind}`);\n\nconst TILE = \"relative block overflow-hidden rounded-xl p-0 cursor-pointer focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-chat-primary\";\n</script>\n\n<template>\n <Button\n v-if=\"items.length === 1\"\n unstyled\n data-testid=\"bubble-image\"\n :aria-label=\"label(items[0]!)\"\n :class=\"[TILE, 'h-40.5 w-85 max-w-full md:max-w-85']\"\n @click.stop=\"emit('preview', 0)\"\n >\n <MediaThumb :item=\"items[0]!\" class=\"size-full\" />\n <UploadProgressOverlay\n v-if=\"sending\"\n :progress=\"sending.progress\"\n :phase=\"sending.phase\"\n size=\"lg\"\n />\n </Button>\n\n <div v-else class=\"flex h-16 max-w-75 items-center gap-x-3\">\n <Button\n v-if=\"items.length > MAX_VISIBLE\"\n unstyled\n :aria-label=\"`+${items.length - MAX_VISIBLE}`\"\n :class=\"[TILE, 'flex aspect-square h-full items-center justify-center bg-surface-variant-2']\"\n @click.stop=\"emit('preview', MAX_VISIBLE)\"\n >\n <span class=\"select-none text-label-md text-on-surface\">\n +{{ items.length - MAX_VISIBLE }}\n </span>\n </Button>\n\n <Button\n v-for=\"(item, index) in displayed\"\n :key=\"index\"\n unstyled\n data-testid=\"bubble-media-item\"\n :aria-label=\"label(item)\"\n :class=\"[TILE, 'aspect-square h-full']\"\n @click.stop=\"emit('preview', index)\"\n >\n <MediaThumb :item=\"item\" badge=\"sm\" :show-duration=\"false\" class=\"size-full\" />\n <UploadProgressOverlay\n v-if=\"sending\"\n :progress=\"sending.progress\"\n :phase=\"sending.phase\"\n size=\"sm\"\n />\n </Button>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** The round mark beside a message while it is selected in select mode. */\ndefineProps<{ selected: boolean }>();\n</script>\n\n<template>\n <div\n class=\"shrink-0 transition-all duration-200 overflow-hidden ease-in-out whitespace-nowrap\"\n :class=\"{ 'w-auto': selected, 'w-0': !selected }\"\n >\n <div\n class=\"transition-all duration-200 ease-in-out w-5 h-5 rounded-full bg-gradient-primary-secondary flex items-center justify-center\"\n :class=\"{\n 'opacity-100 scale-100': selected,\n 'opacity-0 scale-0': !selected,\n }\"\n >\n <div class=\"w-2.5 h-2.5 rounded-full bg-surface\"></div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\nimport type { Contact, ExtendedMessage } from \"~/types\";\n\n// A request message is drawn by the host's own globally registered `RequestCard`. It is looked up\n// here rather than in ChatBubble because a template resolves its components on every render, so\n// every ordinary bubble would warn about a `RequestCard` that hosts without requests never register.\ndefineProps<{ message: ExtendedMessage; contact?: Contact | null }>();\n</script>\n\n<template>\n <RequestCard :message=\"message\" :contact=\"contact\" />\n</template>\n","<script setup lang=\"ts\">\n/**\n * The retry prompt under a message that failed to send. The time and send state of every other\n * message sit inside the bubble, in BubbleMeta.\n */\nimport Button from \"primevue/button\";\nimport type { Message } from \"~/types\";\nimport { useMessagesStore } from \"~/stores/messageStores.js\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatBubble } from \"@i18n/locales\";\n\ndefineProps<{ message: Message }>();\n\nconst { t } = useLocalI18n(chatBubble);\nconst messagesStore = useMessagesStore();\n</script>\n\n<template>\n <div class=\"flex w-full justify-start pt-1\">\n <Button\n text\n size=\"small\"\n severity=\"danger\"\n :label=\"t('sendFailed')\"\n @click.stop=\"messagesStore.retryMessage(message)\"\n >\n <template #icon>\n <BIcon icon=\"PhWarningCircle\" class=\"size-4\" />\n </template>\n </Button>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * A message's time and, on your own messages, its send state, drawn inside the bubble's end corner.\n * `overlay` is the pill form laid over a photo or video, where plain text would not be readable.\n */\nimport { computed } from \"vue\";\nimport type { Message } from \"~/types\";\nimport { useDate } from \"~/composables/useDate.js\";\n\nconst props = withDefaults(\n defineProps<{ message: Message; isMine: boolean; overlay?: boolean }>(),\n { overlay: false },\n);\n\nconst { formatTime } = useDate();\n\nconst checkIcon = computed(() => {\n if (props.message.isFailed) return \"PhWarningCircle\";\n if (props.message.isSent)\n return props.message.isRead ? \"PhChecks\" : \"PhCheck\";\n return \"PhClock\";\n});\n\nconst iconColor = computed(() => {\n if (props.message.isFailed) return \"fill-chat-error\";\n if (props.overlay) return \"fill-white\";\n return props.message.isRead && props.message.isSent\n ? \"fill-chat-primary\"\n : \"fill-chat-muted\";\n});\n</script>\n\n<template>\n <div\n class=\"pointer-events-none flex select-none items-center gap-x-1 text-[11px] leading-none\"\n :class=\"\n overlay\n ? 'rounded-full bg-black/45 px-2 py-1 text-white'\n : 'text-chat-muted'\n \"\n >\n <BIcon v-if=\"isMine\" :icon=\"checkIcon\" class=\"size-3.5\" :class=\"iconColor\" />\n <span>{{ formatTime(message.date) }}</span>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** The quoted message shown at the top of a bubble that replies to another message. */\nimport { computed } from \"vue\";\nimport type { Contact, ExtendedMessage } from \"~/types\";\nimport SafeEmojiText from \"~/components/general/SafeEmojiText.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatBubble } from \"@i18n/locales\";\nimport { albumKind, messageMedia } from \"~/utils/media\";\n\nconst props = defineProps<{\n message: ExtendedMessage;\n contact?: Contact | null;\n isMine: boolean;\n currentUserId: string;\n}>();\n\nconst { t } = useLocalI18n(chatBubble);\n\nconst replied = computed(() => props.message.repliedTo!);\n\nconst senderName = computed(() =>\n replied.value.senderId === props.currentUserId\n ? t(\"you\")\n : `${props.contact?.name ?? \"\"} ${props.contact?.lastName ?? \"\"}`.trim(),\n);\n\nconst preview = computed(() => {\n const m = replied.value;\n if (m.text?.trim()) return m.text;\n const album = messageMedia(m);\n if (album.length) return t(`attachementTypes.${albumKind(album)}`);\n if (m.voiceUrl) return t(\"attachementTypes.voice\");\n if (m.videoUrl) return t(\"attachementTypes.video\");\n if (m.fileUrl) return m.fileName || t(\"attachementTypes.file\");\n return \"\";\n});\n</script>\n\n<template>\n <div\n data-testid=\"reply-preview\"\n class=\"mx-2 mt-2 flex flex-col gap-y-0.5 overflow-hidden rounded-lg border-s-2 border-s-chat-primary px-3 py-1.5 text-body-sm\"\n :class=\"isMine ? 'bg-on-surface/5' : 'bg-surface-variant-2'\"\n >\n <div class=\"truncate text-label-sm text-chat-primary\">{{ senderName }}</div>\n <div class=\"line-clamp-1 text-on-surface/70\">\n <SafeEmojiText :text=\"preview\" />\n </div>\n </div>\n</template>\n","import { ref, onBeforeUnmount } from \"vue\";\n\nexport function useLongPress(callback: (event: PointerEvent) => void) {\n const longPressTimer = ref<ReturnType<typeof setTimeout> | null>(null);\n const touchStartPos = ref({ x: 0, y: 0 });\n\n const onPointerDown = (event: PointerEvent) => {\n if (event.button !== 0 && event.pointerType === \"mouse\") return;\n touchStartPos.value = { x: event.clientX, y: event.clientY };\n longPressTimer.value = setTimeout(() => {\n if (\"vibrate\" in navigator) navigator.vibrate(50);\n callback(event);\n longPressTimer.value = null;\n }, 1000);\n };\n\n const onPointerMove = (event: PointerEvent) => {\n if (!longPressTimer.value) return;\n const deltaX = Math.abs(event.clientX - touchStartPos.value.x);\n const deltaY = Math.abs(event.clientY - touchStartPos.value.y);\n if (deltaX > 10 || deltaY > 10) {\n clearTimeout(longPressTimer.value);\n longPressTimer.value = null;\n }\n };\n\n const onPointerUp = () => {\n if (longPressTimer.value) {\n clearTimeout(longPressTimer.value);\n longPressTimer.value = null;\n }\n };\n\n onBeforeUnmount(() => {\n if (longPressTimer.value) clearTimeout(longPressTimer.value);\n });\n\n return { onPointerDown, onPointerMove, onPointerUp };\n}\n","<script setup lang=\"ts\">\nimport { computed, nextTick, ref, useTemplateRef } from \"vue\";\nimport type { Contact, ExtendedMessage, Message } from \"~/types\";\nimport MediaViewer from \"./chat-bubbles/MediaViewer.vue\";\nimport BubbleOptions from \"./chat-bubbles/BubbleOptions.vue\";\nimport VoiceDisplay from \"./chat-bubbles/VoiceDisplay.vue\";\nimport BubbleVideo from \"./chat-bubbles/BubbleVideo.vue\";\nimport FileDisplay from \"./chat-bubbles/FileDisplay.vue\";\nimport SafeEmojiText from \"../general/SafeEmojiText.vue\";\nimport ContactAvatar from \"./contact/ContactAvatar.vue\";\nimport BubbleDivider from \"./chat-bubbles/BubbleDivider.vue\";\nimport BubbleMedia from \"./chat-bubbles/BubbleMedia.vue\";\nimport BubbleSelectionMark from \"./chat-bubbles/BubbleSelectionMark.vue\";\nimport BubbleRequest from \"./chat-bubbles/BubbleRequest.vue\";\nimport BubbleStatus from \"./chat-bubbles/BubbleStatus.vue\";\nimport BubbleMeta from \"./chat-bubbles/BubbleMeta.vue\";\nimport ReplyPreview from \"./chat-bubbles/ReplyPreview.vue\";\n\nimport { useMessagesStore } from \"~/stores/messageStores.js\";\nimport { useLongPress } from \"~/composables/useLongPress\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { useDate } from \"~/composables/useDate.js\";\nimport { chatBubble } from \"@i18n/locales\";\nimport { messageMedia } from \"~/utils/media\";\nimport { useProfileStore } from \"~/stores/profileStore.js\";\n\nconst props = withDefaults(\n defineProps<{\n message: ExtendedMessage;\n contact: Contact;\n isFirstUnread?: boolean;\n isDeleting?: boolean;\n }>(),\n {\n isFirstUnread: false,\n isDeleting: false,\n },\n);\n\nconst { t } = useLocalI18n(chatBubble);\nconst messagesStore = useMessagesStore();\nconst { formatDateShort } = useDate();\n\ntype MediaViewerInstance = InstanceType<typeof MediaViewer>;\ntype BubbleOptionsInstance = InstanceType<typeof BubbleOptions>;\n\nconst mediaViewerRef = useTemplateRef<MediaViewerInstance>(\"mediaViewer\");\nconst bubbleOptionsRef =\n useTemplateRef<BubbleOptionsInstance>(\"bubbleOptions\");\n\nconst profileStore = useProfileStore();\nconst currentUserId = computed(() => profileStore.userId);\n\nconst isMine = computed(() => props.message.senderId === currentUserId.value);\nconst isSelected = computed(() =>\n messagesStore.selectedMessages.has(props.message.id),\n);\nconst isSelectMode = computed(() => messagesStore.isSelectMode);\n\nconst media = computed(() => messageMedia(props.message));\n\nconst messageType = computed(() => {\n if (props.message.voiceUrl?.trim()) return \"voice\";\n if (media.value.length > 1) return \"multiImage\";\n if (media.value.length === 1) return \"image\";\n if (props.message.videoUrl?.trim()) return \"video\";\n if (props.message.fileUrl?.trim()) return \"file\";\n return \"text\";\n});\n\nconst isTextBased = computed(() =>\n [\"text\", \"file\", \"voice\"].includes(messageType.value),\n);\n\n// Consecutive messages from one sender on one day form a group: they sit close together, share\n// one avatar (on the last) and round off into each other on the sender's side.\nconst sameGroup = (a?: Message | null, b?: Message | null) =>\n !!a &&\n !!b &&\n !a.request &&\n !b.request &&\n a.senderId === b.senderId &&\n new Date(a.date).toDateString() === new Date(b.date).toDateString();\n\n// The unread divider splits a group, like the date divider does.\nconst groupedWithPrev = computed(\n () =>\n !props.isFirstUnread && sameGroup(props.message.prevMessage, props.message),\n);\nconst groupedWithNext = computed(() =>\n sameGroup(props.message, props.message.nextMessage),\n);\n\n// Your messages sit on the right and theirs on the left in either direction, so the sides (and\n// the corners facing them) are physical. The last bubble of a group keeps a tail.\nconst sideClass = computed(() =>\n isMine.value ? \"justify-end rtl:justify-start\" : \"justify-start rtl:justify-end\",\n);\nconst roundingClasses = computed(() => {\n const prev = groupedWithPrev.value;\n const next = groupedWithNext.value;\n if (isMine.value)\n return [prev && \"rounded-tr-md\", next ? \"rounded-br-md\" : \"rounded-br-xs\"];\n return [prev && \"rounded-tl-md\", next ? \"rounded-bl-md\" : \"rounded-bl-xs\"];\n});\n\nconst compressData = computed(() =>\n messagesStore.compressionProgress.get(props.message.id),\n);\nconst uploadData = computed(() =>\n messagesStore.uploadProgress.get(props.message.id),\n);\n\n// --- Actions ---\nconst viewerMounted = ref(false);\nconst previewImage = async (index: number) => {\n if (!viewerMounted.value) {\n viewerMounted.value = true;\n await nextTick();\n }\n mediaViewerRef.value?.open(index);\n};\n\nconst optionsMounted = ref(false);\n\nconst handleRightClick = async (event: MouseEvent | PointerEvent) => {\n if (props.message.request || !props.message.isSent) return;\n if (!messagesStore.isSelectMode) {\n messagesStore.selectedMessages.clear();\n messagesStore.toggleSelection(props.message);\n }\n if (!optionsMounted.value) {\n optionsMounted.value = true;\n await nextTick();\n }\n bubbleOptionsRef.value?.openMenu(event);\n};\n\nconst handleLeftClick = () => {\n if (messagesStore.isSelectMode) messagesStore.toggleSelection(props.message);\n};\n\n// Replaces 40 lines of pointer event logic\nconst longPress = useLongPress(handleRightClick);\n</script>\n\n<template>\n <div\n data-testid=\"chat-bubble\"\n :data-message-id=\"message.id\"\n @contextmenu.prevent=\"handleRightClick\"\n class=\"vue-chat w-full transition-all duration-300 ease-in-out\"\n :class=\"{\n 'max-h-0 opacity-0 overflow-hidden': isDeleting,\n 'max-h-250 opacity-100': !isDeleting,\n }\"\n >\n <BubbleDivider\n v-if=\"message.isFirstInDate || isFirstUnread\"\n :label=\"\n isFirstUnread ? t('unreadMessages') : formatDateShort(message.date)\n \"\n />\n\n <!-- Message Row -->\n <div\n class=\"w-full px-5 transition-all duration-200 flex items-center ease-in-out\"\n :class=\"{\n 'pt-0.5': groupedWithPrev,\n 'pt-3': !groupedWithPrev,\n 'bg-on-surface/5 gap-x-3': isSelectMode && isSelected,\n 'bg-on-surface/0 gap-x-0': !(isSelectMode && isSelected),\n 'cursor-pointer select-none': isSelectMode,\n }\"\n >\n <BubbleSelectionMark\n v-if=\"!message.request\"\n :selected=\"isSelectMode && isSelected\"\n />\n\n <!-- Request Card Fallback -->\n <div v-if=\"message.request\" class=\"py-3 w-full flex justify-center\">\n <BubbleRequest :message=\"message\" :contact=\"contact\" />\n </div>\n\n <!-- Standard Message Bubble -->\n <div\n v-else\n class=\"flex items-center flex-1 min-w-0 relative\"\n :class=\"sideClass\"\n @click=\"handleLeftClick\"\n v-on=\"longPress\"\n >\n <div class=\"select-none md:select-auto w-full\">\n <div\n class=\"w-full flex items-center\"\n :class=\"sideClass\"\n >\n <!-- Their avatar goes on the outer, left side of the bubble. -->\n <div\n class=\"flex max-w-4/5 items-end gap-x-2\"\n :class=\"{ 'flex-row-reverse rtl:flex-row': !isMine }\"\n >\n <div class=\"flex-1 min-w-0\">\n <!-- Text / File / Voice Bubble Wrapper -->\n <div\n v-if=\"isTextBased\"\n class=\"relative rounded-2xl p-1 shadow-xs\"\n :class=\"[\n roundingClasses,\n isMine ? 'bg-chat-bubble-mine' : 'bg-chat-bubble',\n { 'text-chat-base text-chat-on-background': messageType === 'text' },\n ]\"\n >\n <ReplyPreview\n v-if=\"messageType === 'text' && message.repliedTo\"\n :message=\"message\"\n :contact=\"contact\"\n :is-mine=\"isMine\"\n :current-user-id=\"currentUserId\"\n />\n <p\n v-if=\"messageType === 'text'\"\n class=\"max-w-full wrap-break-word px-2.5 py-1.5\"\n >\n <SafeEmojiText :text=\"message.text\" />\n <!-- Holds the last line clear of the time, which sits over the bubble's end corner. -->\n <span\n aria-hidden=\"true\"\n class=\"inline-block h-3\"\n :class=\"isMine ? 'w-14' : 'w-10'\"\n />\n </p>\n <BubbleMeta\n v-if=\"messageType === 'text'\"\n :message=\"message\"\n :is-mine=\"isMine\"\n class=\"absolute end-3 bottom-2\"\n />\n <FileDisplay\n v-else-if=\"messageType === 'file'\"\n :is-mine=\"isMine\"\n :url=\"message.fileUrl ?? ''\"\n :file-name=\"message.fileName\"\n :message-id=\"message.id\"\n :is-sent=\"message.isSent\"\n />\n <VoiceDisplay\n v-else-if=\"messageType === 'voice'\"\n :url=\"message.voiceUrl ?? ''\"\n :message-id=\"message.id\"\n :is-sent=\"message.isSent\"\n />\n <div v-if=\"messageType !== 'text'\" class=\"flex justify-end px-2 pb-1\">\n <BubbleMeta :message=\"message\" :is-mine=\"isMine\" />\n </div>\n </div>\n\n <!-- Photos and video carry the time as a pill over their end corner. -->\n <div v-else class=\"relative\">\n <BubbleMedia\n v-if=\"messageType === 'image' || messageType === 'multiImage'\"\n :items=\"media\"\n :is-sent=\"message.isSent\"\n :upload=\"uploadData\"\n :compress=\"compressData\"\n @preview=\"previewImage\"\n />\n <BubbleVideo\n v-else-if=\"messageType === 'video'\"\n :video-url=\"message.videoUrl\"\n mode=\"playback\"\n />\n <BubbleMeta\n :message=\"message\"\n :is-mine=\"isMine\"\n overlay\n class=\"absolute end-2 bottom-2 z-20\"\n />\n </div>\n\n <BubbleStatus v-if=\"isMine && message.isFailed\" :message=\"message\" />\n </div>\n\n <!-- Avatar, once per group, level with its last bubble. -->\n <div v-if=\"!isMine\" class=\"size-8 shrink-0\">\n <ContactAvatar\n v-if=\"!groupedWithNext\"\n :contact=\"contact\"\n :show-online=\"false\"\n />\n </div>\n </div>\n </div>\n </div>\n\n <!-- Overlays, each mounted on first open: otherwise every bubble keeps idle copies. -->\n <MediaViewer\n v-if=\"viewerMounted && media.length > 0\"\n ref=\"mediaViewer\"\n :items=\"media\"\n :sender=\"isMine ? t('you') : `${contact.name} ${contact.lastName}`.trim()\"\n :date=\"message.date\"\n />\n <BubbleOptions\n v-if=\"optionsMounted\"\n :message=\"message\"\n :is-mine=\"isMine\"\n ref=\"bubbleOptions\"\n />\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * Placeholder bubbles while a conversation's messages load, laid out like ChatBubble: the other\n * side's at the end with an avatar on the last of each group, yours at the start.\n */\nimport { computed } from \"vue\";\nimport Skeleton from \"primevue/skeleton\";\n\nconst props = withDefaults(defineProps<{ count?: number }>(), { count: 6 });\n\n// A fixed, varied pattern, so the placeholder reads as a conversation rather than a stripe.\nconst PATTERN = [\n { mine: false, width: \"55%\", height: \"2.75rem\" },\n { mine: false, width: \"38%\", height: \"2.75rem\" },\n { mine: true, width: \"62%\", height: \"4rem\" },\n { mine: false, width: \"46%\", height: \"2.75rem\" },\n { mine: true, width: \"34%\", height: \"2.75rem\" },\n { mine: true, width: \"50%\", height: \"2.75rem\" },\n];\n\nconst rows = computed(() =>\n Array.from({ length: props.count }, (_, i) => {\n const row = PATTERN[i % PATTERN.length]!;\n const next = PATTERN[(i + 1) % PATTERN.length]!;\n return { ...row, avatar: !row.mine && (i === props.count - 1 || next.mine) };\n }),\n);\n</script>\n\n<template>\n <div class=\"vue-chat flex w-full flex-col gap-y-2 px-5 py-3\" aria-hidden=\"true\">\n <div\n v-for=\"(row, i) in rows\"\n :key=\"i\"\n class=\"flex w-full items-end gap-x-2\"\n :class=\"row.mine ? 'justify-start' : 'justify-end'\"\n >\n <Skeleton\n :width=\"row.width\"\n :height=\"row.height\"\n border-radius=\"1rem\"\n class=\"max-w-4/5\"\n />\n <div v-if=\"!row.mine\" class=\"size-8 shrink-0\">\n <Skeleton v-if=\"row.avatar\" shape=\"circle\" size=\"2rem\" />\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** The date pill that floats over the list while scrolling and fades out when it stops. */\ndefineProps<{ label: string | null; opacity: number }>();\n</script>\n\n<template>\n <div\n class=\"absolute top-4 left-0 right-0 z-20 flex justify-center pointer-events-none transition-opacity duration-200\"\n :style=\"{ opacity }\"\n >\n <div\n v-if=\"label\"\n class=\"rounded-full bg-chat-on-background/10 flex items-center justify-center px-4 py-0.5\"\n >\n <div class=\"text-chat-on-background select-none text-label-sm\">\n {{ label }}\n </div>\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** Jumps back to the newest message; shows how many arrived while the user was scrolled up. */\nimport Badge from \"primevue/badge\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatMessages } from \"@i18n/locales\";\n\ndefineProps<{ visible: boolean; unseen: number }>();\nconst emit = defineEmits<{ click: [] }>();\n\nconst { t } = useLocalI18n(chatMessages);\n</script>\n\n<template>\n <div class=\"relative w-14 pr-3 pb-1\">\n <div\n :class=\"[\n visible\n ? 'pointer-events-auto scale-100 opacity-100'\n : 'pointer-events-none scale-0 opacity-0',\n ]\"\n class=\"origin-bottom transition-all duration-200 ease-in-out\"\n >\n <IconButton\n icon=\"PhArrowDown\"\n icon-class=\"size-6\"\n :label=\"t('actions.scrollToLatest')\"\n :text=\"false\"\n raised\n size=\"large\"\n :tabindex=\"visible ? undefined : -1\"\n @click=\"emit('click')\"\n />\n </div>\n <Badge\n v-if=\"visible && unseen > 0\"\n dir=\"ltr\"\n :value=\"unseen > 99 ? '99+' : unseen\"\n class=\"pointer-events-none absolute! -top-2 right-3\"\n />\n </div>\n</template>\n","import { ref, computed, onScopeDispose, type ComputedRef } from \"vue\";\nimport type { Message, ExtendedMessage } from \"~/types\";\nimport { useMessagesStore } from \"~/stores/messageStores\";\nimport { useChatStore } from \"~/stores/chatStore\";\nimport { useProfileStore } from \"~/stores/profileStore\";\n\nexport function useChatMessageList(chatId: ComputedRef<string | null>) {\n const messagesStore = useMessagesStore();\n const chatStore = useChatStore();\n\n const profileStore = useProfileStore();\n const currentUserId = computed(() => profileStore.userId);\n\n const messages = computed<Message[]>(\n () => messagesStore.messagesMap[chatId.value ?? \"\"] ?? [],\n );\n const isLoading = computed(\n () => !!messagesStore.messagesLoadingMap[chatId.value ?? \"\"],\n );\n\n // --- Enrichment ---\n // Any change to a thread (a new message, an id swap, a read flag) re-runs this computed. Handing\n // back the previous enriched object whenever its inputs are unchanged keeps every other bubble's\n // `message` prop identical, so only the bubbles that actually changed re-render.\n const enrichedCache = new WeakMap<Message, ExtendedMessage>();\n\n const reversedMessages = computed<ExtendedMessage[]>(() => {\n const raw = messages.value;\n // Contacts are keyed by conversation, and in a 1:1 chat that contact is the counterpart.\n const contact = chatStore.getContactById(chatId.value ?? \"\");\n const enriched = new Array<ExtendedMessage>(raw.length);\n\n for (let idx = 0; idx < raw.length; idx++) {\n const msg = raw[idx]!;\n const prev = raw[idx - 1];\n const next = raw[idx + 1];\n\n const cached = enrichedCache.get(msg);\n if (\n cached &&\n cached.prevMessage === prev &&\n cached.nextMessage === next &&\n cached.contact === contact\n ) {\n enriched[raw.length - 1 - idx] = cached;\n continue;\n }\n\n const isFirstInDate =\n !prev ||\n new Date(msg.date).toDateString() !==\n new Date(prev.date).toDateString();\n\n const value: ExtendedMessage = {\n ...msg,\n prevMessage: prev,\n nextMessage: next,\n isFirstInDate,\n contact: contact ?? undefined,\n };\n enrichedCache.set(msg, value);\n enriched[raw.length - 1 - idx] = value;\n }\n return enriched;\n });\n\n const firstUnreadId = computed(() => {\n const unreadMsg = messages.value.find(\n (m) => !m.isRead && m.senderId !== currentUserId.value,\n );\n return unreadMsg ? unreadMsg.id : null;\n });\n\n // --- Fetching ---\n const fetchMessages = async (page: number) => {\n const id = chatId.value;\n if (!id || messagesStore.messagesLoadingMap[id]) return;\n if (page > 1 && !messagesStore.messagesHasNextPage[id]) return;\n await messagesStore.fetchMessages(id, page);\n };\n\n const loadNextPage = () => {\n const id = chatId.value;\n if (!id) return;\n const nextPage = (messagesStore.messagesPage[id] ?? 0) + 1;\n fetchMessages(nextPage);\n };\n\n // --- Animations & Mutations ---\n const animatingIds = ref<Set<string>>(new Set());\n const deletingIds = ref<Set<string>>(new Set());\n\n const addMessages = (newMsgs: Message[]) => {\n if (!newMsgs || newMsgs.length === 0) return;\n const hasMyMessage = newMsgs.some(\n (msg) => msg.senderId === currentUserId.value,\n );\n\n newMsgs.forEach((msg) => animatingIds.value.add(msg.id));\n setTimeout(() => {\n newMsgs.forEach((msg) => animatingIds.value.delete(msg.id));\n }, 400);\n\n // Each message goes to its own conversation, not whichever one is open.\n for (const msg of newMsgs) {\n const id = msg.conversationId;\n messagesStore.messagesMap[id] = [\n ...(messagesStore.messagesMap[id] ?? []),\n msg,\n ];\n }\n\n return hasMyMessage; // Return boolean so component knows whether to scroll down\n };\n\n const executeDelete = (idsToDelete: string[], onDone: () => void) => {\n // Captured now: the user may switch conversation during the animation.\n const id = chatId.value;\n setTimeout(() => {\n idsToDelete.forEach((id) => deletingIds.value.add(id));\n\n setTimeout(() => {\n idsToDelete.forEach((id) => deletingIds.value.delete(id));\n if (id) {\n const remainingMessages = (\n messagesStore.messagesMap[id] ?? []\n ).filter((m) => !idsToDelete.includes(m.id));\n messagesStore.messagesMap[id] = remainingMessages;\n\n const newLastMessage =\n remainingMessages.length > 0\n ? remainingMessages[remainingMessages.length - 1]\n : null;\n\n if (newLastMessage) {\n messagesStore.updateLastMessage(id, newLastMessage);\n } else {\n messagesStore.patchLastMessage(id, \"-1\", {\n text: \"\",\n date: new Date().toISOString(),\n } as unknown as Message);\n }\n }\n messagesStore.clearActions();\n onDone();\n }, 300);\n }, 300);\n };\n\n // --- Event Bus Subscriptions ---\n let unsubSend: () => void;\n let unsubDelete: () => void;\n\n const subscribeToBus = (callbacks: {\n onSend: (hasMyMessage: boolean) => void;\n onDelete: (ids: string[]) => void;\n }) => {\n unsubSend = messagesStore.sendBus.on((newMsgs) => {\n const hasMyMessage = addMessages(newMsgs);\n if (hasMyMessage) callbacks.onSend(true);\n });\n\n unsubDelete = messagesStore.deleteBus.on((ids) => callbacks.onDelete(ids));\n // Updates are applied by the store itself (`patchMessage`), keyed by conversation.\n };\n\n // Auto-unsubscribe when the component scope is destroyed\n onScopeDispose(() => {\n if (unsubSend) unsubSend();\n if (unsubDelete) unsubDelete();\n });\n\n return {\n messages,\n reversedMessages,\n firstUnreadId,\n isLoading,\n animatingIds,\n deletingIds,\n fetchMessages,\n loadNextPage,\n subscribeToBus,\n executeDelete,\n };\n}\n","import { ref, computed, type Ref } from \"vue\";\nimport { useVirtualizer } from \"@tanstack/vue-virtual\";\n\ninterface ScrollOptions {\n scrollContainer: Ref<HTMLElement | null>;\n isLoading: Ref<boolean>;\n isLocked: Ref<boolean>;\n onLoadMore: () => void;\n}\n\nexport function useFlippedVirtualScroll(options: ScrollOptions) {\n const {\n scrollContainer,\n isLoading,\n isLocked,\n onLoadMore,\n } = options;\n\n // --- Virtualizer Setup ---\n // Note: The actual `reversedMessages` and `count` will be injected via a setter\n // to avoid circular dependency issues in the main component.\n const itemCount = ref(0);\n const getItemKey = ref<(index: number) => string | number>(\n (index: number) => index,\n );\n\n const virtualizer = useVirtualizer(\n computed(() => ({\n count: itemCount.value,\n getScrollElement: () => scrollContainer.value,\n estimateSize: () => 80,\n overscan: 15,\n getItemKey: getItemKey.value,\n })),\n );\n\n // --- Scroll State ---\n const headerOpacity = ref(0);\n const scrollOffset = ref(0);\n const topVisibleMessageIndex = ref(0);\n const targetScroll = ref(0);\n let scrollTimer: ReturnType<typeof setTimeout> | null = null;\n let animationFrame: number | null = null;\n\n // The list is flipped: the newest message is at scrollTop 0 (drawn at the bottom of the screen),\n // so \"away from newest\" is scrollTop itself.\n const canScroll = computed(() => scrollOffset.value > 100);\n\n // --- Scroll Handlers ---\n const handleScroll = () => {\n if (isLocked.value) return;\n const el = scrollContainer.value;\n if (!el) return;\n\n scrollOffset.value = el.scrollTop;\n\n // Floating Header Logic\n headerOpacity.value = 1;\n if (scrollTimer) clearTimeout(scrollTimer);\n scrollTimer = setTimeout(() => {\n headerOpacity.value = 0;\n }, 3000);\n\n // Infinite Scroll Trigger (In flipped list, high scrollTop = older messages = top of screen)\n const distanceToTop = el.scrollHeight - el.scrollTop - el.clientHeight;\n if (distanceToTop < 100 && !isLoading.value && itemCount.value > 0) {\n onLoadMore();\n }\n\n // Track Top Visible Message for Floating Header\n const items = virtualizer.value.getVirtualItems();\n if (items.length > 0) {\n const targetOffset = 44;\n const physicalTopOfViewport =\n el.scrollHeight - el.clientHeight - el.scrollTop;\n const targetPhysicalTop = physicalTopOfViewport + targetOffset;\n\n let closestIndex = items[0].index;\n let minDiff = Infinity;\n\n for (const item of items) {\n const diff = Math.abs(item.start - targetPhysicalTop);\n if (diff < minDiff) {\n minDiff = diff;\n closestIndex = item.index;\n }\n }\n topVisibleMessageIndex.value = closestIndex;\n }\n };\n\n const handleWheel = (e: WheelEvent) => {\n if (isLocked.value || !scrollContainer.value || itemCount.value === 0)\n return;\n\n // Start from where the list actually is, not a target left over from an earlier wheel or a\n // touch/keyboard scroll the loop never saw.\n if (!animationFrame) targetScroll.value = scrollContainer.value.scrollTop;\n\n // In a flipped list, positive deltaY raises scrollTop, towards older messages.\n targetScroll.value += e.deltaY;\n\n const maxScroll =\n scrollContainer.value.scrollHeight - scrollContainer.value.clientHeight;\n targetScroll.value = Math.max(0, Math.min(targetScroll.value, maxScroll));\n\n if (!animationFrame) smoothScrollLoop();\n };\n\n const smoothScrollLoop = () => {\n if (!scrollContainer.value) return;\n const current = scrollContainer.value.scrollTop;\n const target = targetScroll.value;\n const distance = (target - current) * 0.22;\n\n if (Math.abs(distance) > 0.5) {\n scrollContainer.value.scrollTop += distance;\n animationFrame = requestAnimationFrame(smoothScrollLoop);\n } else {\n scrollContainer.value.scrollTop = target;\n animationFrame = null;\n }\n };\n\n const resetScroll = () => {\n const el = scrollContainer.value;\n if (!el) return;\n // Let the virtualizer drive the jump. A plain el.scrollTo is cancelled the moment a newly\n // measured row makes the virtualizer shift scrollTop to hold the viewport, stalling short of\n // the newest message; during its own smooth scroll it skips those shifts and keeps going.\n if (animationFrame) cancelAnimationFrame(animationFrame);\n animationFrame = null;\n targetScroll.value = 0;\n virtualizer.value.scrollToOffset(0, { behavior: \"smooth\" });\n };\n\n /** Jumps to a distance from the newest message, e.g. where the user left a conversation. */\n const jumpTo = (offset: number) => {\n if (animationFrame) cancelAnimationFrame(animationFrame);\n animationFrame = null;\n targetScroll.value = offset;\n scrollOffset.value = offset;\n virtualizer.value.scrollToOffset(offset);\n };\n\n const cleanup = () => {\n if (animationFrame) cancelAnimationFrame(animationFrame);\n if (scrollTimer) clearTimeout(scrollTimer);\n };\n\n return {\n virtualizer,\n headerOpacity,\n canScroll,\n topVisibleMessageIndex,\n handleScroll,\n handleWheel,\n resetScroll,\n jumpTo,\n cleanup,\n // Exposed to allow component to pass dynamic data without circular refs\n setItemCount: (count: number) => {\n itemCount.value = count;\n },\n setGetItemKey: (fn: (index: number) => string | number) => {\n getItemKey.value = fn;\n },\n };\n}\n","<template>\n <div v-if=\"contact\" :dir=\"dir\" class=\"vue-chat relative w-full h-full overflow-hidden\">\n <FloatingDateHeader\n :label=\"floatingHeader\"\n :opacity=\"scroll.headerOpacity.value\"\n />\n\n <!-- Flipped Scroll Container -->\n <div\n id=\"list\"\n ref=\"scrollContainer\"\n class=\"h-full w-full max-w-dvw overflow-x-hidden overflow-y-auto pt-4 pb-4 chat-scrollbar flip-vertical bg-chat-surface/30\"\n :class=\"{ 'overflow-hidden': lockScroll }\"\n @scroll=\"scroll.handleScroll\"\n @wheel.prevent=\"scroll.handleWheel\"\n >\n <!-- Never hidden, even while the thread is empty: an empty list is already 0px tall. Rows\n are measured the moment they mount, before a v-show here would reveal them, so a hidden\n wrapper measured a first page arriving into an open conversation as all 0px. The\n virtualizer then read every row's real height as growth above the viewport and moved\n its offset to the oldest end while scrollTop stayed at 0, leaving the newest messages\n unrendered until the next scroll. -->\n <div class=\"w-full max-w-dvw overflow-x-hidden\">\n <div\n :style=\"{\n height: scroll.virtualizer.value.getTotalSize() + 'px',\n width: '100%',\n position: 'relative',\n }\"\n >\n <div\n v-for=\"{ row, message } in virtualRows\"\n :key=\"message.id\"\n :data-index=\"row.index\"\n :ref=\"\n (el) => el && scroll.virtualizer.value.measureElement(el as any)\n \"\n :style=\"{\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%',\n transform: `translateY(${row.start}px)`,\n }\"\n >\n <div\n class=\"flip-vertical pt-0\"\n :class=\"[row.index === 0 ? 'pb-2' : '', enterAnimation(message)]\"\n >\n <ChatBubble\n :is-deleting=\"msgList.deletingIds.value.has(message.id)\"\n :is-first-unread=\"message.id === msgList.firstUnreadId.value\"\n :message=\"message\"\n :contact=\"contact\"\n />\n </div>\n </div>\n </div>\n\n <!-- Older messages on their way in, above the ones already shown. The first page has the\n full-height skeleton below instead. -->\n <div\n v-show=\"msgList.isLoading.value && msgList.messages.value.length\"\n class=\"w-full shrink-0 flip-vertical\"\n >\n <MessagesSkeleton :count=\"2\" />\n </div>\n </div>\n\n <!-- Empty States -->\n <div\n v-show=\"msgList.messages.value.length === 0 && !msgList.isLoading.value\"\n class=\"h-full flex items-center justify-center text-chat-muted text-body-md flip-vertical\"\n >\n <NoDataDisplay :title=\"t('noMessages')\" :image-path=\"NoMessages\" />\n </div>\n\n <div\n v-show=\"msgList.messages.value.length === 0 && msgList.isLoading.value\"\n class=\"w-full flex h-full flip-vertical items-end\"\n >\n <MessagesSkeleton />\n </div>\n\n <div\n class=\"transition-all duration-200 ease-in-out pointer-events-none\"\n :class=\"[scroll.canScroll.value ? 'h-16' : 'h-0']\"\n ></div>\n </div>\n\n <div\n class=\"absolute pointer-events-none bottom-0 right-0 w-full transition-all duration-300 ease-in-out\"\n @click.self.stop\n >\n <ScrollToBottomButton\n :visible=\"scroll.canScroll.value\"\n :unseen=\"newWhileScrolledUp\"\n @click=\"scroll.resetScroll()\"\n />\n </div>\n </div>\n\n <ConfirmModal ref=\"modal\" @action=\"handleModalConfirm\" />\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick, onBeforeUnmount } from \"vue\";\nimport { useDocumentVisibility } from \"@vueuse/core\";\nimport ConfirmModal from \"~/components/general/ConfirmModal.vue\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { chat, chatMessages } from \"@i18n/locales\";\nimport { useAppToast } from \"~/composables/useAppToast\";\nimport ChatBubble from \"./ChatBubble.vue\";\nimport MessagesSkeleton from \"./messages/MessagesSkeleton.vue\";\nimport FloatingDateHeader from \"./messages/FloatingDateHeader.vue\";\nimport ScrollToBottomButton from \"./messages/ScrollToBottomButton.vue\";\nimport type { Contact, ExtendedMessage } from \"~/types\";\nimport NoDataDisplay from \"../general/NoDataDisplay.vue\";\nimport NoMessages from \"~/assets/lib-images/chat/empty-state.webp\";\nimport type { Modal } from \"~/types/components/modal\";\nimport { useMessagesStore } from \"~/stores/messageStores\";\nimport { useChatStore } from \"~/stores/chatStore\";\nimport { useDate } from \"~/composables/useDate\";\nimport { useChatMessageList } from \"~/composables/useChatMessageList.js\";\nimport { useFlippedVirtualScroll } from \"~/composables/useFlippedVirtualScroll.js\";\nimport { useProfileStore } from \"~/stores/profileStore.js\";\n\nwithDefaults(defineProps<{ contact: Contact | null }>(), { contact: null });\n\nconst modal = ref<Modal | null>(null);\nconst chatStore = useChatStore();\nconst messagesStore = useMessagesStore();\n// One call: a component gets a single local scope, so a second useLocalI18n() would return the\n// first one's messages.\nconst { t } = useLocalI18n(chatMessages, chat);\nconst { dir } = useDirection();\nconst { openToast } = useAppToast();\nconst { formatDateShort } = useDate();\nconst profileStore = useProfileStore();\nconst currentUserId = computed(() => profileStore.userId);\n\nconst chatId = computed(() => chatStore.activeConversationId);\nconst lockScroll = computed(() => messagesStore.isOptionMenuOpen);\nconst scrollContainer = ref<HTMLElement | null>(null);\nconst selectedToDelete = ref<string[]>([]);\n\n// --- Initialize Composables ---\n\n// 1. Message List State\nconst msgList = useChatMessageList(chatId);\n\n// 2. Scroll Mechanics (Depends on msgList for loadMore and count updates)\nconst scroll = useFlippedVirtualScroll({\n scrollContainer,\n isLoading: msgList.isLoading,\n isLocked: lockScroll,\n onLoadMore: msgList.loadNextPage,\n});\n\n// Each rendered row paired with its message, so the template looks it up once.\nconst virtualRows = computed(() =>\n scroll.virtualizer.value\n .getVirtualItems()\n .map((row) => ({ row, message: msgList.reversedMessages.value[row.index]! }))\n .filter(({ message }) => !!message),\n);\n\nconst enterAnimation = (message: ExtendedMessage) => {\n if (!msgList.animatingIds.value.has(message.id)) return \"\";\n if (message.request) return \"animate-request-in\";\n return message.senderId === currentUserId.value\n ? \"animate-slide-right\"\n : \"animate-slide-left\";\n};\n\n// Keep Virtualizer count in sync with messages\nwatch(\n () => msgList.reversedMessages.value.length,\n (len) => {\n scroll.setItemCount(len);\n scroll.setGetItemKey(\n (index: number) => msgList.reversedMessages.value[index]?.id ?? index,\n );\n },\n { immediate: true },\n);\n\n// Messages from the other side that arrived while the user was reading history, shown on the\n// scroll-to-bottom button. Keyed off the newest message so older pages loading in don't count.\nconst newWhileScrolledUp = ref(0);\nwatch(\n () => msgList.messages.value.at(-1),\n (last, prev) => {\n if (!last || !prev || last.id === prev.id) return;\n if (last.conversationId !== prev.conversationId) return;\n if (scroll.canScroll.value && last.senderId !== currentUserId.value)\n newWhileScrolledUp.value++;\n },\n);\nwatch(scroll.canScroll, (away) => {\n if (!away) newWhileScrolledUp.value = 0;\n});\nwatch(chatId, () => (newWhileScrolledUp.value = 0));\n\n// --- Event Bus Wiring ---\nmsgList.subscribeToBus({\n onSend: (hasMyMessage) => {\n if (hasMyMessage) nextTick(() => scroll.resetScroll());\n },\n onDelete: (ids) => handleDeleteMessages(ids),\n});\n\n// --- Modal / Delete Actions (UI specific logic stays in component) ---\nconst handleDeleteMessages = (idsToDelete: string[]) => {\n selectedToDelete.value = idsToDelete;\n const isRequestDeletion =\n idsToDelete.length === 1 &&\n msgList.messages.value.find((m) => m.id === idsToDelete[0])?.request;\n\n modal.value?.openModal(\n isRequestDeletion ? t(\"delete.requestTitle\") : t(\"delete.title\"),\n isRequestDeletion\n ? t(\"delete.request\")\n : idsToDelete.length === 1\n ? t(\"delete.singleMessage\")\n : t(\"delete.multipleMessages\", { count: idsToDelete.length }),\n \"error\",\n true,\n t(\"delete.confirm\"),\n );\n};\n\nconst handleModalConfirm = () => {\n if (selectedToDelete.value.length > 0) {\n modal.value?.closeModal();\n const ids = [...selectedToDelete.value];\n const conversationId = chatId.value;\n const snapshot = msgList.messages.value.filter((m) => ids.includes(m.id));\n\n // Removal is optimistic; if the server refuses, wait for the animation to finish removing\n // them and then put them back, so the thread never shows messages that still exist as gone.\n const removed = new Promise<void>((resolve) =>\n msgList.executeDelete(ids, () => {\n selectedToDelete.value = [];\n resolve();\n }),\n );\n messagesStore.confirmDelete(ids).catch(async () => {\n await removed;\n if (conversationId) messagesStore.restoreMessages(conversationId, snapshot);\n openToast(t(\"chat.deleteFailed\"), \"error\");\n });\n }\n};\n\n// --- Floating Header Text ---\nconst floatingHeader = computed(() => {\n const msg =\n msgList.reversedMessages.value[scroll.topVisibleMessageIndex.value];\n if (!msg) return null;\n if (msg.id === msgList.firstUnreadId.value) return t(\"unreadMessages\");\n return formatDateShort(msg.date);\n});\n\n// --- Lifecycle ---\nonMounted(() => {\n shownId = chatId.value;\n if (chatId.value) {\n // On phones the pane is rebuilt each time a conversation opens from the list.\n const offset = offsetToRestore(chatId.value);\n if (offset) nextTick(() => scroll.jumpTo(offset));\n messagesStore.markAsRead(chatId.value);\n msgList.fetchMessages(1);\n }\n});\n\nonBeforeUnmount(() => {\n // The selection is already cleared by now (back to the list on phones), so save under the\n // conversation this pane last showed.\n if (shownId && scrollContainer.value)\n messagesStore.scrollPositions.set(shownId, scrollContainer.value.scrollTop);\n scroll.cleanup();\n});\n\n// The conversation on screen, which `chatId` may already have moved off when the pane unmounts.\nlet shownId: string | null = null;\n\n// The thread stays loaded when the user switches away, so coming back to it picks up where they\n// left it rather than at the bottom. Unless something new came in: that is what they came for.\n// Read before `markAsRead`, which clears the unread count.\nconst offsetToRestore = (id: string) => {\n const hasUnread = (chatStore.getContactById(id)?.unreadCount ?? 0) > 0;\n if (hasUnread || !msgList.messages.value.length) return 0;\n return messagesStore.scrollPositions.get(id) ?? 0;\n};\n\nwatch(\n () => chatId.value,\n (newId, oldId) => {\n // A pre-flush watcher: the container still shows the conversation being left.\n if (oldId && scrollContainer.value)\n messagesStore.scrollPositions.set(oldId, scrollContainer.value.scrollTop);\n shownId = newId;\n if (newId && newId !== oldId) {\n const offset = offsetToRestore(newId);\n messagesStore.markAsRead(newId);\n if (scrollContainer.value) scrollContainer.value.scrollTop = 0;\n if (offset) nextTick(() => scroll.jumpTo(offset));\n msgList.fetchMessages(1);\n }\n },\n);\n\n// A message from someone else that lands while this conversation is on screen has been read, and\n// so has whatever arrived while the tab was in the background, once it is back. Opening the\n// conversation is covered above, before its messages have loaded; this also catches the first\n// page landing, so the host hears about the newest message rather than only the list preview.\nconst visibility = useDocumentVisibility();\nconst newestIncoming = computed(() => {\n const last = msgList.messages.value.at(-1);\n return last && last.senderId !== currentUserId.value && !last.id.startsWith(\"tmp-\")\n ? last.id\n : null;\n});\nwatch([newestIncoming, visibility], ([id, state]) => {\n if (id && state === \"visible\" && chatId.value) messagesStore.markAsRead(chatId.value);\n});\n</script>\n\n<style scoped>\n/* Styles remain exactly the same */\n.flip-vertical {\n transform: scaleY(-1);\n will-change: transform;\n}\n[data-index] {\n will-change: transform;\n backface-visibility: hidden;\n}\n\n@keyframes slide-in-right {\n 0% {\n opacity: 0;\n transform: scaleY(-1) translateX(30px);\n }\n 100% {\n opacity: 1;\n transform: scaleY(-1) translateX(0);\n }\n}\n@keyframes slide-in-left {\n 0% {\n opacity: 0;\n transform: scaleY(-1) translateX(-30px);\n }\n 100% {\n opacity: 1;\n transform: scaleY(-1) translateX(0);\n }\n}\n.animate-slide-right {\n animation: slide-in-right 300ms ease-out forwards;\n will-change: transform, opacity;\n}\n.animate-slide-left {\n animation: slide-in-left 300ms ease-out forwards;\n will-change: transform, opacity;\n}\n#list {\n will-change: padding-top;\n}\n\n.animate-request-in {\n animation: request-in 0.4s ease-out forwards;\n overflow: hidden;\n transform: scaleY(-1);\n}\n@keyframes request-in {\n 0% {\n opacity: 0;\n max-height: 0;\n transform: scaleY(-1) translateY(10px);\n }\n 100% {\n opacity: 1;\n max-height: 1000px;\n transform: scaleY(-1) translateY(0);\n }\n}\n</style>\n","<template>\n <div :dir=\"dir\" class=\"vue-chat relative z-20 w-full\">\n <!-- A size container (`chat-header`): the header folds by its own width, not the screen's, since\n the list, the contact panel and a host's sidebar all take from it. -->\n <header\n v-if=\"selectedChat\"\n ref=\"header\"\n class=\"@container/chat-header relative z-50 flex h-16 w-full items-center gap-x-2 border-b border-b-chat-outline-variant bg-chat-background px-3 md:h-20 md:gap-x-3 md:px-5\"\n >\n <!-- At the start and pointing back, mirrored for right-to-left. -->\n <IconButton\n icon=\"PhArrowLeft\"\n icon-class=\"size-6 rtl:-scale-x-100\"\n :label=\"t('actions.back')\"\n class=\"shrink-0 md:hidden!\"\n @click=\"goBack\"\n />\n\n <!-- Who the conversation is with; opens their contact info. -->\n <Button\n unstyled\n data-testid=\"chat-header-contact\"\n :aria-label=\"t('contactInfo', { name: fullName })\"\n class=\"flex min-w-0 flex-1 cursor-pointer items-center gap-x-3 rounded-xl p-1.5 text-start transition-colors hover:bg-chat-surface/60 focus-visible:outline-2 focus-visible:outline-chat-primary motion-reduce:transition-none\"\n @click=\"openProfile\"\n >\n <span class=\"relative block size-10 shrink-0 md:size-11\">\n <ContactAvatar v-if=\"contact\" :contact=\"contact\" />\n </span>\n <span class=\"flex min-w-0 flex-col select-none\">\n <span class=\"truncate text-label-md font-semibold text-chat-on-background\">\n {{ fullName }}\n </span>\n <span class=\"flex min-w-0 items-center gap-x-1.5 text-body-sm\">\n <span\n v-if=\"selectedChat.isOnline\"\n data-testid=\"chat-header-status\"\n class=\"shrink-0 font-medium text-chat-primary\"\n >\n {{ t(\"online\") }}\n </span>\n <span\n v-else-if=\"selectedChat.lastSeen\"\n data-testid=\"chat-header-status\"\n class=\"min-w-0 truncate text-chat-muted\"\n >\n {{ t(\"lastSeen\", { time: formatRelativeDate(selectedChat.lastSeen) }) }}\n </span>\n <template v-if=\"selectedChat.tag\">\n <span aria-hidden=\"true\" class=\"shrink-0 text-chat-muted\">·</span>\n <span class=\"min-w-0 truncate text-chat-muted\">{{ selectedChat.tag }}</span>\n </template>\n </span>\n </span>\n </Button>\n\n <div\n class=\"flex shrink-0 items-center gap-x-1 transition-transform duration-200 ease-in-out motion-reduce:transition-none md:gap-x-2\"\n :class=\"[isSelectMode ? 'invisible' : 'visible']\"\n >\n <!-- Host actions for the open conversation, before the calls. When the header is narrow\n (`compact`) a host can list them in the menu instead, through `hostOptions`. -->\n <slot name=\"actions\" :contact=\"selectedChat\" :compact=\"compact\" />\n\n <span\n v-if=\"$slots.actions && !compact && (canVoiceCall || canVideoCall)\"\n aria-hidden=\"true\"\n class=\"mx-1 h-6 w-px shrink-0 bg-chat-outline-variant\"\n />\n\n <!-- Others are in a call here: joining it replaces starting one. -->\n <Button\n v-if=\"canJoin\"\n rounded\n severity=\"success\"\n size=\"small\"\n :aria-label=\"joinVideo ? t('joinVideoCall') : t('joinVoiceCall')\"\n data-testid=\"chat-join-call\"\n class=\"min-h-10 shrink-0 gap-x-2! px-3.5!\"\n @click=\"initCall(joinVideo)\"\n >\n <span aria-hidden=\"true\" class=\"relative flex size-2\">\n <span\n class=\"absolute inset-0 animate-ping rounded-full bg-current opacity-75 motion-reduce:animate-none\"\n />\n <span class=\"relative size-2 rounded-full bg-current\" />\n </span>\n <BIcon :icon=\"joinVideo ? 'PhVideoCamera' : 'PhPhone'\" weight=\"fill\" class=\"size-4.5\" />\n <span class=\"text-label-md font-semibold\">{{ t(\"join\") }}</span>\n </Button>\n\n <!-- During a call either button brings the running call back into view. -->\n <IconButton\n v-else-if=\"canVoiceCall\"\n icon=\"PhPhone\"\n icon-class=\"size-5.5\"\n :label=\"isInCall ? t('actions.returnToCall') : t('actions.call')\"\n :data-testid=\"canVideoCall ? 'chat-start-voice-call' : 'chat-start-call'\"\n @click=\"initCall(false)\"\n />\n <!-- When narrow the voice call keeps its button and the video call moves into the menu. -->\n <IconButton\n v-if=\"canVideoCall && !canJoin && !compact\"\n icon=\"PhVideoCamera\"\n icon-class=\"size-5.5\"\n :label=\"isInCall ? t('actions.returnToCall') : t('videoCall')\"\n data-testid=\"chat-start-call\"\n @click=\"initCall(true)\"\n />\n <IconButton\n icon=\"PhSidebarSimple\"\n icon-class=\"size-5.5 ltr:-scale-x-100\"\n :label=\"t('toggleInfo')\"\n :aria-pressed=\"isProfileOpen\"\n data-testid=\"chat-toggle-info\"\n class=\"hidden! md:inline-flex!\"\n :class=\"isProfileOpen && 'bg-chat-primary/10! text-chat-primary!'\"\n @click=\"toggleProfile\"\n />\n <IconButton\n v-if=\"menuItems.length\"\n icon=\"PhDotsThreeVertical\"\n icon-class=\"size-5.5\"\n :label=\"t('actions.moreOptions')\"\n aria-haspopup=\"menu\"\n :aria-expanded=\"menuOpen\"\n data-testid=\"chat-more-options\"\n :class=\"menuOpen && 'bg-chat-primary/10! text-chat-primary!'\"\n @click=\"optionsMenuRef?.toggle($event)\"\n />\n <!-- A card like the message menu: rows a thumb can hit, each led by a tinted icon chip. -->\n <Menu\n ref=\"optionsMenu\"\n :model=\"menuItems\"\n popup\n :dir=\"dir\"\n :pt=\"menuPt\"\n class=\"vue-chat\"\n data-testid=\"chat-more-menu\"\n @show=\"menuOpen = true\"\n @hide=\"menuOpen = false\"\n >\n <template #item=\"{ item, props: itemProps }\">\n <a\n v-bind=\"itemProps.action\"\n :data-testid=\"`chat-menu-${item.key}`\"\n class=\"flex min-h-11 cursor-pointer items-center gap-x-3 px-2 py-1.5\"\n >\n <span\n aria-hidden=\"true\"\n class=\"flex size-8 shrink-0 items-center justify-center rounded-full\"\n :class=\"chipClass(item)\"\n >\n <BIcon\n v-if=\"typeof item.phIcon === 'string'\"\n :icon=\"item.phIcon\"\n class=\"size-4.5\"\n />\n <component :is=\"item.phIcon\" v-else-if=\"item.phIcon\" class=\"size-4.5\" />\n </span>\n <span\n class=\"min-w-0 flex-1 truncate text-label-md\"\n :class=\"item.danger ? 'text-chat-error' : 'text-chat-on-background'\"\n >\n {{ item.label }}\n </span>\n </a>\n </template>\n </Menu>\n </div>\n </header>\n\n <!-- A conversation is open but its contact is still being fetched (e.g. a deep link). -->\n <div\n v-else-if=\"currentConversationId\"\n class=\"relative z-50 flex h-16 w-full items-center gap-x-3 border-b border-b-chat-outline-variant bg-chat-background px-5 md:h-20\"\n >\n <Skeleton shape=\"circle\" size=\"2.75rem\" class=\"shrink-0\" />\n <div class=\"flex flex-col gap-y-2\">\n <Skeleton width=\"8rem\" height=\"0.875rem\" />\n <Skeleton width=\"5rem\" height=\"0.625rem\" />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport Button from \"primevue/button\";\nimport Menu from \"primevue/menu\";\nimport Skeleton from \"primevue/skeleton\";\nimport type { MenuItem } from \"primevue/menuitem\";\nimport type { MenuOption } from \"~/types/components/menu-options\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport BIcon from \"~/components/global/BIcon.vue\";\nimport { useMessagesStore } from \"~/stores/messageStores.js\";\nimport ContactAvatar from \"./contact/ContactAvatar.vue\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { useCallStore } from \"~/stores/callStore.js\";\nimport { useChatStore } from \"~/stores/chatStore.js\";\nimport { useDate } from \"~/composables/useDate.js\";\nimport { chatPageBar } from \"@i18n/locales\";\nimport type { Contact } from \"~/types\";\nimport { computed, ref, useTemplateRef } from \"vue\";\nimport { useElementSize } from \"@vueuse/core\";\n\nconst props = withDefaults(\n defineProps<{\n contact: Contact | null;\n /** Actions for the open conversation, listed in the header's \"more options\" menu. */\n options: MenuOption[];\n /** The host's actions as menu items, listed before `options` while the header is compact. */\n hostOptions?: MenuOption[];\n }>(),\n {\n contact: null,\n options: () => [],\n hostOptions: () => [],\n },\n);\n\nconst emit = defineEmits<{\n call: [];\n \"open-profile\": [];\n select: [key: string];\n}>();\n\nconst optionsMenuRef = useTemplateRef<InstanceType<typeof Menu>>(\"optionsMenu\");\n\n// Below this the header cannot fit a host's actions beside the calls and the contact's name.\nconst COMPACT_BELOW = 640;\nconst headerRef = useTemplateRef<HTMLElement>(\"header\");\nconst { width: headerWidth } = useElementSize(headerRef);\nconst compact = computed(() => headerWidth.value < COMPACT_BELOW);\n\nconst menuOpen = ref(false);\n\nconst menuPt = {\n root: {\n class:\n \"w-64! max-w-[calc(100vw-1.5rem)]! rounded-2xl! border-chat-outline-variant/60! bg-chat-background/95! p-1.5! shadow-xl! backdrop-blur-md!\",\n },\n list: { class: \"gap-y-0.5! p-0!\" },\n itemContent: { class: \"rounded-xl!\" },\n separator: { class: \"mx-2! my-1! border-chat-outline-variant/70!\" },\n // Drops out of the button, which sits at the header's end.\n transition: {\n enterFromClass: \"opacity-0 scale-95\",\n enterActiveClass:\n \"transition duration-150 ease-out origin-top-right rtl:origin-top-left motion-reduce:transition-none\",\n leaveActiveClass: \"transition-opacity duration-100 ease-in motion-reduce:transition-none\",\n leaveToClass: \"opacity-0\",\n },\n};\n\n// The call is the one primary action in the menu, ending the chat the one destructive one.\nconst chipClass = (item: MenuItem) =>\n item.danger\n ? \"bg-chat-error/10 text-chat-error\"\n : item.accent\n ? \"bg-chat-primary/12 text-chat-primary\"\n : \"bg-chat-surface text-chat-on-surface\";\n\nconst toItem = (option: MenuOption): MenuItem => ({\n key: option.key,\n label: option.label,\n phIcon: option.icon,\n accent: option.color === \"primary\",\n danger: option.color === \"error\",\n disabled: option.disabled,\n command: () => (option.command ? option.command() : emit(\"select\", option.key)),\n});\n\n// When compact the menu takes what the header has no room for, in groups set off by a line: the\n// video call, the host's actions, then the conversation's own, so ending it comes last.\nconst menuItems = computed<MenuItem[]>(() => {\n if (!compact.value) return props.options.map(toItem);\n const video: MenuOption[] =\n canVideoCall.value && !canJoin.value\n ? [\n {\n key: \"video-call\",\n label: isInCall.value ? t(\"actions.returnToCall\") : t(\"videoCall\"),\n icon: \"PhVideoCamera\",\n color: \"primary\",\n command: () => initCall(true),\n },\n ]\n : [];\n return [video, props.hostOptions, props.options]\n .filter((group) => group.length)\n .flatMap((group, index) => [...(index ? [{ separator: true }] : []), ...group.map(toItem)]);\n});\n\nconst messagesStore = useMessagesStore();\nconst { formatRelativeDate } = useDate();\nconst { t } = useLocalI18n(chatPageBar);\nconst { dir } = useDirection();\nconst callStore = useCallStore();\nconst chatStore = useChatStore();\n\nconst currentConversationId = computed(() => chatStore.activeConversationId);\nconst isSelectMode = computed(() => messagesStore.isSelectMode);\nconst isProfileOpen = computed(() => chatStore.profileViewOpen);\nconst isInCall = computed(() => callStore.isActive);\nconst selectedChat = computed(() => props.contact);\n\nconst fullName = computed(() =>\n `${selectedChat.value?.name ?? \"\"} ${selectedChat.value?.lastName ?? \"\"}`.trim(),\n);\n\n// An ended conversation takes no calls and a chat-only one none at all. A host that sets no\n// `serviceType` gets both, as the single call button it had before started a video call.\nconst canVoiceCall = computed(\n () => !!selectedChat.value?.isActive && selectedChat.value.serviceType !== \"chat\",\n);\nconst canVideoCall = computed(\n () => canVoiceCall.value && selectedChat.value?.serviceType !== \"voice-call\",\n);\n\n// A call others are in on this conversation. While the user is in a call themselves the buttons\n// keep bringing that one back instead.\nconst ongoingCall = computed(() => callStore.ongoingCall(currentConversationId.value));\nconst canJoin = computed(() => canVoiceCall.value && !isInCall.value && !!ongoingCall.value);\n// Joins the way the call was started, with the camera on only for a video call.\nconst joinVideo = computed(() => canVideoCall.value && !!ongoingCall.value?.video);\n\nconst openProfile = () => {\n emit(\"open-profile\");\n};\n\nconst toggleProfile = () => {\n if (isProfileOpen.value) chatStore.closeProfile();\n else openProfile();\n};\n\nconst goBack = () => {\n chatStore.setSelectedChat(null);\n};\n\nconst initCall = (video: boolean) => {\n if (currentConversationId.value) {\n callStore.startCall(currentConversationId.value, { video });\n }\n};\n</script>\n","<script setup lang=\"ts\">\nimport { defineAsyncComponent } from \"vue\";\nimport type { EmojiExt } from \"vue3-emoji-picker\";\n\n// Loaded when a picker first renders, not with the chat.\nconst EmojiPicker = defineAsyncComponent(async () => {\n const [picker] = await Promise.all([\n import(\"vue3-emoji-picker\"),\n import(\"vue3-emoji-picker/css\"),\n ]);\n return picker.default;\n});\n\nconst emit = defineEmits<{ select: [emoji: EmojiExt] }>();\n</script>\n\n<template>\n <EmojiPicker :native=\"true\" @select=\"(emoji: EmojiExt) => emit('select', emoji)\" />\n</template>\n\n<style>\n.v3-emoji-picker {\n height: 407px;\n width: 332px;\n}\n\n.v3-emoji-picker .v3-footer {\n display: none !important;\n}\n</style>\n","const { locale } = useI18n();\n\nconst formattedSize = computed(() =>\n replaceDigitsByLocale(formatBytes(props.file?.size || 0), locale.value),\n);<template>\n <div class=\"flex w-full items-center gap-x-3 select-none\">\n <div\n aria-hidden=\"true\"\n class=\"flex size-11 shrink-0 items-center justify-center rounded-xl bg-chat-primary/10 text-chat-primary\"\n >\n <span v-if=\"fileExt\" dir=\"ltr\" class=\"text-[11px] font-bold uppercase leading-none tracking-wide\">\n {{ fileExt }}\n </span>\n <BIcon v-else icon=\"PhFile\" class=\"size-5.5\" />\n </div>\n\n <div class=\"flex min-w-0 flex-1 flex-col gap-y-0.5 text-start\">\n <div :title=\"fileName\" class=\"truncate text-label-md text-chat-on-background\">\n <bdi>{{ fileName }}</bdi>\n </div>\n <div dir=\"ltr\" class=\"text-body-sm text-chat-muted rtl:text-end\">\n {{ formattedSize }}\n </div>\n </div>\n\n <IconButton\n icon=\"PhX\"\n :label=\"removeLabel\"\n icon-class=\"size-4.5\"\n class=\"size-9! shrink-0\"\n @click=\"emit('remove')\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from \"vue\";\nimport { useI18n } from \"vue-i18n\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport { formatBytes, replaceDigitsByLocale } from \"~/utils/format\";\n\ninterface AttachmentFile {\n name: string;\n size: number;\n format: string;\n path: string;\n}\n\nconst props = defineProps<{\n file: AttachmentFile;\n /** Accessible name of the remove button. */\n removeLabel: string;\n}>();\n\nconst emit = defineEmits<{ remove: [] }>();\n\n// Up to four letters fit the tile; without an extension it shows a file icon.\nconst fileExt = computed(() => {\n const name = props.file?.name ?? \"\";\n const lastDot = name.lastIndexOf(\".\");\n return lastDot > 0 ? name.slice(lastDot + 1, lastDot + 5) : \"\";\n});\n\nconst fileName = computed(() => props.file?.name || \"Unknown File\");\n\nconst { locale } = useI18n();\n\nconst formattedSize = computed(() =>\n replaceDigitsByLocale(formatBytes(props.file?.size || 0), locale.value),\n);\n</script>\n","import { useFileDialog } from \"@vueuse/core\";\n\nimport type { MediaItem } from \"~/types\";\n\nexport interface PickedMedia {\n file: File;\n path: string;\n kind: MediaItem[\"kind\"];\n}\n\nexport interface PickedFile {\n file: File;\n path: string;\n name: string;\n format: string;\n size: number;\n}\n\nconst UNSAFE_EXTENSIONS = [\".exe\", \".bat\", \".sh\", \".js\"];\n\nconst IMAGE_TYPES = [\"image/jpeg\", \"image/png\", \"image/webp\", \"image/gif\"];\nconst VIDEO_TYPES = [\"video/mp4\", \"video/webm\", \"video/quicktime\"];\nconst MEDIA_TYPES = [...IMAGE_TYPES, ...VIDEO_TYPES];\n\nconst TYPES_OF = { image: IMAGE_TYPES, video: VIDEO_TYPES, all: MEDIA_TYPES };\n\n/**\n * Opens the browser's file chooser for photos, videos or both, or files, and hands back object URLs.\n * Files it refuses are counted to `onRejected`, so the caller can say why they are missing.\n */\nexport function useAttachmentPicker(handlers: {\n onMedia: (media: PickedMedia[]) => void;\n onFiles: (files: PickedFile[]) => void;\n onRejected?: (count: number) => void;\n}) {\n const reportRejected = (all: File[], kept: File[]) => {\n if (all.length > kept.length) handlers.onRejected?.(all.length - kept.length);\n };\n\n // What the open media chooser asked for; anything else that comes back is refused.\n let mediaTypes = MEDIA_TYPES;\n const media = useFileDialog({\n multiple: true,\n accept: MEDIA_TYPES.join(\", \"),\n reset: true,\n });\n media.onChange((list) => {\n const all = Array.from(list ?? []);\n // The chooser's filter is only a hint; some platforms let anything through.\n const kept = all.filter((file) => mediaTypes.includes(file.type));\n reportRejected(all, kept);\n const picked = kept.map((file) => ({\n file,\n path: URL.createObjectURL(file),\n kind: file.type.startsWith(\"video/\") ? (\"video\" as const) : (\"image\" as const),\n }));\n if (picked.length) handlers.onMedia(picked);\n });\n\n const files = useFileDialog({ multiple: true, reset: true });\n files.onChange((list) => {\n const all = Array.from(list ?? []);\n const kept = all.filter(\n (file) => !UNSAFE_EXTENSIONS.some((ext) => file.name.toLowerCase().endsWith(ext)),\n );\n reportRejected(all, kept);\n const picked = kept.map((file) => ({\n file,\n name: file.name,\n path: URL.createObjectURL(file),\n format: file.type || file.name.split(\".\").pop() || \"\",\n size: file.size,\n }));\n if (picked.length) handlers.onFiles(picked);\n });\n\n // Must run inside the click handler: browsers only open a chooser on a user gesture.\n const pickMedia = (kind: MediaItem[\"kind\"] | \"all\" = \"all\") => {\n mediaTypes = TYPES_OF[kind];\n media.open({ accept: mediaTypes.join(\", \") });\n };\n\n return { pickMedia, pickFiles: () => files.open() };\n}\n","<template>\n <div>\n <IconButton\n icon=\"PhPaperclip\"\n :label=\"t('actions.attach')\"\n icon-class=\"size-6\"\n data-testid=\"chat-attach\"\n aria-haspopup=\"menu\"\n :aria-expanded=\"pickerOpen\"\n @click=\"togglePicker\"\n />\n <Popover\n ref=\"picker\"\n :dir=\"dir\"\n class=\"vue-chat\"\n :pt=\"{ content: { class: 'p-1.5!' } }\"\n @show=\"onPickerShow\"\n @hide=\"pickerOpen = false\"\n >\n <div\n ref=\"pickerList\"\n role=\"menu\"\n :aria-label=\"t('actions.attach')\"\n class=\"flex w-64 max-w-[calc(100vw-2rem)] flex-col gap-y-0.5\"\n data-testid=\"chat-attach-menu\"\n @keydown=\"onPickerKeydown\"\n >\n <Button\n v-for=\"option in pickerOptions\"\n :key=\"option.key\"\n role=\"menuitem\"\n text\n severity=\"secondary\"\n class=\"w-full justify-start! gap-x-3! rounded-xl! px-2! py-1.5! text-start\"\n :data-testid=\"`chat-attach-${option.key}`\"\n @click=\"choose(option)\"\n >\n <span\n aria-hidden=\"true\"\n class=\"flex size-10 shrink-0 items-center justify-center rounded-full\"\n :class=\"option.tint\"\n >\n <BIcon :icon=\"option.icon\" weight=\"fill\" class=\"size-5\" />\n </span>\n <span class=\"flex min-w-0 flex-1 flex-col gap-y-0.5\">\n <span class=\"text-label-md text-chat-on-background\">{{ option.label }}</span>\n <span class=\"truncate text-body-sm text-chat-muted\">{{ option.hint }}</span>\n </span>\n </Button>\n </div>\n </Popover>\n\n <ResponsiveDialog\n v-model:visible=\"dialogOpen\"\n :header=\"dialogTitle\"\n width=\"30rem\"\n data-testid=\"chat-attach-dialog\"\n @after-hide=\"discard\"\n >\n <div class=\"flex w-full flex-col gap-y-3\">\n <!-- What is about to go out, and room to add to it. -->\n <div class=\"flex min-h-9 items-center justify-between gap-x-3\">\n <span class=\"text-body-sm text-chat-muted\" aria-live=\"polite\">\n {{ summary.count }} ·\n <bdi dir=\"ltr\">{{ summary.size }}</bdi>\n </span>\n <Button\n v-if=\"canAddMore\"\n text\n size=\"small\"\n :label=\"t('file.addMore')\"\n class=\"shrink-0\"\n @click=\"addMore\"\n >\n <template #icon>\n <BIcon icon=\"PhPlus\" class=\"size-4\" />\n </template>\n </Button>\n </div>\n\n <div\n v-if=\"dialogMode === 'single-media' && selectedMedia[0]\"\n class=\"relative overflow-hidden rounded-xl bg-chat-surface\"\n >\n <MediaThumb\n :item=\"{ url: selectedMedia[0].path, kind: selectedMedia[0].kind }\"\n fit=\"contain\"\n class=\"h-72 max-h-[50dvh] w-full\"\n />\n <button\n type=\"button\"\n :class=\"[removeChip, 'end-2 top-2 size-9']\"\n :aria-label=\"t('file.remove', { name: selectedMedia[0].file.name })\"\n @click=\"removeMedia(0)\"\n >\n <BIcon icon=\"PhX\" weight=\"bold\" class=\"size-4\" />\n </button>\n </div>\n\n <ul\n v-else-if=\"dialogMode === 'multi-media'\"\n class=\"-m-1 grid max-h-[min(20rem,45dvh)] grid-cols-3 gap-2 overflow-y-auto p-1\"\n >\n <li\n v-for=\"(media, index) in selectedMedia\"\n :key=\"media.path\"\n class=\"relative aspect-square overflow-hidden rounded-lg bg-chat-surface\"\n >\n <MediaThumb\n :item=\"{ url: media.path, kind: media.kind }\"\n badge=\"sm\"\n class=\"size-full\"\n />\n <button\n type=\"button\"\n :class=\"[removeChip, 'end-1 top-1 size-8']\"\n :aria-label=\"t('file.remove', { name: media.file.name })\"\n @click=\"removeMedia(index)\"\n >\n <BIcon icon=\"PhX\" weight=\"bold\" class=\"size-3.5\" />\n </button>\n </li>\n </ul>\n\n <ul\n v-else\n class=\"max-h-[min(20rem,45dvh)] divide-y divide-chat-outline-variant overflow-y-auto rounded-xl border border-chat-outline-variant\"\n >\n <li v-for=\"(file, index) in selectedFiles\" :key=\"file.path\" class=\"py-2 ps-3 pe-1.5\">\n <AttachementFileDisplay\n :file=\"file\"\n :remove-label=\"t('file.remove', { name: file.name })\"\n @remove=\"removeFile(index)\"\n />\n </li>\n </ul>\n\n <!-- The chat bubble shows the compression, then the upload, once it is sent. -->\n <p\n v-if=\"dialogMode !== 'file' && videoCount > 0\"\n class=\"flex items-center gap-x-2 text-body-sm text-chat-muted\"\n data-testid=\"chat-attach-compress\"\n >\n <BIcon icon=\"PhFilmStrip\" class=\"size-4.5 shrink-0\" aria-hidden=\"true\" />\n {{ canCompress ? t(\"compress.note\", videoCount) : t(\"compress.unsupported\") }}\n </p>\n\n <Textarea\n v-model=\"caption\"\n :placeholder=\"t('caption')\"\n :aria-label=\"t('caption')\"\n rows=\"1\"\n auto-resize\n :autofocus=\"!isTouch\"\n class=\"max-h-32 w-full\"\n @keydown.enter.exact=\"onCaptionEnter\"\n />\n </div>\n\n <template #footer>\n <div class=\"flex w-full items-center justify-end gap-x-2\">\n <Button\n class=\"flex-1 md:flex-none\"\n severity=\"secondary\"\n text\n :label=\"t('file.cancel')\"\n @click=\"dialogOpen = false\"\n />\n <Button\n class=\"flex-1 md:min-w-28 md:flex-none\"\n :label=\"t('send')\"\n :disabled=\"itemCount === 0\"\n data-testid=\"chat-attach-send\"\n @click=\"send\"\n >\n <template #icon>\n <BIcon\n icon=\"PhPaperPlaneTilt\"\n weight=\"fill\"\n class=\"size-4.5 rtl:-scale-x-100\"\n />\n </template>\n </Button>\n </div>\n </template>\n </ResponsiveDialog>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick } from \"vue\";\nimport { useMediaQuery } from \"@vueuse/core\";\nimport Button from \"primevue/button\";\nimport Popover from \"primevue/popover\";\nimport Textarea from \"primevue/textarea\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport MediaThumb from \"~/components/general/MediaThumb.vue\";\nimport ResponsiveDialog from \"~/components/general/ResponsiveDialog.vue\";\nimport AttachementFileDisplay from \"./AttachementFileDisplay.vue\";\nimport {\n useAttachmentPicker,\n type PickedFile,\n type PickedMedia,\n} from \"~/composables/useAttachmentPicker\";\nimport { canCompressVideo } from \"~/utils/compressVideo\";\nimport { useAppToast } from \"~/composables/useAppToast\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { inputAttachement } from \"@i18n/locales\";\nimport { formatBytes, replaceDigitsByLocale } from \"~/utils/format\";\n\ntype DialogMode = \"single-media\" | \"multi-media\" | \"file\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype AttachmentData = any;\n\ninterface PickerOption {\n key: \"photo\" | \"video\" | \"file\";\n icon: string;\n label: string;\n hint: string;\n tint: string;\n pick: () => void;\n}\n\nconst MAX_MEDIA = 10;\n\n// Sits over any photo, so it carries its own dark backing rather than a theme colour.\nconst removeChip =\n \"absolute flex cursor-pointer items-center justify-center rounded-full bg-black/55 text-white backdrop-blur-sm transition-colors hover:bg-black/70 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-chat-primary motion-reduce:transition-none\";\n\nconst props = withDefaults(\n defineProps<{\n initialCaption?: string;\n }>(),\n {\n initialCaption: \"\",\n },\n);\n\nconst emit = defineEmits<{\n \"send-attachments\": [messages: AttachmentData[]];\n}>();\n\nconst { t, locale } = useLocalI18n(inputAttachement);\nconst { dir } = useDirection();\nconst { openToast } = useAppToast();\nconst localDigits = (value: string | number) => replaceDigitsByLocale(value, locale.value);\nconst size = (bytes: number) => localDigits(formatBytes(bytes));\n// Focusing the caption on a phone would throw the keyboard over the preview.\nconst isTouch = useMediaQuery(\"(pointer: coarse)\");\n\nconst dialogOpen = ref(false);\nconst dialogMode = ref<DialogMode>(\"file\");\nconst caption = ref(\"\");\nconst selectedMedia = ref<PickedMedia[]>([]);\nconst selectedFiles = ref<PickedFile[]>([]);\n// Sent object URLs back the optimistic bubbles; only the ones never sent are released.\nlet sent = false;\n\nwatch(\n () => props.initialCaption,\n (newVal) => {\n caption.value = newVal;\n },\n { immediate: true },\n);\n\n// Videos are compressed after Send, by the messages store, with the progress on the bubble.\nconst canCompress = canCompressVideo();\nconst videoCount = computed(() => selectedMedia.value.filter((m) => m.kind === \"video\").length);\n\n/* --- Picking ----------------------------------------------------------------------------- */\n\nconst itemCount = computed(() =>\n dialogMode.value === \"file\" ? selectedFiles.value.length : selectedMedia.value.length,\n);\n\nconst syncMediaMode = () => {\n dialogMode.value = selectedMedia.value.length === 1 ? \"single-media\" : \"multi-media\";\n};\n\nconst handleMediaSelected = (incoming: PickedMedia[]) => {\n const remaining = MAX_MEDIA - selectedMedia.value.length;\n const accepted = incoming.slice(0, Math.max(remaining, 0));\n incoming.slice(accepted.length).forEach((m) => URL.revokeObjectURL(m.path));\n\n if (accepted.length < incoming.length) openToast(t(\"errors.maxFilesReached\"), \"error\");\n if (!accepted.length) return;\n\n selectedMedia.value = [...selectedMedia.value, ...accepted];\n syncMediaMode();\n dialogOpen.value = true;\n};\n\nconst handleFilesSelected = (files: PickedFile[]) => {\n selectedFiles.value = [...selectedFiles.value, ...files];\n dialogMode.value = \"file\";\n dialogOpen.value = true;\n};\n\nconst { pickMedia, pickFiles } = useAttachmentPicker({\n onMedia: handleMediaSelected,\n onFiles: handleFilesSelected,\n onRejected: (count) => openToast(t(\"errors.unsupported\", { count: localDigits(count) }, count), \"error\"),\n});\n\nconst removeMedia = (index: number) => {\n const [removed] = selectedMedia.value.splice(index, 1);\n if (removed) {\n URL.revokeObjectURL(removed.path);\n }\n if (selectedMedia.value.length === 0) dialogOpen.value = false;\n else syncMediaMode();\n};\n\nconst removeFile = (index: number) => {\n const [removed] = selectedFiles.value.splice(index, 1);\n if (removed) URL.revokeObjectURL(removed.path);\n if (selectedFiles.value.length === 0) dialogOpen.value = false;\n};\n\nconst canAddMore = computed(\n () => dialogMode.value === \"file\" || selectedMedia.value.length < MAX_MEDIA,\n);\n// An album takes photos and videos alike, whichever it was started from.\nconst addMore = () => (dialogMode.value === \"file\" ? pickFiles() : pickMedia());\n\nconst discard = () => {\n if (!sent) {\n selectedMedia.value.forEach((m) => URL.revokeObjectURL(m.path));\n selectedFiles.value.forEach((f) => URL.revokeObjectURL(f.path));\n }\n sent = false;\n selectedMedia.value = [];\n selectedFiles.value = [];\n};\n\n/* --- The attach popover ------------------------------------------------------------------ */\n\nconst picker = ref<InstanceType<typeof Popover> | null>(null);\nconst pickerList = ref<HTMLElement | null>(null);\nconst pickerOpen = ref(false);\nlet pickerTrigger: HTMLElement | null = null;\n\nconst pickerOptions = computed<PickerOption[]>(() => [\n {\n key: \"photo\",\n icon: \"PhImage\",\n label: t(\"file.attachPhoto\"),\n hint: t(\"file.photoHint\"),\n tint: \"bg-chat-primary/12 text-chat-primary\",\n pick: () => pickMedia(\"image\"),\n },\n {\n key: \"video\",\n icon: \"PhVideoCamera\",\n label: t(\"file.attachVideo\"),\n hint: canCompress ? t(\"file.videoHint\") : t(\"file.videoHintPlain\"),\n tint: \"bg-chat-secondary/14 text-chat-secondary\",\n pick: () => pickMedia(\"video\"),\n },\n {\n key: \"file\",\n icon: \"PhFileText\",\n label: t(\"file.attachFile\"),\n hint: t(\"file.fileHint\"),\n tint: \"bg-chat-surface-3 text-chat-on-surface\",\n pick: pickFiles,\n },\n]);\n\nconst togglePicker = (event: MouseEvent) => {\n pickerTrigger = event.currentTarget as HTMLElement;\n picker.value?.toggle(event);\n};\n\nconst pickerItems = () =>\n Array.from(pickerList.value?.querySelectorAll<HTMLElement>('[role=\"menuitem\"]') ?? []);\n\nconst onPickerShow = async () => {\n pickerOpen.value = true;\n await nextTick();\n pickerItems()[0]?.focus();\n};\n\n// Arrow keys, Home and End move between the options, as in a menu; Escape returns to the clip.\nconst onPickerKeydown = (event: KeyboardEvent) => {\n const items = pickerItems();\n const current = items.indexOf(document.activeElement as HTMLElement);\n const go = (index: number) => {\n event.preventDefault();\n items[(index + items.length) % items.length]?.focus();\n };\n if (event.key === \"ArrowDown\") go(current + 1);\n else if (event.key === \"ArrowUp\") go(current - 1);\n else if (event.key === \"Home\") go(0);\n else if (event.key === \"End\") go(items.length - 1);\n else if (event.key === \"Escape\") {\n event.preventDefault();\n picker.value?.hide();\n pickerTrigger?.focus();\n }\n};\n\nconst choose = (option: PickerOption) => {\n discard();\n // The chooser only opens inside the click itself.\n option.pick();\n picker.value?.hide();\n};\n\n/* --- Sending ----------------------------------------------------------------------------- */\n\nconst dialogTitle = computed(() => {\n if (dialogMode.value === \"file\") {\n return selectedFiles.value.length > 1 ? t(\"file.sendFiles\") : t(\"file.sendFile\");\n }\n\n const kinds = new Set(selectedMedia.value.map((m) => m.kind));\n const single = dialogMode.value === \"single-media\";\n if (kinds.size > 1) return t(\"file.sendMedia\");\n if (kinds.has(\"video\")) return single ? t(\"file.sendVideo\") : t(\"file.sendVideos\");\n return single ? t(\"file.sendImage\") : t(\"file.sendImages\");\n});\n\n// \"3 of 10 · 4.2 MB\" for an album, \"2 files · 1.3 MB\" for files, as picked.\nconst summary = computed(() => {\n const items = dialogMode.value === \"file\" ? selectedFiles.value : selectedMedia.value;\n const bytes = items.reduce((total, item) => total + item.file.size, 0);\n const count =\n dialogMode.value === \"file\"\n ? t(\"file.fileCount\", { count: localDigits(selectedFiles.value.length) }, selectedFiles.value.length)\n : t(\"file.mediaCount\", {\n count: localDigits(selectedMedia.value.length),\n max: localDigits(MAX_MEDIA),\n });\n return { count, size: size(bytes) };\n});\n\n// Enter sends, as in the message box; Shift+Enter and an IME's own Enter keep typing.\nconst onCaptionEnter = (event: KeyboardEvent) => {\n if (event.isComposing) return;\n event.preventDefault();\n send();\n};\n\nconst send = () => {\n if (itemCount.value === 0) return;\n const messagesToEmit: AttachmentData[] = [];\n\n if (caption.value.trim()) {\n messagesToEmit.push({\n type: \"text\",\n text: caption.value,\n });\n }\n\n if (dialogMode.value !== \"file\" && selectedMedia.value.length > 0) {\n messagesToEmit.push({\n type: \"image\",\n // Hosts that only know photos read `imageUrl`; the rest read the whole album from `media`.\n imageUrl: selectedMedia.value.filter((m) => m.kind === \"image\").map((m) => m.path),\n media: selectedMedia.value.map((m) => ({ url: m.path, kind: m.kind })),\n files: selectedMedia.value.map((m) => m.file),\n });\n }\n\n if (dialogMode.value === \"file\") {\n selectedFiles.value.forEach((fileData) => {\n messagesToEmit.push({\n type: \"file\",\n fileUrl: fileData.path,\n file: fileData.file,\n fileName: fileData.name,\n });\n });\n }\n\n sent = true;\n emit(\"send-attachments\", messagesToEmit);\n dialogOpen.value = false;\n};\n</script>\n","// @ts-nocheck — grandfathered legacy chat-tree type errors; lift incrementally\n// composables/useChatRecording.ts\nimport { ref, computed, onBeforeUnmount, type Ref } from \"vue\";\n\nexport function useChatRecording(\n inputWidth: Ref<number | undefined>,\n callbacks: {\n onStart: () => void;\n onCancel: () => void;\n onSend?: (mediaUrl?: string) => void;\n requestPermission: () => Promise<boolean>;\n getMode?: () => \"video\" | \"voice\";\n },\n) {\n const isRecording = ref(false);\n const isLocked = ref(false);\n const isPaused = ref(false);\n const recordingTime = ref(0);\n let timerInterval: ReturnType<typeof setInterval> | null = null;\n\n const mediaStream = ref<MediaStream | null>(null);\n let mediaRecorder: MediaRecorder | null = null;\n const recordedChunks: Blob[] = [];\n const currentFacingMode = ref<\"user\" | \"environment\">(\"user\");\n\n const pickRecorderMime = (isVideo: boolean) => {\n const candidates = isVideo\n ? [\n \"video/webm;codecs=vp9,opus\",\n \"video/webm;codecs=vp8,opus\",\n \"video/webm\",\n \"video/mp4\",\n ]\n : [\"audio/webm;codecs=opus\", \"audio/webm\", \"audio/mp4\"];\n for (const c of candidates) {\n if (\n typeof MediaRecorder !== \"undefined\" &&\n MediaRecorder.isTypeSupported(c)\n )\n return c;\n }\n return isVideo ? \"video/webm\" : \"audio/webm\";\n };\n\n const startRecorder = () => {\n const stream = mediaStream.value;\n if (!stream || typeof MediaRecorder === \"undefined\") return;\n recordedChunks.length = 0;\n const isVideo = stream.getVideoTracks().length > 0;\n let recorder: MediaRecorder;\n try {\n recorder = new MediaRecorder(stream, {\n mimeType: pickRecorderMime(isVideo),\n });\n } catch {\n try {\n recorder = new MediaRecorder(stream);\n } catch (err) {\n console.error(\"Failed to create MediaRecorder:\", err);\n return;\n }\n }\n recorder.ondataavailable = (event) => {\n if (event.data && event.data.size > 0) recordedChunks.push(event.data);\n };\n recorder.start(250);\n mediaRecorder = recorder;\n };\n\n const stopStream = () => {\n if (mediaStream.value) {\n mediaStream.value.getTracks().forEach((t) => t.stop());\n mediaStream.value = null;\n }\n };\n\n const finalizeAndSend = () => {\n const chunks = recordedChunks.slice();\n const mimeType =\n (mediaRecorder && mediaRecorder.mimeType) ||\n (chunks.length ? chunks[0].type : \"video/webm\");\n mediaRecorder = null;\n recordedChunks.length = 0;\n stopStream();\n if (chunks.length === 0) {\n callbacks.onCancel();\n return;\n }\n const blob = new Blob(chunks, { type: mimeType });\n if (blob.size === 0) {\n callbacks.onCancel();\n return;\n }\n callbacks.onSend?.(URL.createObjectURL(blob));\n };\n\n const toggleCamera = async () => {\n if (!mediaStream.value || !isRecording.value) return;\n currentFacingMode.value =\n currentFacingMode.value === \"user\" ? \"environment\" : \"user\";\n\n const oldTrack = mediaStream.value.getVideoTracks()[0];\n if (oldTrack) oldTrack.stop();\n\n try {\n const newStream = await navigator.mediaDevices.getUserMedia({\n video: { facingMode: currentFacingMode.value },\n });\n if (mediaStream.value && newStream.getVideoTracks()[0]) {\n mediaStream.value.removeTrack(oldTrack);\n mediaStream.value.addTrack(newStream.getVideoTracks()[0]);\n }\n } catch (err) {\n console.error(\"Failed to flip camera:\", err);\n }\n };\n\n // Drag State\n const isDragging = ref(false);\n const startX = ref(0);\n const startY = ref(0);\n const dragOffset = ref({ x: 0, y: 0 });\n const dragAxis = ref<\"x\" | \"y\" | null>(null);\n\n const pressTimer = ref<ReturnType<typeof setTimeout> | null>(null);\n const isPointerDown = ref(false);\n const isLongPress = ref(false);\n\n const formattedTime = computed(() => {\n const m = Math.floor(recordingTime.value / 60)\n .toString()\n .padStart(2, \"0\");\n const s = (recordingTime.value % 60).toString().padStart(2, \"0\");\n return `${m}:${s}`;\n });\n\n const lockOpacity = computed(() => (dragAxis.value === \"x\" ? 0 : 1));\n const cancelOpacity = computed(() =>\n dragAxis.value === \"y\"\n ? 1\n : 1 - Math.min(Math.abs(dragOffset.value.x) / 80, 1),\n );\n\n const resetDrag = () => {\n isDragging.value = false;\n dragOffset.value = { x: 0, y: 0 };\n dragAxis.value = null;\n };\n\n const togglePause = () => {\n isPaused.value = !isPaused.value;\n if (mediaRecorder && mediaRecorder.state !== \"inactive\") {\n try {\n if (isPaused.value) mediaRecorder.pause();\n else mediaRecorder.resume();\n } catch {\n // ignore — recorder pause/resume best-effort\n }\n }\n if (!isPaused.value) {\n timerInterval = setInterval(() => recordingTime.value++, 1000);\n } else if (timerInterval) {\n clearInterval(timerInterval);\n }\n };\n\n const stopRecording = (triggerSend = false) => {\n if (timerInterval) clearInterval(timerInterval);\n isRecording.value = false;\n isLocked.value = false;\n isPaused.value = false;\n recordingTime.value = 0;\n resetDrag();\n\n const recorder = mediaRecorder;\n if (triggerSend && recorder && recorder.state !== \"inactive\") {\n recorder.onstop = finalizeAndSend;\n try {\n recorder.stop();\n } catch {\n finalizeAndSend();\n }\n return;\n }\n if (recorder && recorder.state !== \"inactive\") {\n try {\n recorder.stop();\n } catch {\n // ignore\n }\n }\n mediaRecorder = null;\n recordedChunks.length = 0;\n stopStream();\n callbacks.onCancel();\n };\n\n const onPointerDown = (event: PointerEvent) => {\n isPointerDown.value = true;\n isLongPress.value = false;\n startX.value = event.clientX;\n startY.value = event.clientY;\n resetDrag();\n\n window.addEventListener(\"pointermove\", onPointerMove);\n window.addEventListener(\"pointerup\", onPointerUp);\n window.addEventListener(\"pointercancel\", onPointerUp);\n\n if (pressTimer.value) clearTimeout(pressTimer.value);\n\n pressTimer.value = setTimeout(async () => {\n isLongPress.value = true;\n // Await the permission UI\n const hasPermission = await callbacks.requestPermission();\n\n if (hasPermission && isPointerDown.value) {\n isDragging.value = true;\n isRecording.value = true;\n isPaused.value = false;\n recordingTime.value = 0;\n callbacks.onStart();\n timerInterval = setInterval(() => recordingTime.value++, 1000);\n\n try {\n const isVideo = !callbacks.getMode || callbacks.getMode() === \"video\";\n mediaStream.value = await navigator.mediaDevices.getUserMedia({\n video: isVideo ? { facingMode: currentFacingMode.value } : false,\n audio: true,\n });\n startRecorder();\n } catch (err) {\n console.error(\"Stream failed\", err);\n }\n }\n }, 400);\n };\n\n const onPointerMove = (event: PointerEvent) => {\n if (!isRecording.value || isLocked.value || !isDragging.value) return;\n\n const deltaX = event.clientX - startX.value;\n const deltaY = event.clientY - startY.value;\n\n if (!dragAxis.value) {\n if (deltaY < -10) dragAxis.value = \"y\";\n else if (deltaX < -10) dragAxis.value = \"x\";\n }\n\n if (dragAxis.value === \"y\") {\n dragOffset.value.y = Math.max(-100, Math.min(0, deltaY));\n if (dragOffset.value.y <= -60) {\n isLocked.value = true;\n resetDrag();\n }\n } else if (dragAxis.value === \"x\") {\n const cancelThreshold = inputWidth.value ? inputWidth.value / 3 : 150;\n dragOffset.value.x = Math.max(-cancelThreshold, Math.min(0, deltaX));\n if (deltaX <= -cancelThreshold) stopRecording(false);\n }\n };\n\n const onPointerUp = () => {\n isPointerDown.value = false;\n window.removeEventListener(\"pointermove\", onPointerMove);\n window.removeEventListener(\"pointerup\", onPointerUp);\n window.removeEventListener(\"pointercancel\", onPointerUp);\n\n if (pressTimer.value) {\n clearTimeout(pressTimer.value);\n pressTimer.value = null;\n }\n\n if (isRecording.value && !isLocked.value) {\n if (dragAxis.value === \"x\") stopRecording(false);\n else stopRecording(true);\n }\n resetDrag();\n };\n\n // Release the MediaStream and stop the timer if the host component\n // unmounts mid-recording (e.g. route change while recording).\n onBeforeUnmount(() => {\n if (pressTimer.value) {\n clearTimeout(pressTimer.value);\n pressTimer.value = null;\n }\n window.removeEventListener(\"pointermove\", onPointerMove);\n window.removeEventListener(\"pointerup\", onPointerUp);\n window.removeEventListener(\"pointercancel\", onPointerUp);\n if (isRecording.value) stopRecording(false);\n });\n\n return {\n isRecording,\n isLocked,\n isPaused,\n formattedTime,\n dragOffset,\n isDragging,\n lockOpacity,\n cancelOpacity,\n isLongPress,\n onPointerDown,\n mediaStream,\n toggleCamera,\n togglePause,\n stopRecording,\n };\n}\n","<template>\n <div\n class=\"pointer-events-none fixed left-0 top-0 z-20 h-dvh w-dvw overflow-visible md:absolute md:h-0 md:w-full md:backdrop-blur-none\"\n :class=\"[\n isOpen\n ? 'bg-chat-on-background/10 backdrop-blur-lg md:bg-transparent'\n : 'backdrop-blur-none',\n ]\"\n >\n <div\n class=\"pointer-events-none flex h-full flex-col items-center justify-between py-26 md:h-auto md:-translate-y-full md:items-end md:pr-4 md:py-4\"\n >\n <!-- Spacer for mobile layout to push video up -->\n <div class=\"md:hidden\" />\n\n <!-- Video Bubble -->\n <div\n class=\"transition-all duration-200 ease-in-out\"\n :class=\"[\n isOpen\n ? 'pointer-events-auto translate-y-0 scale-100 opacity-100'\n : 'pointer-events-none translate-y-1/4 scale-0 opacity-0',\n ]\"\n >\n <BubbleVideo\n mode=\"recording\"\n :stream=\"stream\"\n :is-paused=\"isPaused\"\n :recording-time=\"recordingTime\"\n :max-duration=\"60\"\n />\n </div>\n\n <!-- Mobile Bottom Toolbar -->\n <div\n class=\"origin-bottom flex items-center gap-x-2 rounded-full bg-chat-background px-4 py-3 shadow-floating md:hidden\"\n :class=\"[\n isOpen\n ? 'pointer-events-auto translate-y-0 scale-100 opacity-100'\n : 'pointer-events-none translate-y-1/4 scale-0 opacity-0',\n ]\"\n >\n <IconButton\n v-for=\"option in mobileOptions\"\n :key=\"option.key\"\n :icon=\"option.icon\"\n :label=\"option.label\"\n icon-class=\"size-6\"\n :disabled=\"option.disabled\"\n @click=\"handleOption(option.key)\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<!-- Normal script block used to export the interface for parent components to import -->\n<script lang=\"ts\">\nexport interface VideoRecordDisplayExposed {\n open: () => void;\n close: () => void;\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, onMounted, watch } from \"vue\";\nimport BubbleVideo from \"../chat-bubbles/BubbleVideo.vue\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatInput } from \"@i18n/locales\";\n\nconst props = withDefaults(\n defineProps<{\n stream?: MediaStream | null;\n isPaused?: boolean;\n recordingTime?: number;\n }>(),\n {\n stream: null,\n isPaused: false,\n recordingTime: 0,\n },\n);\n\nconst emit = defineEmits<{\n \"flip-camera\": [];\n}>();\n\nconst { t } = useLocalI18n(chatInput);\nconst isOpen = ref(false);\nconst isFlashOn = ref(false);\nconst hasMultipleCameras = ref(false);\nconst supportsTorch = ref(false);\n\nconst flashIcon = computed(() =>\n isFlashOn.value ? \"PhLightningSlash\" : \"PhLightning\",\n);\n\nonMounted(async () => {\n try {\n const devices = await navigator.mediaDevices.enumerateDevices();\n const videoInputs = devices.filter((d) => d.kind === \"videoinput\");\n hasMultipleCameras.value = videoInputs.length > 1;\n } catch (err) {\n console.error(\"Failed to enumerate devices for camera count\", err);\n }\n});\n\nwatch(\n () => props.stream,\n (newStream) => {\n if (newStream) {\n const track = newStream.getVideoTracks()[0];\n if (track && track.getCapabilities) {\n const caps = track.getCapabilities();\n supportsTorch.value = \"torch\" in caps;\n } else {\n supportsTorch.value = false;\n }\n } else {\n supportsTorch.value = false;\n isFlashOn.value = false;\n }\n },\n { immediate: true },\n);\n\nconst mobileOptions = computed(() => [\n {\n icon: \"PhArrowsClockwise\",\n label: t(\"actions.flipCamera\"),\n key: \"flip-camera\" as const,\n disabled: !hasMultipleCameras.value,\n },\n {\n icon: flashIcon.value,\n label: t(\"actions.flashlight\"),\n key: \"toggle-flash\" as const,\n disabled: !supportsTorch.value,\n },\n]);\n\nconst handleOption = async (key: string) => {\n const option = mobileOptions.value.find((o) => o.key === key);\n if (option?.disabled) return;\n\n switch (key) {\n case \"toggle-flash\": {\n const track = props.stream?.getVideoTracks()[0];\n if (track) {\n try {\n isFlashOn.value = !isFlashOn.value;\n // Apply the native torch constraint to the existing track.\n // `torch` is a non-standard Chromium-only MediaTrackConstraint, so TS doesn't know it;\n // cast through `unknown` to satisfy the type checker without silencing it broadly.\n await track.applyConstraints({\n advanced: [{ torch: isFlashOn.value }],\n } as unknown as MediaTrackConstraints);\n } catch (err) {\n console.error(\"Failed to toggle flash:\", err);\n isFlashOn.value = !isFlashOn.value; // Revert UI if hardware rejects it\n }\n }\n break;\n }\n case \"flip-camera\":\n emit(\"flip-camera\");\n break;\n }\n};\n\nconst open = () => {\n isOpen.value = true;\n};\n\nconst close = () => {\n isOpen.value = false;\n};\n\ndefineExpose<VideoRecordDisplayExposed>({\n open,\n close,\n});\n</script>\n","import { ref, nextTick, type Ref } from \"vue\";\nimport { parseEmojiArray } from \"~/utils/emojiParser\";\n\nexport function useRichTextEditor(inputRef: Ref<HTMLDivElement | null>) {\n const messageText = ref(\"\");\n const savedRange = ref<Range | null>(null);\n const isSelectingEmoji = ref(false);\n\n const adjustHeight = () => {\n const el = inputRef.value;\n if (!el) return;\n\n // 1. Temporarily shrink to get the accurate scroll height of the content\n el.style.height = \"0px\";\n\n // 2. Cap at 144 to match the CSS max-height. This prevents JS from assigning\n // a height larger than 144px, which would break the parent flex layout.\n const maxHeight = 144;\n el.style.height = `${Math.min(el.scrollHeight, maxHeight)}px`;\n };\n const saveCursorPosition = () => {\n const selection = window.getSelection();\n if (selection && selection.rangeCount > 0 && inputRef.value) {\n if (inputRef.value.contains(selection.anchorNode)) {\n savedRange.value = selection.getRangeAt(0).cloneRange();\n }\n }\n };\n\n const handleContentInput = () => {\n if (!inputRef.value) return;\n messageText.value = inputRef.value.innerText;\n adjustHeight();\n };\n\n const handleEmojiSelect = (emoji: string, shouldBlurAfter = false) => {\n isSelectingEmoji.value = true;\n if (!inputRef.value) return;\n\n inputRef.value.focus();\n const selection = window.getSelection();\n let range: Range;\n\n if (savedRange.value) {\n range = savedRange.value;\n selection?.removeAllRanges();\n selection?.addRange(range);\n } else {\n range = document.createRange();\n range.selectNodeContents(inputRef.value);\n range.collapse(false);\n selection?.removeAllRanges();\n selection?.addRange(range);\n }\n\n range.deleteContents();\n\n const parsed = parseEmojiArray(emoji);\n if (parsed.length > 0 && parsed[0].type === \"emoji\") {\n const chunk = parsed[0];\n const span = document.createElement(\"span\");\n span.textContent = chunk.content;\n span.className =\n \"emoji-glyph inline-block h-5 w-5 mx-0.5 leading-5 text-xl align-middle select-text pointer-events-none\";\n span.setAttribute(\"contenteditable\", \"false\");\n\n range.insertNode(span);\n range.setStartAfter(span);\n range.collapse(true);\n selection?.removeAllRanges();\n selection?.addRange(range);\n savedRange.value = range.cloneRange();\n }\n\n handleContentInput();\n\n nextTick(() => {\n if (shouldBlurAfter) inputRef.value?.blur();\n adjustHeight();\n });\n\n isSelectingEmoji.value = false;\n };\n\n /** Replaces the content with plain text, e.g. a restored draft or a message being edited. */\n const setText = (text: string) => {\n messageText.value = text;\n savedRange.value = null;\n if (inputRef.value) inputRef.value.innerText = text;\n nextTick(() => adjustHeight());\n };\n\n const clearInput = () => {\n messageText.value = \"\";\n if (inputRef.value) inputRef.value.innerHTML = \"\";\n nextTick(() => adjustHeight());\n };\n\n return {\n messageText,\n isSelectingEmoji,\n saveCursorPosition,\n handleContentInput,\n handleEmojiSelect,\n clearInput,\n setText,\n adjustHeight,\n };\n}\n","<script setup lang=\"ts\">\n/** The strip above the input while replying to or editing a message. */\nimport SafeEmojiText from \"~/components/general/SafeEmojiText.vue\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatInput } from \"@i18n/locales\";\n\ndefineProps<{\n mode: \"normal\" | \"edit\" | \"reply\";\n /** Who wrote the message being replied to. */\n name: string;\n text: string;\n}>();\nconst emit = defineEmits<{ cancel: [] }>();\n\nconst { t } = useLocalI18n(chatInput);\n</script>\n\n<template>\n <div\n :class=\"[mode !== 'normal' ? ' h-10' : 'h-0']\"\n class=\"gap-x-3 px-3 w-full whitespace-nowrap overflow-hidden border-t select-none text-body-sm border-t-outline-variant flex relative z-30 justify-between items-center transition-all duration-200 ease-in-out bg-surface\"\n >\n <BIcon\n :icon=\"mode === 'edit' ? 'PhPencilSimpleLine' : 'PhArrowBendUpLeft'\"\n class=\"w-5 h-5 fill-on-surface shrink-0\"\n />\n <div class=\"flex-1 flex items-center gap-x-2\">\n <div v-if=\"mode === 'reply'\" class=\"shrink-0 text-chat-muted\">\n {{ name }} :\n </div>\n <div class=\"flex-1\">\n <div\n class=\"text-on-surface w-full overflow-hidden text-ellipsis line-clamp-1\"\n >\n <SafeEmojiText :text=\"text\" />\n </div>\n </div>\n </div>\n <IconButton\n icon=\"PhX\"\n :label=\"t('cancel')\"\n size=\"small\"\n class=\"shrink-0\"\n @click=\"emit('cancel')\"\n />\n </div>\n</template>\n","<script setup lang=\"ts\">\n/** Replaces the text field while recording: swipe-to-cancel hint (or Cancel once locked) and the timer. */\nimport Button from \"primevue/button\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chat, chatInput } from \"@i18n/locales\";\n\ndefineProps<{ locked: boolean; cancelOpacity: number; time: string }>();\nconst emit = defineEmits<{ cancel: [] }>();\n\nconst { t } = useLocalI18n(chatInput, chat);\n</script>\n\n<template>\n <div class=\"flex-1 justify-between -translate-y-2 flex items-center\">\n <div></div>\n <div\n class=\"flex justify-center items-center text-body-md text-on-surface/70 transition-opacity\"\n :style=\"{ opacity: cancelOpacity }\"\n >\n <span v-if=\"!locked\">{{ t(\"chat.swipeToCancel\") }}</span>\n <Button\n v-else\n text\n size=\"small\"\n class=\"z-20\"\n :label=\"t('chat.cancel')\"\n @click=\"emit('cancel')\"\n />\n </div>\n\n <div class=\"left-6 flex items-center gap-x-2 shrink-0 z-10\">\n <div class=\"w-2.5 h-2.5 relative\">\n <div class=\"w-2.5 h-2.5 rounded-full bg-error\"></div>\n <div\n class=\"w-2.5 h-2.5 rounded-full bg-error animate-ping absolute top-0 left-0 inset-0\"\n ></div>\n </div>\n <span\n class=\"text-body-md min-w-12 text-center text-on-surface tabular-nums mt-0.5\"\n dir=\"ltr\"\n >{{ time }}</span\n >\n </div>\n </div>\n</template>\n","<script setup lang=\"ts\">\n/**\n * The primary action beside the input: the microphone/camera button (hold to record, tap to\n * switch between voice and video), or the send button once there is text or a locked recording.\n * While recording it floats the lock pill above itself, which becomes pause/resume once locked.\n */\nimport { computed } from \"vue\";\nimport Button from \"primevue/button\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport useLocalI18n from \"~/composables/useLocalI18n\";\nimport { chatInput } from \"@i18n/locales\";\n\nconst props = defineProps<{\n isRecording: boolean;\n isLocked: boolean;\n isPaused: boolean;\n hasText: boolean;\n icon: string;\n disabled?: boolean;\n lockOpacity: number;\n dragOffset: { x: number; y: number };\n isDragging: boolean;\n}>();\n\nconst emit = defineEmits<{\n pointerdown: [event: PointerEvent];\n toggleType: [];\n togglePause: [];\n send: [];\n}>();\n\nconst { t } = useLocalI18n(chatInput);\n\nconst showSend = computed(() => props.isLocked || props.hasText);\n</script>\n\n<template>\n <div\n class=\"relative z-30 mb-0.5 flex shrink-0 items-center justify-center\"\n :style=\"{\n transform: `translate(${dragOffset.x}px, ${dragOffset.y}px)`,\n transition: isDragging\n ? 'none'\n : 'transform 0.2s cubic-bezier(0.4, 0, 0.2, 1)',\n }\"\n >\n <div\n v-if=\"isRecording\"\n class=\"absolute -top-20 flex w-10 flex-col items-center justify-center rounded-full bg-chat-background shadow-floating transition-opacity\"\n :class=\"[\n isLocked ? 'pointer-events-auto py-1' : 'pointer-events-none gap-y-3 py-3',\n ]\"\n :style=\"{ opacity: lockOpacity }\"\n >\n <BIcon v-if=\"!isLocked\" icon=\"PhLockKey\" class=\"size-5\" />\n <IconButton\n v-else\n :icon=\"isPaused ? 'PhPlayCircle' : 'PhPauseCircle'\"\n :label=\"isPaused ? t('actions.resume') : t('actions.pause')\"\n icon-class=\"size-6\"\n @click=\"emit('togglePause')\"\n />\n <BIcon icon=\"PhCaretUp\" class=\"size-4 animate-bounce opacity-60\" />\n </div>\n\n <Button\n v-if=\"showSend\"\n rounded\n :aria-label=\"t('actions.sendMessage')\"\n :disabled=\"disabled\"\n @click=\"emit('send')\"\n >\n <template #icon>\n <BIcon icon=\"PhPaperPlaneTilt\" class=\"size-6 rtl:-scale-x-100\" />\n </template>\n </Button>\n <!-- Hold to record; a tap switches between voice and video. -->\n <Button\n v-else\n rounded\n :text=\"!isRecording\"\n :severity=\"isRecording ? undefined : 'secondary'\"\n :aria-label=\"icon === 'PhCamera' ? t('actions.recordVideo') : t('actions.recordVoice')\"\n :disabled=\"disabled\"\n class=\"touch-none\"\n @pointerdown=\"emit('pointerdown', $event)\"\n @click=\"emit('toggleType')\"\n >\n <template #icon>\n <BIcon\n :icon=\"icon\"\n :weight=\"isRecording ? 'fill' : 'regular'\"\n class=\"size-6\"\n />\n </template>\n </Button>\n </div>\n</template>\n","import { onMounted, watch, type Ref } from \"vue\";\nimport { useChatStore } from \"~/stores/chatStore\";\nimport { useMessagesStore } from \"~/stores/messageStores\";\n\ninterface DraftEditor {\n messageText: Ref<string>;\n setText: (text: string) => void;\n}\n\n/**\n * Keeps the input's unsent text per conversation: saved as it is typed, swapped when the open\n * conversation changes, and restored on mount. Text typed while editing a message is not a draft.\n */\nexport function useInputDraft(editor: DraftEditor, isEditing: () => boolean) {\n const chatStore = useChatStore();\n const messagesStore = useMessagesStore();\n\n /** Puts the open conversation's draft (or nothing) back into the input. */\n const restoreDraft = () => {\n const id = chatStore.activeConversationId;\n editor.setText((id && messagesStore.drafts[id]) || \"\");\n };\n\n watch(editor.messageText, (text) => {\n const id = chatStore.activeConversationId;\n if (id && !isEditing()) messagesStore.setDraft(id, text);\n });\n\n watch(\n () => chatStore.activeConversationId,\n () => {\n // An edit belongs to the conversation it started in.\n if (isEditing()) messagesStore.clearActions();\n restoreDraft();\n },\n );\n\n onMounted(() => {\n const id = chatStore.activeConversationId;\n if (id && messagesStore.drafts[id]) restoreDraft();\n });\n\n return { restoreDraft };\n}\n","<template>\n <div :dir=\"dir\" class=\"vue-chat w-full relative\">\n <VideoRecordDisplay\n ref=\"videoDisplay\"\n :stream=\"mediaStream\"\n :is-paused=\"isPaused\"\n :recording-time=\"currentRecordingSeconds\"\n @flip-camera=\"handleFlipCamera\"\n />\n <InputActionBar\n :mode=\"textMode\"\n :name=\"displayActionName\"\n :text=\"displayedActionText ?? ''\"\n @cancel=\"cancelAction\"\n />\n <div\n @contextmenu.prevent\n ref=\"rootElements\"\n class=\"px-4 transition-all duration-200 ease-in-out min-h-19 py-4 w-full bg-surface flex items-end border-t border-t-outline-variant gap-x-5 relative z-40 overflow-visible select-none\"\n >\n <RecordButton\n :is-recording=\"isRecording\"\n :is-locked=\"isLocked\"\n :is-paused=\"isPaused\"\n :has-text=\"editor.messageText.value.trim().length > 0\"\n :icon=\"secondaryMessageIcon\"\n :disabled=\"inputDisabled\"\n :lock-opacity=\"lockOpacity\"\n :drag-offset=\"dragOffset\"\n :is-dragging=\"isDragging\"\n @pointerdown=\"handlePointerDown\"\n @toggle-type=\"toggleSecondaryMessageType\"\n @toggle-pause=\"togglePause\"\n @send=\"handleSend\"\n />\n\n <div v-show=\"!isRecording\" class=\"flex-1 flex items-end gap-x-5\">\n <div class=\"min-h-11 flex items-center w-full\">\n <div\n ref=\"input\"\n data-testid=\"chat-input\"\n contenteditable=\"true\"\n @keydown.enter.exact.prevent=\"handleEnterKey\"\n @input=\"editor.handleContentInput\"\n @focus=\"onInputFocus\"\n @blur=\"editor.saveCursorPosition\"\n @keyup=\"editor.saveCursorPosition\"\n @mouseup=\"editor.saveCursorPosition\"\n :data-placeholder=\"inputPlaceholder\"\n class=\"text-body-md text-on-surface outline-none flex-1 bg-transparent z-10 [unicode-bidi:plaintext] max-h-[144px] overflow-y-auto hide-scrollbar leading-6 py-1 cursor-text whitespace-pre-wrap break-words empty:before:content-[attr(data-placeholder)] empty:before:text-chat-muted pointer-events-auto\"\n ></div>\n </div>\n <div class=\"z-10 flex h-11 shrink-0 items-center gap-x-2\">\n <!-- A popover on wide screens; on phones the picker opens under the input instead. -->\n <IconButton\n icon=\"PhSmiley\"\n icon-class=\"size-6\"\n :label=\"t('actions.emoji')\"\n :disabled=\"inputDisabled\"\n data-testid=\"chat-emoji\"\n class=\"hidden! md:inline-flex!\"\n @mousedown.prevent\n @click=\"openEmojiPopover\"\n />\n <Popover ref=\"emojiPopover\" :dir=\"dir\" class=\"vue-chat\">\n <BEmojiPicker v-if=\"emojiUsed\" @select=\"handleEmojiSelect\" />\n </Popover>\n <IconButton\n icon=\"PhSmiley\"\n icon-class=\"size-6\"\n :label=\"t('actions.emoji')\"\n :disabled=\"inputDisabled\"\n class=\"md:hidden!\"\n @mousedown.prevent\n @click=\"toggleMobileEmoji\"\n />\n <InputAttachement\n :initial-caption=\"editor.messageText.value\"\n @send-attachments=\"handleAttachments\"\n />\n </div>\n </div>\n\n <RecordingStatus\n v-show=\"isRecording\"\n :locked=\"isLocked\"\n :cancel-opacity=\"cancelOpacity\"\n :time=\"formattedTime\"\n @cancel=\"cancelRecording\"\n />\n </div>\n <div\n class=\"md:hidden w-full transition-all relative z-30 duration-300 ease-[cubic-bezier(0.33,1,0.68,1)] overflow-hidden\"\n :class=\"\n showMobileEmojiPicker ? 'max-h-60 opacity-100' : 'max-h-0 opacity-0'\n \"\n >\n <BEmojiPicker v-if=\"emojiUsed\" @select=\"handleEmojiSelect\" />\n </div>\n </div>\n</template>\n<script setup lang=\"ts\">\nimport {\n ref,\n computed,\n nextTick,\n watch,\n onMounted,\n onUnmounted,\n useTemplateRef,\n} from \"vue\";\nimport Popover from \"primevue/popover\";\nimport IconButton from \"~/components/general/IconButton.vue\";\nimport type { ExtendedMessage, Message } from \"~/types\";\nimport InputAttachement from \"./chat-input/InputAttachement.vue\";\nimport {\n useAppPermissions,\n type PopupState,\n} from \"~/composables/useAppPermissions\";\nimport { useChatRecording } from \"~/composables/chat/useChatRecording\";\nimport VideoRecordDisplay from \"./chat-input/VideoRecordDisplay.vue\";\nimport { useRichTextEditor } from \"~/composables/useRichTextEditor\";\nimport { useMessagesStore } from \"~/stores/messageStores.js\";\nimport { useProfileStore } from \"~/stores/profileStore.js\";\nimport InputActionBar from \"./chat-input/InputActionBar.vue\";\nimport RecordingStatus from \"./chat-input/RecordingStatus.vue\";\nimport RecordButton from \"./chat-input/RecordButton.vue\";\nimport { useInputDraft } from \"~/composables/chat/useInputDraft\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { useChatStore } from \"~/stores/chatStore.js\";\nimport { useCallStore } from \"~/stores/callStore.js\";\nimport { type EmojiExt } from \"vue3-emoji-picker\";\nimport { chat, chatInput } from \"@i18n/locales\";\nimport { albumKind, messageMedia } from \"~/utils/media\";\n\nconst props = withDefaults(\n defineProps<{\n isActive?: boolean;\n }>(),\n { isActive: false },\n);\n\nconst emit = defineEmits<{\n send: [];\n edit: [];\n}>();\n\nconst { t } = useLocalI18n(chatInput, chat);\nconst { dir } = useDirection();\nconst { requestWithPopup, checkMediaStatus } = useAppPermissions();\nconst messagesStore = useMessagesStore();\nconst chatStore = useChatStore();\nconst callStore = useCallStore();\n\nconst profileStore = useProfileStore();\nconst currentUserId = computed(() => profileStore.userId);\n\n// Template Refs (Properly typed, no 'any')\nconst rootElementsRef = useTemplateRef<HTMLElement>(\"rootElements\");\nconst inputRef = useTemplateRef<HTMLDivElement>(\"input\");\nconst emojiPopoverRef = useTemplateRef<InstanceType<typeof Popover>>(\"emojiPopover\");\nconst videoDisplayRef =\n useTemplateRef<InstanceType<typeof VideoRecordDisplay>>(\"videoDisplay\");\n\n// Local State\nconst showMobileEmojiPicker = ref(false);\n/** The pickers mount on first use: they are heavy, and most messages have no emoji. */\nconst emojiUsed = ref(false);\nconst textMode = ref<\"normal\" | \"edit\" | \"reply\">(\"normal\");\nconst editingMessageData = ref<ExtendedMessage | null>(null);\nconst replyingToMessageData = ref<ExtendedMessage | null>(null);\nconst secondaryMessageType = ref<\"video\" | \"voice\">(\"voice\");\n\n// Composables\nconst editor = useRichTextEditor(inputRef);\nconst { restoreDraft } = useInputDraft(editor, () => textMode.value === \"edit\");\nconst inputWidth = computed(() => rootElementsRef.value?.clientWidth || 0);\n\n// --- Computed UI States ---\nconst inputDisabled = computed(() => !props.isActive);\nconst inputPlaceholder = computed(() =>\n props.isActive ? t(\"placeholder\") : t(\"chatLocked\"),\n);\n\nconst secondaryMessageIcon = computed(() =>\n secondaryMessageType.value === \"voice\" ? \"PhMicrophone\" : \"PhCamera\",\n);\n\n// Replaces messy inline template logic\nconst showSecondaryAction = computed(\n () =>\n !isRecording.value &&\n !isLocked.value &&\n editor.messageText.value.trim().length === 0,\n);\nconst showSendButton = computed(() => !showSecondaryAction.value);\n\nconst displayedActionText = computed(() => {\n const message =\n textMode.value === \"edit\"\n ? editingMessageData.value\n : replyingToMessageData.value;\n if (!message) return \"\";\n // Fixed typos: attachementTypes -> attachmentTypes\n if (message.voiceUrl?.trim()) return t(\"attachmentTypes.voice\");\n if (message.videoUrl?.trim()) return t(\"attachmentTypes.video\");\n const album = messageMedia(message);\n if (album.length) return t(`attachmentTypes.${albumKind(album)}`);\n if (message.fileUrl?.trim()) return t(\"attachmentTypes.file\");\n return message.text;\n});\n\nconst displayActionName = computed(() => {\n if (textMode.value === \"edit\") return t(\"you\");\n if (replyingToMessageData.value?.senderId === currentUserId.value)\n return t(\"you\");\n return replyingToMessageData.value?.contact?.name || \"\";\n});\n\n// --- Recording Composable ---\nconst recording = useChatRecording(inputWidth, {\n onStart: () => {\n if (secondaryMessageType.value === \"video\") videoDisplayRef.value?.open();\n },\n onCancel: () => {\n if (secondaryMessageType.value === \"video\") videoDisplayRef.value?.close();\n },\n onSend: (mediaUrl?: string) => {\n const finalUrl = mediaUrl || \"placeholder\";\n const msg = createBaseMessage();\n console.log(msg);\n msg.type = secondaryMessageType.value as Message[\"type\"];\n if (msg.type === \"voice\") msg.voiceUrl = finalUrl;\n if (msg.type === \"video\") msg.videoUrl = finalUrl;\n\n messagesStore.sendMessage([msg]);\n messagesStore.clearActions();\n if (secondaryMessageType.value === \"video\") videoDisplayRef.value?.close();\n },\n requestPermission: async () => await ensurePermissions(),\n getMode: () => secondaryMessageType.value,\n});\n\nconst {\n isRecording,\n isLocked,\n isPaused,\n dragOffset,\n isDragging,\n formattedTime,\n isLongPress,\n onPointerDown: onRecordPointerDown,\n stopRecording,\n mediaStream,\n lockOpacity,\n cancelOpacity,\n togglePause,\n} = recording;\n\nconst currentRecordingSeconds = computed(() => {\n if (!formattedTime.value) return 0;\n const [minutes, seconds] = formattedTime.value.split(\":\").map(Number);\n return (minutes || 0) * 60 + (seconds || 0);\n});\n\nwatch(currentRecordingSeconds, (sec) => {\n if (sec >= 60 && isRecording.value) stopRecording(true);\n});\n\n// --- Permissions ---\nconst ensurePermissions = async () => {\n const isVideo = secondaryMessageType.value === \"video\";\n const currentStatus = await checkMediaStatus();\n const status = isVideo ? currentStatus.cam : currentStatus.mic;\n\n if (status === \"granted\") return true;\n\n const state: PopupState = isVideo\n ? status === \"denied\"\n ? \"cam-error\"\n : \"cam-permission\"\n : status === \"denied\"\n ? \"mic-error\"\n : \"mic-permission\";\n\n return await requestWithPopup(state);\n};\n\n// --- Message Handling ---\nconst createBaseMessage = (): Message =>\n ({\n id: String(Date.now() + Math.floor(Math.random() * 1000)),\n conversationId: chatStore.activeConversationId ?? \"\",\n date: new Date(),\n type: \"text\",\n isEdited: false,\n senderId: currentUserId.value,\n isSent: false,\n isRead: false,\n repliedTo: messagesStore.replyingTo || undefined,\n }) as Message;\n\nconst handleAttachments = (payloads: Message[]) => {\n const newMessages = payloads.map((payload) => {\n const msg = createBaseMessage();\n msg.type = payload.type;\n if (payload.type === \"text\") msg.text = payload.text;\n if (payload.type === \"image\") {\n msg.imageUrl = payload.imageUrl;\n msg.media = payload.media;\n }\n if (payload.type === \"file\") {\n msg.fileUrl = payload.fileUrl;\n msg.fileName = payload.fileName;\n }\n if (payload.type === \"voice\") msg.voiceUrl = payload.voiceUrl;\n if (payload.type === \"video\") msg.videoUrl = payload.videoUrl;\n return msg;\n });\n\n messagesStore.sendMessage(newMessages);\n editor.clearInput();\n messagesStore.clearActions();\n};\n\nconst sendMessage = () => {\n if (editor.messageText.value.trim().length === 0) return;\n\n if (textMode.value === \"edit\" && editingMessageData.value) {\n // Clears `editingMessage`; its watcher leaves edit mode and restores the draft.\n messagesStore.saveEditMessage(\n editingMessageData.value.id,\n editor.messageText.value,\n );\n return;\n } else {\n const msg = createBaseMessage();\n msg.type = \"text\";\n msg.text = editor.messageText.value;\n messagesStore.sendMessage([msg]);\n }\n\n editor.clearInput();\n textMode.value = \"normal\";\n messagesStore.clearActions();\n};\n\nconst cancelAction = () => messagesStore.clearActions();\n\nconst handleEditMessage = (msg: ExtendedMessage) => {\n textMode.value = \"edit\";\n editingMessageData.value = msg;\n editor.setText(msg.text || \"\");\n nextTick(() => inputRef.value?.focus());\n};\n\n// --- Watchers ---\n// The store sets `editingMessage` from the bubble menu; enter edit mode from it, and leave it\n// (restoring the draft the edit displaced) when the edit is saved or cancelled.\nwatch(\n () => messagesStore.editingMessage,\n (msg) => {\n if (msg) {\n handleEditMessage(msg);\n } else if (textMode.value === \"edit\") {\n textMode.value = \"normal\";\n editingMessageData.value = null;\n restoreDraft();\n }\n },\n);\n\nwatch(\n () => messagesStore.replyingTo,\n (msg) => {\n if (msg) {\n textMode.value = \"reply\";\n replyingToMessageData.value = msg;\n nextTick(() => inputRef.value?.focus());\n } else if (textMode.value === \"reply\") {\n textMode.value = \"normal\";\n replyingToMessageData.value = null;\n }\n },\n);\n\n// --- Input Interactions ---\nconst onInputFocus = () => {\n if (editor.isSelectingEmoji.value) return;\n showMobileEmojiPicker.value = false;\n};\n\nconst handlePointerDown = (event: PointerEvent) => {\n if (editor.messageText.value.trim().length > 0) {\n sendMessage();\n return;\n }\n emojiPopoverRef.value?.hide();\n recording.onPointerDown(event);\n\n // NOTE: The 300ms setTimeout has been completely removed from here.\n // The @click event now handles the toggle safely!\n};\n\nconst handleEnterKey = (e: KeyboardEvent) => {\n if (e.shiftKey) return;\n e.preventDefault();\n sendMessage();\n};\n\nconst openEmojiPopover = (event: MouseEvent) => {\n emojiUsed.value = true;\n emojiPopoverRef.value?.toggle(event);\n};\n\nconst toggleMobileEmoji = () => {\n emojiUsed.value = true;\n showMobileEmojiPicker.value = !showMobileEmojiPicker.value;\n if (showMobileEmojiPicker.value) {\n editor.saveCursorPosition();\n inputRef.value?.blur();\n }\n};\n\nconst handleEmojiSelect = (emoji: EmojiExt) => {\n editor.handleEmojiSelect(emoji.i, showMobileEmojiPicker.value);\n};\n\n// Cleaned up pointer/click handlers\nconst handleActionPointerDown = (e: PointerEvent) => {\n if (showSecondaryAction.value) onRecordPointerDown(e);\n};\n\nconst handleActionClick = () => {\n if (showSecondaryAction.value) toggleSecondaryMessageType();\n};\n\nconst toggleSecondaryMessageType = () => {\n if (!isLongPress.value && !isRecording.value) {\n secondaryMessageType.value =\n secondaryMessageType.value === \"voice\" ? \"video\" : \"voice\";\n }\n};\n\nconst handleFlipCamera = () => {\n if (typeof recording.toggleCamera === \"function\") recording.toggleCamera();\n};\n\n// The send button sends the typed text, or a recording once it has been locked.\nconst handleSend = () => (isLocked.value ? stopRecording(true) : sendMessage());\nconst cancelRecording = () => stopRecording(false);\n\n// --- Global Keys ---\n// PrimeVue closes its own overlays on Escape, in listeners that run before this one on `window`\n// while the overlay is still in the DOM. When one is open, Escape is for it alone: it must not\n// also cancel a reply or close the conversation behind it.\nconst OVERLAYS =\n \".p-menu-overlay, .p-contextmenu, .p-popover, .p-dialog-mask, .p-drawer-mask, .p-galleria-mask\";\n\nconst handleGlobalKeyDown = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n if (event.defaultPrevented || document.querySelector(OVERLAYS)) return;\n if (textMode.value !== \"normal\" || messagesStore.selectedArray.length > 0) {\n cancelAction();\n } else {\n const isCallMode = callStore.isActive;\n const isProfileView = chatStore.profileViewOpen;\n\n if (isCallMode) callStore.minimize();\n else if (isProfileView) chatStore.closeProfile();\n else chatStore.setSelectedChat(null);\n }\n }\n};\n\nonMounted(() => window.addEventListener(\"keydown\", handleGlobalKeyDown));\nonUnmounted(() => window.removeEventListener(\"keydown\", handleGlobalKeyDown));\n\ndefineExpose({ focus: () => inputRef.value?.focus() });\n</script>\n","<template>\n <div :dir=\"dir\" class=\"vue-chat h-full w-full bg-chat-surface\">\n <div class=\"flex h-full w-full\">\n <ChatProfileOverview :profile=\"selectedChat\" @end=\"handleOption('end-chat')\" />\n\n <!-- On phones the open profile takes the whole screen. -->\n <div\n v-show=\"chatId\"\n class=\"h-full flex-1 flex-col items-center justify-between\"\n :class=\"isProfile ? 'hidden md:flex' : 'flex'\"\n >\n <div class=\"h-16 w-full bg-chat-background md:h-20\">\n <ChatPageBar\n :contact=\"selectedChat\"\n :options=\"medicOptions\"\n :host-options=\"headerOptions\"\n @open-profile=\"openProfile\"\n @select=\"handleOption\"\n >\n <template v-if=\"$slots['header-actions']\" #actions=\"{ contact, compact }\">\n <slot name=\"header-actions\" :contact=\"contact\" :compact=\"compact\" />\n </template>\n </ChatPageBar>\n </div>\n <!-- Host content between the header and the messages, e.g. a toolbar for this chat. -->\n <div v-if=\"$slots['conversation-top']\" class=\"w-full\">\n <slot\n name=\"conversation-top\"\n :conversation-id=\"chatId\"\n :contact=\"selectedChat\"\n />\n </div>\n <div class=\"min-h-0 w-full flex-1 overflow-hidden\">\n <!-- Renders nothing without a contact, so no v-show: it can't apply to an empty root. -->\n <ChatMessages :contact=\"selectedChat\" />\n <!-- The open conversation's contact is still being fetched (e.g. a deep link). -->\n <div v-if=\"isResolving\" class=\"flex h-full w-full items-end\">\n <MessagesSkeleton />\n </div>\n </div>\n <slot\n v-if=\"selectedChat?.isActive\"\n name=\"above-input\"\n :conversation-id=\"chatId\"\n :contact=\"selectedChat\"\n />\n <ChatInput\n v-if=\"selectedChat?.isActive\"\n ref=\"chatInput\"\n :is-active=\"true\"\n />\n <!-- In place of the input, so the thread keeps its full height. -->\n <div\n v-else-if=\"selectedChat\"\n class=\"flex w-full items-center justify-center gap-x-2 border-t border-t-chat-outline-variant bg-chat-background px-5 py-4 text-body-md text-chat-on-background/60\"\n >\n <BIcon icon=\"PhLockKey\" class=\"size-5 shrink-0\" />\n <span>{{ t(\"chatEnded\") }}</span>\n </div>\n </div>\n\n <div\n v-show=\"!chatId\"\n class=\"flex h-full w-full items-center justify-center\"\n />\n </div>\n\n <PermissionPopup />\n <ConfirmModal ref=\"modal\" :loading=\"ending\" @action=\"endConversation\" />\n <Toast :group=\"TOAST_GROUP\" position=\"top-center\" :dir=\"dir\" class=\"vue-chat\" />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref, nextTick, watch } from \"vue\";\nimport Toast from \"primevue/toast\";\nimport PermissionPopup from \"~/components/chat/chat-input/PermissionPopup.vue\";\nimport ChatProfileOverview from \"~/components/chat/ChatProfileOverview.vue\";\nimport type { ChatTextField } from \"~/types/components/chat-input\";\nimport type { MenuOption } from \"~/types/components/menu-options\";\nimport ChatMessages from \"~/components/chat/ChatMessages.vue\";\nimport MessagesSkeleton from \"~/components/chat/messages/MessagesSkeleton.vue\";\nimport ChatPageBar from \"~/components/chat/ChatPageBar.vue\";\nimport ChatInput from \"~/components/chat/ChatInput.vue\";\nimport ConfirmModal from \"~/components/general/ConfirmModal.vue\";\nimport type { Modal } from \"~/types/components/modal\";\nimport { TOAST_GROUP } from \"~/composables/useAppToast\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { useChatStore } from \"~/stores/chatStore\";\nimport { chatView } from \"@i18n/locales\";\n\nwithDefaults(\n defineProps<{\n /** The host's actions, listed in the header's \"more options\" menu while it is compact. */\n headerOptions?: MenuOption[];\n }>(),\n { headerOptions: () => [] },\n);\n\nconst chatStore = useChatStore();\nconst { t } = useLocalI18n(chatView);\nconst { dir } = useDirection();\n// Template Refs\nconst chatInput = ref<ChatTextField | null>(null);\n\nconst chatId = computed(() => chatStore.activeConversationId);\nconst isProfile = computed(() => chatStore.profileViewOpen);\n\nconst selectedChat = computed(() => {\n if (!chatId.value) return null;\n return chatStore.getContactById(chatId.value);\n});\n\n// Until the contact arrives the pane would otherwise read as an ended chat.\nconst isResolving = computed(() => !!chatId.value && !selectedChat.value);\n\nconst medicOptions = computed<MenuOption[]>(() =>\n chatStore.canEndConversation && selectedChat.value?.isActive\n ? [\n {\n label: t(\"barOptions.endChat\"),\n icon: \"PhX\",\n key: \"end-chat\",\n color: \"error\",\n },\n ]\n : [],\n);\n\nconst modal = ref<Modal | null>(null);\nconst ending = ref(false);\n\nconst handleOption = (key: string) => {\n if (key !== \"end-chat\" || !chatId.value) return;\n modal.value?.openModal(\n t(\"endChat.title\"),\n t(\"endChat.message\"),\n \"error\",\n true,\n t(\"endChat.confirm\"),\n );\n};\n\nconst endConversation = () => {\n // Stay open with the button spinning until the server answers; the host reports failures.\n if (ending.value || !chatId.value) return;\n ending.value = true;\n chatStore\n .endConversation(chatId.value)\n .catch(() => {})\n .finally(() => {\n ending.value = false;\n modal.value?.closeModal();\n });\n};\n\nconst openProfile = () => {\n chatStore.openProfile();\n};\n\nwatch(\n () => chatStore.activeConversationId,\n () => {\n if (chatId.value && selectedChat.value?.isActive) {\n nextTick(() => {\n chatInput.value?.focus();\n });\n }\n },\n);\n</script>\n","<script setup lang=\"ts\">\nimport NoChatSelected from \"../assets/lib-images/chat/empty-state.webp\";\nimport NoDataDisplay from \"./general/NoDataDisplay.vue\";\nimport useLocalI18n, { useDirection } from \"~/composables/useLocalI18n\";\nimport { useChatStore } from \"../stores/chatStore\";\nimport ChatList from \"./chat/contact/ChatList.vue\";\nimport { useCallStore } from \"~/stores/callStore\";\nimport ChatView from \"./chat/ChatView.vue\";\nimport { chatPage } from \"@i18n/locales\";\nimport { computed, defineAsyncComponent, useSlots } from \"vue\";\n\n// Loaded with the first call, not with the chat.\nconst Call = defineAsyncComponent(() => import(\"./call/Call.vue\"));\nimport type { Contact } from \"~/types\";\nimport type { MenuOption } from \"~/types/components/menu-options\";\n\nconst props = withDefaults(\n defineProps<{\n /**\n * Render the call view here. Set to false and mount `<Call />` once near the app root to\n * keep the call on screen while the user navigates away from the chat.\n */\n renderCall?: boolean;\n /**\n * Host actions as items of the conversation header's \"more options\" menu, listed while the\n * header is too narrow for `header-actions` (that slot's `compact`).\n */\n headerOptions?: MenuOption[];\n }>(),\n { renderCall: true, headerOptions: () => [] },\n);\n\ndefineSlots<{\n /** Replaces the \"no conversation selected\" placeholder. */\n empty?: () => unknown;\n /**\n * Extra actions in the conversation header, beside the call button. `compact` is true while the\n * header is too narrow for them: hide them then, and list them through `headerOptions`.\n */\n \"header-actions\"?: (props: { contact: Contact | null; compact: boolean }) => unknown;\n /** Between the header and the messages. */\n \"conversation-top\"?: (props: {\n conversationId: string | null;\n contact: Contact | null;\n }) => unknown;\n /** Above the input, only while the conversation is active. */\n \"above-input\"?: (props: {\n conversationId: string | null;\n contact: Contact | null;\n }) => unknown;\n}>();\n\nconst slots = useSlots();\n\nconst chatStore = useChatStore();\nconst callStore = useCallStore();\nconst { t } = useLocalI18n(chatPage);\n// The chat follows its locale's direction, not the host page's.\nconst { dir } = useDirection();\n\nconst isInChat = computed(() => chatStore.activeConversationId !== null);\n</script>\n<template>\n <div\n :dir=\"dir\"\n class=\"vue-chat flex w-full h-full max-h-full overflow-hidden font-chat-family text-chat-base text-chat-on-background bg-chat-background\"\n >\n <!-- On phones only one pane shows: the list, or the open conversation. -->\n <div\n class=\"relative h-full flex-1\"\n :class=\"isInChat ? 'block' : 'hidden md:block'\"\n >\n <!-- Each is forwarded only when filled, so ChatView's `$slots[...]` checks stay accurate. -->\n <ChatView v-if=\"isInChat\" :header-options=\"props.headerOptions\">\n <template v-if=\"slots['header-actions']\" #header-actions=\"scope\">\n <slot name=\"header-actions\" v-bind=\"scope\" />\n </template>\n <template v-if=\"slots['conversation-top']\" #conversation-top=\"scope\">\n <slot name=\"conversation-top\" v-bind=\"scope\" />\n </template>\n <template v-if=\"slots['above-input']\" #above-input=\"scope\">\n <slot name=\"above-input\" v-bind=\"scope\" />\n </template>\n </ChatView>\n <div v-else class=\"w-full h-full flex items-center justify-center\">\n <slot name=\"empty\">\n <NoDataDisplay\n :image-path=\"NoChatSelected\"\n :title=\"t('noConversationSelected')\"\n />\n </slot>\n </div>\n </div>\n\n <div\n class=\"h-full w-full shrink-0 border-l border-chat-outline-variant md:w-80\"\n :class=\"isInChat ? 'hidden md:block' : 'block'\"\n >\n <ChatList />\n </div>\n </div>\n <Call v-if=\"props.renderCall && callStore.session\" />\n</template>\n","import type { CallHandlers } from \"../types\";\nimport { useCallStore } from \"../stores/callStore\";\n\n/**\n * Gives the chat its call handlers from inside a component's setup. `createChat({ call })` does\n * the same app-wide; use this when the handlers only exist further down the tree.\n */\nexport function provideCallHandlers(handlers: CallHandlers) {\n useCallStore().setHandlers(handlers);\n}\n","import type { App, Plugin } from \"vue\";\nimport type { Pinia } from \"pinia\";\nimport ToastService from \"primevue/toastservice\";\nimport type {\n CallHandlers,\n ChatHandlers,\n MediaHandlers,\n MessagesHandlers,\n ProfileHandlers,\n} from \"./types\";\nimport { useCallStore } from \"./stores/callStore\";\nimport { useChatStore } from \"./stores/chatStore\";\nimport { useMessagesStore } from \"./stores/messageStores\";\nimport { useMediaStore } from \"./stores/mediaStore\";\nimport { useProfileStore } from \"./stores/profileStore\";\nimport { provideHostI18n } from \"./composables/useHostI18n\";\n\nexport interface ChatUser {\n id: string;\n name: string;\n avatar?: Blob;\n}\n\nexport interface ChatOptions {\n chat: ChatHandlers;\n messages: MessagesHandlers;\n media: MediaHandlers;\n /** Needed for the profile panel's media and files tabs. */\n profile?: ProfileHandlers;\n /** Omit to leave calling out; `provideCallHandlers()` can still supply them later. */\n call?: CallHandlers;\n /** The signed-in user. Can also be set later through `useProfileStore()`. */\n user?: ChatUser;\n}\n\n/**\n * Wires the chat into an app in one call:\n *\n * app.use(createPinia()).use(i18n).use(PrimeVue, { theme }).use(createChat({ chat, messages, media, user }))\n *\n * Pinia, vue-i18n and PrimeVue must be installed first; the stores, translations and UI depend\n * on them.\n */\nexport function createChat(options: ChatOptions): Plugin {\n return {\n install(app: App) {\n const pinia = app.config.globalProperties.$pinia as Pinia | undefined;\n if (!pinia) {\n throw new Error(\n \"[vue-chat] Install Pinia before createChat(): app.use(createPinia()).use(createChat(...))\",\n );\n }\n if (!app.config.globalProperties.$i18n) {\n throw new Error(\n \"[vue-chat] Install vue-i18n (legacy: false) before createChat()\",\n );\n }\n // The UI is built from PrimeVue components, themed by the host's own preset.\n if (!app.config.globalProperties.$primevue) {\n throw new Error(\n \"[vue-chat] Install PrimeVue before createChat(): app.use(PrimeVue, { theme }).use(createChat(...))\",\n );\n }\n // The chat's toasts go through PrimeVue's toast service; hosts that use it already keep theirs.\n if (!app.config.globalProperties.$toast) app.use(ToastService);\n\n // Lets stores translate without a component, so they can be created anywhere.\n provideHostI18n(app);\n\n // Configure each store when it first comes to life, whoever creates it.\n pinia.use(({ store }) => {\n switch (store.$id) {\n case useChatStore.$id:\n store.setHandlers(options.chat);\n break;\n case useMessagesStore.$id:\n store.setHandlers(options.messages);\n break;\n case useMediaStore.$id:\n store.setHandlers(options.media);\n break;\n case useCallStore.$id:\n if (options.call) store.setHandlers(options.call);\n break;\n case useProfileStore.$id:\n if (options.profile) store.setHandlers(options.profile);\n if (options.user) {\n store.userId = options.user.id;\n store.userName = options.user.name;\n store.userAvatar = options.user.avatar;\n }\n break;\n }\n });\n\n },\n };\n}\n","import \"./assets/css/main.css\";\nimport { defineAsyncComponent } from \"vue\";\nimport { useCallStore } from \"./stores/callStore\";\nimport { useChatStore } from \"./stores/chatStore\";\nimport { useMessagesStore } from \"./stores/messageStores\";\nimport { useMediaStore } from \"./stores/mediaStore\";\nimport { useProfileStore } from \"./stores/profileStore\";\n\nexport { default as ChatPage } from \"./components/ChatPage.vue\";\n// Async, so hosts that never call don't download it. Render it while `callStore.session` is set.\nexport const Call = defineAsyncComponent(() => import(\"./components/call/Call.vue\"));\n\n// Building blocks, for hosts that compose their own layout instead of <ChatPage />. They read\n// the same stores, so they work together as long as the handlers are registered.\nexport { default as ChatList } from \"./components/chat/contact/ChatList.vue\";\nexport { default as ChatConversation } from \"./components/chat/ChatView.vue\";\nexport { default as ChatHeader } from \"./components/chat/ChatPageBar.vue\";\nexport { default as ChatMessages } from \"./components/chat/ChatMessages.vue\";\nexport { default as ChatInput } from \"./components/chat/ChatInput.vue\";\nexport { default as ChatBubble } from \"./components/chat/ChatBubble.vue\";\n\nexport { default as BVirtualVerticalList } from \"./components/global/BVirtualVerticalList.vue\";\nexport { default as BEmojiPicker } from \"./components/global/BEmojiPicker.vue\";\nexport { default as BIcon } from \"./components/global/BIcon.vue\";\n\nexport * from \"./types\";\nexport * from \"./stores/messageStores\";\nexport * from \"./stores/chatStore\";\nexport * from \"./stores/mediaStore\";\nexport * from \"./stores/profileStore\";\n\nexport { messageMedia } from \"./utils/media\";\nexport { provideCallHandlers } from \"./provider/callProvider\";\nexport { createChat } from \"./plugin\";\nexport type { ChatOptions, ChatUser } from \"./plugin\";\n\nexport {\n useChatStore,\n useCallStore,\n useMessagesStore,\n useMediaStore,\n useProfileStore,\n};\n\n/**\n * Forgets everything the chat loaded for the signed-in user: conversations, threads, drafts,\n * shared media, the downloaded-file cache, and the running call, which is ended. Call it when the\n * user changes (sign-out, switching accounts) while the app keeps running; the stores outlive\n * pages, so the next user would otherwise see the previous one's conversations. The handlers the\n * host registered stay. Call it before the next user's chat mounts: a list loads when it mounts\n * empty.\n */\nexport async function resetChat(): Promise<void> {\n useCallStore().reset();\n useMessagesStore().reset();\n useProfileStore().reset();\n useChatStore().reset();\n await useMediaStore().clearCache();\n}\n"],"names":["clear","members","search","result","file","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_createVNode","_unref","$slots","_hoisted_4","_renderSlot","_createElementVNode","MediaImage","_hoisted_3","_toDisplayString","_mergeProps","_normalizeClass","_normalizeStyle","_Fragment","_renderList","_vShow","_createBlock","_resolveDynamicComponent","draft","_withDirectives","ContactAvatar","_hoisted_5","_hoisted_6","SafeEmojiText","$attrs","BIcon","_useModel","IconButton","filters","ChatListSearch","ContactSkeleton","_withCtx","ChatContactDisplay","_hoisted_7","_hoisted_8","_hoisted_9","NoDataDisplay","NoData","_normalizeProps","_guardReactiveProps","ResponsiveDialog","formatDuration","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_createTextVNode","FileDisplay","title","sentOn","ViewerImage","ViewerVideo","MediaThumb","TILE","readers","request","status","LoadingStatus","FileFormatDisplay","sending","UploadProgressOverlay","_withModifiers","BubbleDivider","BubbleSelectionMark","BubbleRequest","_toHandlers","ReplyPreview","BubbleMeta","VoiceDisplay","BubbleMedia","BubbleVideo","BubbleStatus","MediaViewer","BubbleOptions","id","options","FloatingDateHeader","ChatBubble","MessagesSkeleton","NoMessages","ScrollToBottomButton","ConfirmModal","caption","_a","send","AttachementFileDisplay","VideoRecordDisplay","InputActionBar","RecordButton","InputAttachement","RecordingStatus","chatInput","ChatProfileOverview","ChatPageBar","ChatInput","PermissionPopup","Call","ChatView","ChatList"],"mappings":"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"}