This commit is contained in:
Henry Jameson 2026-07-21 18:25:56 +03:00
commit 2871326c35
9 changed files with 79 additions and 46 deletions

View file

@ -17,7 +17,6 @@ export const paramsString = (params = {}) => {
}
})()
const arrays = []
const nonArrays = []

View file

@ -7,9 +7,9 @@ import ChatMessageDate from 'src/components/chat_message_date/chat_message_date.
import Gallery from 'src/components/gallery/gallery.vue'
import LinkPreview from 'src/components/link-preview/link-preview.vue'
import Popover from 'src/components/popover/popover.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
import StatusBody from 'src/components/status_body/status_body.vue'
import StatusActionButtons from 'src/components/status_action_buttons/status_action_buttons.vue'
import StatusBody from 'src/components/status_body/status_body.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
import UserAvatar from 'src/components/user_avatar/user_avatar.vue'
import UserPopover from 'src/components/user_popover/user_popover.vue'
@ -28,7 +28,14 @@ library.add(faTimes, faEllipsisH, faCircleNotch)
const ChatMessage = {
name: 'ChatMessage',
props: ['edited', 'noHeading', 'previousItem', 'chatItem', 'previousItem', 'hoveredMessageChain'],
props: [
'edited',
'noHeading',
'previousItem',
'chatItem',
'previousItem',
'hoveredMessageChain',
],
emits: ['hover', 'replyRequested'],
components: {
Popover,
@ -40,7 +47,8 @@ const ChatMessage = {
Gallery,
LinkPreview,
ChatMessageDate,
UserPopover,},
UserPopover,
},
computed: {
// Returns HH:MM (hours and minutes) in local time.
createdAt() {
@ -74,10 +82,14 @@ const ChatMessage = {
console.log('==')
console.log('PREV', toValue(this.previousItem.data.raw_html))
console.log('CURR', toValue(this.chatItem.data.raw_html))
return this.previousItem.data.id !== this.chatItem.data.in_reply_to_status_id
return (
this.previousItem.data.id !== this.chatItem.data.in_reply_to_status_id
)
},
customReplyTo() {
return find(this.$store.state.statuses.allStatuses, { id: this.chatItem.data.in_reply_to_status_id })
return find(this.$store.state.statuses.allStatuses, {
id: this.chatItem.data.in_reply_to_status_id,
})
},
messageForStatusContent() {
return {

View file

@ -51,6 +51,9 @@ const Chat = {
ChatTitle,
PostStatusForm,
},
props: {
testMode: Boolean,
},
data() {
return {
// Main info
@ -76,6 +79,7 @@ const Chat = {
}
},
created() {
if (this.testMode) return
this.startFetching()
window.addEventListener('resize', this.handleResize)
},
@ -210,13 +214,16 @@ const Chat = {
if (!isNewMessage) return
await readChat({
id: this.chat.id,
lastReadId,
credentials: useOAuthStore().token,
})
if (!this.testMode)
await readChat({
id: this.chat.id,
lastReadId,
credentials: useOAuthStore().token,
})
useChatsStore().readChat(this.chat.id)
this.lastReadMessageId = this.maxId
this.newMessageCount = 0
},
bottomedOut(offset) {
return isBottomedOut(offset)
@ -224,24 +231,27 @@ const Chat = {
reachedTop() {
return window.scrollY <= 0
},
cullOlder() {
const maxIndex = this.messages.length
const minIndex = maxIndex - 50
if (maxIndex <= 50) return
this.messages = sortBy(this.messages, ['id'])
this.minId = this.messages[minIndex].id
for (const message of this.messages) {
if (message.id < this.minId) {
delete this.messagesIndex[message.id]
delete this.idempotencyKeyIndex[message.idempotency_key]
}
}
this.messages = this.messages.slice(minIndex, maxIndex)
},
cullOlderCheck() {
window.setTimeout(() => {
if (this.bottomedOut(JUMP_TO_BOTTOM_BUTTON_VISIBILITY_OFFSET)) {
const maxIndex = this.messages.length
const minIndex = maxIndex - 50
if (maxIndex <= 50) return
this.messages = sortBy(this.messages, ['id'])
this.minId = this.messages[minIndex].id
for (const message of this.messages) {
if (message.id < this.minId) {
delete this.messagesIndex[message.id]
delete this.idempotencyKeyIndex[message.idempotency_key]
}
}
this.messages = this.messages.slice(minIndex, maxIndex)
this.cullOlder()
}
}, 5000)
},
@ -354,11 +364,12 @@ const Chat = {
this.fetchChat({ isFirstFetch: true })
},
async deleteChatMessage({ chatId, messageId }) {
await deleteChatMessage({
chatId,
messageId,
credentials: useOAuthStore().token,
})
if (!this.testMode)
await deleteChatMessage({
chatId,
messageId,
credentials: useOAuthStore().token,
})
this.messages = this.messages.filter((m) => m.id !== messageId)
delete this.messagesIndex[messageId]
@ -406,7 +417,7 @@ const Chat = {
}
if (!this.messagesIndex[message.id] && !isConfirmation(this, message)) {
if (this.lastSeenMessageId < message.id) {
if (this.lastReadMessageId < message.id) {
this.newMessageCount++
}
this.messagesIndex[message.id] = message

View file

@ -2,11 +2,11 @@ import { clone, filter, findIndex, get, reduce } from 'lodash'
import { mapState as mapPiniaState } from 'pinia'
import { mapState } from 'vuex'
import StatusContent from 'src/components/status_content/status_content.vue'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import ChatMessageList from 'src/components/chat_message_list/chat_message_list.vue'
import PostStatusForm from 'src/components/post_status_form/post_status_form.vue'
import QuickFilterSettings from 'src/components/quick_filter_settings/quick_filter_settings.vue'
import QuickViewSettings from 'src/components/quick_view_settings/quick_view_settings.vue'
import StatusContent from 'src/components/status_content/status_content.vue'
import ThreadTree from 'src/components/thread_tree/thread_tree.vue'
import { useInterfaceStore } from 'src/stores/interface'
@ -25,7 +25,13 @@ import {
faTimes,
} from '@fortawesome/free-solid-svg-icons'
library.add(faAngleDoubleDown, faAngleDoubleLeft, faChevronLeft, faReply, faTimes)
library.add(
faAngleDoubleDown,
faAngleDoubleLeft,
faChevronLeft,
faReply,
faTimes,
)
const sortById = (a, b) => {
const idA = a.type === 'retweet' ? a.retweeted_status.id : a.id

View file

@ -7,12 +7,12 @@ import GestureService from '../../services/gesture_service/gesture_service'
import { unseenNotificationsFromStore } from '../../services/notification_utils/notification_utils'
import { useAnnouncementsStore } from 'src/stores/announcements'
import { useChatsStore } from 'src/stores/chats.js'
import { useInstanceStore } from 'src/stores/instance.js'
import { useInstanceCapabilitiesStore } from 'src/stores/instance_capabilities.js'
import { useInterfaceStore } from 'src/stores/interface'
import { useMergedConfigStore } from 'src/stores/merged_config.js'
import { useShoutStore } from 'src/stores/shout'
import { useChatsStore } from 'src/stores/chats.js'
import { library } from '@fortawesome/fontawesome-svg-core'
import {

View file

@ -105,7 +105,9 @@ export default {
return useMergedConfigStore().mergedConfig.hidePostStats
},
buttonInnerClass() {
const buttonStyleClass = this.defaultButtonStyle ? 'button-default' : 'button-unstyled'
const buttonStyleClass = this.defaultButtonStyle
? 'button-default'
: 'button-unstyled'
return [
this.button.name + '-button',
{

View file

@ -42,7 +42,7 @@ export default {
),
),
},
props: ['button', 'status', 'defaultButton','hideLabel'],
props: ['button', 'status', 'defaultButton', 'hideLabel'],
emits: ['emojiPickerShown'],
mounted() {
if (this.button.name === 'mute') {

View file

@ -38,7 +38,7 @@ const StatusActionButtons = {
hideLabels: {
type: Boolean,
default: false,
}
},
},
emits: ['toggleReplying', 'onSuccess', 'onError'],
data() {
@ -64,7 +64,8 @@ const StatusActionButtons = {
},
computed: {
...mapState(useSyncConfigStore, {
userPinnedItems: (store) => new Set(store.prefsStorage.collections.pinnedStatusActions),
userPinnedItems: (store) =>
new Set(store.prefsStorage.collections.pinnedStatusActions),
}),
pinnedItems() {
if (this.fixedPinned) {

View file

@ -1,7 +1,7 @@
import { createTestingPinia } from '@pinia/testing'
import { shallowMount } from '@vue/test-utils'
import { setActivePinia } from 'pinia'
import { createTestingPinia } from '@pinia/testing'
import { HttpResponse, http } from 'msw'
import ChatView from './chat_view.vue'
const message1 = {
@ -32,7 +32,7 @@ const global = {
$store: {
state: {
api: {},
users: {}
users: {},
},
},
$route: {
@ -41,8 +41,10 @@ const global = {
},
},
$router: {
push: () => {}
}
push: () => {
/* noop */
},
},
},
stubs: {
FAIcon: true,