From 5b1408fde753f9390748c2999413af025b25a018 Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Sun, 27 Oct 2024 01:11:06 +0900 Subject: [PATCH 1/4] =?UTF-8?q?status=E3=81=8CNone=E3=81=AE=E3=83=A6?= =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=83=BC=E3=81=AF=E5=8F=B3=E4=B8=8A=E3=81=A7?= =?UTF-8?q?=E8=96=84=E3=81=8F=E8=A1=A8=E7=A4=BA=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChannelSidebar/ChannelSidebar.vue | 3 +++ .../ChannelSidebar/ChannelSidebarContent.vue | 2 ++ .../ChannelSidebar/ChannelSidebarHidden.vue | 2 ++ .../ChannelSidebar/ChannelSidebarViewers.vue | 3 +++ .../ChannelSidebarViewersDetail.vue | 18 +++++++++++++++- .../Main/MainView/ChannelView/ChannelView.vue | 5 ++++- .../MainView/DMView/DMSidebar/DMSidebar.vue | 8 ++++++- .../DMView/DMSidebar/DMSidebarContent.vue | 2 ++ .../Main/MainView/DMView/DMView.vue | 4 +++- src/components/UI/UserIcon.vue | 9 ++++++-- src/components/UI/UserIconEllipsisList.vue | 21 ++++++++++++++++++- src/composables/useCurrentViewers.ts | 14 +++++++++++-- 12 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebar.vue b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebar.vue index e98d4b055..ee170c12d 100644 --- a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebar.vue +++ b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebar.vue @@ -10,6 +10,7 @@ v-model:is-viewers-detail-open="isViewersDetailOpen" :channel-id="channelId" :viewer-ids="viewingUsers" + :inactive-viewer-ids="inactiveViewingUsers" :pinned-messages-count="pinnedMessages.length" @move-to-pinned="moveToPinnedPage" @move-to-events="moveToEventsPage" @@ -30,6 +31,7 @@ @@ -31,6 +33,7 @@ import { useModelValueSyncer } from '/@/composables/useModelSyncer' const props = withDefaults( defineProps<{ viewerIds?: readonly UserId[] + inactiveViewerIds?: readonly UserId[] modelValue: boolean }>(), { diff --git a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarViewersDetail.vue b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarViewersDetail.vue index 7d1291865..c6e8c3ece 100644 --- a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarViewersDetail.vue +++ b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarViewersDetail.vue @@ -4,6 +4,14 @@
{{ user.displayName }}
+
+ +
{{ user.displayName }}
+
@@ -18,9 +26,11 @@ import { useUsersStore } from '/@/store/entities/users' const props = withDefaults( defineProps<{ viewerIds?: readonly UserId[] + inactiveViewerIds?: readonly UserId[] }>(), { - viewerIds: () => [] + viewerIds: () => [], + inactiveViewerIds: () => [] } ) @@ -32,6 +42,9 @@ const { usersMap } = useUsersStore() const users = computed(() => props.viewerIds.map(id => usersMap.value.get(id)).filter(isDefined) ) +const inactiveUsers = computed(() => + props.inactiveViewerIds.map(id => usersMap.value.get(id)).filter(isDefined) +) diff --git a/src/components/UI/UserIconEllipsisList.vue b/src/components/UI/UserIconEllipsisList.vue index 401c732dc..c36c419b8 100644 --- a/src/components/UI/UserIconEllipsisList.vue +++ b/src/components/UI/UserIconEllipsisList.vue @@ -15,6 +15,16 @@ > +{{ inVisibleCount }} + [], + inactiveUserIds: () => [], borderWidth: 4, iconSize: 40 as const, overlap: 12, @@ -91,7 +103,14 @@ const styles = computed(() => { const visibleIconIds = computed(() => [...props.userIds].reverse().slice(0, props.max) ) -const inVisibleCount = computed(() => props.userIds.length - props.max) +const visibleInactiveIconIds = computed(() => + [...props.inactiveUserIds] + .reverse() + .slice(0, props.max - visibleIconIds.value.length) +) +const inVisibleCount = computed( + () => props.userIds.length + props.inactiveUserIds.length - props.max +) const onCountClick = () => { if (props.countClickable) { diff --git a/src/composables/useCurrentViewers.ts b/src/composables/useCurrentViewers.ts index 37aacbada..984df0650 100644 --- a/src/composables/useCurrentViewers.ts +++ b/src/composables/useCurrentViewers.ts @@ -16,7 +16,17 @@ const useCurrentViewers = (channelId: Ref) => { /** * チャンネルを見ている人(入力中、バックグラウンド表示中も含む)のIDの一覧(古い順) */ - const viewingUsers = computed(() => currentViewers.value.map(v => v.userId)) + const viewingUsers = computed(() => + currentViewers.value + .filter(v => v.state === ChannelViewState.Monitoring) + .map(v => v.userId) + ) + + const inactiveViewingUsers = computed(() => + currentViewers.value + .filter(v => v.state === ChannelViewState.None) + .map(v => v.userId) + ) /** * チャンネルで入力中の人のIDの一覧(新しい順) @@ -36,7 +46,7 @@ const useCurrentViewers = (channelId: Ref) => { }) // NOTE: 再接続時にはCHANNEL_VIEWERS_CHANGEDが送られてくる - return { viewingUsers, typingUsers } + return { viewingUsers, typingUsers, inactiveViewingUsers } } export default useCurrentViewers From 858dcf05658add9e6236b7c07cc51ac22fa3bb7f Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Sun, 27 Oct 2024 01:39:05 +0900 Subject: [PATCH 2/4] =?UTF-8?q?=E3=83=95=E3=82=A9=E3=83=BC=E3=82=AB?= =?UTF-8?q?=E3=82=B9=E3=81=AE=E6=9C=89=E7=84=A1=E3=81=A7status=E3=82=92?= =?UTF-8?q?=E5=88=87=E3=82=8A=E5=88=86=E3=81=91=E3=82=8B=E3=82=88=E3=81=86?= =?UTF-8?q?=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/composables/useViewStateSender.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/views/composables/useViewStateSender.ts b/src/views/composables/useViewStateSender.ts index c584b8cb7..3bab0bca4 100644 --- a/src/views/composables/useViewStateSender.ts +++ b/src/views/composables/useViewStateSender.ts @@ -57,11 +57,31 @@ const useViewStateSender = () => { } changeViewState(currentChannelId.value, ChannelViewState.None) } + const focusListeiner = () => { + if (!currentChannelId.value) { + changeViewState(null) + return + } + changeViewState(currentChannelId.value, state.value) + } + + const blurListeiner = () => { + if (!currentChannelId.value) { + changeViewState(null) + return + } + changeViewState(currentChannelId.value, ChannelViewState.None) + } + onMounted(() => { document.addEventListener('visibilitychange', visibilitychangeListener) + window.addEventListener('focus', focusListeiner) + window.addEventListener('blur', blurListeiner) }) onUnmounted(() => { document.removeEventListener('visibilitychange', visibilitychangeListener) + window.removeEventListener('focus', focusListeiner) + window.removeEventListener('blur', blurListeiner) }) } From fa5ac654d0a2b3f91a72cdfc2fdd1f3022423e5c Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Sun, 27 Oct 2024 04:40:02 +0900 Subject: [PATCH 3/4] =?UTF-8?q?=E3=83=A1=E3=83=83=E3=82=BB=E3=83=BC?= =?UTF-8?q?=E3=82=B8=E3=81=8C=E8=BF=BD=E5=8A=A0=E3=81=95=E3=82=8C=E3=81=9F?= =?UTF-8?q?=E3=81=A8=E3=81=8D=E3=81=AE=E6=8C=99=E5=8B=95=E3=82=92=E6=94=B9?= =?UTF-8?q?=E5=96=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChannelViewContentMain.vue | 16 ++++++++++++++-- .../MessagesScroller/MessagesScroller.vue | 15 ++++++++++++--- .../composables/useMessagesFetcher.ts | 4 ++++ src/composables/useCurrentViewers.ts | 6 +++++- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/src/components/Main/MainView/ChannelView/ChannelViewContent/ChannelViewContentMain.vue b/src/components/Main/MainView/ChannelView/ChannelViewContent/ChannelViewContentMain.vue index 90e131e4c..17539ec37 100644 --- a/src/components/Main/MainView/ChannelView/ChannelViewContent/ChannelViewContentMain.vue +++ b/src/components/Main/MainView/ChannelView/ChannelViewContent/ChannelViewContentMain.vue @@ -86,6 +86,9 @@ const { onLoadAroundMessagesRequest } = useChannelMessageFetcher(scrollerEle, props) +const { unreadChannelsMap, deleteUnreadChannelWithSend } = + useSubscriptionStore() + const { messagesMap } = useMessagesStore() const firstUnreadMessageId = computed(() => { if (!unreadSince.value) return '' @@ -114,9 +117,18 @@ const messagePinnedUserMap = computed( () => new Map(props.pinnedMessages.map(pin => [pin.message.id, pin.userId])) ) -const { unreadChannelsMap } = useSubscriptionStore() const resetIsReachedLatest = () => { - if (!unreadChannelsMap.value.get(props.channelId)) return + const unread = unreadChannelsMap.value.get(props.channelId) + if (unread === undefined) return + //最後まで読み込まれている時は「ここから未読」の位置を修正し、未読を消す。 + //TODO: 関数名とやってることが違いすぎるので、どうにかする。今日はもう眠いので寝る。 + if ( + unread.updatedAt === + messagesMap.value.get(messageIds.value.at(-1) ?? '')?.createdAt + ) { + unreadSince.value = unread.since + deleteUnreadChannelWithSend(props.channelId) + } isReachedLatest.value = false } diff --git a/src/components/Main/MainView/MessagesScroller/MessagesScroller.vue b/src/components/Main/MainView/MessagesScroller/MessagesScroller.vue index dd139fb99..c698e57f1 100644 --- a/src/components/Main/MainView/MessagesScroller/MessagesScroller.vue +++ b/src/components/Main/MainView/MessagesScroller/MessagesScroller.vue @@ -191,7 +191,6 @@ watch( (ids, prevIds) => { if (!rootRef.value) return /* state.height の更新を忘れないようにすること */ - const newHeight = rootRef.value.scrollHeight if ( props.lastLoadingDirection === 'latest' || @@ -206,7 +205,6 @@ watch( if (ids.length - prevIds.length === 0) { const scrollBottom = rootRef.value.scrollTop + rootRef.value.clientHeight - // 一番下のメッセージあたりを見ているときに、 // 新規に一つ追加された場合は一番下までスクロール if (state.height - 50 <= scrollBottom) { @@ -246,16 +244,27 @@ const requestLoadMessages = () => { const handleScroll = throttle(17, requestLoadMessages) const visibilitychangeListener = () => { + emit('resetIsReachedLatest') if (document.visibilityState === 'visible') { - requestLoadMessages() + nextTick(requestLoadMessages) } +} +const focusListener = () => { + emit('resetIsReachedLatest') + nextTick(requestLoadMessages) +} +const blurListener = () => { emit('resetIsReachedLatest') } onMounted(() => { document.addEventListener('visibilitychange', visibilitychangeListener) + window.addEventListener('focus', focusListener) + window.addEventListener('blur', blurListener) }) onUnmounted(() => { document.removeEventListener('visibilitychange', visibilitychangeListener) + window.removeEventListener('focus', focusListener) + window.removeEventListener('blur', blurListener) }) const { onClick } = useMarkdownInternalHandler() diff --git a/src/components/Main/MainView/MessagesScroller/composables/useMessagesFetcher.ts b/src/components/Main/MainView/MessagesScroller/composables/useMessagesFetcher.ts index 0a3ee9a5f..a4f7ad1c9 100644 --- a/src/components/Main/MainView/MessagesScroller/composables/useMessagesFetcher.ts +++ b/src/components/Main/MainView/MessagesScroller/composables/useMessagesFetcher.ts @@ -114,6 +114,10 @@ const useMessageFetcher = ( isLoading.value = false isInitialLoad.value = false lastLoadingDirection.value = 'latter' + // 一番新しいメッセージに達した時は`latest`にする + if (isReachedLatest.value) { + lastLoadingDirection.value = 'latest' + } messageIds.value = [...new Set([...messageIds.value, ...newMessageIds])] } ) diff --git a/src/composables/useCurrentViewers.ts b/src/composables/useCurrentViewers.ts index 984df0650..6374f485f 100644 --- a/src/composables/useCurrentViewers.ts +++ b/src/composables/useCurrentViewers.ts @@ -18,7 +18,11 @@ const useCurrentViewers = (channelId: Ref) => { */ const viewingUsers = computed(() => currentViewers.value - .filter(v => v.state === ChannelViewState.Monitoring) + .filter( + v => + v.state === ChannelViewState.Monitoring || + v.state === ChannelViewState.Editing + ) .map(v => v.userId) ) From 68d238f3e8c5616d6328a183c10e387f796ebbd2 Mon Sep 17 00:00:00 2001 From: nokhnaton Date: Sun, 27 Oct 2024 13:01:57 +0900 Subject: [PATCH 4/4] =?UTF-8?q?=E6=9C=80=E6=96=B0=E3=83=A1=E3=83=83?= =?UTF-8?q?=E3=82=BB=E3=83=BC=E3=82=B8=E3=82=92=E8=AA=AD=E3=81=BF=E8=BE=BC?= =?UTF-8?q?=E3=82=93=E3=81=A0=E3=81=A8=E3=81=8D=E3=81=AB=E3=82=B9=E3=82=AF?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E3=83=AB=E3=81=8C=E4=B8=8A=E3=81=AB=E5=90=B9?= =?UTF-8?q?=E3=81=8D=E9=A3=9B=E3=81=B6=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ChannelViewContentMain.vue | 5 ++- .../MessagesScroller/MessagesScroller.vue | 33 ++++++++++--------- .../composables/useMessagesFetcher.ts | 4 --- 3 files changed, 20 insertions(+), 22 deletions(-) diff --git a/src/components/Main/MainView/ChannelView/ChannelViewContent/ChannelViewContentMain.vue b/src/components/Main/MainView/ChannelView/ChannelViewContent/ChannelViewContentMain.vue index 17539ec37..daf5f099b 100644 --- a/src/components/Main/MainView/ChannelView/ChannelViewContent/ChannelViewContentMain.vue +++ b/src/components/Main/MainView/ChannelView/ChannelViewContent/ChannelViewContentMain.vue @@ -12,7 +12,7 @@ @request-load-former="onLoadFormerMessagesRequest" @request-load-latter="onLoadLatterMessagesRequest" @scroll-passive="handleScroll" - @reset-is-reached-latest="resetIsReachedLatest" + @window-viewd="onWindowViewd" >