- Chat rework: Chats (private DMs with user search, online dots, unread badges) and Team chats tabs; shared message component with reactions, edit, image attachments, message search and typing indicators - Flat modern inline SVG icon set (no external dependency) replaces emoji chrome across nav, headers, buttons, tabs and settings - Uploaded avatar/background images apply instantly (auto-save) with confirmation note; per-user permission matrix in dashboard members - Login localized, invite header uses icon, comment header cleaned
53 lines
1.7 KiB
Vue
53 lines
1.7 KiB
Vue
<script setup>
|
|
import { computed, onMounted } from 'vue';
|
|
import { useAuthStore } from './stores/auth';
|
|
import { useThemeStore } from './stores/theme';
|
|
import { useLocaleStore } from './stores/locale';
|
|
import { useUiStore } from './stores/ui';
|
|
import { fileUrl } from './files';
|
|
import { connectSocket } from './socket';
|
|
import SettingsWindow from './components/SettingsWindow.vue';
|
|
import TimeTrackerButton from './components/TimeTrackerButton.vue';
|
|
import Bell from './components/Bell.vue';
|
|
import Icon from './components/Icon.vue';
|
|
|
|
const auth = useAuthStore();
|
|
const theme = useThemeStore();
|
|
const locale = useLocaleStore();
|
|
const ui = useUiStore();
|
|
|
|
const bgRaw = computed(() => auth.user?.bgImage || '');
|
|
const bgIsImage = computed(() => /^(https?:\/\/|\/uploads|data:)/.test(bgRaw.value));
|
|
const bgStyle = computed(() => {
|
|
if (!bgRaw.value) return {};
|
|
const style = {
|
|
backgroundImage: bgIsImage.value ? `url("${fileUrl(bgRaw.value)}")` : bgRaw.value,
|
|
backgroundSize: 'cover',
|
|
backgroundPosition: 'center',
|
|
};
|
|
if (auth.user?.bgBlur !== false) style.filter = 'blur(16px) brightness(0.9)';
|
|
return style;
|
|
});
|
|
const glassOn = computed(() => !!bgRaw.value && auth.user?.bgGlass !== false);
|
|
|
|
onMounted(() => {
|
|
locale.set(locale.locale);
|
|
theme.apply();
|
|
auth.applyPrefs();
|
|
if (auth.isLoggedIn) connectSocket();
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div :class="{ 'has-bg': !!bgRaw, glass: glassOn }">
|
|
<div v-if="bgRaw" class="bg-layer" :style="bgStyle"></div>
|
|
<div v-if="auth.isLoggedIn" class="top-right">
|
|
<Bell />
|
|
<TimeTrackerButton />
|
|
<button class="ghost icon-btn" @click="ui.openSettings()" title="Settings"><Icon name="settings" /></button>
|
|
</div>
|
|
<router-view />
|
|
<SettingsWindow />
|
|
</div>
|
|
</template>
|