embystream 0.0.36

Another Emby streaming application (frontend/backend separation) written in Rust.
Documentation
<script setup lang="ts">
import { computed } from "vue";
import { Icon } from "@iconify/vue";
import { useI18n } from "vue-i18n";
import { useRouter } from "vue-router";

import AppWorkspaceShell from "@/components/blocks/AppWorkspaceShell.vue";
import GlassPanel from "@/components/ui/GlassPanel.vue";
import { useDocumentLocale } from "@/composables/useDocumentLocale";
import { useSessionStore } from "@/stores/session";

const { t } = useI18n();
const router = useRouter();
const sessionStore = useSessionStore();

useDocumentLocale();

const groups = computed(() => {
  const workspace = [
    {
      key: "account",
      icon: "ph:user-circle",
      label: t("nav.account"),
      action: () => router.push({ name: "account", query: { from: "more" } }),
    },
    {
      key: "docs",
      icon: "ph:book-open-text",
      label: t("nav.docs"),
      action: () => router.push({ name: "docs", query: { from: "more" } }),
    },
    {
      key: "settings",
      icon: "ph:gear-six",
      label: t("nav.settings"),
      action: () => router.push({ name: "settings", query: { from: "more" } }),
    },
  ];

  const system = sessionStore.isAdmin
    ? [
        {
          key: "logs",
          icon: "ph:receipt",
          label: t("nav.logs"),
          action: () => router.push({ name: "logs", query: { from: "more" } }),
        },
        {
          key: "users",
          icon: "ph:users-three",
          label: t("nav.users"),
          action: () => router.push({ name: "users", query: { from: "more" } }),
        },
      ]
    : [];

  const info = [
    {
      key: "about",
      icon: "ph:seal-check",
      label: t("account.aboutOpen"),
      action: () => router.push({ name: "about", query: { from: "more" } }),
    },
    {
      key: "disclaimer",
      icon: "ph:warning-diamond",
      label: t("common.disclaimer"),
      action: () =>
        router.push({ name: "disclaimer", query: { from: "more" } }),
    },
  ];

  return [
    { key: "workspace", title: t("common.workspace"), items: workspace },
    ...(system.length
      ? [{ key: "system", title: t("common.system"), items: system }]
      : []),
    { key: "info", title: t("common.support"), items: info },
  ];
});
</script>

<template>
  <AppWorkspaceShell
    :body="t('more.body')"
    :eyebrow="t('more.eyebrow')"
    :title="t('more.title')"
  >
    <section class="more-stack">
      <section v-for="group in groups" :key="group.key" class="more-section">
        <p class="section-label">{{ group.title }}</p>

        <GlassPanel class="more-group">
          <button
            v-for="item in group.items"
            :key="item.key"
            class="more-row"
            type="button"
            @click="item.action()"
          >
            <span class="more-row__icon">
              <Icon :icon="item.icon" width="22" />
            </span>
            <span class="more-row__label">{{ item.label }}</span>
            <Icon class="more-row__chevron" icon="ph:caret-right" width="18" />
          </button>
        </GlassPanel>
      </section>
    </section>
  </AppWorkspaceShell>
</template>

<style scoped>
.more-stack {
  display: grid;
  gap: 1rem;
}

.more-section {
  display: grid;
  gap: 0.75rem;
}

.more-group {
  display: grid;
  gap: 0;
  padding: 0.3rem;
  overflow: hidden;
}

.more-row {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  min-height: 4rem;
  border: 0;
  border-radius: 1rem;
  background: transparent;
  box-shadow: none;
}

.more-row + .more-row {
  border-top: 1px solid
    color-mix(in srgb, var(--border-strong) 80%, transparent);
  border-top-left-radius: 0;
  border-top-right-radius: 0;
}

.more-row__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.7rem;
  height: 2.7rem;
  border-radius: 1rem;
  border: 1px solid var(--border-strong);
  background: color-mix(in srgb, var(--bg-soft) 74%, transparent);
  color: var(--text-main);
  flex-shrink: 0;
}

.more-row__label {
  flex: 1;
  text-align: left;
  color: var(--text-main);
  font-size: 1rem;
  font-weight: 700;
}

.more-row__chevron {
  color: var(--text-faint);
}
</style>