-
+
@@ -90,6 +90,7 @@ import { topbarHeight } from '@/store/variables'
import { mdiAlertOctagonOutline, mdiContentSave, mdiFileUpload, mdiClose, mdiCloseThick } from '@mdi/js'
import EmergencyStopDialog from '@/components/dialogs/EmergencyStopDialog.vue'
import InlineSvg from 'vue-inline-svg'
+import ThemeMixin from '@/components/mixins/theme'
type uploadSnackbar = {
status: boolean
@@ -112,7 +113,7 @@ type uploadSnackbar = {
TheNotificationMenu,
},
})
-export default class TheTopbar extends Mixins(BaseMixin) {
+export default class TheTopbar extends Mixins(BaseMixin, ThemeMixin) {
mdiAlertOctagonOutline = mdiAlertOctagonOutline
mdiContentSave = mdiContentSave
mdiFileUpload = mdiFileUpload
@@ -188,12 +189,8 @@ export default class TheTopbar extends Mixins(BaseMixin) {
return this.$store.state.gui.uiSettings.boolHideUploadAndPrintButton ?? false
}
- get sidebarLogo(): string {
- return this.$store.getters['files/getSidebarLogo']
- }
-
get isSvgLogo() {
- return this.sidebarLogo.includes('.svg?timestamp=')
+ return this.sidebarLogo.includes('.svg?timestamp=') || this.sidebarLogo.endsWith('.svg')
}
get logoColor(): string {
diff --git a/src/components/mixins/theme.ts b/src/components/mixins/theme.ts
index fee4bfb5b..b3f612a8a 100644
--- a/src/components/mixins/theme.ts
+++ b/src/components/mixins/theme.ts
@@ -12,6 +12,18 @@ export default class ThemeMixin extends Vue {
return this.fgColor(alpha, !this.$vuetify.theme.dark)
}
+ get themeName() {
+ return this.$store.getters['gui/theme']
+ }
+
+ get theme() {
+ return this.$store.getters['gui/getTheme']
+ }
+
+ get themeMode() {
+ return this.$store.state.gui.uiSettings.mode ?? 'dark'
+ }
+
get fgColorHi() {
return this.fgColor(0.8)
}
@@ -42,6 +54,40 @@ export default class ThemeMixin extends Vue {
}
get sidebarBgImage() {
+ if (this.theme.sidebarBackground?.show) {
+ if (this.theme.sidebarBackground?.light && this.themeMode === 'light')
+ return `/img/themes/sidebarBackground-${this.themeName}-light.png`
+
+ return `/img/themes/sidebarBackground-${this.themeName}.png`
+ }
+
return this.$vuetify.theme.dark ? '/img/sidebar-background.svg' : '/img/sidebar-background-light.svg'
}
+
+ get sidebarLogo(): string {
+ const url = this.$store.getters['files/getSidebarLogo']
+ if (url !== '' || this.themeName === 'mainsail') return url
+
+ // if no theme is set, return empty string to load the default logo
+ if (!(this.theme.logo?.show ?? false)) return ''
+
+ // return light logo if theme is light and sidebarLogo is set to both
+ if (this.theme.logo?.light && this.themeMode === 'light')
+ return `/img/themes/sidebarLogo-${this.themeName}-light.svg`
+
+ // return dark/generic theme logo
+ return `/img/themes/sidebarLogo-${this.themeName}.svg`
+ }
+
+ get mainBgImage() {
+ const url = this.$store.getters['files/getMainBackground']
+ if (url || this.themeName === 'mainsail') return url
+
+ if (!this.theme.mainBackground?.show) return null
+
+ if (this.theme.mainBackground?.light && this.themeMode === 'light')
+ return `/img/themes/mainBackground-${this.themeName}-light.png`
+
+ return `/img/themes/mainBackground-${this.themeName}.png`
+ }
}
diff --git a/src/components/settings/SettingsUiSettingsTab.vue b/src/components/settings/SettingsUiSettingsTab.vue
index cef4286d9..dcba86ff4 100644
--- a/src/components/settings/SettingsUiSettingsTab.vue
+++ b/src/components/settings/SettingsUiSettingsTab.vue
@@ -2,6 +2,12 @@
+
+
+
+
@@ -276,34 +282,42 @@
diff --git a/src/locales/en.json b/src/locales/en.json
index 50ba5a85f..69b336d68 100644
--- a/src/locales/en.json
+++ b/src/locales/en.json
@@ -1221,6 +1221,8 @@
"Logo": "Logo",
"ManualProbeDialog": "Manual Probe Helper Dialog",
"ManualProbeDialogDescription": "Display helper dialog for PROBE_CALIBRATE or Z_ENDSTOP_CALIBRATE.",
+ "Mode": "Mode",
+ "ModeDescription": "Change the overall look and feel of the application.",
"NavigationStyle": "Navigation style",
"NavigationStyleDescription": "Change navigation appearance",
"NavigationStyleIconsAndText": "Icons + Text",
@@ -1238,7 +1240,7 @@
"TempchartHeightDescription": "Modify the height of the temperature chart on the Dashboard.",
"Theme": "Theme",
"ThemeDark": "Dark",
- "ThemeDescription": "Change the overall look and feel of the application",
+ "ThemeDescription": "Customizes the branding of the interface.",
"ThemeLight": "Light",
"UiSettings": "UI-Settings"
},
diff --git a/src/main.ts b/src/main.ts
index 13127500a..7cff4da1c 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -35,7 +35,7 @@ import { DatasetComponent, GridComponent, LegendComponent, TooltipComponent } fr
import 'vue-resize/dist/vue-resize.css'
// @ts-ignore
import VueResize from 'vue-resize'
-import { defaultTheme } from './store/variables'
+import { defaultMode } from './store/variables'
Vue.config.productionTip = false
@@ -80,9 +80,9 @@ const initLoad = async () => {
await setAndLoadLocale(file.defaultLocale as string)
}
- // Handle theme outside of store init and before vue mount for consistency in dialog
- const theme = file.defaultTheme ?? defaultTheme
- vuetify.framework.theme.dark = theme !== 'light'
+ // Handle mode outside store init and before vue mount for consistency in dialog
+ const mode = file.defaultMode ?? defaultMode
+ vuetify.framework.theme.dark = mode !== 'light'
} catch (e) {
window.console.error('Failed to load config.json')
window.console.error(e)
diff --git a/src/store/gui/getters.ts b/src/store/gui/getters.ts
index bdd6c980a..5975dab59 100644
--- a/src/store/gui/getters.ts
+++ b/src/store/gui/getters.ts
@@ -1,10 +1,24 @@
import { GetterTree } from 'vuex'
import { GuiState } from '@/store/gui/types'
import { GuiMacrosStateMacrogroup } from '@/store/gui/macros/types'
-import { allDashboardPanels } from '@/store/variables'
+import { allDashboardPanels, defaultTheme, themes } from '@/store/variables'
+import { Theme } from '@/store/types'
// eslint-disable-next-line
export const getters: GetterTree = {
+ theme: (state): string => {
+ const theme = state.uiSettings.theme
+
+ // return defaultTheme, if theme doesnt exists
+ if (themes.findIndex((tmp: Theme) => tmp.name === theme) === -1) return defaultTheme
+
+ return theme
+ },
+
+ getTheme: (state, getters): Theme => {
+ return themes.find((theme: Theme) => theme.name === getters.theme) ?? themes[0]
+ },
+
getDatasetValue: (state) => (payload: { name: string; type: string }) => {
if (
payload.name in state.view.tempchart.datasetSettings &&
diff --git a/src/store/gui/index.ts b/src/store/gui/index.ts
index 5241a333a..6f94a5344 100644
--- a/src/store/gui/index.ts
+++ b/src/store/gui/index.ts
@@ -3,7 +3,13 @@ import { Module } from 'vuex'
import { actions } from '@/store/gui/actions'
import { mutations } from '@/store/gui/mutations'
import { getters } from '@/store/gui/getters'
-import { defaultTheme, defaultLogoColor, defaultPrimaryColor, defaultBigThumbnailBackground } from '@/store/variables'
+import {
+ defaultTheme,
+ defaultLogoColor,
+ defaultPrimaryColor,
+ defaultBigThumbnailBackground,
+ defaultMode,
+} from '@/store/variables'
// load modules
import { console } from '@/store/gui/console'
@@ -150,6 +156,7 @@ export const getDefaultState = (): GuiState => {
entries: [],
},
uiSettings: {
+ mode: defaultMode,
theme: defaultTheme,
logo: defaultLogoColor,
primary: defaultPrimaryColor,
diff --git a/src/store/gui/types.ts b/src/store/gui/types.ts
index d54ab0203..a1bef68e2 100644
--- a/src/store/gui/types.ts
+++ b/src/store/gui/types.ts
@@ -98,7 +98,8 @@ export interface GuiState {
presets?: GuiPresetsState
remoteprinters?: GuiRemoteprintersState
uiSettings: {
- theme: 'dark' | 'light'
+ mode: 'dark' | 'light'
+ theme: string
logo: string
primary: string
displayCancelPrint: boolean
diff --git a/src/store/types.ts b/src/store/types.ts
index 8efa504a2..f0aeea56b 100644
--- a/src/store/types.ts
+++ b/src/store/types.ts
@@ -38,3 +38,22 @@ export interface ConfigJsonInstance {
port?: number
path?: string
}
+
+export interface Theme {
+ name: string
+ displayName: string
+ colorLogo: string
+ colorPrimary?: string
+ logo?: {
+ show: boolean
+ light: boolean
+ }
+ sidebarBackground?: {
+ show: boolean
+ light: boolean
+ }
+ mainBackground?: {
+ show: boolean
+ light: boolean
+ }
+}
diff --git a/src/store/variables.ts b/src/store/variables.ts
index 4db839504..3f4a91c4a 100644
--- a/src/store/variables.ts
+++ b/src/store/variables.ts
@@ -1,4 +1,7 @@
-export const defaultTheme = 'dark'
+import { Theme } from '@/store/types'
+
+export const defaultMode = 'dark'
+export const defaultTheme = 'mainsail'
export const defaultLogoColor = '#D41216'
export const defaultPrimaryColor = '#2196f3'
export const defaultBigThumbnailBackground = '#1e1e1e'
@@ -140,3 +143,16 @@ export const genericLogfiles = ['klippy', 'moonraker', 'crowsnest', 'mmu', 'sona
* List of all rollover logfiles
*/
export const rolloverLogfiles = ['klipper', 'moonraker']
+
+/*
+ * List of all Themes
+ */
+export const themes: Theme[] = [
+ { name: 'mainsail', displayName: 'Mainsail', colorLogo: defaultLogoColor },
+ {
+ name: 'klipper',
+ displayName: 'Klipper',
+ colorLogo: '#b12f35',
+ logo: { show: true, light: false },
+ },
+]