Dark mode and minor interface tweaks (#2016)

Co-authored-by: Sam Freund <samf.236@proton.me>
This commit is contained in:
Devon Doyle
2025-08-04 01:15:33 -04:00
committed by GitHub
parent 3e19cd45cc
commit fce54d12c1
36 changed files with 956 additions and 765 deletions

View File

@@ -6,6 +6,7 @@ import { useStateStore } from "@/stores/StateStore";
<v-snackbar
v-model="useStateStore().snackbarData.show"
location="top"
variant="elevated"
:color="useStateStore().snackbarData.color"
:timeout="useStateStore().snackbarData.timeout"
>

View File

@@ -74,7 +74,7 @@ document.addEventListener("keydown", (e) => {
<template>
<v-dialog v-model="useStateStore().showLogModal" width="1500" dark>
<v-card class="dialog-container pa-5" color="primary" flat>
<v-card class="dialog-container pa-5" color="surface" flat>
<!-- Logs header -->
<v-row class="pb-3">
<v-col cols="4">
@@ -82,7 +82,7 @@ document.addEventListener("keydown", (e) => {
</v-col>
<v-col class="align-self-center pl-3" style="text-align: right">
<v-btn variant="text" color="white" @click="handleLogExport">
<v-icon start class="menu-icon"> mdi-download </v-icon>
<v-icon start class="menu-icon" size="large"> mdi-download </v-icon>
<span class="menu-label">Download</span>
<!-- Special hidden link that gets 'clicked' when the user exports journalctl logs -->
@@ -95,11 +95,11 @@ document.addEventListener("keydown", (e) => {
/>
</v-btn>
<v-btn variant="text" color="white" @click="handleLogClear">
<v-icon start class="menu-icon"> mdi-trash-can-outline </v-icon>
<v-icon start class="menu-icon" size="large"> mdi-trash-can-outline </v-icon>
<span class="menu-label">Clear Client Logs</span>
</v-btn>
<v-btn variant="text" color="white" @click="() => (useStateStore().showLogModal = false)">
<v-icon start class="menu-icon"> mdi-close </v-icon>
<v-icon start class="menu-icon" size="large"> mdi-close </v-icon>
<span class="menu-label">Close</span>
</v-btn>
</v-col>
@@ -110,26 +110,31 @@ document.addEventListener("keydown", (e) => {
<div class="dialog-data">
<!-- Log view options -->
<v-row no-gutters class="pt-4 pt-md-0" style="display: flex; justify-content: space-between">
<v-col cols="12" md="7" style="display: flex; align-items: center">
<v-col cols="12" md="7" style="display: flex; align-items: center" class="pr-3">
<v-text-field
v-model="searchQuery"
density="compact"
clearable
hide-details="auto"
prepend-icon="mdi-magnify"
color="accent"
color="primary"
label="Search"
variant="underlined"
/>
<input v-model="timeInput" type="time" step="1" class="text-white pl-3" />
<v-btn icon variant="flat" @click="timeInput = undefined">
<v-icon>mdi-close-circle-outline</v-icon>
<v-icon>mdi-close</v-icon>
</v-btn>
</v-col>
<v-col v-for="level in [0, 1, 2, 3]" :key="level" class="pr-3">
<div class="pb-0 pt-0" style="display: flex; align-items: center; flex: min-content">
{{ getLogLevelFromIndex(level)
}}<v-switch v-model="selectedLogLevels[level]" class="pl-2" hide-details color="#ffd843"></v-switch>
}}<v-switch
v-model="selectedLogLevels[level]"
class="pl-2"
hide-details
color="rgb(var(--v-theme-primary))"
></v-switch>
</div>
</v-col>
</v-row>
@@ -170,7 +175,7 @@ document.addEventListener("keydown", (e) => {
/* Dialog data size - options */
height: calc(100% - 56px);
padding: 10px;
background-color: #232c37 !important;
background-color: rgb(var(--v-theme-logsBackground)) !important;
border-radius: 5px;
}

View File

@@ -4,7 +4,8 @@ import { useSettingsStore } from "@/stores/settings/GeneralSettingsStore";
import { useStateStore } from "@/stores/StateStore";
import { useCameraSettingsStore } from "@/stores/settings/CameraSettingsStore";
import { useRoute } from "vue-router";
import { useDisplay } from "vuetify";
import { useDisplay, useTheme } from "vuetify";
import { onBeforeMount } from "vue";
const compact = computed<boolean>({
get: () => {
@@ -16,17 +17,32 @@ const compact = computed<boolean>({
});
const { mdAndUp } = useDisplay();
const theme = useTheme();
const changeTheme = () => {
const newTheme = theme.global.name.value === "LightTheme" ? "DarkTheme" : "LightTheme";
theme.global.name.value = newTheme;
localStorage.setItem("theme", newTheme);
};
onBeforeMount(() => {
const storedTheme = localStorage.getItem("theme");
if (storedTheme) {
theme.global.name.value = storedTheme;
}
});
const renderCompact = computed<boolean>(() => compact.value || !mdAndUp.value);
</script>
<template>
<v-navigation-drawer permanent :rail="renderCompact" color="primary">
<v-list nav>
<v-navigation-drawer permanent :rail="renderCompact" color="sidebar">
<v-list nav color="primary">
<!-- List item for the heading; note that there are some tricks in setting padding and image width make things look right -->
<v-list-item :class="renderCompact ? 'pr-0 pl-0' : ''" style="display: flex; justify-content: center">
<template #prepend>
<img v-if="!renderCompact" class="logo" src="@/assets/images/logoLarge.svg" alt="large logo" />
<img v-else class="logo" src="@/assets/images/logoSmall.svg" alt="small logo" />
<img v-else class="logo" src="@/assets/images/logoSmallTransparent.svg" alt="small logo" />
</template>
</v-list-item>
@@ -67,20 +83,35 @@ const renderCompact = computed<boolean>(() => compact.value || !mdAndUp.value);
:prepend-icon="`mdi-chevron-${compact || !mdAndUp ? 'right' : 'left'}`"
@click="() => (compact = !compact)"
>
<v-list-item-title>Compact Mode</v-list-item-title>
<v-list-item-title>Compact</v-list-item-title>
</v-list-item>
<v-list-item
:prepend-icon="
useSettingsStore().network.runNTServer
? 'mdi-server'
: useStateStore().ntConnectionStatus.connected
? 'mdi-robot'
: 'mdi-robot-off'
"
link
:prepend-icon="theme.global.name.value === 'LightTheme' ? 'mdi-white-balance-sunny' : 'mdi-weather-night'"
@click="changeTheme"
>
<v-list-item-title>Theme</v-list-item-title>
</v-list-item>
<v-list-item>
<template #prepend>
<v-icon
:icon="
useSettingsStore().network.runNTServer
? 'mdi-server'
: useStateStore().ntConnectionStatus.connected
? 'mdi-robot'
: 'mdi-robot-off'
"
:color="
useSettingsStore().network.runNTServer || useStateStore().ntConnectionStatus.connected
? '#00ff00'
: '#ff0000'
"
/>
</template>
<v-list-item-title v-if="useSettingsStore().network.runNTServer" v-show="!renderCompact" class="text-wrap">
NetworkTables server running for
<span class="text-accent">{{ useStateStore().ntConnectionStatus.clients || 0 }}</span> clients
<span class="text-primary">{{ useStateStore().ntConnectionStatus.clients || 0 }}</span> clients
</v-list-item-title>
<v-list-item-title
v-else-if="useStateStore().ntConnectionStatus.connected && useStateStore().backendConnected"
@@ -89,9 +120,7 @@ const renderCompact = computed<boolean>(() => compact.value || !mdAndUp.value);
style="flex-direction: column; display: flex"
>
NetworkTables Server Connected!
<span class="text-accent">
{{ useStateStore().ntConnectionStatus.address }}
</span>
<span class="text-primary"> {{ useStateStore().ntConnectionStatus.address }} </span>
</v-list-item-title>
<v-list-item-title
v-else
@@ -102,10 +131,15 @@ const renderCompact = computed<boolean>(() => compact.value || !mdAndUp.value);
Not connected to NetworkTables Server!
</v-list-item-title>
</v-list-item>
<v-list-item :prepend-icon="useStateStore().backendConnected ? 'mdi-server-network' : 'mdi-server-network-off'">
<v-list-item>
<template #prepend>
<v-icon
:icon="useStateStore().backendConnected ? 'mdi-server-network' : 'mdi-server-network-off'"
:color="useStateStore().backendConnected ? '#00ff00' : '#ff0000'"
/>
</template>
<v-list-item-title v-show="!renderCompact" class="text-wrap">
{{ useStateStore().backendConnected ? "Backend connected" : "Trying to connect to backend" }}
{{ useStateStore().backendConnected ? "Backend connected" : "Trying to connect to backend..." }}
</v-list-item-title>
</v-list-item>
</v-list>
@@ -114,6 +148,14 @@ const renderCompact = computed<boolean>(() => compact.value || !mdAndUp.value);
</template>
<style scoped>
.v-navigation-drawer {
border: none;
}
.v-navigation-drawer--rail {
border: none;
}
.v-list-item-title {
font-size: 1rem !important;
line-height: 1.2rem !important;