Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/components/Dashboard/TalkDashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { EventBus } from '../../services/EventBus.ts'
import { useActorStore } from '../../stores/actor.ts'
import { useDashboardStore } from '../../stores/dashboard.ts'
import { hasUnreadMentions } from '../../utils/conversation.ts'
import { convertToUnix } from '../../utils/formattedTime.ts'
import { copyConversationLinkToClipboard } from '../../utils/handleUrl.ts'

const supportsUpcomingReminders = hasTalkFeature('local', 'upcoming-reminders')
Expand Down Expand Up @@ -141,7 +142,7 @@ async function startMeeting() {
roomName: conversationName.value || t('spreed', 'Meeting'),
roomType: CONVERSATION.TYPE.PUBLIC,
objectType: CONVERSATION.OBJECT_TYPE.INSTANT_MEETING,
objectId: Math.floor(Date.now() / 1000).toString(),
objectId: convertToUnix(new Date()).toString(),
})
await copyConversationLinkToClipboard(conversation.token)
await router.push({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { ATTENDEE, CONVERSATION, PARTICIPANT } from '../../../constants.ts'
import { leaveConversation } from '../../../services/participantsService.js'
import storeConfig from '../../../store/storeConfig.js'
import { findNcActionButton } from '../../../test-helpers.js'
import { convertToUnix } from '../../../utils/formattedTime.ts'

vi.mock('../../../services/participantsService', () => ({
leaveConversation: vi.fn(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { useActorStore } from '../../../../../stores/actor.ts'
import { useIntegrationsStore } from '../../../../../stores/integrations.js'
import { useTokenStore } from '../../../../../stores/token.ts'
import { findNcActionButton, findNcButton } from '../../../../../test-helpers.js'
import { convertToUnix } from '../../../../../utils/formattedTime.ts'

describe('MessageButtonsBar.vue', () => {
const TOKEN = 'XXTOKENXX'
Expand Down Expand Up @@ -65,7 +66,7 @@ describe('MessageButtonsBar.vue', () => {
messageParameters: {},
id: 123,
isReplyable: true,
timestamp: new Date('2020-05-07 09:23:00').getTime() / 1000,
timestamp: convertToUnix(new Date('2020-05-07 09:23:00')),
token: TOKEN,
systemMessage: '',
messageType: MESSAGE.TYPE.COMMENT,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { EventBus } from '../../../../services/EventBus.ts'
import storeConfig from '../../../../store/storeConfig.js'
import { useActorStore } from '../../../../stores/actor.ts'
import { useTokenStore } from '../../../../stores/token.ts'
import { convertToUnix } from '../../../../utils/formattedTime.ts'

let store

Expand Down Expand Up @@ -92,7 +93,7 @@ describe('MessageItem.vue', () => {
messageParameters: {},
id: 123,
isReplyable: true,
timestamp: new Date('2020-05-07 09:23:00').getTime() / 1000,
timestamp: convertToUnix(new Date('2020-05-07 09:23:00')),
token: TOKEN,
systemMessage: '',
messageType: MESSAGE.TYPE.COMMENT,
Expand Down Expand Up @@ -483,7 +484,7 @@ describe('MessageItem.vue', () => {
})

test('does not render actions for temporary messages', async () => {
messageProps.message.timestamp = 0
messageProps.message.id = 'temp-123'

const wrapper = mountMessage(messageProps)

Expand Down Expand Up @@ -594,7 +595,7 @@ describe('MessageItem.vue', () => {
})

test('displays the message already with a spinner while sending it', () => {
messageProps.message.timestamp = 0
messageProps.message.id = 'temp-123'
const wrapper = mountMessage(messageProps)
const message = wrapper.findComponent(NcRichText)
expect(message.text()).toBe('test message')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ import { EventBus } from '../../../../services/EventBus.ts'
import { useActorStore } from '../../../../stores/actor.ts'
import { useChatExtrasStore } from '../../../../stores/chatExtras.ts'
import { getItemTypeFromMessage } from '../../../../utils/getItemTypeFromMessage.ts'
import { isTemporaryId } from '../../../../utils/message.ts'

const LocationCard = defineAsyncComponent(() => import('./MessagePart/LocationCard.vue'))

Expand Down Expand Up @@ -187,7 +188,7 @@ export default {
},

isTemporary() {
return !this.isScheduledMessage && this.message.timestamp === 0
return !this.isScheduledMessage && isTemporaryId(this.message.id)
},

isDeletedMessage() {
Expand Down Expand Up @@ -332,7 +333,7 @@ export default {
}

return this.message.id === this.message.threadId
|| this.message.id.toString().startsWith('temp-')
|| isTemporaryId(this.message.id)
|| (this.isScheduledMessage && this.message.threadId === -1)
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ import { useChatExtrasStore } from '../../../../../stores/chatExtras.ts'
import { usePollsStore } from '../../../../../stores/polls.ts'
import { useUploadStore } from '../../../../../stores/upload.ts'
import { formatDateTime } from '../../../../../utils/formattedTime.ts'
import { isTemporaryId } from '../../../../../utils/message.ts'
import { parseMentions, parseSpecialSymbols } from '../../../../../utils/textParse.ts'

// Regular expression to check for Unicode emojis in message text
Expand Down Expand Up @@ -410,7 +411,7 @@ export default {
},

isTemporary() {
return !this.isScheduledMessage && this.message.timestamp === 0
return !this.isScheduledMessage && isTemporaryId(this.message.id)
},

isScheduledSendingFailure() {
Expand Down
3 changes: 2 additions & 1 deletion src/components/MessagesList/MessagesList.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import router from '../../__mocks__/router.js'
import { ATTENDEE, MESSAGE } from '../../constants.ts'
import storeConfig from '../../store/storeConfig.js'
import { useChatStore } from '../../stores/chat.ts'
import { convertToUnix } from '../../utils/formattedTime.ts'

vi.mock('vuex', async () => {
const vuex = await vi.importActual('vuex')
Expand Down Expand Up @@ -48,7 +49,7 @@ vi.mock('../../composables/useGetMessages.ts', async () => ({
})),
}))

const fakeTimestamp = (value) => new Date(value).getTime() / 1000
const fakeTimestamp = (value) => convertToUnix(new Date(value))

describe('MessagesList.vue', () => {
const TOKEN = 'XXTOKENXX'
Expand Down
5 changes: 1 addition & 4 deletions src/components/MessagesList/MessagesList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ export default {
if (!this.messagesShouldBeGrouped(message, lastMessage)) {
groupId = message.id
if (message.timestamp === 0) {
// This is a temporary message, the timestamp is today
// This is a scheduled message that failed to send, the timestamp is today
dateTimestamp = this.currentDay
} else {
dateTimestamp = convertToUnix(new Date(message.timestamp * 1000).setHours(0, 0, 0, 0))
Expand Down Expand Up @@ -625,9 +625,6 @@ export default {
* @return {object} Date object
*/
getDateOfMessage(message) {
if (message.id.toString().startsWith('temp-')) {
return new Date()
}
return new Date(message.timestamp * 1000)
},

Expand Down
11 changes: 6 additions & 5 deletions src/composables/__tests__/useMessageInfo.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useStore } from 'vuex'
import { ATTENDEE, CONVERSATION, MESSAGE } from '../../constants.ts'
import { useActorStore } from '../../stores/actor.ts'
import { useGuestNameStore } from '../../stores/guestName.ts'
import { convertToUnix } from '../../utils/formattedTime.ts'
import { useConversationInfo } from '../useConversationInfo.ts'
import { useMessageInfo } from '../useMessageInfo.ts'

Expand Down Expand Up @@ -49,7 +50,7 @@ describe('message actions', () => {
messageParameters: {},
id: 123,
isReplyable: true,
timestamp: new Date('2024-05-01 16:15:00').getTime() / 1000,
timestamp: convertToUnix(new Date('2024-05-01 16:15:00')),
token: TOKEN,
systemMessage: '',
messageType: MESSAGE.TYPE.COMMENT,
Expand Down Expand Up @@ -78,7 +79,7 @@ describe('message actions', () => {

test('message is not deleteable when it is older than 6 hours and unlimited capability is disabled', () => {
// Arrange
message.value.timestamp = new Date('2024-05-01 7:20:00').getTime() / 1000
message.value.timestamp = convertToUnix(new Date('2024-05-01 7:20:00'))
// Act
const result = useMessageInfo(message)
// Assert
Expand Down Expand Up @@ -173,7 +174,7 @@ describe('message actions', () => {

test('can edit own message in note to self', () => {
// Arrange
message.value.timestamp = new Date('2024-04-28 7:20:00').getTime() / 1000
message.value.timestamp = convertToUnix(new Date('2024-04-28 7:20:00'))
conversationProps.type = CONVERSATION.TYPE.NOTE_TO_SELF
// Act
const result = useMessageInfo(message)
Expand Down Expand Up @@ -368,11 +369,11 @@ describe('message actions', () => {
messageParameters: {},
id: 123,
isReplyable: true,
lastEditTimestamp: new Date('2024-05-01 16:30:00').getTime() / 1000,
lastEditTimestamp: convertToUnix(new Date('2024-05-01 16:30:00')),
lastEditActorId: 'user-id-1',
lastEditActorType: ATTENDEE.ACTOR_TYPE.USERS,
lastEditActorDisplayName: 'user-display-name-1',
timestamp: new Date('2024-05-01 16:15:00').getTime() / 1000,
timestamp: convertToUnix(new Date('2024-05-01 16:15:00')),
token: TOKEN,
systemMessage: '',
messageType: MESSAGE.TYPE.COMMENT,
Expand Down
3 changes: 2 additions & 1 deletion src/store/conversationsStore.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import { setConversationUnread, updateLastReadMessage } from '../services/messag
import { useActorStore } from '../stores/actor.ts'
import { useTalkHashStore } from '../stores/talkHash.js'
import { generateOCSErrorResponse, generateOCSResponse } from '../test-helpers.js'
import { convertToUnix } from '../utils/formattedTime.ts'
import storeConfig from './storeConfig.js'

vi.mock('../services/conversationsService', () => ({
Expand Down Expand Up @@ -1021,7 +1022,7 @@ describe('conversationsStore', () => {
vi.useRealTimers()

const changedConversation = store.getters.conversation(testToken)
expect(changedConversation.lastActivity).toBe(mockDate.getTime() / 1000)
expect(changedConversation.lastActivity).toBe(convertToUnix(mockDate))
})
})

Expand Down
8 changes: 4 additions & 4 deletions src/store/messagesStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import { useSharedItemsStore } from '../stores/sharedItems.ts'
import CancelableRequest from '../utils/CancelableRequest.ts'
import { debugTimer } from '../utils/debugTimer.ts'
import { convertToUnix } from '../utils/formattedTime.ts'
import { isHiddenSystemMessage } from '../utils/message.ts'
import { isHiddenSystemMessage, isTemporaryId } from '../utils/message.ts'

/**
* Returns whether the given message contains a mention to self, directly
Expand Down Expand Up @@ -166,7 +166,7 @@ const getters = {

return Object.values(state.messages[token]).filter((message) => {
return message.referenceId === referenceId
&& ('' + message.id).startsWith('temp-')
&& isTemporaryId(message.id)
})
},

Expand All @@ -188,7 +188,7 @@ const getters = {

return getters.messagesList(token).find((message) => {
return message.id >= readMessageId
&& !String(message.id).startsWith('temp-')
&& !isTemporaryId(message.id)
&& !isHiddenSystemMessage(message)
})?.id
},
Expand All @@ -201,7 +201,7 @@ const getters = {
return getters.messagesList(token).findLast((message) => {
return message.id < readMessageId
&& isMessageVisible(message.id)
&& !String(message.id).startsWith('temp-')
&& !isTemporaryId(message.id)
&& !isHiddenSystemMessage(message)
})?.id
},
Expand Down
3 changes: 2 additions & 1 deletion src/store/participantsStore.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { useGuestNameStore } from '../stores/guestName.ts'
import { useSessionStore } from '../stores/session.ts'
import { useTokenStore } from '../stores/token.ts'
import { generateOCSErrorResponse, generateOCSResponse } from '../test-helpers.js'
import { convertToUnix } from '../utils/formattedTime.ts'
import participantsStore from './participantsStore.js'
import storeConfig from './storeConfig.js'

Expand Down Expand Up @@ -1002,7 +1003,7 @@ describe('participantsStore', () => {
*/
function prepareTestJoinWithMaxPingAge(lastPingAge, inCall) {
const mockDate = new Date('2020-01-01 20:00:00')
participantData.lastPing = mockDate.getTime() / 1000 - lastPingAge
participantData.lastPing = convertToUnix(mockDate) - lastPingAge
participantData.inCall = inCall

vi.useFakeTimers().setSystemTime(mockDate)
Expand Down
7 changes: 4 additions & 3 deletions src/stores/__tests__/callView.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { CONVERSATION } from '../../constants.ts'
import BrowserStorage from '../../services/BrowserStorage.js'
import vuexStore from '../../store/index.js'
import { convertToUnix } from '../../utils/formattedTime.ts'
import { useCallViewStore } from '../callView.ts'

vi.mock('../../services/BrowserStorage.js', () => ({
Expand Down Expand Up @@ -267,19 +268,19 @@ describe('callViewStore', () => {
})

it('sets timeout if timestamp is lesser than 10 seconds', () => {
callViewStore.setCallHasJustEnded(Date.now() / 1000 - 3)
callViewStore.setCallHasJustEnded(convertToUnix(Date.now()) - 3)
expect(callViewStore.callHasJustEnded).toBeTruthy()
})

it('does not set timeout if timestamp is bigger than 10 seconds', () => {
callViewStore.setCallHasJustEnded(Date.now() / 1000 - 15)
callViewStore.setCallHasJustEnded(convertToUnix(Date.now()) - 15)
expect(callViewStore.callHasJustEnded).toBeFalsy()
})

it('resets callHasJustEnded after passed time', () => {
// Arrange
vi.useFakeTimers()
callViewStore.setCallHasJustEnded(Date.now() / 1000 - 2)
callViewStore.setCallHasJustEnded(convertToUnix(Date.now()) - 2)
expect(callViewStore.callHasJustEnded).toBeTruthy()
// Skip 4 seconds
vi.advanceTimersByTime(4000)
Expand Down
20 changes: 17 additions & 3 deletions src/stores/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import type {
import { defineStore } from 'pinia'
import { reactive } from 'vue'
import { useStore } from 'vuex'
import { isHiddenSystemMessage } from '../utils/message.ts'
import { isHiddenSystemMessage, isTemporaryId } from '../utils/message.ts'
import { useChatExtrasStore } from './chatExtras.ts'

type GetMessagesListOptions = {
Expand Down Expand Up @@ -57,7 +57,7 @@ function checkIfBelongsToContext(message: ChatMessage, threadId?: number): boole
// In thread context, only thread messages with given threadId are allowed
? threadId === message.threadId
// In main context, only non-thread messages, topmost thread messages and temporary messages are allowed
: (!message.isThread || message.id === message.threadId || message.id.toString().startsWith('temp-'))
: (!message.isThread || message.id === message.threadId || isTemporaryId(message.id))
}

/**
Expand Down Expand Up @@ -123,7 +123,21 @@ export const useChatStore = defineStore('chat', () => {
* @param threadId
*/
function prepareMessagesList(token: string, block: Set<number>, threadId?: number): ChatMessage[] {
return Array.from(block).sort((a, b) => a - b)
return Array.from(block)
.sort((a, b) => {
const aIsTemporary = isTemporaryId(a)
const bIsTemporary = isTemporaryId(b)
if (aIsTemporary !== bIsTemporary) {
// Temporary messages always sorted to the end
return aIsTemporary ? 1 : -1
} else if (aIsTemporary) {
// Temporary messages are not sorted between themselves
return 0
} else {
// Numeric id messages have incremental order
return a - b
}
})
.reduce<ChatMessage[]>((acc, id) => {
const message = store.state.messagesStore.messages[token][id]
// Check for exceptions (message should not be added to the displayed list):
Expand Down
3 changes: 2 additions & 1 deletion src/utils/__tests__/prepareTemporaryMessage.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { ATTENDEE, MESSAGE } from '../../constants.ts'
import { convertToUnix } from '../formattedTime.ts'
import { prepareTemporaryMessage } from '../prepareTemporaryMessage.ts'

describe('prepareTemporaryMessage', () => {
Expand Down Expand Up @@ -40,7 +41,7 @@ describe('prepareTemporaryMessage', () => {
reactions: {},
referenceId: expect.stringMatching(/^[a-zA-Z0-9]{64}$/),
systemMessage: '',
timestamp: 0,
timestamp: convertToUnix(new Date('2020-01-01T20:00:00')),
token: TOKEN,
silent: false,
threadId: undefined,
Expand Down
9 changes: 9 additions & 0 deletions src/utils/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,15 @@ export function isFileShareMessage(message: ChatMessage): boolean {
return Object.keys(message.messageParameters ?? {}).some((key) => key.startsWith('file'))
}

/**
* Returns whether the given id belongs to a temporary message
*
* @param id message id
*/
export function isTemporaryId(id: ChatMessage['id'] | string): boolean {
return id.toString().startsWith('temp-')
}

/**
* Returns whether the given system message should be hidden in the UI
*
Expand Down
3 changes: 2 additions & 1 deletion src/utils/prepareTemporaryMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import Hex from 'crypto-js/enc-hex.js'
import SHA256 from 'crypto-js/sha256.js'
import { MESSAGE } from '../constants.ts'
import { hasTalkFeature } from '../services/CapabilitiesManager.ts'
import { convertToUnix } from './formattedTime.ts'

export type RawTemporaryMessagePayload = Pick<ChatMessage, | 'message'
| 'token'
Expand Down Expand Up @@ -129,7 +130,7 @@ export function prepareTemporaryMessage({
// @ts-expect-error: type 'string' is not assignable to type 'number'
id: tempId,
token,
timestamp: 0,
timestamp: convertToUnix(date),
expirationTimestamp: 0,
systemMessage: '',
markdown: hasTalkFeature(token, 'markdown-messages'),
Expand Down
Loading