mirror of
https://github.com/PhotonVision/photonvision
synced 2026-07-02 02:51:40 +00:00
Dark mode and minor interface tweaks (#2016)
Co-authored-by: Sam Freund <samf.236@proton.me>
This commit is contained in:
@@ -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"
|
||||
>
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user