update system

This commit is contained in:
2024-04-17 10:03:57 +02:00
parent 6e0e34e425
commit 4c78f4b5e6
260 changed files with 8100 additions and 7799 deletions

View File

@@ -0,0 +1,34 @@
import icons from "lib/icons"
import Row from "./Row"
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export default (title: string, ...rows: ReturnType<typeof Row<any>>[]) => Widget.Box(
{
class_name: "group",
vertical: true,
},
Widget.Box([
Widget.Label({
hpack: "start",
vpack: "end",
class_name: "group-title",
label: title,
setup: w => Utils.idle(() => w.visible = !!title),
}),
title ? Widget.Button({
hexpand: true,
hpack: "end",
child: Widget.Icon(icons.ui.refresh),
class_name: "group-reset",
sensitive: Utils.merge(
rows.map(({ attribute: { opt } }) => opt.bind().as(v => v !== opt.initial)),
(...values) => values.some(b => b),
),
on_clicked: () => rows.forEach(row => row.attribute.opt.reset()),
}) : Widget.Box(),
]),
Widget.Box({
vertical: true,
children: rows,
}),
)

View File

@@ -0,0 +1,19 @@
import Group from "./Group"
export default <T>(
name: string,
icon: string,
...groups: ReturnType<typeof Group<T>>[]
) => Widget.Box({
class_name: "page",
attribute: { name, icon },
child: Widget.Scrollable({
css: "min-height: 300px;",
child: Widget.Box({
class_name: "page-content",
vexpand: true,
vertical: true,
children: groups,
}),
}),
})

View File

@@ -0,0 +1,55 @@
import { Opt } from "lib/option"
import Setter from "./Setter"
import icons from "lib/icons"
export type RowProps<T> = {
opt: Opt<T>
title: string
note?: string
type?:
| "number"
| "color"
| "float"
| "object"
| "string"
| "enum"
| "boolean"
| "img"
| "font"
enums?: string[]
max?: number
min?: number
}
export default <T>(props: RowProps<T>) => Widget.Box(
{
attribute: { opt: props.opt },
class_name: "row",
tooltip_text: props.note ? `note: ${props.note}` : "",
},
Widget.Box(
{ vertical: true, vpack: "center" },
Widget.Label({
xalign: 0,
class_name: "row-title",
label: props.title,
}),
Widget.Label({
xalign: 0,
class_name: "id",
label: props.opt.id,
}),
),
Widget.Box({ hexpand: true }),
Widget.Box(
{ vpack: "center" },
Setter(props),
),
Widget.Button({
vpack: "center",
class_name: "reset",
child: Widget.Icon(icons.ui.refresh),
on_clicked: () => props.opt.reset(),
sensitive: props.opt.bind().as(v => v !== props.opt.initial),
}),
)

View File

@@ -0,0 +1,93 @@
import { type RowProps } from "./Row"
import { Opt } from "lib/option"
import icons from "lib/icons"
import Gdk from "gi://Gdk"
function EnumSetter(opt: Opt<string>, values: string[]) {
const lbl = Widget.Label({ label: opt.bind().as(v => `${v}`) })
const step = (dir: 1 | -1) => {
const i = values.findIndex(i => i === lbl.label)
opt.setValue(dir > 0
? i + dir > values.length - 1 ? values[0] : values[i + dir]
: i + dir < 0 ? values[values.length - 1] : values[i + dir],
)
}
const next = Widget.Button({
child: Widget.Icon(icons.ui.arrow.right),
on_clicked: () => step(+1),
})
const prev = Widget.Button({
child: Widget.Icon(icons.ui.arrow.left),
on_clicked: () => step(-1),
})
return Widget.Box({
class_name: "enum-setter",
children: [lbl, prev, next],
})
}
export default function Setter<T>({
opt,
type = typeof opt.value as RowProps<T>["type"],
enums,
max = 1000,
min = 0,
}: RowProps<T>) {
switch (type) {
case "number": return Widget.SpinButton({
setup(self) {
self.set_range(min, max)
self.set_increments(1, 5)
self.on("value-changed", () => opt.value = self.value as T)
self.hook(opt, () => self.value = opt.value as number)
},
})
case "float":
case "object": return Widget.Entry({
on_accept: self => opt.value = JSON.parse(self.text || ""),
setup: self => self.hook(opt, () => self.text = JSON.stringify(opt.value)),
})
case "string": return Widget.Entry({
on_accept: self => opt.value = self.text as T,
setup: self => self.hook(opt, () => self.text = opt.value as string),
})
case "enum": return EnumSetter(opt as unknown as Opt<string>, enums!)
case "boolean": return Widget.Switch()
.on("notify::active", self => opt.value = self.active as T)
.hook(opt, self => self.active = opt.value as boolean)
case "img": return Widget.FileChooserButton({
on_file_set: ({ uri }) => { opt.value = uri!.replace("file://", "") as T },
})
case "font": return Widget.FontButton({
show_size: false,
use_size: false,
setup: self => self
.hook(opt, () => self.font = opt.value as string)
.on("font-set", ({ font }) => opt.value = font!
.split(" ").slice(0, -1).join(" ") as T),
})
case "color": return Widget.ColorButton()
.hook(opt, self => {
const rgba = new Gdk.RGBA()
rgba.parse(opt.value as string)
self.rgba = rgba
})
.on("color-set", ({ rgba: { red, green, blue } }) => {
const hex = (n: number) => {
const c = Math.floor(255 * n).toString(16)
return c.length === 1 ? `0${c}` : c
}
opt.value = `#${hex(red)}${hex(green)}${hex(blue)}` as T
})
default: return Widget.Label({
label: `no setter with type ${type}`,
})
}
}

View File

@@ -0,0 +1,63 @@
import RegularWindow from "widget/RegularWindow"
import layout from "./layout"
import icons from "lib/icons"
import options from "options"
const current = Variable(layout[0].attribute.name)
const Header = () => Widget.CenterBox({
class_name: "header",
start_widget: Widget.Button({
class_name: "reset",
on_clicked: options.reset,
hpack: "start",
vpack: "start",
child: Widget.Icon(icons.ui.refresh),
tooltip_text: "Reset",
}),
center_widget: Widget.Box({
class_name: "pager horizontal",
children: layout.map(({ attribute: { name, icon } }) => Widget.Button({
xalign: 0,
class_name: current.bind().as(v => `${v === name ? "active" : ""}`),
on_clicked: () => current.value = name,
child: Widget.Box([
Widget.Icon(icon),
Widget.Label(name),
]),
})),
}),
end_widget: Widget.Button({
class_name: "close",
hpack: "end",
vpack: "start",
child: Widget.Icon(icons.ui.close),
on_clicked: () => App.closeWindow("settings-dialog"),
}),
})
const PagesStack = () => Widget.Stack({
transition: "slide_left_right",
children: layout.reduce((obj, page) => ({ ...obj, [page.attribute.name]: page }), {}),
shown: current.bind() as never,
})
export default () => RegularWindow({
name: "settings-dialog",
class_name: "settings-dialog",
title: "Settings",
setup(win) {
win.on("delete-event", () => {
win.hide()
return true
})
win.set_default_size(500, 600)
},
child: Widget.Box({
vertical: true,
children: [
Header(),
PagesStack(),
],
}),
})

View File

@@ -0,0 +1,31 @@
import wallpaper from "service/wallpaper"
export default () => Widget.Box(
{ class_name: "row wallpaper" },
Widget.Box(
{ vertical: true },
Widget.Label({
xalign: 0,
class_name: "row-title",
label: "Wallpaper",
vpack: "start",
}),
Widget.Button({
on_clicked: wallpaper.random,
label: "Random",
}),
Widget.FileChooserButton({
on_file_set: ({ uri }) => wallpaper.set(uri!.replace("file://", "")),
}),
),
Widget.Box({ hexpand: true }),
Widget.Box({
class_name: "preview",
css: wallpaper.bind("wallpaper").as(wp => `
min-height: 120px;
min-width: 200px;
background-image: url('${wp}');
background-size: cover;
`),
}),
)

View File

@@ -0,0 +1,147 @@
/* eslint-disable max-len */
import Row from "./Row"
import Group from "./Group"
import Page from "./Page"
import Wallpaper from "./Wallpaper"
import options from "options"
import icons from "lib/icons"
const {
autotheme: at,
font,
theme,
bar: b,
launcher: l,
overview: ov,
powermenu: pm,
quicksettings: qs,
osd,
hyprland: h,
} = options
const {
dark,
light,
blur,
scheme,
padding,
spacing,
radius,
shadows,
widget,
border,
} = theme
export default [
Page("Theme", icons.ui.themes,
Group("",
Wallpaper() as ReturnType<typeof Row>,
Row({ opt: at, title: "Auto Generate Color Scheme" }),
Row({ opt: scheme, title: "Color Scheme", type: "enum", enums: ["dark", "light"] }),
),
Group("Dark Colors",
Row({ opt: dark.bg, title: "Background", type: "color" }),
Row({ opt: dark.fg, title: "Foreground", type: "color" }),
Row({ opt: dark.primary.bg, title: "Primary", type: "color" }),
Row({ opt: dark.primary.fg, title: "On Primary", type: "color" }),
Row({ opt: dark.error.bg, title: "Error", type: "color" }),
Row({ opt: dark.error.fg, title: "On Error", type: "color" }),
Row({ opt: dark.widget, title: "Widget", type: "color" }),
Row({ opt: dark.border, title: "Border", type: "color" }),
),
Group("Light Colors",
Row({ opt: light.bg, title: "Background", type: "color" }),
Row({ opt: light.fg, title: "Foreground", type: "color" }),
Row({ opt: light.primary.bg, title: "Primary", type: "color" }),
Row({ opt: light.primary.fg, title: "On Primary", type: "color" }),
Row({ opt: light.error.bg, title: "Error", type: "color" }),
Row({ opt: light.error.fg, title: "On Error", type: "color" }),
Row({ opt: light.widget, title: "Widget", type: "color" }),
Row({ opt: light.border, title: "Border", type: "color" }),
),
Group("Theme",
Row({ opt: shadows, title: "Shadows" }),
Row({ opt: widget.opacity, title: "Widget Opacity", max: 100 }),
Row({ opt: border.opacity, title: "Border Opacity", max: 100 }),
Row({ opt: border.width, title: "Border Width" }),
Row({ opt: blur, title: "Blur", note: "0 to disable", max: 70 }),
),
Group("UI",
Row({ opt: padding, title: "Padding" }),
Row({ opt: spacing, title: "Spacing" }),
Row({ opt: radius, title: "Roundness" }),
Row({ opt: font.size, title: "Font Size" }),
Row({ opt: font.name, title: "Font Name", type: "font" }),
),
),
Page("Bar", icons.ui.toolbars,
Group("General",
Row({ opt: b.flatButtons, title: "Flat Buttons" }),
Row({ opt: b.position, title: "Position", type: "enum", enums: ["top", "bottom"] }),
Row({ opt: b.corners, title: "Corners" }),
),
Group("Launcher",
Row({ opt: b.launcher.icon.icon, title: "Icon" }),
Row({ opt: b.launcher.icon.colored, title: "Colored Icon" }),
Row({ opt: b.launcher.label.label, title: "Label" }),
Row({ opt: b.launcher.label.colored, title: "Colored Label" }),
),
Group("Workspaces",
Row({ opt: b.workspaces.workspaces, title: "Number of Workspaces", note: "0 to make it dynamic" }),
),
Group("Taskbar",
Row({ opt: b.taskbar.iconSize, title: "Icon Size" }),
Row({ opt: b.taskbar.monochrome, title: "Monochrome" }),
Row({ opt: b.taskbar.exclusive, title: "Exclusive to workspaces" }),
),
Group("Date",
Row({ opt: b.date.format, title: "Date Format" }),
),
Group("Media",
Row({ opt: b.media.monochrome, title: "Monochrome" }),
Row({ opt: b.media.preferred, title: "Preferred Player" }),
Row({ opt: b.media.direction, title: "Slide Direction", type: "enum", enums: ["left", "right"] }),
Row({ opt: b.media.format, title: "Format of the Label" }),
Row({ opt: b.media.length, title: "Max Length of Label" }),
),
Group("Battery",
Row({ opt: b.battery.bar, title: "Style", type: "enum", enums: ["hidden", "regular", "whole"] }),
Row({ opt: b.battery.blocks, title: "Number of Blocks" }),
Row({ opt: b.battery.width, title: "Width of Bar" }),
Row({ opt: b.battery.charging, title: "Charging Color", type: "color" }),
),
Group("Powermenu",
Row({ opt: b.powermenu.monochrome, title: "Monochrome" }),
),
),
Page("General", icons.ui.settings,
Group("Hyprland",
Row({ opt: h.gapsWhenOnly, title: "Gaps When Only" }),
),
Group("Launcher",
Row({ opt: l.width, title: "Width" }),
Row({ opt: l.apps.iconSize, title: "Icon Size" }),
Row({ opt: l.apps.max, title: "Max Items" }),
),
Group("Overview",
Row({ opt: ov.scale, title: "Scale", max: 100 }),
Row({ opt: ov.workspaces, title: "Workspaces", max: 11, note: "set this to 0 to make it dynamic" }),
Row({ opt: ov.monochromeIcon, title: "Monochrome Icons" }),
),
Group("Powermenu",
Row({ opt: pm.layout, title: "Layout", type: "enum", enums: ["box", "line"] }),
Row({ opt: pm.labels, title: "Show Labels" }),
),
Group("Quicksettings",
Row({ opt: qs.avatar.image, title: "Avatar", type: "img" }),
Row({ opt: qs.avatar.size, title: "Avatar Size" }),
Row({ opt: qs.media.monochromeIcon, title: "Media Monochrome Icons" }),
Row({ opt: qs.media.coverSize, title: "Media Cover Art Size" }),
),
Group("On Screen Indicator",
Row({ opt: osd.progress.vertical, title: "Vertical" }),
Row({ opt: osd.progress.pack.h, title: "Horizontal Alignment", type: "enum", enums: ["start", "center", "end"] }),
Row({ opt: osd.progress.pack.v, title: "Vertical Alignment", type: "enum", enums: ["start", "center", "end"] }),
),
),
] as const

View File

@@ -0,0 +1,144 @@
window.settings-dialog {
background-color: $bg;
color: $fg;
.header {
.pager {
@include spacing(.5);
}
padding: $padding;
button {
@include button;
font-weight: bold;
padding: $padding*.5 $padding;
box {
@include spacing($spacing: .3em);
}
}
button.close {
padding: $padding * .5;
}
button.reset {
@include button($flat: true);
padding: $padding*.5;
}
}
.page {
@include scrollable($top: true);
.page-content {
padding: $padding*2;
padding-top: 0;
}
}
.group {
.group-title {
color: $primary-bg;
margin-bottom: $spacing*.5;
}
.group-reset {
@include button($flat: true);
margin: $spacing * .5;
padding: $padding * .5;
&:disabled {
color: transparent;
}
}
&:not(:first-child) {
margin-top: $spacing;
}
}
.row {
background-color: $widget-bg;
padding: $padding;
border: $border;
border-top: none;
&:first-child {
border-radius: $radius $radius 0 0;
border: $border;
}
&:last-child {
border-radius: 0 0 $radius $radius;
}
&:first-child:last-child {
border-radius: $radius;
border: $border;
}
button.reset {
margin-left: $spacing;
}
label.id,
label.note {
color: transparentize($fg, .4)
}
entry,
button {
@include button;
padding: $padding;
}
switch {
@include switch;
}
spinbutton {
@include unset;
entry {
border-radius: $radius 0 0 $radius;
}
button {
border-radius: 0;
}
button:last-child {
border-radius: 0 $radius $radius 0;
}
}
.enum-setter {
label {
background-color: $widget-bg;
border: $border;
padding: 0 $padding;
border-radius: $radius 0 0 $radius;
}
button {
border-radius: 0;
}
button:last-child {
border-radius: 0 $radius $radius 0;
}
}
&.wallpaper {
button {
margin-top: $spacing * .5;
}
.preview {
border-radius: $radius;
}
}
}
}