Seperate themes and layouts into seperate settings #63

Merged
twig merged 13 commits from better-themes into main 2025-08-05 21:47:20 +00:00
5 changed files with 72 additions and 48 deletions
Showing only changes of commit 37ebcb74aa - Show all commits

View file

@ -9,14 +9,13 @@
<script lang="ts" setup>
import ContextMenu from '~/components/UserInterface/ContextMenu.vue';
import type { ContextMenuInterface } from './types/interfaces';
import loadPreferredTheme from '~/utils/loadPreferredTheme';
const banner = useState("banner", () => false);
const contextMenu = useState<ContextMenuInterface>("contextMenu");
onMounted(() => {
loadPreferredTheme()
loadPreferredThemes()
document.removeEventListener("contextmenu", contextMenuHandler);
document.addEventListener("contextmenu", (e) => {

View file

@ -7,7 +7,9 @@
<p class="subtitle">STYLES</p>
<div class="styles">
<div v-for="style of styles" class="theme-preview-container">
<div class="theme-instance" :title="style.displayName">
<span class="theme-instance"
:title="style.displayName"
@click="changeTheme(StyleLayout.style, style)">
<div class="theme-content-container">
<span class="style-background"
:style="{background:`linear-gradient(${style.previewGradient})`}"
@ -16,13 +18,15 @@
{{ style.displayName }}
</span>
</div>
</div>
</span>
</div>
</div>
<p class="subtitle">LAYOUTS</p>
<div class="layouts">
<div v-for="layout of layouts" class="theme-preview-container">
<div class="theme-instance" :title="layout.displayName">
<div class="theme-instance"
:title="layout.displayName"
@click="changeTheme(StyleLayout.layout, layout)">
<div class="theme-content-container">
<span class="layout-background"
:style="{backgroundImage:`url(${layout.previewImageUrl})`}"
@ -51,8 +55,7 @@
<script lang="ts" setup>
import RadioButtons from '~/components/UserInterface/RadioButtons.vue';
import type { TimeFormat } from '~/types/settings';
import loadPreferredTheme from '~/utils/loadPreferredTheme';
import settingSave from '~/utils/settingSave';
import { settingSave, settingsLoad } from '#imports';
const runtimeConfig = useRuntimeConfig()
const baseURL = runtimeConfig.app.baseURL;
@ -61,15 +64,27 @@ const layoutFolder = `${baseURL}themes/layout`
const timeFormatTextStrings = ["Auto", "12-Hour", "24-Hour"]
enum StyleLayout {
style,
twig marked this conversation as resolved Outdated

Enum options should use PascalCase

Enum options should use PascalCase
twig marked this conversation as resolved Outdated

Both enum and enum options should use PascalCase/CamelCase, that's what I meant.

enum StyleLayout  {
  Style,
  Layout
}
Both _enum_ and enum _options_ should use PascalCase/CamelCase, that's what I meant. ```ts enum StyleLayout { Style, Layout } ```

okay this makes more sense

okay this makes more sense
layout
}
interface Theme {
displayName: string
complementaryColor: string
cssData: string
themeUrl: string
previewGradient?: string
previewImageUrl?: string
}
async function parseThemeCss(styleData: string): Promise<Theme | void> {
async function parseTheme(url: string): Promise<Theme | void> {
const styleData: any = await $fetch(url)
if (typeof styleData != "string") {
return
}
const metadataMatch = styleData.match(/\/\*([\s\S]*?)\*\//);
if (!metadataMatch) {
alert(`Failed to fetch metadata for a theme, panicing`)
@ -113,18 +128,18 @@ async function parseThemeCss(styleData: string): Promise<Theme | void> {
displayName,
complementaryColor,
cssData,
themeUrl: url,
previewGradient,
previewImageUrl,
}
}
async function parseThemeData(
async function parseThemeLayout(
folder: string,
incomingThemeList: Array<string>,
outputThemeList: Array<Theme>) {
twig marked this conversation as resolved Outdated

string[] instead of Array<string>

`string[]` instead of `Array<string>`
for (const theme of incomingThemeList) {
twig marked this conversation as resolved Outdated

string[] instead of Array<string>

`string[]` instead of `Array<string>`
const themeData = await $fetch(`${folder}/${theme}`)
const parsedThemeData = await parseThemeCss(themeData)
const parsedThemeData = await parseTheme(`${folder}/${theme}`)
if (parsedThemeData) {
outputThemeList.push(parsedThemeData)
@ -139,18 +154,19 @@ const styleList: any = await $fetch(`${styleFolder}/styles.json`)
const layoutList: any = await $fetch(`${layoutFolder}/layouts.json`)
twig marked this conversation as resolved Outdated

Avoid use of any

Avoid use of `any`
twig marked this conversation as resolved Outdated

Avoid use of any

Avoid use of `any`
if (Array.isArray(styleList)) {
await parseThemeData(styleFolder, styleList, styles)
await parseThemeLayout(styleFolder, styleList, styles)
}
if (Array.isArray(layoutList)) {
await parseThemeData(layoutFolder, layoutList, layouts)
await parseThemeLayout(layoutFolder, layoutList, layouts)
}
console.log(layouts)
function changeTheme(id: string, url: string) {
settingSave("selectedThemeStyle", id)
loadPreferredTheme()
function changeTheme(themeType: StyleLayout, theme: Theme) {
if (themeType == StyleLayout.style) {
settingSave("selectedThemeStyle", theme.themeUrl)
} else {
settingSave("selectedThemeLayout", theme.themeUrl)
}
loadPreferredThemes()
}
async function onTimeFormatClicked(index: number) {

View file

@ -1,6 +1,7 @@
export interface ClientSettings {
selectedThemeId?: string, // the ID of the theme, not the URL, for example "dark"
timeFormat?: TimeFormat
selectedThemeStyle?: string // URL
selectedThemeLayout?: string // URL
}
export interface TimeFormat {

View file

@ -1,28 +0,0 @@
let themeLinkElement: HTMLLinkElement | null;
export default function loadPreferredTheme() {
const currentTheme = settingsLoad().selectedThemeId ?? "dark"
if (themeLinkElement) {
themeLinkElement.href = getThemeUrl(currentTheme);
} else {
// create the theme link if one doesn't already exist
useHead({
link: [{
id: "main-theme",
rel: "stylesheet",
href: getThemeUrl(currentTheme)
}]
})
themeLinkElement = document.getElementById('main-theme') as HTMLLinkElement;
}
}
function getThemeUrl(id: string): string {
const runtimeConfig = useRuntimeConfig()
const baseURL = runtimeConfig.app.baseURL;
// this should preferrably use version hash, but that's not implemented yet
return `${baseURL}themes/style/${id}.css?v=${runtimeConfig.public.buildTimeString}`
}

View file

@ -0,0 +1,36 @@
let styleLinkElement: HTMLLinkElement | null;
let layoutLinkElement: HTMLLinkElement | null;
export default function loadPreferredThemes() {
const runtimeConfig = useRuntimeConfig()
const baseURL = runtimeConfig.app.baseURL;
const currentStyle = settingsLoad().selectedThemeStyle ?? `${baseURL}themes/style/dark.css`
const currentLayout = settingsLoad().selectedThemeLayout ?? `${baseURL}themes/layout/gorb.css`
if (styleLinkElement) {
styleLinkElement.href = currentStyle;
} else {
createStyleHead("style-theme", currentStyle)
styleLinkElement = document.getElementById('style-theme') as HTMLLinkElement;
}
if (layoutLinkElement) {
layoutLinkElement.href = currentLayout;
} else {
createStyleHead("style-layout", currentLayout)
layoutLinkElement = document.getElementById('style-layout') as HTMLLinkElement;
}
}
// create a new theme link if one doesn't already exist
function createStyleHead(id: string, themeUrl: string) {
useHead({
link: [{
id: id,
rel: "stylesheet",
href: themeUrl
}]
})
}