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..6374f485f 100644 --- a/src/composables/useCurrentViewers.ts +++ b/src/composables/useCurrentViewers.ts @@ -16,7 +16,21 @@ 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 || + v.state === ChannelViewState.Editing + ) + .map(v => v.userId) + ) + + const inactiveViewingUsers = computed(() => + currentViewers.value + .filter(v => v.state === ChannelViewState.None) + .map(v => v.userId) + ) /** * チャンネルで入力中の人のIDの一覧(新しい順) @@ -36,7 +50,7 @@ const useCurrentViewers = (channelId: Ref) => { }) // NOTE: 再接続時にはCHANNEL_VIEWERS_CHANGEDが送られてくる - return { viewingUsers, typingUsers } + return { viewingUsers, typingUsers, inactiveViewingUsers } } export default useCurrentViewers 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) }) }