This commit is contained in:
2026-05-23 19:54:03 +09:00
parent c3383b778b
commit 1fd95616a5
46 changed files with 3920 additions and 107 deletions
+91 -17
View File
@@ -7,21 +7,42 @@
<div class="modals-container" />
<main class="layout" v-if="serverInfo.success && account.success">
<main class="layout">
<div class="left-menu">
<div :class='$route.path === "/" ? "isActive" : ""'>
<img :src="serverInfo.icon" />
</div>
<RouterLink
to="/"
:class='$route.path === "/"
? "isActive"
: ""'
>
<img :src='"icon" in serverInfo
? serverInfo.icon
: "/assets/lynqchat.svg"'
/>
</RouterLink>
<div :class='$route.path === "/home" ? "isActive" : ""'>
<Icon icon="material-symbols:home-rounded" />
</div>
<RouterLink
v-for="community of communitys"
:to="`/community/${community.id}`"
:class='$route.path === `/community/${community.id}`
? "isActive"
: ""'
>
<img
v-if="community.icon"
:src="community.icon"
/>
<Icon
v-else
icon="material-symbols:groups-rounded"
/>
</RouterLink>
</div>
<div class="content-main">
<div class="content-header">
{{
$route.meta.title
title
?? (serverInfo.success
? serverInfo.name
: null)
@@ -61,7 +82,8 @@ main.layout {
-webkit-user-select: none;
}
.left-menu div {
.left-menu a {
display: block;
position: relative;
z-index: 0;
border-radius: 0.5rem;
@@ -71,19 +93,20 @@ main.layout {
transition: background-color 200ms ease-out;
}
.left-menu div * {
.left-menu a * {
font-size: 3rem;
padding: 0.25rem;
border-radius: 0.5rem;
width: 3rem;
height: 3rem;
color: var(--text-color);
display: block;
overflow: hidden;
object-fit: contain;
box-sizing: border-box;
}
.left-menu div.isActive::before {
.left-menu a.isActive::before {
content: "";
display: block;
position: absolute;
@@ -96,8 +119,8 @@ main.layout {
background-color: var(--text-color);
}
.left-menu div:hover,
.left-menu div.isActive {
.left-menu a:hover,
.left-menu a.isActive {
background-color: var(--border-color);
}
@@ -122,6 +145,7 @@ main.layout {
}
.route-main {
display: flex;
padding: 1.25rem;
padding-bottom: 0;
overflow: scroll;
@@ -156,16 +180,25 @@ main.layout {
</style>
<script lang="ts" setup>
import { RouterView, useRouter } from "vue-router";
import routerStatus from "@/lib/router";
import { RouterView, RouterLink, useRouter, useRoute } from "vue-router";
import routerStatus, { title } from "@/lib/router";
import { Icon } from "@iconify/vue";
import Progress from "@/components/Progress.vue";
import { account, serverInfo } from "@/lib/account";
import { communitys, serverInfo } from "@/lib/account";
import { onBeforeUnmount, onMounted, watch } from "vue";
import { createModal } from "@/lib/modal";
import ErrorModal from "@/components/Modal/Error.vue";
const router = useRouter();
const route = useRoute();
watch(route, () => {
if (typeof route.meta.title === "string")
title.value = route.meta.title;
});
if (!serverInfo.value.success) {
throw new Error();
throw new Error("サーバー情報の取得に失敗しました。");
}
if (!serverInfo.value.isInitialized) {
@@ -175,4 +208,45 @@ if (!serverInfo.value.isInitialized) {
if (!serverInfo.value.isFirstAdminExists) {
router.replace("/setup/create-admin");
}
function handleError(event: ErrorEvent | PromiseRejectionEvent) {
let content = event instanceof PromiseRejectionEvent
? event.reason
: event;
if (content instanceof Error) {
content = content.message;
}
createModal({
component: ErrorModal,
props: {
error: content ?? "不明なエラー",
canClose: false,
},
});
}
onMounted(async () => {
window.addEventListener("error", handleError);
window.addEventListener("unhandledrejection", handleError);
if ("serviceWorker" in navigator) {
const swFile = import.meta.env.MODE === "production"
? "/sw.js"
: "/dev-sw.js?dev-sw";
navigator.serviceWorker.register(swFile, {
type: import.meta.env.MODE === "production"
? "classic"
: "module",
scope: "/",
});
}
});
onBeforeUnmount(() => {
window.removeEventListener("error", handleError);
window.removeEventListener("unhandledrejection", handleError);
});
</script>