diff --git a/frontend/src/App.vue b/frontend/src/App.vue index c97b84c..a21e397 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -31,6 +31,7 @@ import { useAccountStore } from '@/stores/account' import { useMailStore } from '@/stores/mail' import { useMessagesStore } from '@/stores/messages' import { useDarkChatStore } from '@/stores/darkchat' +import { useFlareStore } from '@/stores/flare' import { useFlipTokStore } from '@/stores/fliptok' import { useMediaStore } from '@/stores/media' import { useMarketplaceStore } from '@/stores/marketplace' @@ -61,6 +62,7 @@ type AppMessage = { | MarketplaceEventData | MessagesEventData | DarkChatEventData + | FlareEventData | FlipTokVerificationData | FlipTokNotificationData | PhoneCall @@ -100,6 +102,15 @@ type DarkChatEventData = { title?: string } +type FlareEventData = { + body?: string + device?: PhoneNotificationDevicePayload + matchId?: string + sender?: string + text?: string + title?: string +} + type MarketplaceEventData = { counts?: MarketplaceCounts device?: PhoneNotificationDevicePayload @@ -147,6 +158,7 @@ const banking = useBankingStore() const mail = useMailStore() const messages = useMessagesStore() const darkchat = useDarkChatStore() +const flare = useFlareStore() const fliptok = useFlipTokStore() const media = useMediaStore() const marketplace = useMarketplaceStore() @@ -441,6 +453,44 @@ function onMessage(event: MessageEvent): void { } notifications.show(notification) } + } else if ( + (event.data?.type === 'flare:new-match' || + event.data?.type === 'flare:new-message') && + event.data.data + ) { + const data = event.data.data as FlareEventData + void flare.bootstrap() + if ( + data.matchId && + event.data.type === 'flare:new-message' && + flare.activeMatchId === data.matchId + ) { + void flare.loadThread(data.matchId) + } + const notification: PhoneNotificationInput = { + appId: 'flare', + subtitle: data.sender, + text: + data.text ?? + phone.t( + event.data.type === 'flare:new-match' + ? 'Apps.flare.newMatchNotification' + : 'Apps.flare.newMessageNotification', + { sender: data.sender ?? '' }, + ), + title: data.title ?? phone.t('Apps.flare.name'), + } + if ( + data.device && + (!phone.isOpen || data.device.imei !== phone.device?.imei) + ) { + notification.device = { + imei: data.device.imei, + name: data.device.name, + preferences: parsePhonePreferences(data.device.settings ?? null), + } + } + notifications.show(notification) } else if (event.data?.type === 'calls:changed') { void calls.loadRecents() } else if (event.data?.type === 'banking:changed') { diff --git a/frontend/src/assets/img/app-icons/flare.svg b/frontend/src/assets/img/app-icons/flare.svg new file mode 100644 index 0000000..3cad880 --- /dev/null +++ b/frontend/src/assets/img/app-icons/flare.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/frontend/src/assets/img/flare/profiles-source.png b/frontend/src/assets/img/flare/profiles-source.png new file mode 100644 index 0000000..b376352 Binary files /dev/null and b/frontend/src/assets/img/flare/profiles-source.png differ diff --git a/frontend/src/components/MessageAttachmentBubble.vue b/frontend/src/components/MessageAttachmentBubble.vue index a8372f1..729eaed 100644 --- a/frontend/src/components/MessageAttachmentBubble.vue +++ b/frontend/src/components/MessageAttachmentBubble.vue @@ -2,9 +2,15 @@ import { Camera, Pause, Play } from 'lucide-vue-next' import { computed, ref } from 'vue' -import type { SmsMessage } from '@/types/messages' +import type { SmsMessageType } from '@/types/messages' -const props = defineProps<{ message: SmsMessage }>() +type MessageAttachment = { + media_asset_id: string | null + media_duration_ms: number | null + message_type: SmsMessageType +} + +const props = defineProps<{ message: MessageAttachment }>() const playing = ref(false) const video = ref() @@ -66,7 +72,13 @@ function durationLabel(milliseconds: number | null): string { class="messages-attachment messages-attachment--image" :style="{ background }" > - +
- GIF + GIF