Newer
Older
navi-1 / webclient / src / components / sidebar / SessionList.vue
<template>
  <div class="session-list-wrap">
    <div
      v-if="!visibleSessions.length && !sessionsStore.loading"
      class="empty-sessions"
    >
      <i class="ph ph-chat-dots"></i>
      <p>No conversations yet</p>
    </div>

    <RecycleScroller
      v-else
      class="session-scroller"
      :items="visibleSessions"
      :item-size="74"
      key-field="session_id"
    >
      <template #default="{ item }">
        <SessionItem
          :session="item"
          :active="item.session_id === chatStore.currentId"
          @select="onSelect(item)"
          @delete="onDelete(item)"
          @pin="onPin(item)"
        />
      </template>
    </RecycleScroller>
  </div>
</template>

<script setup>
import { computed } from 'vue'
import { RecycleScroller } from 'vue-virtual-scroller'
import 'vue-virtual-scroller/dist/vue-virtual-scroller.css'
import { useSessionsStore } from '@/stores/sessions.js'
import { useChatStore } from '@/stores/chat.js'
import { useProfilesStore } from '@/stores/profiles.js'
import SessionItem from './SessionItem.vue'

const emit = defineEmits(['select'])

const sessionsStore = useSessionsStore()
const chatStore = useChatStore()
const profilesStore = useProfilesStore()

const visibleSessions = computed(() => {
  const pid = profilesStore.selectedProfileId
  if (!pid) return sessionsStore.sessions
  return sessionsStore.sessions.filter(s => s.profile_id === pid)
})

async function onSelect(session) {
  await chatStore.loadSession(session.session_id)
  emit('select', session)
}

async function onDelete(session) {
  const wasActive = session.session_id === chatStore.currentId
  await sessionsStore.deleteSession(session.session_id)
  if (wasActive && sessionsStore.sessions.length) {
    await chatStore.loadSession(sessionsStore.sessions[0].session_id)
  }
}

async function onPin(session) {
  await sessionsStore.pinSession(session.session_id, !session.pinned)
}
</script>

<style scoped>
.session-list-wrap {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.session-scroller {
  flex: 1;
  overflow-y: auto;
}

.empty-sessions {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 32px 16px;
  color: var(--color-text-dark, #787c99);
  font-size: 13px;

  i { font-size: 32px; opacity: 0.4; }
  p { margin: 0; }
}
</style>