feat(App): add emergency banner for active mode and enhance changelog modal with version tracking; improve notification logic for incoming messages
Some checks failed
Tests / test (pull_request) Failing after 12m30s
Benchmarks / benchmark (push) Successful in 15m13s
Benchmarks / benchmark (pull_request) Successful in 23m54s
CI / test-backend (push) Successful in 4s
CI / test-backend (pull_request) Successful in 4s
Build and Publish Docker Image / build (pull_request) Has been skipped
Build Test / Build and Test (pull_request) Failing after 1m23s
CI / build-frontend (push) Successful in 1m31s
CI / lint (push) Failing after 5m4s
CI / lint (pull_request) Failing after 5m5s
Build Test / Build and Test (push) Successful in 6m4s
CI / build-frontend (pull_request) Successful in 9m43s
Tests / test (push) Failing after 9m53s
Build and Publish Docker Image / build-dev (pull_request) Successful in 12m43s
Some checks failed
Tests / test (pull_request) Failing after 12m30s
Benchmarks / benchmark (push) Successful in 15m13s
Benchmarks / benchmark (pull_request) Successful in 23m54s
CI / test-backend (push) Successful in 4s
CI / test-backend (pull_request) Successful in 4s
Build and Publish Docker Image / build (pull_request) Has been skipped
Build Test / Build and Test (pull_request) Failing after 1m23s
CI / build-frontend (push) Successful in 1m31s
CI / lint (push) Failing after 5m4s
CI / lint (pull_request) Failing after 5m5s
Build Test / Build and Test (push) Successful in 6m4s
CI / build-frontend (pull_request) Successful in 9m43s
Tests / test (push) Failing after 9m53s
Build and Publish Docker Image / build-dev (pull_request) Successful in 12m43s
This commit is contained in:
@@ -3,6 +3,17 @@
|
||||
:class="{ dark: config?.theme === 'dark' }"
|
||||
class="h-screen w-full flex flex-col bg-slate-50 dark:bg-zinc-950 transition-colors"
|
||||
>
|
||||
<!-- emergency banner -->
|
||||
<div
|
||||
v-if="appInfo?.emergency"
|
||||
class="relative z-[100] bg-red-600 text-white px-4 py-2 text-center text-sm font-bold shadow-md animate-pulse"
|
||||
>
|
||||
<div class="flex items-center justify-center gap-2">
|
||||
<MaterialDesignIcon icon-name="alert-decagram" class="size-5" />
|
||||
<span>{{ $t("app.emergency_mode_active") }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<RouterView v-if="$route.name === 'auth'" />
|
||||
|
||||
<template v-else>
|
||||
@@ -437,7 +448,7 @@
|
||||
<ConfirmDialog />
|
||||
<CommandPalette />
|
||||
<IntegrityWarningModal />
|
||||
<ChangelogModal ref="changelogModal" />
|
||||
<ChangelogModal ref="changelogModal" :app-version="appInfo?.version" />
|
||||
<TutorialModal ref="tutorialModal" />
|
||||
|
||||
<!-- identity switching overlay -->
|
||||
@@ -723,7 +734,8 @@ export default {
|
||||
}
|
||||
|
||||
// show notification for new messages if window is not focussed
|
||||
if (!document.hasFocus()) {
|
||||
// only for incoming messages
|
||||
if (!document.hasFocus() && json.lxmf_message?.is_incoming) {
|
||||
NotificationUtils.showNewMessageNotification(
|
||||
json.remote_identity_name,
|
||||
json.lxmf_message?.content
|
||||
@@ -761,8 +773,12 @@ export default {
|
||||
this.hasCheckedForModals = true;
|
||||
if (this.appInfo && !this.appInfo.tutorial_seen) {
|
||||
this.$refs.tutorialModal.show();
|
||||
} else if (this.appInfo && this.appInfo.changelog_seen_version !== this.appInfo.version) {
|
||||
// show changelog if version changed
|
||||
} else if (
|
||||
this.appInfo &&
|
||||
this.appInfo.changelog_seen_version !== "999.999.999" &&
|
||||
this.appInfo.changelog_seen_version !== this.appInfo.version
|
||||
) {
|
||||
// show changelog if version changed and not silenced forever
|
||||
this.$refs.changelogModal.show();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,9 +50,9 @@
|
||||
<div v-else-if="error" class="flex flex-col items-center justify-center h-full text-center space-y-4">
|
||||
<v-icon icon="mdi-alert-circle-outline" size="64" color="red"></v-icon>
|
||||
<div class="text-red-500 font-bold text-lg">{{ error }}</div>
|
||||
<v-btn color="#3b82f6" variant="flat" class="text-white font-bold" @click="fetchChangelog"
|
||||
>Retry</v-btn
|
||||
>
|
||||
<v-btn color="blue" variant="flat" class="font-bold uppercase px-6" rounded="lg" @click="fetchChangelog">
|
||||
Retry
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<div
|
||||
@@ -66,20 +66,30 @@
|
||||
|
||||
<!-- Footer -->
|
||||
<v-divider class="dark:border-zinc-800"></v-divider>
|
||||
<v-card-actions class="px-6 py-4 bg-gray-50 dark:bg-zinc-950/50">
|
||||
<v-checkbox
|
||||
v-model="dontShowAgain"
|
||||
:label="$t('app.do_not_show_again', 'Do not show again for this version')"
|
||||
density="compact"
|
||||
hide-details
|
||||
color="blue"
|
||||
class="my-0 text-gray-700 dark:text-zinc-300 font-medium"
|
||||
></v-checkbox>
|
||||
<v-card-actions class="px-6 py-4 bg-gray-50 dark:bg-zinc-950/50 flex-wrap gap-y-2">
|
||||
<div class="flex flex-col">
|
||||
<v-checkbox
|
||||
v-model="dontShowAgain"
|
||||
:label="$t('app.do_not_show_again', 'Do not show again for this version')"
|
||||
density="compact"
|
||||
hide-details
|
||||
color="blue"
|
||||
class="my-0 text-gray-700 dark:text-zinc-300 font-medium"
|
||||
></v-checkbox>
|
||||
<v-checkbox
|
||||
v-model="dontShowEver"
|
||||
:label="$t('app.do_not_show_ever', 'Do not show ever again')"
|
||||
density="compact"
|
||||
hide-details
|
||||
color="red"
|
||||
class="my-0 text-gray-700 dark:text-zinc-300 font-medium"
|
||||
></v-checkbox>
|
||||
</div>
|
||||
<v-spacer></v-spacer>
|
||||
<v-btn
|
||||
variant="tonal"
|
||||
variant="flat"
|
||||
color="blue"
|
||||
class="px-8 font-black tracking-tighter text-white uppercase"
|
||||
class="px-8 font-black tracking-tighter uppercase text-white dark:text-zinc-900"
|
||||
rounded="xl"
|
||||
@click="close"
|
||||
>
|
||||
@@ -121,9 +131,9 @@
|
||||
<div v-else-if="error" class="flex flex-col items-center justify-center py-20 text-center space-y-4">
|
||||
<v-icon icon="mdi-alert-circle-outline" size="64" color="red"></v-icon>
|
||||
<div class="text-red-500 font-bold text-lg">{{ error }}</div>
|
||||
<v-btn color="#3b82f6" variant="flat" class="text-white font-bold" @click="fetchChangelog"
|
||||
>Retry</v-btn
|
||||
>
|
||||
<v-btn color="blue" variant="flat" class="font-bold uppercase px-6" rounded="lg" @click="fetchChangelog">
|
||||
Retry
|
||||
</v-btn>
|
||||
</div>
|
||||
|
||||
<div v-else class="changelog-content max-w-none prose dark:prose-invert pb-20">
|
||||
@@ -138,6 +148,12 @@
|
||||
<script>
|
||||
export default {
|
||||
name: "ChangelogModal",
|
||||
props: {
|
||||
appVersion: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
@@ -146,9 +162,13 @@ export default {
|
||||
changelogHtml: "",
|
||||
version: "",
|
||||
dontShowAgain: false,
|
||||
dontShowEver: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
currentVersion() {
|
||||
return this.version || this.appVersion;
|
||||
},
|
||||
isPage() {
|
||||
return this.$route?.meta?.isPage === true;
|
||||
},
|
||||
@@ -187,18 +207,43 @@ export default {
|
||||
}
|
||||
},
|
||||
async close() {
|
||||
this.visible = false;
|
||||
// logic moved to onVisibleUpdate
|
||||
},
|
||||
async onVisibleUpdate(val) {
|
||||
if (!val && this.dontShowAgain) {
|
||||
// mark as seen for current version automatically on close if not already marked
|
||||
if (!this.dontShowEver && !this.dontShowAgain) {
|
||||
try {
|
||||
await window.axios.post("/api/v1/app/changelog/seen", {
|
||||
version: this.version,
|
||||
version: this.currentVersion || "0.0.0",
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Failed to mark changelog as seen:", e);
|
||||
console.error("Failed to auto-mark changelog as seen:", e);
|
||||
}
|
||||
} else {
|
||||
await this.markAsSeen();
|
||||
}
|
||||
this.visible = false;
|
||||
},
|
||||
async markAsSeen() {
|
||||
if (this.dontShowEver) {
|
||||
try {
|
||||
await window.axios.post("/api/v1/app/changelog/seen", {
|
||||
version: "999.999.999",
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Failed to mark changelog as seen forever:", e);
|
||||
}
|
||||
} else if (this.dontShowAgain) {
|
||||
try {
|
||||
await window.axios.post("/api/v1/app/changelog/seen", {
|
||||
version: this.currentVersion,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error("Failed to mark changelog as seen for this version:", e);
|
||||
}
|
||||
}
|
||||
},
|
||||
async onVisibleUpdate(val) {
|
||||
if (!val) {
|
||||
// handle case where dialog is closed by clicking outside or ESC
|
||||
await this.markAsSeen();
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
leave-from-class="transform opacity-100 scale-100"
|
||||
leave-to-class="transform opacity-0 scale-95"
|
||||
>
|
||||
<div v-if="isShowingMenu" class="absolute left-0 z-10 ml-4">
|
||||
<div v-if="isShowingMenu" class="absolute left-0 z-[100] mt-2">
|
||||
<v-color-picker
|
||||
v-model="colourPickerValue"
|
||||
:modes="['hex']"
|
||||
|
||||
@@ -1,16 +1,25 @@
|
||||
<template>
|
||||
<div v-if="customImage" class="rounded-full overflow-hidden" :class="iconClass">
|
||||
<div
|
||||
v-if="customImage"
|
||||
class="rounded-full overflow-hidden shrink-0 flex items-center justify-center"
|
||||
:class="iconClass || 'size-6'"
|
||||
>
|
||||
<img :src="customImage" class="w-full h-full object-cover" />
|
||||
</div>
|
||||
<div
|
||||
v-else-if="iconName"
|
||||
class="p-2 rounded-full"
|
||||
:style="{ color: iconForegroundColour, 'background-color': iconBackgroundColour }"
|
||||
class="p-[15%] rounded-full shrink-0 flex items-center justify-center"
|
||||
:style="{ 'background-color': iconBackgroundColour }"
|
||||
:class="iconClass || 'size-6'"
|
||||
>
|
||||
<MaterialDesignIcon :icon-name="iconName" :class="iconClass" />
|
||||
<MaterialDesignIcon :icon-name="iconName" class="w-full h-full" :style="{ color: iconForegroundColour }" />
|
||||
</div>
|
||||
<div v-else class="bg-gray-200 dark:bg-zinc-700 text-gray-500 dark:text-gray-400 p-2 rounded-full">
|
||||
<MaterialDesignIcon icon-name="account-outline" :class="iconClass" />
|
||||
<div
|
||||
v-else
|
||||
class="bg-gray-200 dark:bg-zinc-700 text-gray-500 dark:text-gray-400 p-[15%] rounded-full shrink-0 flex items-center justify-center"
|
||||
:class="iconClass || 'size-6'"
|
||||
>
|
||||
<MaterialDesignIcon icon-name="account-outline" class="w-full h-full" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -32,15 +41,15 @@ export default {
|
||||
},
|
||||
iconForegroundColour: {
|
||||
type: String,
|
||||
default: "",
|
||||
default: "#6b7280",
|
||||
},
|
||||
iconBackgroundColour: {
|
||||
type: String,
|
||||
default: "",
|
||||
default: "#e5e7eb",
|
||||
},
|
||||
iconClass: {
|
||||
type: String,
|
||||
default: "size-6",
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
role="img"
|
||||
:aria-label="iconName"
|
||||
fill="currentColor"
|
||||
width="100%"
|
||||
height="100%"
|
||||
style="display: inline-block; vertical-align: middle; shape-rendering: inherit"
|
||||
class="antialiased"
|
||||
>
|
||||
@@ -20,18 +22,26 @@ export default {
|
||||
props: {
|
||||
iconName: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: false,
|
||||
default: "",
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
mdiIconName() {
|
||||
if (!this.iconName) return "mdiAccountOutline";
|
||||
|
||||
// if already starts with mdi and is camelCase, return as is
|
||||
if (this.iconName.startsWith("mdi") && /[A-Z]/.test(this.iconName)) {
|
||||
return this.iconName;
|
||||
}
|
||||
|
||||
// convert icon name from lxmf icon appearance to format expected by the @mdi/js library
|
||||
// e.g: alien-outline -> mdiAlienOutline
|
||||
// https://pictogrammers.github.io/@mdi/font/5.4.55/
|
||||
return (
|
||||
"mdi" +
|
||||
this.iconName
|
||||
.split("-")
|
||||
.filter(word => word.length > 0)
|
||||
.map((word) => {
|
||||
// capitalise first letter of each part
|
||||
return word.charAt(0).toUpperCase() + word.slice(1);
|
||||
@@ -40,8 +50,13 @@ export default {
|
||||
);
|
||||
},
|
||||
iconPath() {
|
||||
// find icon, otherwise fallback to question mark, and if that doesn't exist, show nothing...
|
||||
return mdi[this.mdiIconName] || mdi["mdiProgressQuestion"] || "";
|
||||
if (!mdi) return "";
|
||||
|
||||
const path = mdi[this.mdiIconName];
|
||||
if (path) return path;
|
||||
|
||||
// fallback logic
|
||||
return mdi["mdiHelpCircleOutline"] || mdi["mdiProgressQuestion"] || "";
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -154,7 +154,8 @@
|
||||
<div class="text-lg font-semibold text-gray-900 dark:text-white mb-4">
|
||||
{{ $t("about.dependency_chain") }}
|
||||
</div>
|
||||
<div class="relative">
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 relative">
|
||||
<!-- Main Dependencies -->
|
||||
<div class="flex flex-col space-y-4">
|
||||
<!-- MeshChatX -->
|
||||
<div class="flex items-center gap-4">
|
||||
@@ -213,65 +214,65 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Side Dependencies -->
|
||||
<div class="mt-8 pt-6 border-t border-gray-100 dark:border-zinc-800">
|
||||
<div
|
||||
class="text-xs font-bold text-gray-400 dark:text-zinc-500 uppercase tracking-wider mb-3"
|
||||
>
|
||||
{{ $t("about.other_core_components", "Other Core Components") }}
|
||||
</div>
|
||||
<div class="grid grid-cols-2 sm:grid-cols-3 gap-4">
|
||||
<div v-if="appInfo.lxst_version" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">LXST</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ appInfo.lxst_version }}</span
|
||||
>
|
||||
<!-- Side & Python Dependencies -->
|
||||
<div class="space-y-8">
|
||||
<!-- Side Dependencies -->
|
||||
<div>
|
||||
<div
|
||||
class="text-xs font-bold text-gray-400 dark:text-zinc-500 uppercase tracking-wider mb-3"
|
||||
>
|
||||
{{ $t("about.other_core_components", "Other Core Components") }}
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">Python</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ appInfo.python_version }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="electronVersion" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">Electron</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ electronVersion }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="chromeVersion" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">Chrome</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ chromeVersion }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="nodeVersion" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">Node</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ nodeVersion }}</span
|
||||
>
|
||||
<div class="grid grid-cols-2 sm:grid-cols-3 gap-4">
|
||||
<div v-if="appInfo.lxst_version" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">LXST</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ appInfo.lxst_version }}</span
|
||||
>
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">Python</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ appInfo.python_version }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="electronVersion" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">Electron</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ electronVersion }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="chromeVersion" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">Chrome</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ chromeVersion }}</span
|
||||
>
|
||||
</div>
|
||||
<div v-if="nodeVersion" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500 uppercase">Node</span>
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-300"
|
||||
>v{{ nodeVersion }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Python Dependencies -->
|
||||
<div
|
||||
v-if="appInfo.dependencies"
|
||||
class="mt-8 pt-6 border-t border-gray-100 dark:border-zinc-800"
|
||||
>
|
||||
<div
|
||||
class="text-xs font-bold text-gray-400 dark:text-zinc-500 uppercase tracking-wider mb-3"
|
||||
>
|
||||
{{ $t("about.backend_dependencies") }}
|
||||
</div>
|
||||
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
|
||||
<div v-for="(version, name) in appInfo.dependencies" :key="name" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500/70 uppercase">{{
|
||||
name.replace("_", " ")
|
||||
}}</span>
|
||||
<span class="text-xs font-medium text-gray-600 dark:text-zinc-400"
|
||||
>v{{ version }}</span
|
||||
>
|
||||
<!-- Python Dependencies -->
|
||||
<div v-if="appInfo.dependencies" class="pt-6 border-t border-gray-100 dark:border-zinc-800">
|
||||
<div
|
||||
class="text-xs font-bold text-gray-400 dark:text-zinc-500 uppercase tracking-wider mb-3"
|
||||
>
|
||||
{{ $t("about.backend_dependencies") }}
|
||||
</div>
|
||||
<div class="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 gap-4">
|
||||
<div v-for="(version, name) in appInfo.dependencies" :key="name" class="flex flex-col">
|
||||
<span class="text-[10px] font-black text-blue-500/70 uppercase">{{
|
||||
name.replace("_", " ")
|
||||
}}</span>
|
||||
<span class="text-xs font-medium text-gray-600 dark:text-zinc-400"
|
||||
>v{{ version }}</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
:icon-name="activeCall.remote_icon ? activeCall.remote_icon.icon_name : ''"
|
||||
:icon-foreground-colour="activeCall.remote_icon ? activeCall.remote_icon.foreground_colour : ''"
|
||||
:icon-background-colour="activeCall.remote_icon ? activeCall.remote_icon.background_colour : ''"
|
||||
class="size-8"
|
||||
icon-class="size-8"
|
||||
/>
|
||||
</div>
|
||||
<div class="text-center w-full min-w-0">
|
||||
@@ -246,7 +246,7 @@
|
||||
:icon-name="activeCall.remote_icon ? activeCall.remote_icon.icon_name : ''"
|
||||
:icon-foreground-colour="activeCall.remote_icon ? activeCall.remote_icon.foreground_colour : ''"
|
||||
:icon-background-colour="activeCall.remote_icon ? activeCall.remote_icon.background_colour : ''"
|
||||
class="size-5 shrink-0"
|
||||
icon-class="size-5 shrink-0"
|
||||
/>
|
||||
<div class="flex flex-col min-w-0">
|
||||
<span class="text-sm font-medium text-gray-700 dark:text-zinc-200 truncate block">
|
||||
|
||||
@@ -127,7 +127,7 @@
|
||||
? (activeCall || lastCall).remote_icon.background_colour
|
||||
: ''
|
||||
"
|
||||
class="size-20"
|
||||
icon-class="size-20"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -601,7 +601,7 @@
|
||||
:icon-background-colour="
|
||||
entry.remote_icon ? entry.remote_icon.background_colour : ''
|
||||
"
|
||||
class="size-10"
|
||||
icon-class="size-10"
|
||||
/>
|
||||
<div
|
||||
class="absolute -bottom-1 -right-1 bg-white dark:bg-zinc-900 rounded-full p-0.5 shadow-sm border border-gray-100 dark:border-zinc-800 shrink-0 flex items-center justify-center size-5"
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
:icon-background-colour="
|
||||
selectedPeer.lxmf_user_icon ? selectedPeer.lxmf_user_icon.background_colour : ''
|
||||
"
|
||||
class="size-10"
|
||||
icon-class="size-10"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="max-w-4xl mx-auto p-4 space-y-6">
|
||||
<!-- Header with Preview -->
|
||||
<div
|
||||
class="bg-white dark:bg-zinc-900 rounded-xl shadow-sm border border-gray-200 dark:border-zinc-800 overflow-hidden"
|
||||
class="bg-white dark:bg-zinc-900 rounded-xl shadow-sm border border-gray-200 dark:border-zinc-800"
|
||||
>
|
||||
<div class="p-6 border-b border-gray-200 dark:border-zinc-800">
|
||||
<div class="flex items-center justify-between">
|
||||
@@ -51,6 +51,7 @@
|
||||
<div class="text-sm font-medium text-gray-700 dark:text-zinc-300">Preview</div>
|
||||
<div class="p-8 bg-gray-50 dark:bg-zinc-800 rounded-2xl">
|
||||
<LxmfUserIcon
|
||||
:key="iconName + iconForegroundColour + iconBackgroundColour"
|
||||
:icon-name="iconName"
|
||||
:icon-foreground-colour="iconForegroundColour"
|
||||
:icon-background-colour="iconBackgroundColour"
|
||||
@@ -66,7 +67,7 @@
|
||||
|
||||
<!-- Color Selection -->
|
||||
<div
|
||||
class="bg-white dark:bg-zinc-900 rounded-xl shadow-sm border border-gray-200 dark:border-zinc-800 overflow-hidden"
|
||||
class="bg-white dark:bg-zinc-900 rounded-xl shadow-sm border border-gray-200 dark:border-zinc-800"
|
||||
>
|
||||
<div class="p-4 border-b border-gray-200 dark:border-zinc-800">
|
||||
<h3 class="text-lg font-semibold text-gray-900 dark:text-white">Colors</h3>
|
||||
@@ -252,14 +253,17 @@ export default {
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
config() {
|
||||
if (this.config) {
|
||||
this.iconName = this.config.lxmf_user_icon_name || null;
|
||||
this.iconForegroundColour = this.config.lxmf_user_icon_foreground_colour || "#6b7280";
|
||||
this.iconBackgroundColour = this.config.lxmf_user_icon_background_colour || "#e5e7eb";
|
||||
config: {
|
||||
handler() {
|
||||
if (this.config) {
|
||||
this.iconName = this.config.lxmf_user_icon_name || null;
|
||||
this.iconForegroundColour = this.config.lxmf_user_icon_foreground_colour || "#6b7280";
|
||||
this.iconBackgroundColour = this.config.lxmf_user_icon_background_colour || "#e5e7eb";
|
||||
|
||||
this.saveOriginalValues();
|
||||
}
|
||||
this.saveOriginalValues();
|
||||
}
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
iconForegroundColour() {
|
||||
this.debouncedAutoSave();
|
||||
|
||||
Reference in New Issue
Block a user