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 @@
@@ -57,6 +59,7 @@ const props = defineProps<{
isSidebarOpenerReady: boolean
pinnedMessages: Pin[]
viewingUsers: UserId[]
+ inactiveViewingUsers: UserId[]
}>()
const { channelsMap } = useChannelsStore()
diff --git a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarContent.vue b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarContent.vue
index 8da728d95..a26d79cdc 100644
--- a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarContent.vue
+++ b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarContent.vue
@@ -3,6 +3,7 @@
(),
diff --git a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarHidden.vue b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarHidden.vue
index 8d99f2bb8..43bd49b8b 100644
--- a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarHidden.vue
+++ b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarHidden.vue
@@ -13,6 +13,7 @@
count-clickable
show-count
:user-ids="viewerIds"
+ :inactive-user-ids="inactiveViewerIds"
:class="$style.rest"
@count-click="emit('openViewers')"
/>
@@ -27,6 +28,7 @@ import type { UserId } from '/@/types/entity-ids'
withDefaults(
defineProps<{
viewerIds?: readonly UserId[]
+ inactiveViewerIds?: readonly UserId[]
}>(),
{
viewerIds: () => []
diff --git a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarViewers.vue b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarViewers.vue
index 7ff71789d..a74227f1e 100644
--- a/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarViewers.vue
+++ b/src/components/Main/MainView/ChannelView/ChannelSidebar/ChannelSidebarViewers.vue
@@ -9,12 +9,14 @@
direction="row"
transition="fade-right"
:user-ids="viewerIds"
+ :inactive-user-ids="inactiveViewerIds"
@toggle="toggle"
/>
@@ -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)
})
}