This commit is contained in:
gsinghpal
2026-05-10 10:25:12 -04:00
parent 6c6a59ceef
commit 6b7b44264a
59 changed files with 2461 additions and 324 deletions

View File

@@ -0,0 +1,81 @@
/** @odoo-module **/
import { Component, useState } from "@odoo/owl";
import { browser } from "@web/core/browser/browser";
import { cookie } from "@web/core/browser/cookie";
import { _t } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { user } from "@web/core/user";
import { useService } from "@web/core/utils/hooks";
const VALID_SCHEMES = ["light", "dark"];
function currentScheme() {
const cookieScheme = cookie.get("color_scheme");
if (VALID_SCHEMES.includes(cookieScheme)) {
return cookieScheme;
}
const userScheme = user.settings?.color_scheme;
return VALID_SCHEMES.includes(userScheme) ? userScheme : "light";
}
export class FusionThemeToggleSystray extends Component {
static template = "fusion_theme_switcher.ThemeToggleSystray";
static props = [];
setup() {
this.notification = useService("notification");
this.state = useState({
scheme: currentScheme(),
loading: false,
});
}
get isDark() {
return this.state.scheme === "dark";
}
get nextScheme() {
return this.isDark ? "light" : "dark";
}
get title() {
return this.nextScheme === "dark" ? _t("Switch to dark mode") : _t("Switch to light mode");
}
get iconClass() {
return this.isDark ? "fa fa-sun-o" : "fa fa-moon-o";
}
async onToggleTheme() {
if (this.state.loading) {
return;
}
const nextScheme = this.nextScheme;
this.state.loading = true;
try {
await user.setUserSettings("color_scheme", nextScheme);
user.updateUserSettings("color_scheme", nextScheme);
cookie.set("color_scheme", nextScheme);
this.state.scheme = nextScheme;
browser.location.reload();
} catch {
this.state.loading = false;
this.notification.add(_t("Theme switch failed. Please try again."), {
type: "danger",
});
}
}
}
export const fusionThemeToggleSystrayItem = {
Component: FusionThemeToggleSystray,
isDisplayed: () => Boolean(user.userId && user.isInternalUser && user.settings?.id),
};
registry.category("systray").add("fusion_theme_switcher.theme_toggle", fusionThemeToggleSystrayItem, {
sequence: 100,
});

View File

@@ -0,0 +1,48 @@
.o_fts_theme_toggle {
align-items: center;
background: transparent;
border: 0;
border-radius: 6px;
color: #4b5563;
display: flex;
height: 20px;
justify-content: center;
line-height: 1;
margin: 0 4px;
padding: 0;
align-self: center;
transition: background-color 120ms ease, color 120ms ease, opacity 120ms ease;
width: 24px;
&:hover,
&:focus-visible {
background-color: rgba(0, 0, 0, 0.08);
color: #111827;
outline: none;
}
&:focus-visible {
box-shadow: 0 0 0 2px rgba(113, 75, 103, 0.35);
}
.fa {
font-size: 16px;
line-height: 1;
transform: translateY(-1px);
}
}
.o_fts_theme_toggle_dark {
color: #fbbf24;
&:hover,
&:focus-visible {
background-color: rgba(255, 255, 255, 0.12);
color: #fde68a;
}
}
.o_fts_theme_toggle_loading {
cursor: wait;
opacity: 0.7;
}

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-name="fusion_theme_switcher.ThemeToggleSystray">
<button type="button"
t-att-title="title"
t-att-aria-label="title"
t-att-disabled="state.loading"
t-att-class="{
'o_fts_theme_toggle': true,
'o_fts_theme_toggle_dark': isDark,
'o_fts_theme_toggle_loading': state.loading,
}"
t-on-click="onToggleTheme">
<i t-att-class="iconClass"/>
<span class="visually-hidden" t-esc="title"/>
</button>
</t>
</templates>