mirror of
https://github.com/sky-systems/sky_phone.git
synced 2026-09-04 09:13:24 +00:00
ADD - share contacts and rich content in chats
This commit is contained in:
@@ -95,6 +95,8 @@ export const useDarkChatStore = defineStore('darkchat', () => {
|
||||
messageType: outgoing.messageType,
|
||||
reactions: {},
|
||||
replyToId: outgoing.replyToId,
|
||||
sharePayload:
|
||||
outgoing.messageType === 'share' ? outgoing.sharePayload : null,
|
||||
}
|
||||
messages.value.push(optimistic)
|
||||
if (outgoing.messageType === 'voice' && outgoing.mediaPayload) {
|
||||
|
||||
@@ -85,6 +85,7 @@ describe('easyshare store', () => {
|
||||
expect(easyShare.consumeChatDraft('messages')).toEqual({
|
||||
appId: 'messages',
|
||||
body: 'Meet at Mission Row.\nhttps://notes.sky/note-1',
|
||||
payload: { ...payload, link: 'https://notes.sky/note-1' },
|
||||
targetId: '5551234567',
|
||||
})
|
||||
expect(easyShare.consumeChatDraft('messages')).toBeNull()
|
||||
@@ -98,6 +99,7 @@ describe('easyshare store', () => {
|
||||
expect(easyShare.consumeChatDraft('darkchat')).toEqual({
|
||||
appId: 'darkchat',
|
||||
body: 'Meet at Mission Row.',
|
||||
payload,
|
||||
targetId: null,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -56,6 +56,7 @@ export const useEasyShareStore = defineStore('easyshare', () => {
|
||||
chatDraft.value = {
|
||||
appId,
|
||||
body: [...new Set(parts)].join('\n'),
|
||||
payload: { ...payload.value },
|
||||
targetId,
|
||||
}
|
||||
return Boolean(chatDraft.value.body)
|
||||
|
||||
@@ -78,6 +78,47 @@ describe('messages store', () => {
|
||||
expect(messages.messages[0].delivery_status).toBe('failed')
|
||||
})
|
||||
|
||||
it('shows a shared contact immediately and sends only its id', async () => {
|
||||
const contact = {
|
||||
avatar_url: 'https://picsum.photos/seed/shared-alex/240/240',
|
||||
name: 'Alex Rivera',
|
||||
organization: 'Maze Bank',
|
||||
phone_number: '4205550137',
|
||||
}
|
||||
const serverMessage: SmsMessage = {
|
||||
...sentMessage('contact-server-id'),
|
||||
body: contact.name,
|
||||
contact,
|
||||
message_type: 'contact',
|
||||
}
|
||||
mockNuiCall
|
||||
.mockResolvedValueOnce({ data: [], success: true })
|
||||
.mockResolvedValueOnce({ data: [], success: true })
|
||||
.mockResolvedValueOnce({ data: serverMessage, success: true })
|
||||
.mockResolvedValueOnce({ data: [], success: true })
|
||||
|
||||
const messages = useMessagesStore()
|
||||
await messages.openThread('4205550196')
|
||||
const sending = messages.send({
|
||||
contact,
|
||||
contactId: 'contact-alex',
|
||||
messageType: 'contact',
|
||||
})
|
||||
|
||||
expect(messages.messages[0]).toMatchObject({
|
||||
contact,
|
||||
delivery_status: 'sending',
|
||||
message_type: 'contact',
|
||||
})
|
||||
|
||||
await sending
|
||||
expect(mockNuiCall).toHaveBeenNthCalledWith(3, 'messages:send', {
|
||||
contactId: 'contact-alex',
|
||||
messageType: 'contact',
|
||||
phoneNumber: '4205550196',
|
||||
})
|
||||
})
|
||||
|
||||
it('normalizes numeric phone data from the NUI boundary', async () => {
|
||||
mockNuiCall.mockResolvedValueOnce({
|
||||
data: [
|
||||
|
||||
@@ -57,8 +57,12 @@ export const useMessagesStore = defineStore('messages', () => {
|
||||
if (!activeNumber.value) return { success: false, error: 'invalid_number' }
|
||||
const clientId = `pending-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
||||
const optimistic: SmsMessage = {
|
||||
body: outgoing.messageType === 'text' ? outgoing.body.trim() : '',
|
||||
body:
|
||||
outgoing.messageType === 'text' || outgoing.messageType === 'share'
|
||||
? outgoing.body?.trim() ?? ''
|
||||
: '',
|
||||
client_id: clientId,
|
||||
contact: outgoing.messageType === 'contact' ? outgoing.contact : null,
|
||||
created_at: new Date().toISOString().slice(0, 19).replace('T', ' '),
|
||||
delivery_status: 'sending',
|
||||
direction: 'sent',
|
||||
@@ -78,6 +82,7 @@ export const useMessagesStore = defineStore('messages', () => {
|
||||
media_waveform:
|
||||
outgoing.messageType === 'voice' ? outgoing.mediaWaveform : null,
|
||||
message_type: outgoing.messageType,
|
||||
share: outgoing.messageType === 'share' ? outgoing.sharePayload : null,
|
||||
read_at: null,
|
||||
recipient_number: activeNumber.value,
|
||||
sender_number: '',
|
||||
@@ -88,10 +93,19 @@ export const useMessagesStore = defineStore('messages', () => {
|
||||
`data:${outgoing.mediaMime};base64,${outgoing.mediaPayload}`
|
||||
}
|
||||
|
||||
const response = await nuiCall<SmsMessage>('messages:send', {
|
||||
...outgoing,
|
||||
phoneNumber: activeNumber.value,
|
||||
})
|
||||
const response = await nuiCall<SmsMessage>(
|
||||
'messages:send',
|
||||
outgoing.messageType === 'contact'
|
||||
? {
|
||||
contactId: outgoing.contactId,
|
||||
messageType: outgoing.messageType,
|
||||
phoneNumber: activeNumber.value,
|
||||
}
|
||||
: {
|
||||
...outgoing,
|
||||
phoneNumber: activeNumber.value,
|
||||
},
|
||||
)
|
||||
const index = messages.value.findIndex(
|
||||
(message) => message.client_id === clientId,
|
||||
)
|
||||
|
||||
@@ -47,6 +47,20 @@ const defaultLocales: LocaleTree = {
|
||||
destinations: 'Share destinations',
|
||||
newMessage: 'New Message',
|
||||
shareProfile: 'Share Profile',
|
||||
kinds: {
|
||||
contact: 'Contact',
|
||||
document: 'Document',
|
||||
link: 'Link',
|
||||
location: 'Location',
|
||||
note: 'Note',
|
||||
photo: 'Photo',
|
||||
playlist: 'Playlist',
|
||||
post: 'Post',
|
||||
profile: 'Profile',
|
||||
text: 'Message',
|
||||
track: 'Track',
|
||||
video: 'Video',
|
||||
},
|
||||
chooseConversation: 'Choose a conversation',
|
||||
sentToChat: 'Sent to chat.',
|
||||
savedToNotes: 'Saved to Notes.',
|
||||
@@ -1122,6 +1136,7 @@ const defaultLocales: LocaleTree = {
|
||||
photo: 'Photo',
|
||||
gif: 'GIF',
|
||||
video: 'Video',
|
||||
contact: 'Contact',
|
||||
attachPhoto: 'Attach Photo',
|
||||
takePhoto: 'Take Photo',
|
||||
attachGif: 'Attach GIF',
|
||||
@@ -1129,6 +1144,10 @@ const defaultLocales: LocaleTree = {
|
||||
photos: 'Photos',
|
||||
gifs: 'GIFs',
|
||||
videos: 'Videos',
|
||||
contacts: 'Contacts',
|
||||
shareContact: 'Share Contact',
|
||||
noContactsToShare: 'Save a contact first to share it here.',
|
||||
contactSaved: 'Contact Saved',
|
||||
noPhotos: 'Take a photo first to attach it here.',
|
||||
noVideos: 'Record a video in Camera first.',
|
||||
searchGifs: 'Search GIPHY',
|
||||
@@ -1172,6 +1191,8 @@ const defaultLocales: LocaleTree = {
|
||||
invalid_message: 'Enter a message.',
|
||||
invalid_voice: 'The audio message is invalid.',
|
||||
invalid_attachment: 'The attachment is invalid.',
|
||||
invalid_contact: 'The contact is invalid.',
|
||||
contact_not_found: 'This contact is no longer available.',
|
||||
media_provider_unconfigured: 'Photo uploads are not configured.',
|
||||
capture_provider_unavailable: 'The screenshot resource is unavailable.',
|
||||
capture_failed: 'The photo could not be captured.',
|
||||
|
||||
Reference in New Issue
Block a user