Files
openStack/frontend/src/App.vue
T
x3 4fe56265c9
ci / backend (push) Canceled after 0s
ci / frontend (push) Canceled after 0s
feat(frontend): chat tabs, flat SVG icons, upload autosave, per-user rights
- 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
2026-09-22 14:41:42 +02:00

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>