Settings menu now warns when a setting is unsaved. (#65)

* Settings menu now warns when a setting is unsaved. Additionally, font-weight increments properly now.

* Remove font weight fix - another PR already open for fix.
This commit is contained in:
Jas Singh
2024-08-02 20:00:28 -07:00
committed by GitHub
parent 1f7c5a70ca
commit 6166fdbe0f
18 changed files with 110 additions and 34 deletions

View File

@@ -6,7 +6,7 @@ import options from "options";
export const BarSettings = () => {
return Widget.Scrollable({
vscroll: "always",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page paged-container",
child: Widget.Box({
vertical: true,

View File

@@ -7,7 +7,7 @@ export const DashboardMenuSettings = () => {
return Widget.Scrollable({
class_name: "bar-theme-page paged-container",
vscroll: "always",
hscroll: "never",
hscroll: "automatic",
vexpand: true,
overlayScrolling: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const BarTheme = () => {
return Widget.Scrollable({
vscroll: "always",
hscroll: "never",
hscroll: "automatic",
class_name: "bar-theme-page paged-container",
child: Widget.Box({
vertical: true,

View File

@@ -6,7 +6,7 @@ import options from "options";
export const BatteryMenuTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page battery paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const BluetoothMenuTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page bluetooth paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const ClockMenuTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page clock paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const DashboardMenuTheme = () => {
return Widget.Scrollable({
vscroll: "always",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page dashboard paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const MenuTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const MediaMenuTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page media paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const NetworkMenuTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page network paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const NotificationsMenuTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page notifications paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const SystrayMenuTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page systray paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const VolumeMenuTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "menu-theme-page volume paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const NotificationsTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "notifications-theme-page paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -6,7 +6,7 @@ import options from "options";
export const OsdTheme = () => {
return Widget.Scrollable({
vscroll: "automatic",
hscroll: "never",
hscroll: "automatic",
class_name: "osd-theme-page paged-container",
vexpand: true,
child: Widget.Box({

View File

@@ -2,6 +2,7 @@ import { Opt } from "lib/option"
import Gdk from "gi://Gdk"
import icons from "lib/icons"
import { RowProps } from "lib/types/options"
import { Variable } from "types/variable";
const EnumSetter = (opt: Opt<string>, values: string[]) => {
const lbl = Widget.Label({ label: opt.bind().as(v => `${v}`) })
@@ -34,33 +35,99 @@ export const Inputter = <T>({
min = 0,
increment = 1
}: RowProps<T>,
className: string
className: string,
isUnsaved: Variable<boolean>
) => {
return Widget.Box({
class_name: "inputter-container",
setup: self => {
switch (type) {
case "number": return self.child = Widget.SpinButton({
setup(self) {
self.set_range(min, max)
self.set_increments(1 * increment, 5 * increment)
self.on("value-changed", () => opt.value = self.value as T)
self.hook(opt, () => self.value = opt.value as number)
},
})
case "number": return self.children = [
Widget.Box({
class_name: "unsaved-icon-container",
child: isUnsaved.bind("value").as(unsvd => {
if (unsvd) {
return Widget.Icon({
class_name: "unsaved-icon",
icon: icons.ui.warning,
tooltipText: "Press 'Enter' to apply your changes."
})
}
return Widget.Box();
}),
}),
Widget.SpinButton({
setup(self) {
self.set_range(min, max)
self.set_increments(1 * increment, 5 * increment)
self.on("value-changed", () => {
opt.value = self.value as T;
})
self.hook(opt, () => {
self.value = opt.value as number;
isUnsaved.value = Number(self.text) !== opt.value as number;
})
self.connect("key-release-event", () => {
isUnsaved.value = Number(self.text) !== opt.value as number;
})
},
})
]
case "float":
case "object": return self.child = Widget.Entry({
class_name: className,
on_accept: self => opt.value = JSON.parse(self.text || ""),
setup: self => self.hook(opt, () => self.text = JSON.stringify(opt.value)),
})
case "object": return self.children = [
Widget.Box({
class_name: "unsaved-icon-container",
child: isUnsaved.bind("value").as(unsvd => {
if (unsvd) {
return Widget.Icon({
class_name: "unsaved-icon",
icon: icons.ui.warning,
tooltipText: "Press 'Enter' to apply your changes."
})
}
return Widget.Box();
}),
}),
Widget.Entry({
class_name: className,
on_change: self => isUnsaved.value = self.text !== JSON.stringify(opt.value),
on_accept: self => opt.value = JSON.parse(self.text || ""),
setup: self => self.hook(opt, () => {
self.text = JSON.stringify(opt.value);
isUnsaved.value = self.text !== JSON.stringify(opt.value);
})
})
]
case "string": return self.child = Widget.Entry({
on_accept: self => opt.value = self.text as T,
setup: self => self.hook(opt, () => self.text = opt.value as string),
})
case "string": return self.children = [
Widget.Box({
class_name: "unsaved-icon-container",
child: isUnsaved.bind("value").as(unsvd => {
if (unsvd) {
return Widget.Icon({
class_name: "unsaved-icon",
icon: icons.ui.warning,
tooltipText: "Press 'Enter' to apply your changes."
})
}
return Widget.Box();
}),
}),
Widget.Entry({
class_name: isUnsaved.bind("value").as(unsaved => unsaved ? "unsaved" : ""),
on_change: self => isUnsaved.value = self.text !== opt.value,
on_accept: self => {
opt.value = self.text as T;
},
setup: self => self.hook(opt, () => {
isUnsaved.value = self.text !== opt.value;
self.text = opt.value as string;
}),
})
]
case "enum": return self.child = EnumSetter(opt as unknown as Opt<string>, enums!)
case "boolean": return self.child = Widget.Switch()

View File

@@ -8,7 +8,10 @@ type Option = {
subtitle: string,
}
export const Option = <T>(props: RowProps<T>, className: string = '') => {
const isUnsaved = Variable(false);
return Widget.Box({
class_name: "option-item",
hexpand: true,
@@ -19,7 +22,7 @@ export const Option = <T>(props: RowProps<T>, className: string = '') => {
hexpand: true,
child: Label(props.title, props.subtitle || ""),
}),
Inputter(props, className),
Inputter(props, className, isUnsaved),
Widget.Button({
vpack: "center",
class_name: "reset-options",