summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorsyuilo <4439005+syuilo@users.noreply.github.com>2025-04-03 15:34:13 +0900
committersyuilo <4439005+syuilo@users.noreply.github.com>2025-04-03 15:34:13 +0900
commit8b7cba1edeee88695bacefb726f8a5a009c4eeac (patch)
tree57324fcddb012faf1b38e6931cbe2226dd888418 /packages
parentfix: チャット周りの修正 (#15741) (diff)
downloadsharkey-8b7cba1edeee88695bacefb726f8a5a009c4eeac.tar.gz
sharkey-8b7cba1edeee88695bacefb726f8a5a009c4eeac.tar.bz2
sharkey-8b7cba1edeee88695bacefb726f8a5a009c4eeac.zip
🎨
Diffstat (limited to 'packages')
-rw-r--r--packages/frontend/src/pages/chat/room.vue25
-rw-r--r--packages/frontend/src/utility/timeline-date-separate.ts63
2 files changed, 87 insertions, 1 deletions
diff --git a/packages/frontend/src/pages/chat/room.vue b/packages/frontend/src/pages/chat/room.vue
index dcce70ae89..9942dbeee9 100644
--- a/packages/frontend/src/pages/chat/room.vue
+++ b/packages/frontend/src/pages/chat/room.vue
@@ -38,7 +38,14 @@ SPDX-License-Identifier: AGPL-3.0-only
:moveClass="prefer.s.animation ? $style.transition_x_move : ''"
tag="div" class="_gaps"
>
- <XMessage v-for="message in messages.toReversed()" :key="message.id" :message="message"/>
+ <template v-for="item in timeline.toReversed()" :key="item.id">
+ <XMessage v-if="item.type === 'item'" :message="item.data"/>
+ <div v-else-if="item.type === 'date'" :class="$style.dateDivider">
+ <span><i class="ti ti-chevron-up"></i> {{ item.nextText }}</span>
+ <span style="height: 1em; width: 1px; background: var(--MI_THEME-divider);"></span>
+ <span>{{ item.prevText }} <i class="ti ti-chevron-down"></i></span>
+ </div>
+ </template>
</TransitionGroup>
</div>
@@ -101,6 +108,7 @@ import MkButton from '@/components/MkButton.vue';
import { useRouter } from '@/router.js';
import { useMutationObserver } from '@/use/use-mutation-observer.js';
import MkInfo from '@/components/MkInfo.vue';
+import { makeDateSeparatedTimelineComputedRef } from '@/utility/timeline-date-separate.js';
const $i = ensureSignin();
const router = useRouter();
@@ -126,6 +134,7 @@ const room = ref<Misskey.entities.ChatRoom | null>(null);
const connection = ref<Misskey.IChannelConnection<Misskey.Channels['chatUser']> | Misskey.IChannelConnection<Misskey.Channels['chatRoom']> | null>(null);
const showIndicator = ref(false);
const timelineEl = useTemplateRef('timelineEl');
+const timeline = makeDateSeparatedTimelineComputedRef(messages);
const SCROLL_HEAD_THRESHOLD = 200;
@@ -489,4 +498,18 @@ definePage(computed(() => {
transition: opacity 0.5s;
opacity: 0;
}
+
+.dateDivider {
+ display: flex;
+ font-size: 85%;
+ align-items: center;
+ justify-content: center;
+ gap: 0.5em;
+ opacity: 0.75;
+ border: solid 0.5px var(--MI_THEME-divider);
+ border-radius: 999px;
+ width: fit-content;
+ padding: 0.5em 1em;
+ margin: 0 auto;
+}
</style>
diff --git a/packages/frontend/src/utility/timeline-date-separate.ts b/packages/frontend/src/utility/timeline-date-separate.ts
new file mode 100644
index 0000000000..f9876a20ff
--- /dev/null
+++ b/packages/frontend/src/utility/timeline-date-separate.ts
@@ -0,0 +1,63 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { computed } from 'vue';
+import type { Ref } from 'vue';
+
+function getDateText(dateInstance: Date) {
+ const date = dateInstance.getDate();
+ const month = dateInstance.getMonth() + 1;
+ return `${month.toString()}/${date.toString()}`;
+}
+
+export type DateSeparetedTimelineItem<T> = {
+ id: string;
+ type: 'item';
+ data: T;
+} | {
+ id: string;
+ type: 'date';
+ prev: Date;
+ prevText: string;
+ next: Date;
+ nextText: string;
+};
+
+export function makeDateSeparatedTimelineComputedRef<T extends { id: string; createdAt: string; }>(items: Ref<T[]>) {
+ return computed<DateSeparetedTimelineItem<T>[]>(() => {
+ const tl: DateSeparetedTimelineItem<T>[] = [];
+ for (let i = 0; i < items.value.length; i++) {
+ const item = items.value[i];
+
+ const date = new Date(item.createdAt);
+ const nextDate = items.value[i + 1] ? new Date(items.value[i + 1].createdAt) : null;
+
+ tl.push({
+ id: item.id,
+ type: 'item',
+ data: item,
+ });
+
+ if (
+ i !== items.value.length - 1 &&
+ nextDate != null && (
+ date.getFullYear() !== nextDate.getFullYear() ||
+ date.getMonth() !== nextDate.getMonth() ||
+ date.getDate() !== nextDate.getDate()
+ )
+ ) {
+ tl.push({
+ id: `date-${item.id}`,
+ type: 'date',
+ prev: date,
+ prevText: getDateText(date),
+ next: nextDate,
+ nextText: getDateText(nextDate),
+ });
+ }
+ }
+ return tl;
+ });
+}