💥 fix(control-center/page, control-center/pages): scope errors
i basically restructured the page widget lol
This commit is contained in:
@@ -2,16 +2,13 @@ import { register } from "ags/gobject";
|
|||||||
import { Gtk } from "ags/gtk4";
|
import { Gtk } from "ags/gtk4";
|
||||||
import { Page } from "./pages/Page";
|
import { Page } from "./pages/Page";
|
||||||
import { timeout } from "ags/time";
|
import { timeout } from "ags/time";
|
||||||
import { variableToBoolean } from "../../scripts/utils";
|
|
||||||
|
|
||||||
import AstalIO from "gi://AstalIO";
|
import AstalIO from "gi://AstalIO";
|
||||||
import { createRoot } from "ags";
|
|
||||||
|
|
||||||
|
|
||||||
export { Pages };
|
export { Pages };
|
||||||
export type PagesProps = {
|
export type PagesProps = {
|
||||||
initialPage?: Page;
|
initialPage?: Page;
|
||||||
class?: string;
|
|
||||||
transitionDuration?: number;
|
transitionDuration?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -19,21 +16,20 @@ export type PagesProps = {
|
|||||||
class Pages extends Gtk.Box {
|
class Pages extends Gtk.Box {
|
||||||
#timeouts: Array<[AstalIO.Time, (() => void)|undefined]> = [];
|
#timeouts: Array<[AstalIO.Time, (() => void)|undefined]> = [];
|
||||||
#page: (Page|undefined);
|
#page: (Page|undefined);
|
||||||
#pageWidget: (Gtk.Revealer|undefined);
|
|
||||||
#transDuration: number;
|
#transDuration: number;
|
||||||
#transType: Gtk.RevealerTransitionType = Gtk.RevealerTransitionType.SLIDE_DOWN;
|
#transType: Gtk.RevealerTransitionType = Gtk.RevealerTransitionType.SLIDE_DOWN;
|
||||||
|
|
||||||
get isOpen() { return Boolean(this.get_first_child()); }
|
get isOpen() { return Boolean(this.#page); }
|
||||||
|
get page() { return this.#page; }
|
||||||
|
|
||||||
constructor(props?: PagesProps) {
|
constructor(props?: PagesProps) {
|
||||||
super({
|
super({
|
||||||
orientation: Gtk.Orientation.VERTICAL,
|
orientation: Gtk.Orientation.VERTICAL,
|
||||||
cssName: "pages"
|
cssName: "pages",
|
||||||
|
name: "pages"
|
||||||
});
|
});
|
||||||
|
|
||||||
this.name = "pages";
|
this.add_css_class("pages");
|
||||||
props?.class?.split(' ').filter(variableToBoolean).forEach(clss =>
|
|
||||||
this.add_css_class(clss));
|
|
||||||
|
|
||||||
this.#transDuration = props?.transitionDuration ?? 280;
|
this.#transDuration = props?.transitionDuration ?? 280;
|
||||||
|
|
||||||
@@ -53,7 +49,7 @@ class Pages extends Gtk.Box {
|
|||||||
}
|
}
|
||||||
|
|
||||||
toggle(newPage?: Page, onToggled?: () => void): void {
|
toggle(newPage?: Page, onToggled?: () => void): void {
|
||||||
if(!newPage || (this.#page?.id === newPage?.id)) {
|
if(!newPage || (this.#page?.id === newPage.id)) {
|
||||||
this.close(onToggled);
|
this.close(onToggled);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -69,38 +65,35 @@ class Pages extends Gtk.Box {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
open(newPage: Page, onOpened?: () => void) {
|
open(newPage: Page, onOpen?: () => void) {
|
||||||
const pageWidget = createRoot(() => <Gtk.Revealer
|
|
||||||
transitionDuration={this.#transDuration}
|
|
||||||
transitionType={this.#transType}
|
|
||||||
revealChild={false}>
|
|
||||||
|
|
||||||
{newPage as unknown as Gtk.Widget}
|
|
||||||
</Gtk.Revealer> as Gtk.Revealer);
|
|
||||||
|
|
||||||
this.prepend(pageWidget);
|
|
||||||
|
|
||||||
this.#pageWidget = pageWidget;
|
|
||||||
this.#page = newPage;
|
this.#page = newPage;
|
||||||
|
|
||||||
this.reorder_child_after(this.get_last_child()!, null);
|
this.prepend(
|
||||||
(this.get_first_child() as Gtk.Revealer).revealChild = true;
|
<Gtk.Revealer revealChild={false} transitionType={this.#transType}
|
||||||
onOpened?.();
|
transitionDuration={this.#transDuration}>
|
||||||
|
|
||||||
|
{newPage.create()}
|
||||||
|
</Gtk.Revealer> as Gtk.Revealer
|
||||||
|
);
|
||||||
|
|
||||||
|
(this.get_first_child() as Gtk.Revealer)?.set_reveal_child(true);
|
||||||
|
onOpen?.();
|
||||||
}
|
}
|
||||||
|
|
||||||
close(onClosed?: () => void): void {
|
close(onClosed?: () => void): void {
|
||||||
if(!this.#pageWidget) return;
|
const page = this.get_first_child() as Gtk.Revealer|null;
|
||||||
|
if(!page) return;
|
||||||
|
|
||||||
this.#pageWidget.revealChild = false;
|
this.#page?.actionClosed?.();
|
||||||
const closingPage = this.#pageWidget!;
|
this.#page = undefined;
|
||||||
|
|
||||||
|
page.set_reveal_child(false);
|
||||||
this.#timeouts.push([
|
this.#timeouts.push([
|
||||||
timeout(closingPage.transitionDuration, () => {
|
timeout(page.transitionDuration, () => {
|
||||||
this.remove(closingPage);
|
this.remove(page);
|
||||||
onClosed?.();
|
onClosed?.();
|
||||||
}),
|
}),
|
||||||
onClosed]);
|
onClosed
|
||||||
|
]);
|
||||||
this.#pageWidget = undefined;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ import { Gtk } from "ags/gtk4";
|
|||||||
import { Windows } from "../../windows";
|
import { Windows } from "../../windows";
|
||||||
import { Wallpaper } from "../../scripts/wallpaper";
|
import { Wallpaper } from "../../scripts/wallpaper";
|
||||||
import { execApp } from "../../scripts/apps";
|
import { execApp } from "../../scripts/apps";
|
||||||
import GLib from "gi://GLib?version=2.0";
|
|
||||||
import { Accessor } from "ags";
|
import { Accessor } from "ags";
|
||||||
import { createPoll } from "ags/time";
|
import { createPoll } from "ags/time";
|
||||||
|
|
||||||
|
import GLib from "gi://GLib?version=2.0";
|
||||||
|
import Gio from "gi://Gio?version=2.0";
|
||||||
|
|
||||||
|
|
||||||
|
const userFace: Gio.File = Gio.File.new_for_path(`${GLib.get_home_dir()}/.face`);
|
||||||
const uptime: Accessor<string> = createPoll("Just turned on", 1000, "uptime -p");
|
const uptime: Accessor<string> = createPoll("Just turned on", 1000, "uptime -p");
|
||||||
|
|
||||||
function LockButton(): Gtk.Button {
|
function LockButton(): Gtk.Button {
|
||||||
@@ -57,22 +59,25 @@ function LogoutButton(): Gtk.Button {
|
|||||||
|
|
||||||
export const QuickActions = () =>
|
export const QuickActions = () =>
|
||||||
<Gtk.Box class={"quickactions"}>
|
<Gtk.Box class={"quickactions"}>
|
||||||
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} halign={Gtk.Align.START}
|
<Gtk.Box halign={Gtk.Align.START} class={"left"} hexpand>
|
||||||
hexpand={true} class={"left"}>
|
{userFace.query_exists(null) &&
|
||||||
|
<Gtk.Box class={"user-face"} css={
|
||||||
|
`background-image: url("${userFace.get_path()!}");`}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
<Gtk.Box orientation={Gtk.Orientation.VERTICAL}>
|
||||||
|
<Gtk.Label class={"hostname"} xalign={0} tooltipText={"Host name"}
|
||||||
|
label={GLib.get_host_name()} />
|
||||||
|
|
||||||
<Gtk.Label class={"hostname"} xalign={0} tooltipText={"Host name"}
|
<Gtk.Box>
|
||||||
label={GLib.get_host_name()} />
|
<Gtk.Image iconName={"hourglass-symbolic"} />
|
||||||
|
<Gtk.Label class={"uptime"} xalign={0} tooltipText={"Up time"}
|
||||||
<Gtk.Box>
|
label={uptime.as(str => str.replace(/^up /, ""))} />
|
||||||
<Gtk.Image iconName={"hourglass-symbolic"} />
|
</Gtk.Box>
|
||||||
<Gtk.Label class={"uptime"} xalign={0} tooltipText={"Up time"}
|
|
||||||
label={uptime.as(str => str.replace(/^up /, ""))} />
|
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
|
|
||||||
<Gtk.Box class={"right button-row"} halign={Gtk.Align.END}
|
<Gtk.Box class={"right button-row"} halign={Gtk.Align.END} hexpand>
|
||||||
hexpand={true}>
|
|
||||||
|
|
||||||
<LockButton />
|
<LockButton />
|
||||||
<ColorPickerButton />
|
<ColorPickerButton />
|
||||||
<ScreenshotButton />
|
<ScreenshotButton />
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { Wireplumber } from "../../scripts/volume";
|
|||||||
import { Pages } from "./Pages";
|
import { Pages } from "./Pages";
|
||||||
import { PageSound } from "./pages/Sound";
|
import { PageSound } from "./pages/Sound";
|
||||||
import { PageMicrophone } from "./pages/Microphone";
|
import { PageMicrophone } from "./pages/Microphone";
|
||||||
import { createBinding, createRoot, With } from "ags";
|
import { createBinding, With } from "ags";
|
||||||
|
|
||||||
import AstalWp from "gi://AstalWp";
|
import AstalWp from "gi://AstalWp";
|
||||||
|
|
||||||
@@ -11,51 +11,43 @@ import AstalWp from "gi://AstalWp";
|
|||||||
export let slidersPages: Pages|undefined;
|
export let slidersPages: Pages|undefined;
|
||||||
|
|
||||||
export function Sliders() {
|
export function Sliders() {
|
||||||
slidersPages = createRoot(() => new Pages())!;
|
|
||||||
|
|
||||||
return <Gtk.Box class={"sliders"} orientation={Gtk.Orientation.VERTICAL}
|
return <Gtk.Box class={"sliders"} orientation={Gtk.Orientation.VERTICAL}
|
||||||
hexpand spacing={10} onDestroy={() => slidersPages = undefined}>
|
hexpand spacing={10} onUnmap={() => slidersPages = undefined}>
|
||||||
|
|
||||||
<With value={createBinding(Wireplumber.getWireplumber(), "defaultSpeaker")}>
|
<With value={createBinding(Wireplumber.getWireplumber(), "defaultSpeaker")}>
|
||||||
{(sink: AstalWp.Endpoint) => <Gtk.Box class={"sink speaker"} spacing={3}>
|
{(sink: AstalWp.Endpoint) => <Gtk.Box class={"sink speaker"} spacing={3}>
|
||||||
<Gtk.Button onClicked={Wireplumber.getDefault().toggleMuteSink}
|
<Gtk.Button onClicked={() => Wireplumber.getDefault().toggleMuteSink()}
|
||||||
iconName={createBinding(sink, "volumeIcon").as((icon) =>
|
iconName={createBinding(sink, "volumeIcon").as((icon) =>
|
||||||
(!Wireplumber.getDefault().isMutedSink() &&
|
(!Wireplumber.getDefault().isMutedSink() &&
|
||||||
Wireplumber.getDefault().getSinkVolume() > 0) ?
|
Wireplumber.getDefault().getSinkVolume() > 0
|
||||||
icon
|
) ? icon : "audio-volume-muted-symbolic"
|
||||||
: "audio-volume-muted-symbolic"
|
|
||||||
)} />
|
)} />
|
||||||
|
|
||||||
<Astal.Slider drawValue={false} hexpand={true}
|
<Astal.Slider drawValue={false} hexpand value={createBinding(sink, "volume")}
|
||||||
$={(self) => self.value = Math.floor(sink.volume * 100)}
|
max={Wireplumber.getDefault().getMaxSinkVolume() / 100}
|
||||||
value={createBinding(sink, "volume").as(v => Math.floor(v * 100))}
|
onChangeValue={(_, __, value) => sink.set_volume(value)} />
|
||||||
max={Wireplumber.getDefault().getMaxSinkVolume()}
|
|
||||||
onChangeValue={(_, _scrollType, value) => sink.set_volume(value / 100)} />
|
|
||||||
|
|
||||||
<Gtk.Button class={"more"} iconName={"go-next-symbolic"} onClicked={(_) =>
|
<Gtk.Button class={"more"} iconName={"go-next-symbolic"} onClicked={() =>
|
||||||
slidersPages!.toggle(PageSound())} />
|
slidersPages?.toggle(PageSound)} />
|
||||||
</Gtk.Box>}
|
</Gtk.Box>}
|
||||||
</With>
|
</With>
|
||||||
<With value={createBinding(Wireplumber.getWireplumber(), "defaultMicrophone")}>
|
<With value={createBinding(Wireplumber.getWireplumber(), "defaultMicrophone")}>
|
||||||
{(source: AstalWp.Endpoint) => <Gtk.Box class={"source microphone"} spacing={3}>
|
{(source: AstalWp.Endpoint) => <Gtk.Box class={"source microphone"} spacing={3}>
|
||||||
<Gtk.Button onClicked={Wireplumber.getDefault().toggleMuteSink}
|
<Gtk.Button onClicked={() => Wireplumber.getDefault().toggleMuteSource()}
|
||||||
iconName={createBinding(source, "volumeIcon").as((icon) =>
|
iconName={createBinding(source, "volumeIcon").as((icon) =>
|
||||||
(!Wireplumber.getDefault().isMutedSink() &&
|
(!Wireplumber.getDefault().isMutedSource() &&
|
||||||
Wireplumber.getDefault().getSinkVolume() > 0) ?
|
Wireplumber.getDefault().getSourceVolume() > 0
|
||||||
icon
|
) ? icon : "microphone-sensitivity-muted-symbolic"
|
||||||
: "microphone-sensitivity-muted-symbolic"
|
|
||||||
)} />
|
)} />
|
||||||
|
|
||||||
<Astal.Slider drawValue={false} hexpand={true}
|
<Astal.Slider drawValue={false} hexpand value={createBinding(source, "volume")}
|
||||||
$={(self) => self.value = Math.floor(source.volume * 100)}
|
max={Wireplumber.getDefault().getMaxSourceVolume() / 100}
|
||||||
value={createBinding(source, "volume").as(v => Math.floor(v * 100))}
|
onChangeValue={(_, __, value) => source.set_volume(value)} />
|
||||||
max={Wireplumber.getDefault().getMaxSinkVolume()}
|
|
||||||
onChangeValue={(_, _scrollType, value) => source.set_volume(value / 100)} />
|
|
||||||
|
|
||||||
<Gtk.Button class={"more"} iconName={"go-next-symbolic"} onClicked={(_) =>
|
<Gtk.Button class={"more"} iconName={"go-next-symbolic"} onClicked={() =>
|
||||||
slidersPages!.toggle(PageMicrophone())} />
|
slidersPages?.toggle(PageMicrophone)} />
|
||||||
</Gtk.Box>}
|
</Gtk.Box>}
|
||||||
</With>
|
</With>
|
||||||
{slidersPages}
|
<Pages $={(self) => slidersPages = self} />
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import { TileDND } from "./tiles/DoNotDisturb";
|
|||||||
import { TileRecording } from "./tiles/Recording";
|
import { TileRecording } from "./tiles/Recording";
|
||||||
import { TileNightLight } from "./tiles/NightLight";
|
import { TileNightLight } from "./tiles/NightLight";
|
||||||
import { Pages } from "./Pages";
|
import { Pages } from "./Pages";
|
||||||
import { createRoot } from "/usr/share/ags/js/gnim/src/jsx/scope";
|
|
||||||
|
|
||||||
|
|
||||||
export let TilesPages: Pages|undefined;
|
export let TilesPages: Pages|undefined;
|
||||||
@@ -19,18 +18,15 @@ export const tileList: Array<() => JSX.Element|Gtk.Widget> = [
|
|||||||
|
|
||||||
export function Tiles(): Gtk.Widget {
|
export function Tiles(): Gtk.Widget {
|
||||||
return <Gtk.Box class={"tiles-container"} orientation={Gtk.Orientation.VERTICAL}
|
return <Gtk.Box class={"tiles-container"} orientation={Gtk.Orientation.VERTICAL}
|
||||||
onDestroy={() => TilesPages = undefined} $={(self) => {
|
onUnmap={() => TilesPages = undefined}>
|
||||||
if(!TilesPages)
|
|
||||||
TilesPages = createRoot(() => new Pages({ class: "tile-pages" }));
|
|
||||||
|
|
||||||
self.append(TilesPages!);
|
|
||||||
}}>
|
|
||||||
|
|
||||||
<Gtk.FlowBox orientation={Gtk.Orientation.HORIZONTAL} rowSpacing={6}
|
<Gtk.FlowBox orientation={Gtk.Orientation.HORIZONTAL} rowSpacing={6}
|
||||||
columnSpacing={6} minChildrenPerLine={2} activateOnSingleClick
|
columnSpacing={6} minChildrenPerLine={2} activateOnSingleClick
|
||||||
maxChildrenPerLine={2} hexpand vexpand homogeneous>
|
maxChildrenPerLine={2} hexpand homogeneous>
|
||||||
|
|
||||||
{tileList.map(t => t())}
|
{tileList.map(t => t())}
|
||||||
</Gtk.FlowBox>
|
</Gtk.FlowBox>
|
||||||
|
|
||||||
|
<Pages class={"tile-pages"} $={(self) => TilesPages = self} />
|
||||||
</Gtk.Box> as Gtk.Box;
|
</Gtk.Box> as Gtk.Box;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,60 +4,70 @@ import { tr } from "../../../i18n/intl";
|
|||||||
import { Windows } from "../../../windows";
|
import { Windows } from "../../../windows";
|
||||||
import { Notifications } from "../../../scripts/notifications";
|
import { Notifications } from "../../../scripts/notifications";
|
||||||
import { execApp } from "../../../scripts/apps";
|
import { execApp } from "../../../scripts/apps";
|
||||||
|
import { createBinding, createComputed, For, With } from "ags";
|
||||||
|
|
||||||
import AstalNotifd from "gi://AstalNotifd";
|
import AstalNotifd from "gi://AstalNotifd";
|
||||||
import AstalBluetooth from "gi://AstalBluetooth";
|
import AstalBluetooth from "gi://AstalBluetooth";
|
||||||
import { variableToBoolean } from "../../../scripts/utils";
|
|
||||||
import { createBinding, createComputed, For, With } from "ags";
|
|
||||||
|
|
||||||
|
|
||||||
export const BluetoothPage = () => <Page
|
export const BluetoothPage = new Page({
|
||||||
id={"bluetooth"} title={tr("control_center.pages.bluetooth.title")}
|
id: "bluetooth",
|
||||||
description={tr("control_center.pages.bluetooth.description")}
|
title: tr("control_center.pages.bluetooth.title"),
|
||||||
class={"bluetooth"} headerButtons={[
|
spacing: 6,
|
||||||
<Gtk.Button class={"discover"} iconName={createBinding(
|
description: tr("control_center.pages.bluetooth.description"),
|
||||||
AstalBluetooth.get_default().adapter, "discovering"
|
headerButtons: [{
|
||||||
).as(discovering => discovering ?
|
icon: createBinding(AstalBluetooth.get_default().adapter, "discovering")
|
||||||
"arrow-circular-top-right-symbolic"
|
.as(discovering => !discovering ?
|
||||||
: "media-playback-stop-symbolic")} tooltipText={
|
"arrow-circular-top-right-symbolic"
|
||||||
createBinding(AstalBluetooth.get_default().adapter, "discovering").as((discovering) =>
|
: "media-playback-stop-symbolic"
|
||||||
!discovering ?
|
),
|
||||||
tr("control_center.pages.bluetooth.start_discovering")
|
tooltipText: createBinding(AstalBluetooth.get_default().adapter, "discovering")
|
||||||
: tr("control_center.pages.bluetooth.stop_discovering"))}
|
.as((discovering) => !discovering ?
|
||||||
onClicked={() => {
|
tr("control_center.pages.bluetooth.start_discovering")
|
||||||
if(AstalBluetooth.get_default().adapter.discovering) {
|
: tr("control_center.pages.bluetooth.stop_discovering")),
|
||||||
AstalBluetooth.get_default().adapter.stop_discovery();
|
actionClicked: () => {
|
||||||
return;
|
if(AstalBluetooth.get_default().adapter.discovering) {
|
||||||
}
|
AstalBluetooth.get_default().adapter.stop_discovery();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
AstalBluetooth.get_default().adapter.start_discovery();
|
AstalBluetooth.get_default().adapter.start_discovery();
|
||||||
}}
|
}
|
||||||
/>
|
}],
|
||||||
]}
|
actionClosed: () => AstalBluetooth.get_default().adapter.discovering &&
|
||||||
actionClose={() => AstalBluetooth.get_default().adapter.discovering &&
|
AstalBluetooth.get_default().adapter.stop_discovery(),
|
||||||
AstalBluetooth.get_default().adapter.stop_discovery()}
|
bottomButtons: [{
|
||||||
bottomButtons={[{
|
|
||||||
title: tr("control_center.pages.more_settings"),
|
title: tr("control_center.pages.more_settings"),
|
||||||
onClick: () => {
|
actionClicked: () => {
|
||||||
Windows.getDefault().close("control-center");
|
Windows.getDefault().close("control-center");
|
||||||
execApp("overskride", "[float; animation slide right]");
|
execApp("overskride", "[float; animation slide right]");
|
||||||
}
|
}
|
||||||
}]} spacing={2}>
|
}],
|
||||||
<Gtk.Box class={"adapters"} visible={variableToBoolean(createBinding(
|
content: () => [
|
||||||
AstalBluetooth.get_default(), "adapters"))} spacing={2}>
|
<Gtk.Box class={"adapters"} visible={createBinding(AstalBluetooth.get_default(), "adapters")
|
||||||
|
.as(adptrs => adptrs.length > 1)
|
||||||
|
} spacing={2}>
|
||||||
|
|
||||||
<Gtk.Label class={"sub-header"} label={tr("control_center.pages.bluetooth.adapters")} />
|
<Gtk.Label class={"sub-header"} label={tr("control_center.pages.bluetooth.adapters")} />
|
||||||
<For each={createBinding(AstalBluetooth.get_default(), "adapters")}>
|
<With value={createBinding(AstalBluetooth.get_default(), "adapters").as(adpts =>
|
||||||
{(adapter: AstalBluetooth.Adapter) =>
|
adpts.length > 1)}>
|
||||||
<PageButton title={adapter.alias ?? "Adapter"}
|
|
||||||
icon={"bluetooth-active-symbolic"} />
|
{(hasMoreAdapters: boolean) => hasMoreAdapters &&
|
||||||
|
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} spacing={2}>
|
||||||
|
<For each={createBinding(AstalBluetooth.get_default(), "adapters")}>
|
||||||
|
{(adapter: AstalBluetooth.Adapter) =>
|
||||||
|
<PageButton title={adapter.alias ?? "Adapter"}
|
||||||
|
icon={"bluetooth-active-symbolic"} />
|
||||||
|
}
|
||||||
|
</For>
|
||||||
|
</Gtk.Box>
|
||||||
}
|
}
|
||||||
</For>
|
</With>
|
||||||
</Gtk.Box>
|
</Gtk.Box>,
|
||||||
<Gtk.Box class={"connections"} orientation={Gtk.Orientation.VERTICAL} hexpand={true}
|
<Gtk.Box class={"connections"} orientation={Gtk.Orientation.VERTICAL} hexpand={true}
|
||||||
spacing={2}>
|
spacing={2}>
|
||||||
|
|
||||||
<Gtk.Box class={"paired"} orientation={Gtk.Orientation.VERTICAL} spacing={2}
|
<Gtk.Box class={"paired"} orientation={Gtk.Orientation.VERTICAL} spacing={4}
|
||||||
visible={createBinding(AstalBluetooth.get_default(), "devices").as(devs =>
|
visible={createBinding(AstalBluetooth.get_default(), "devices").as(devs =>
|
||||||
devs.filter(dev => dev.paired || dev.connected || dev.trusted).length > 0)}>
|
devs.filter(dev => dev.paired || dev.connected || dev.trusted).length > 0)}>
|
||||||
|
|
||||||
@@ -68,7 +78,7 @@ export const BluetoothPage = () => <Page
|
|||||||
{(dev: AstalBluetooth.Device) => <DeviceWidget device={dev} />}
|
{(dev: AstalBluetooth.Device) => <DeviceWidget device={dev} />}
|
||||||
</For>
|
</For>
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
<Gtk.Box class={"discovered"} orientation={Gtk.Orientation.VERTICAL} spacing={2}
|
<Gtk.Box class={"discovered"} orientation={Gtk.Orientation.VERTICAL} spacing={4}
|
||||||
visible={createBinding(AstalBluetooth.get_default(), "devices").as(devs =>
|
visible={createBinding(AstalBluetooth.get_default(), "devices").as(devs =>
|
||||||
devs.filter(dev => !dev.connected && !dev.paired && !dev.trusted).length > 0)}>
|
devs.filter(dev => !dev.connected && !dev.paired && !dev.trusted).length > 0)}>
|
||||||
|
|
||||||
@@ -80,7 +90,8 @@ export const BluetoothPage = () => <Page
|
|||||||
</For>
|
</For>
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
</Page> as Page;
|
]
|
||||||
|
});
|
||||||
|
|
||||||
function DeviceWidget({ device }: { device: AstalBluetooth.Device }): Gtk.Widget {
|
function DeviceWidget({ device }: { device: AstalBluetooth.Device }): Gtk.Widget {
|
||||||
return <PageButton class={createBinding(device, "connected").as(conn =>
|
return <PageButton class={createBinding(device, "connected").as(conn =>
|
||||||
@@ -93,7 +104,7 @@ function DeviceWidget({ device }: { device: AstalBluetooth.Device }): Gtk.Widget
|
|||||||
tooltipText={
|
tooltipText={
|
||||||
createBinding(device, "connected").as(connected =>
|
createBinding(device, "connected").as(connected =>
|
||||||
!connected ? tr("connect") : "")
|
!connected ? tr("connect") : "")
|
||||||
} onClick={() => {
|
} actionClicked={() => {
|
||||||
if(device.connected) return;
|
if(device.connected) return;
|
||||||
|
|
||||||
let skipConnection: boolean = false;
|
let skipConnection: boolean = false;
|
||||||
@@ -135,8 +146,8 @@ function DeviceWidget({ device }: { device: AstalBluetooth.Device }): Gtk.Widget
|
|||||||
createBinding(device, "connected"),
|
createBinding(device, "connected"),
|
||||||
createBinding(device, "trusted")
|
createBinding(device, "trusted")
|
||||||
])}>
|
])}>
|
||||||
{([connected, trusted]: [boolean, boolean]) => trusted &&
|
{([connected, trusted]: [boolean, boolean]) =>
|
||||||
<Gtk.Box class={"button-row"}>
|
<Gtk.Box visible={connected || trusted}>
|
||||||
{<Gtk.Button iconName={connected ?
|
{<Gtk.Button iconName={connected ?
|
||||||
"list-remove-symbolic"
|
"list-remove-symbolic"
|
||||||
: "user-trash-symbolic"} tooltipText={tr(connected ?
|
: "user-trash-symbolic"} tooltipText={tr(connected ?
|
||||||
@@ -157,7 +168,8 @@ function DeviceWidget({ device }: { device: AstalBluetooth.Device }): Gtk.Widget
|
|||||||
`control_center.pages.bluetooth.${trusted ? "un" : ""}trust_device`
|
`control_center.pages.bluetooth.${trusted ? "un" : ""}trust_device`
|
||||||
)} onClicked={() => device.set_trusted(!trusted)}
|
)} onClicked={() => device.set_trusted(!trusted)}
|
||||||
/>
|
/>
|
||||||
</Gtk.Box>}
|
</Gtk.Box>
|
||||||
|
}
|
||||||
</With>}
|
</With>}
|
||||||
/> as Page;
|
/> as Gtk.Widget;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,27 +3,32 @@ import { Wireplumber } from "../../../scripts/volume";
|
|||||||
import { Gtk } from "ags/gtk4";
|
import { Gtk } from "ags/gtk4";
|
||||||
import { tr } from "../../../i18n/intl";
|
import { tr } from "../../../i18n/intl";
|
||||||
import { createBinding, For } from "ags";
|
import { createBinding, For } from "ags";
|
||||||
import AstalWp from "gi://AstalWp?version=0.1";
|
|
||||||
import { lookupIcon } from "../../../scripts/apps";
|
import { lookupIcon } from "../../../scripts/apps";
|
||||||
|
|
||||||
|
import AstalWp from "gi://AstalWp?version=0.1";
|
||||||
|
|
||||||
export const PageMicrophone = () =>
|
|
||||||
<Page id={"microphone"} title={tr("control_center.pages.microphone.title")}
|
|
||||||
description={tr("control_center.pages.microphone.description")}>
|
|
||||||
|
|
||||||
<Gtk.Label class={"sub-header"} label={tr("devices")} xalign={0} />
|
export const PageMicrophone = new Page({
|
||||||
<For each={createBinding(Wireplumber.getWireplumber().get_audio()!, "microphones")}>
|
id: "microphone",
|
||||||
{(source: AstalWp.Endpoint) => <PageButton class={
|
title: tr("control_center.pages.microphone.title"),
|
||||||
createBinding(source, "isDefault").as(isDefault => isDefault ? "default" : "")
|
description: tr("control_center.pages.microphone.description"),
|
||||||
} icon={createBinding(source, "icon").as(ico => lookupIcon(ico) ?
|
content: () => [
|
||||||
ico : "audio-input-microphone-symbolic")} title={
|
<Gtk.Label class={"sub-header"} label={tr("devices")} xalign={0} />,
|
||||||
createBinding(source, "description").as(desc => desc ?? "Microphone")
|
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} spacing={4}>
|
||||||
} onClick={() => !source.isDefault && source.set_is_default(true)}
|
<For each={createBinding(Wireplumber.getWireplumber().get_audio()!, "microphones")}>
|
||||||
endWidget={
|
{(source: AstalWp.Endpoint) => <PageButton class={
|
||||||
<Gtk.Image iconName={"object-select-symbolic"} visible={
|
createBinding(source, "isDefault").as(isDefault => isDefault ? "default" : "")
|
||||||
createBinding(source, "isDefault")} css={"font-size: 18px;"}
|
} icon={createBinding(source, "icon").as(ico => lookupIcon(ico) ?
|
||||||
/>
|
ico : "audio-input-microphone-symbolic")} title={
|
||||||
}
|
createBinding(source, "description").as(desc => desc ?? "Microphone")
|
||||||
/>}
|
} actionClicked={() => !source.isDefault && source.set_is_default(true)}
|
||||||
</For>
|
endWidget={
|
||||||
</Page> as Page;
|
<Gtk.Image iconName={"object-select-symbolic"} visible={
|
||||||
|
createBinding(source, "isDefault")} css={"font-size: 18px;"}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>}
|
||||||
|
</For>
|
||||||
|
</Gtk.Box>
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|||||||
@@ -6,32 +6,34 @@ import { execApp } from "../../../scripts/apps";
|
|||||||
import { Notifications } from "../../../scripts/notifications";
|
import { Notifications } from "../../../scripts/notifications";
|
||||||
import { AskPopup, AskPopupProps } from "../../AskPopup";
|
import { AskPopup, AskPopupProps } from "../../AskPopup";
|
||||||
import { encoder, variableToBoolean } from "../../../scripts/utils";
|
import { encoder, variableToBoolean } from "../../../scripts/utils";
|
||||||
|
import { createBinding, For, With } from "ags";
|
||||||
|
|
||||||
import GLib from "gi://GLib?version=2.0";
|
import GLib from "gi://GLib?version=2.0";
|
||||||
import NM from "gi://NM";
|
import NM from "gi://NM";
|
||||||
import AstalNetwork from "gi://AstalNetwork";
|
import AstalNetwork from "gi://AstalNetwork";
|
||||||
import { createBinding, For, With } from "ags";
|
|
||||||
|
|
||||||
|
|
||||||
export const PageNetwork = () =>
|
export const PageNetwork = new Page({
|
||||||
<Page id={"network"} title={tr("control_center.pages.network.title")}
|
id: "network",
|
||||||
class={"network"} headerButtons={[
|
title: tr("control_center.pages.network.title"),
|
||||||
<Gtk.Button class={"reload"} iconName={"arrow-circular-top-right-symbolic"}
|
headerButtons: createBinding(AstalNetwork.get_default(), "primary").as(primary =>
|
||||||
visible={createBinding(AstalNetwork.get_default(), "primary").as(primary =>
|
primary === AstalNetwork.Primary.WIFI ? [{
|
||||||
primary === AstalNetwork.Primary.WIFI)}
|
icon: "arrow-circular-top-right-symbolic",
|
||||||
tooltipText={"Re-scan networks"} onClicked={() =>
|
tooltipText: "Re-scan networks",
|
||||||
AstalNetwork.get_default().wifi.scan()}
|
actionClicked: () => AstalNetwork.get_default().wifi.scan()
|
||||||
/>
|
}] : []
|
||||||
]} bottomButtons={[{
|
),
|
||||||
title: tr("control_center.pages.more_settings"),
|
bottomButtons: [{
|
||||||
onClick: () => {
|
title: tr("control_center.pages.more_settings"),
|
||||||
Windows.getDefault().close("control-center");
|
actionClicked: () => {
|
||||||
execApp("nm-connection-editor", "[animationstyle gnomed]");
|
Windows.getDefault().close("control-center");
|
||||||
}
|
execApp("nm-connection-editor", "[animationstyle gnomed]");
|
||||||
}]}>
|
}
|
||||||
|
}],
|
||||||
<Gtk.Box class={"devices"} hexpand={true} orientation={Gtk.Orientation.VERTICAL}
|
content: () => [
|
||||||
visible={variableToBoolean(createBinding(AstalNetwork.get_default().client, "devices"))}>
|
<Gtk.Box class={"devices"} hexpand orientation={Gtk.Orientation.VERTICAL}
|
||||||
|
visible={variableToBoolean(createBinding(AstalNetwork.get_default().client, "devices"))}
|
||||||
|
spacing={4}>
|
||||||
|
|
||||||
<Gtk.Label label={tr("devices")} xalign={0} class={"sub-header"} />
|
<Gtk.Label label={tr("devices")} xalign={0} class={"sub-header"} />
|
||||||
<For each={createBinding(AstalNetwork.get_default().client, "devices").as(devs =>
|
<For each={createBinding(AstalNetwork.get_default().client, "devices").as(devs =>
|
||||||
@@ -52,8 +54,7 @@ export const PageNetwork = () =>
|
|||||||
]}
|
]}
|
||||||
/>}
|
/>}
|
||||||
</For>
|
</For>
|
||||||
</Gtk.Box>
|
</Gtk.Box>,
|
||||||
|
|
||||||
<With value={createBinding(AstalNetwork.get_default(), "primary").as(primary =>
|
<With value={createBinding(AstalNetwork.get_default(), "primary").as(primary =>
|
||||||
primary === AstalNetwork.Primary.WIFI)}>
|
primary === AstalNetwork.Primary.WIFI)}>
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ export const PageNetwork = () =>
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}}/>
|
}}/>
|
||||||
]} onClick={() => {
|
]} actionClicked={() => {
|
||||||
const uuid = NM.utils_uuid_generate();
|
const uuid = NM.utils_uuid_generate();
|
||||||
const ssidBytes = GLib.Bytes.new(encoder.encode(ap.ssid));
|
const ssidBytes = GLib.Bytes.new(encoder.encode(ap.ssid));
|
||||||
|
|
||||||
@@ -129,7 +130,8 @@ export const PageNetwork = () =>
|
|||||||
</For>
|
</For>
|
||||||
</Gtk.Box>}
|
</Gtk.Box>}
|
||||||
</With>
|
</With>
|
||||||
</Page> as Page;
|
]
|
||||||
|
});
|
||||||
|
|
||||||
function activateWirelessConnection(connection: NM.RemoteConnection, ssid: string): void {
|
function activateWirelessConnection(connection: NM.RemoteConnection, ssid: string): void {
|
||||||
AstalNetwork.get_default().get_client().activate_connection_async(
|
AstalNetwork.get_default().get_client().activate_connection_async(
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ import { Astal, Gtk } from "ags/gtk4";
|
|||||||
import { addSliderMarksFromMinMax } from "../../../scripts/utils";
|
import { addSliderMarksFromMinMax } from "../../../scripts/utils";
|
||||||
import { createBinding } from "ags";
|
import { createBinding } from "ags";
|
||||||
|
|
||||||
export const PageNightLight = () =>
|
export const PageNightLight = new Page({
|
||||||
<Page id={"night-light"} title={tr("control_center.pages.night_light.title")}
|
id: "night-light",
|
||||||
description={tr("control_center.pages.night_light.description")}
|
title: tr("control_center.pages.night_light.title"),
|
||||||
class={"night-light"}>
|
description: tr("control_center.pages.night_light.description"),
|
||||||
|
content: () => [
|
||||||
<Gtk.Label class={"sub-header"} label={tr(
|
<Gtk.Label class={"sub-header"} label={tr(
|
||||||
"control_center.pages.night_light.temperature"
|
"control_center.pages.night_light.temperature"
|
||||||
)} xalign={0} />
|
)} xalign={0} />,
|
||||||
<Astal.Slider class={"temperature"} $={(self) => {
|
<Astal.Slider class={"temperature"} $={(self) => {
|
||||||
self.value = NightLight.getDefault().temperature;
|
self.value = NightLight.getDefault().temperature;
|
||||||
addSliderMarksFromMinMax(self, 5, "{}K");
|
addSliderMarksFromMinMax(self, 5, "{}K");
|
||||||
@@ -24,10 +24,10 @@ export const PageNightLight = () =>
|
|||||||
if(type != undefined && type !== null)
|
if(type != undefined && type !== null)
|
||||||
NightLight.getDefault().temperature = Math.floor(value)
|
NightLight.getDefault().temperature = Math.floor(value)
|
||||||
}}
|
}}
|
||||||
/>
|
/>,
|
||||||
<Gtk.Label class={"sub-header"} label={tr(
|
<Gtk.Label class={"sub-header"} label={tr(
|
||||||
"control_center.pages.night_light.gamma"
|
"control_center.pages.night_light.gamma"
|
||||||
)} xalign={0} />
|
)} xalign={0} />,
|
||||||
<Astal.Slider class={"gamma"} $={(self) => {
|
<Astal.Slider class={"gamma"} $={(self) => {
|
||||||
self.value = NightLight.getDefault().gamma;
|
self.value = NightLight.getDefault().gamma;
|
||||||
addSliderMarksFromMinMax(self, 5, "{}%");
|
addSliderMarksFromMinMax(self, 5, "{}%");
|
||||||
@@ -39,4 +39,5 @@ export const PageNightLight = () =>
|
|||||||
NightLight.getDefault().gamma = Math.floor(value)
|
NightLight.getDefault().gamma = Math.floor(value)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</Page> as Page;
|
]
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,24 +1,21 @@
|
|||||||
import { register } from "ags/gobject";
|
|
||||||
import { Gtk } from "ags/gtk4";
|
import { Gtk } from "ags/gtk4";
|
||||||
import { Separator } from "../../Separator";
|
import { Separator } from "../../Separator";
|
||||||
import { Accessor, For } from "ags";
|
import { Accessor, createRoot } from "ags";
|
||||||
import { transform, transformWidget, variableToBoolean, WidgetNodeType } from "../../../scripts/utils";
|
import { transformWidget, variableToBoolean, WidgetNodeType } from "../../../scripts/utils";
|
||||||
|
|
||||||
import Pango from "gi://Pango?version=1.0";
|
import Pango from "gi://Pango?version=1.0";
|
||||||
|
|
||||||
|
|
||||||
export type PageProps = {
|
export type PageProps = {
|
||||||
$?: () => void;
|
|
||||||
actionClose?: () => void;
|
|
||||||
id: string;
|
id: string;
|
||||||
class?: string | Accessor<string>;
|
title: string;
|
||||||
title: string | Accessor<string>;
|
description?: string;
|
||||||
description?: string | Accessor<string>;
|
headerButtons?: Array<HeaderButton> | Accessor<Array<HeaderButton>>;
|
||||||
headerButtons?: Array<JSX.Element> | Accessor<Array<JSX.Element>>;
|
|
||||||
bottomButtons?: Array<BottomButton> | Accessor<Array<BottomButton>>;
|
bottomButtons?: Array<BottomButton> | Accessor<Array<BottomButton>>;
|
||||||
orientation?: Gtk.Orientation | Accessor<Gtk.Orientation>;
|
orientation?: Gtk.Orientation | Accessor<Gtk.Orientation>;
|
||||||
spacing?: number;
|
spacing?: number | Accessor<number>;
|
||||||
children?: WidgetNodeType;
|
content: () => WidgetNodeType;
|
||||||
|
actionClosed?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type BottomButton = {
|
export type BottomButton = {
|
||||||
@@ -26,142 +23,134 @@ export type BottomButton = {
|
|||||||
description?: string | Accessor<string>;
|
description?: string | Accessor<string>;
|
||||||
tooltipText?: string | Accessor<string>;
|
tooltipText?: string | Accessor<string>;
|
||||||
tooltipMarkup?: string | Accessor<string>;
|
tooltipMarkup?: string | Accessor<string>;
|
||||||
onClick?: () => void;
|
actionClicked?: () => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { Page };
|
export type HeaderButton = {
|
||||||
|
label?: string|Accessor<string>;
|
||||||
|
icon: string|Accessor<string>;
|
||||||
|
tooltipText?: string | Accessor<string>;
|
||||||
|
tooltipMarkup?: string | Accessor<string>;
|
||||||
|
actionClicked?: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
@register({ GTypeName: "Page" })
|
export class Page {
|
||||||
class Page extends Gtk.Box {
|
#title: string;
|
||||||
#id: string | number = "";
|
#description?: string;
|
||||||
readonly bottomButtons?: Array<BottomButton> = [];
|
#orientation: Gtk.Orientation|Accessor<
|
||||||
|
Gtk.Orientation> = Gtk.Orientation.VERTICAL;
|
||||||
#subs: Array<() => void> = [];
|
#spacing: number|Accessor<number> = 4;
|
||||||
#title: string | Accessor<string> = "";
|
#headerButtons?: Array<HeaderButton>|Accessor<Array<HeaderButton>>;
|
||||||
#description?: string | Accessor<string>;
|
#bottomButtons?: Array<BottomButton>|Accessor<Array<BottomButton>>;
|
||||||
|
readonly #id?: string;
|
||||||
|
readonly #create: () => WidgetNodeType;
|
||||||
|
|
||||||
|
public get id() { return this.#id; }
|
||||||
public get title() { return this.#title; }
|
public get title() { return this.#title; }
|
||||||
public get description() { return this.#description; }
|
public get description() { return this.#description; }
|
||||||
public get id() { return this.#id; }
|
public get headerButtons() { return this.#headerButtons; }
|
||||||
public actionClose?: () => void = () => {};
|
public get bottomButtons() { return this.#bottomButtons; }
|
||||||
|
public readonly actionClosed?: () => void;
|
||||||
|
|
||||||
constructor(props: PageProps) {
|
constructor(props: PageProps) {
|
||||||
super();
|
|
||||||
|
|
||||||
this.set_hexpand(true);
|
|
||||||
this.set_orientation(Gtk.Orientation.VERTICAL);
|
|
||||||
|
|
||||||
if(props.class instanceof Accessor) {
|
|
||||||
this.#subs.push(props.class.subscribe(() => {
|
|
||||||
const clss = (props.class as Accessor<string>).get();
|
|
||||||
|
|
||||||
this.cssClasses = ["page", ...clss.split(' ').filter(s => s !== "")];
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
if(props.class)
|
|
||||||
this.cssClasses = ["page",
|
|
||||||
...(props.class as string).split(' ').filter(s => s)];
|
|
||||||
else
|
|
||||||
this.add_css_class("page");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.#id = props.id;
|
this.#id = props.id;
|
||||||
this.#title = props.title;
|
this.#title = props.title;
|
||||||
this.#description = props.description;
|
this.#description = props.description;
|
||||||
this.actionClose = props.actionClose;
|
this.#create = props.content;
|
||||||
|
this.actionClosed = props.actionClosed;
|
||||||
|
|
||||||
this.prepend(<Gtk.Box class={"header"} orientation={Gtk.Orientation.VERTICAL}
|
if(props.orientation != null)
|
||||||
hexpand={true}>
|
this.#orientation = props.orientation;
|
||||||
|
|
||||||
<Gtk.Box class={"top"}>
|
if(props.spacing != null)
|
||||||
<Gtk.Label hexpand={true} class={"title"} ellipsize={Pango.EllipsizeMode.END}
|
this.#spacing = props.spacing;
|
||||||
visible={variableToBoolean(props.title)} label={props.title}
|
|
||||||
halign={Gtk.Align.START} />
|
if(props.headerButtons != null)
|
||||||
|
this.#headerButtons = props.headerButtons;
|
||||||
|
}
|
||||||
|
|
||||||
|
public create(): Gtk.Box {
|
||||||
|
return createRoot((dispose) =>
|
||||||
|
<Gtk.Box hexpand class={`page container ${this.#id ?? ""}`} cssName={"page"} name={"page"}
|
||||||
|
orientation={Gtk.Orientation.VERTICAL} onUnmap={() => dispose()}>
|
||||||
|
|
||||||
|
<Gtk.Box class={"header"} orientation={Gtk.Orientation.VERTICAL}>
|
||||||
|
<Gtk.Box class={"top"} hexpand>
|
||||||
|
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} hexpand>
|
||||||
|
<Gtk.Label class={"title"} label={this.#title} xalign={0}
|
||||||
|
ellipsize={Pango.EllipsizeMode.END} />
|
||||||
|
|
||||||
|
<Gtk.Label class={"description"} label={this.#description}
|
||||||
|
xalign={0} ellipsize={Pango.EllipsizeMode.END}
|
||||||
|
visible={variableToBoolean(this.#description)} />
|
||||||
|
</Gtk.Box>
|
||||||
|
<Gtk.Box class={"button-row"} visible={variableToBoolean(this.#headerButtons)}
|
||||||
|
hexpand={false}>
|
||||||
|
|
||||||
|
{this.#headerButtons && transformWidget(this.#headerButtons, (button) =>
|
||||||
|
<Gtk.Button class={"header-button"} label={button.label}
|
||||||
|
iconName={button.icon} onClicked={() => button.actionClicked?.()}
|
||||||
|
tooltipText={button.tooltipText} tooltipMarkup={button.tooltipMarkup}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Gtk.Box>
|
||||||
|
</Gtk.Box>
|
||||||
|
</Gtk.Box>
|
||||||
|
<Gtk.Box class={"content"} hexpand={false} orientation={this.#orientation}
|
||||||
|
spacing={this.#spacing}>
|
||||||
|
|
||||||
|
{this.#create()}
|
||||||
|
</Gtk.Box>
|
||||||
|
<Separator alpha={.2} spacing={6} orientation={Gtk.Orientation.VERTICAL}
|
||||||
|
visible={variableToBoolean(this.#bottomButtons)}
|
||||||
|
/>
|
||||||
|
<Gtk.Box class={"bottom-buttons"} orientation={Gtk.Orientation.VERTICAL}
|
||||||
|
visible={variableToBoolean(this.#bottomButtons)} spacing={2}>
|
||||||
|
|
||||||
{props.headerButtons && <Gtk.Box class={"button-row"} visible={variableToBoolean(props.headerButtons)}>
|
{this.#bottomButtons && transformWidget(this.#bottomButtons, (button) =>
|
||||||
{
|
<Gtk.Button onClicked={() => button?.actionClicked?.()} tooltipText={button?.tooltipText}
|
||||||
(props.headerButtons instanceof Accessor) ?
|
tooltipMarkup={button?.tooltipMarkup}>
|
||||||
<For each={props.headerButtons}>
|
|
||||||
{(button) => button}
|
|
||||||
</For>
|
|
||||||
: props.headerButtons
|
|
||||||
}
|
|
||||||
</Gtk.Box>}
|
|
||||||
|
|
||||||
<Gtk.Label class={"description"} hexpand={true} ellipsize={Pango.EllipsizeMode.END}
|
|
||||||
xalign={0} visible={variableToBoolean(props.description)} label={props.description} />
|
|
||||||
|
|
||||||
</Gtk.Box>
|
<Gtk.Label class={"title"} label={button?.title} xalign={0} />
|
||||||
</Gtk.Box> as Gtk.Box);
|
<Gtk.Label class={"description"} label={button?.description}
|
||||||
|
xalign={0} visible={variableToBoolean(button?.description)} />
|
||||||
|
</Gtk.Button>
|
||||||
|
)}
|
||||||
|
</Gtk.Box>
|
||||||
|
</Gtk.Box> as Gtk.Box
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this.append(<Gtk.Box class={"content"} spacing={props.spacing ?? 4} hexpand={true} vexpand={true}
|
public static getContent(pageWidget: Gtk.Box) {
|
||||||
orientation={props.orientation ?? Gtk.Orientation.VERTICAL}>
|
return pageWidget.get_first_child()!.get_next_sibling()! as Gtk.Box;
|
||||||
|
|
||||||
{props.children}
|
|
||||||
</Gtk.Box> as Gtk.Box);
|
|
||||||
|
|
||||||
this.append(<Separator alpha={.2} spacing={6} orientation={Gtk.Orientation.VERTICAL}
|
|
||||||
visible={(props.bottomButtons instanceof Accessor) ?
|
|
||||||
props.bottomButtons.as(buttons => buttons.length > 0)
|
|
||||||
: (!props.bottomButtons ? false : props.bottomButtons.length > 0)}
|
|
||||||
/> as Gtk.Widget);
|
|
||||||
|
|
||||||
this.append(<Gtk.Box class={"bottom-buttons"} orientation={Gtk.Orientation.VERTICAL}
|
|
||||||
visible={variableToBoolean(props.bottomButtons)} spacing={2}>
|
|
||||||
|
|
||||||
{transformWidget(props.bottomButtons, (button) =>
|
|
||||||
<Gtk.Button onClicked={button?.onClick} tooltipText={button?.tooltipText}
|
|
||||||
tooltipMarkup={button?.tooltipMarkup}>
|
|
||||||
|
|
||||||
<Gtk.Label class={"title"} label={button?.title} xalign={0} />
|
|
||||||
<Gtk.Label class={"description"} label={button?.description}
|
|
||||||
xalign={0} visible={variableToBoolean(button?.description)} />
|
|
||||||
</Gtk.Button>
|
|
||||||
)}
|
|
||||||
</Gtk.Box> as Gtk.Box);
|
|
||||||
|
|
||||||
props.$?.();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function BottomButton(props: BottomButton) {
|
export function PageButton({ onUnmap, ...props }: {
|
||||||
return <Gtk.Button onClicked={props.onClick} tooltipMarkup={props.tooltipMarkup}
|
|
||||||
tooltipText={props.tooltipText}>
|
|
||||||
|
|
||||||
<Gtk.Box orientation={Gtk.Orientation.VERTICAL}>
|
|
||||||
<Gtk.Label class={"title"} label={props.title} xalign={0} />
|
|
||||||
<Gtk.Label class={"description"} label={props.description}
|
|
||||||
visible={Boolean(props.description)} xalign={0} />
|
|
||||||
</Gtk.Box>
|
|
||||||
</Gtk.Button> as Gtk.Button;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function PageButton({ onDestroy, ...props }: {
|
|
||||||
class?: string | Accessor<string>;
|
class?: string | Accessor<string>;
|
||||||
icon?: string | Accessor<string>;
|
icon?: string | Accessor<string>;
|
||||||
title: string | Accessor<string>;
|
title: string | Accessor<string>;
|
||||||
endWidget?: WidgetNodeType;
|
endWidget?: WidgetNodeType;
|
||||||
description?: string | Accessor<string>;
|
description?: string | Accessor<string>;
|
||||||
extraButtons?: Array<WidgetNodeType> | WidgetNodeType;
|
extraButtons?: Array<WidgetNodeType> | WidgetNodeType;
|
||||||
onDestroy?: (self: Gtk.Box) => void;
|
maxWidthChars?: number | Accessor<number>;
|
||||||
onClick?: (self: Gtk.Button) => void;
|
onUnmap?: (self: Gtk.Box) => void;
|
||||||
|
actionClicked?: (self: Gtk.Button) => void;
|
||||||
tooltipText?: string | Accessor<string>;
|
tooltipText?: string | Accessor<string>;
|
||||||
tooltipMarkup?: string | Accessor<string>;
|
tooltipMarkup?: string | Accessor<string>;
|
||||||
}) {
|
}): Gtk.Box {
|
||||||
return <Gtk.Box onDestroy={onDestroy}>
|
return <Gtk.Box onUnmap={(self) => onUnmap?.(self)} class={"page-button"}>
|
||||||
<Gtk.Button onClicked={props.onClick} class={props.class} hexpand={true}
|
<Gtk.Button onClicked={props.actionClicked} class={props.class} hexpand
|
||||||
tooltipText={props.tooltipText} tooltipMarkup={props.tooltipMarkup}>
|
tooltipText={props.tooltipText} tooltipMarkup={props.tooltipMarkup}>
|
||||||
|
|
||||||
<Gtk.Box class={"page-button"} hexpand={true} vexpand={true}>
|
<Gtk.Box class={"container"} hexpand>
|
||||||
{props.icon && <Gtk.Image iconName={props.icon} visible={variableToBoolean(props.icon)}
|
{props.icon && <Gtk.Image iconName={props.icon} visible={variableToBoolean(props.icon)}
|
||||||
css={"font-size: 20px; margin-right: 6px;"} />}
|
css={"font-size: 20px; margin-right: 6px;"} />}
|
||||||
|
|
||||||
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} hexpand={true} vexpand={false}>
|
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} hexpand vexpand={false}>
|
||||||
<Gtk.Label class={"title"} xalign={0} tooltipText={props.title}
|
<Gtk.Label class={"title"} xalign={0} tooltipText={props.title}
|
||||||
ellipsize={Pango.EllipsizeMode.END} label={
|
ellipsize={Pango.EllipsizeMode.END} label={props.title}
|
||||||
transform(props.title, (title) =>
|
maxWidthChars={props.maxWidthChars ?? 28}
|
||||||
`${title.substring(0, 35)}${title.length > 35 ? '…' : ""}`)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Gtk.Label class={"description"} xalign={0} visible={variableToBoolean(props.description)}
|
<Gtk.Label class={"description"} xalign={0} visible={variableToBoolean(props.description)}
|
||||||
label={props.description} ellipsize={Pango.EllipsizeMode.END}
|
label={props.description} ellipsize={Pango.EllipsizeMode.END}
|
||||||
@@ -174,7 +163,7 @@ export function PageButton({ onDestroy, ...props }: {
|
|||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
</Gtk.Button>
|
</Gtk.Button>
|
||||||
|
|
||||||
<Gtk.Box class={"extra-buttons button-row"} visible={variableToBoolean(props.extraButtons)}>
|
<Gtk.Box class={"extra-buttons"} visible={variableToBoolean(props.extraButtons)}>
|
||||||
{props.extraButtons}
|
{props.extraButtons}
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
</Gtk.Box> as Gtk.Box;
|
</Gtk.Box> as Gtk.Box;
|
||||||
|
|||||||
@@ -4,92 +4,93 @@ import { getAppIcon, lookupIcon } from "../../../scripts/apps";
|
|||||||
import { Wireplumber } from "../../../scripts/volume";
|
import { Wireplumber } from "../../../scripts/volume";
|
||||||
import { tr } from "../../../i18n/intl";
|
import { tr } from "../../../i18n/intl";
|
||||||
import { createBinding, For } from "ags";
|
import { createBinding, For } from "ags";
|
||||||
import AstalWp from "gi://AstalWp";
|
|
||||||
import { variableToBoolean } from "../../../scripts/utils";
|
import { variableToBoolean } from "../../../scripts/utils";
|
||||||
|
|
||||||
|
import AstalWp from "gi://AstalWp";
|
||||||
import GObject from "gi://GObject?version=2.0";
|
import GObject from "gi://GObject?version=2.0";
|
||||||
import Pango from "gi://Pango?version=1.0";
|
import Pango from "gi://Pango?version=1.0";
|
||||||
|
|
||||||
export const PageSound = () =>
|
|
||||||
<Page id={"sound"} title={tr("control_center.pages.sound.title")}
|
|
||||||
description={tr("control_center.pages.sound.description")}>
|
|
||||||
|
|
||||||
<Gtk.Label class={"sub-header"} label={tr("devices")} xalign={0} />
|
export const PageSound = new Page({
|
||||||
<For each={createBinding(Wireplumber.getWireplumber().audio!, "speakers")}>
|
id: "sound",
|
||||||
{(sink: AstalWp.Endpoint) =>
|
title: tr("control_center.pages.sound.title"),
|
||||||
<PageButton class={createBinding(sink, "isDefault").as(isDefault =>
|
description: tr("control_center.pages.sound.description"),
|
||||||
isDefault ? "default" : "")}
|
content: () => [
|
||||||
icon={createBinding(sink, "icon").as(ico =>
|
<Gtk.Label class={"sub-header"} label={tr("devices")} xalign={0} />,
|
||||||
lookupIcon(ico) ? ico : "audio-card-symbolic")}
|
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} spacing={4}>
|
||||||
title={createBinding(sink, "description").as(desc =>
|
<For each={createBinding(Wireplumber.getWireplumber().audio!, "speakers")}>
|
||||||
desc ?? "Speaker")}
|
{(sink: AstalWp.Endpoint) =>
|
||||||
onClick={() => !sink.isDefault && sink.set_is_default(true)}
|
<PageButton class={createBinding(sink, "isDefault").as(isDefault =>
|
||||||
endWidget={
|
isDefault ? "default" : "")}
|
||||||
<Gtk.Image iconName={"object-select-symbolic"}
|
icon={createBinding(sink, "icon").as(ico =>
|
||||||
visible={createBinding(sink, "isDefault")}
|
lookupIcon(ico) ? ico : "audio-card-symbolic")}
|
||||||
css={"font-size: 18px;"}
|
title={createBinding(sink, "description").as(desc =>
|
||||||
/>
|
desc ?? "Speaker")}
|
||||||
}
|
actionClicked={() => !sink.isDefault && sink.set_is_default(true)}
|
||||||
/>}
|
endWidget={
|
||||||
</For>
|
<Gtk.Image iconName={"object-select-symbolic"}
|
||||||
|
visible={createBinding(sink, "isDefault")}
|
||||||
|
css={"font-size: 18px;"}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>}
|
||||||
|
</For>
|
||||||
|
</Gtk.Box>,
|
||||||
|
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} spacing={8}>
|
||||||
|
<Gtk.Label class={"sub-header"} label={tr("apps")} xalign={0}
|
||||||
|
visible={variableToBoolean(
|
||||||
|
createBinding(Wireplumber.getWireplumber().audio!, "streams")
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<For each={createBinding(Wireplumber.getWireplumber().audio!, "streams")}>
|
||||||
|
{(stream: AstalWp.Stream) =>
|
||||||
|
<Gtk.Box hexpand $={(self) => {
|
||||||
|
const conns: Map<GObject.Object, Array<number>> = new Map();
|
||||||
|
const controllerMotion = Gtk.EventControllerMotion.new();
|
||||||
|
|
||||||
<Gtk.Label class={"sub-header"} label={tr("apps")} xalign={0}
|
self.add_controller(controllerMotion);
|
||||||
visible={variableToBoolean(
|
|
||||||
createBinding(Wireplumber.getWireplumber().audio!, "streams")
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<For each={createBinding(Wireplumber.getWireplumber().audio!, "streams")}>
|
|
||||||
{(stream: AstalWp.Stream) =>
|
|
||||||
<Gtk.Box hexpand={true} $={(self) => {
|
|
||||||
const conns: Map<GObject.Object, Array<number>> = new Map();
|
|
||||||
const controllerMotion = Gtk.EventControllerMotion.new();
|
|
||||||
|
|
||||||
self.add_controller(controllerMotion);
|
conns.set(controllerMotion, [
|
||||||
|
controllerMotion.connect("enter", () => {
|
||||||
|
const revealer = self.get_last_child()!.get_first_child() as Gtk.Revealer;
|
||||||
|
revealer.set_reveal_child(true);
|
||||||
|
}),
|
||||||
|
controllerMotion.connect("leave", () => {
|
||||||
|
const revealer = self.get_last_child()!.get_first_child() as Gtk.Revealer;
|
||||||
|
revealer.set_reveal_child(false);
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
|
||||||
conns.set(controllerMotion, [
|
conns.set(self, [
|
||||||
controllerMotion.connect("enter", () => {
|
self.connect("destroy", () => conns.forEach((ids, obj) =>
|
||||||
const revealer = self.get_last_child()!.get_first_child() as Gtk.Revealer;
|
ids.forEach(id => obj.disconnect(id))
|
||||||
revealer.set_reveal_child(true);
|
))
|
||||||
}),
|
]);
|
||||||
controllerMotion.connect("leave", () => {
|
}}>
|
||||||
const revealer = self.get_first_child()!.get_first_child() as Gtk.Revealer;
|
<Gtk.Image iconName={createBinding(stream, "name").as(name =>
|
||||||
revealer.set_reveal_child(true);
|
getAppIcon(name.split(' ')[0]) ?? "application-x-executable-symbolic")}
|
||||||
})
|
css={"font-size: 18px; margin-right: 6px;"} />
|
||||||
]);
|
|
||||||
|
|
||||||
conns.set(self, [
|
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} hexpand={true}>
|
||||||
self.connect("destroy", () => conns.forEach((ids, obj) =>
|
<Gtk.Revealer transitionDuration={180}
|
||||||
ids.forEach(id => obj.disconnect(id))
|
transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN}>
|
||||||
))
|
|
||||||
]);
|
<Gtk.Label label={createBinding(stream, "description").as(desc =>
|
||||||
}}>
|
desc ?? "Unnamed audio stream")}
|
||||||
|
ellipsize={Pango.EllipsizeMode.END}
|
||||||
|
tooltipText={createBinding(stream, "name")}
|
||||||
|
class={"name"} xalign={0}
|
||||||
|
/>
|
||||||
|
</Gtk.Revealer>
|
||||||
|
|
||||||
<Gtk.Image iconName={createBinding(stream, "name").as(name =>
|
<Astal.Slider drawValue={false} value={createBinding(stream, "volume")}
|
||||||
getAppIcon(name.split(' ')[0]) ?? "application-x-executable-symbolic")}
|
onChangeValue={(_, __, value) => stream.set_volume(value)}
|
||||||
css={"font-size: 18px; margin-right: 6px;"} />
|
hexpand min={0} max={1.5}
|
||||||
|
|
||||||
<Gtk.Box orientation={Gtk.Orientation.VERTICAL} hexpand={true}>
|
|
||||||
<Gtk.Revealer transitionDuration={180}
|
|
||||||
transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN}>
|
|
||||||
|
|
||||||
<Gtk.Label label={createBinding(stream, "name").as(name =>
|
|
||||||
name ?? "Unnamed audio stream")}
|
|
||||||
ellipsize={Pango.EllipsizeMode.END}
|
|
||||||
tooltipText={createBinding(stream, "name")}
|
|
||||||
class={"name"} xalign={0}
|
|
||||||
/>
|
/>
|
||||||
</Gtk.Revealer>
|
</Gtk.Box>
|
||||||
|
|
||||||
<Astal.Slider drawValue={false} max={100} $={(self) => {
|
|
||||||
self.value = Math.floor(stream.volume * 100);
|
|
||||||
}} value={createBinding(stream, "volume").as(vol =>
|
|
||||||
Math.floor(vol * 100))}
|
|
||||||
onChangeValue={(_, type, value) => {
|
|
||||||
if(type !== undefined && type !== null)
|
|
||||||
stream.volume = Math.floor(value / 100);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Gtk.Box>
|
</Gtk.Box>
|
||||||
</Gtk.Box>
|
}
|
||||||
}
|
</For>
|
||||||
</For>
|
</Gtk.Box>
|
||||||
</Page> as Page;
|
]
|
||||||
|
});
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export const TileBluetooth = () =>
|
|||||||
return connected && connectedDev ? connectedDev.get_alias() : ""
|
return connected && connectedDev ? connectedDev.get_alias() : ""
|
||||||
})} onToggledOn={() => AstalBluetooth.get_default().adapter?.set_powered(true)}
|
})} onToggledOn={() => AstalBluetooth.get_default().adapter?.set_powered(true)}
|
||||||
onToggledOff={() => AstalBluetooth.get_default().adapter?.set_powered(false)}
|
onToggledOff={() => AstalBluetooth.get_default().adapter?.set_powered(false)}
|
||||||
onClickMore={() => TilesPages?.toggle(BluetoothPage())}
|
onClickMore={() => TilesPages?.toggle(BluetoothPage)}
|
||||||
enableOnClickMore={true} iconSize={16}
|
enableOnClickMore={true} iconSize={16}
|
||||||
toggleState={createBinding(AstalBluetooth.get_default(), "isPowered")}
|
toggleState={createBinding(AstalBluetooth.get_default(), "isPowered")}
|
||||||
icon={createComputed([
|
icon={createComputed([
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const TileNetwork = () => <Gtk.Box>
|
|||||||
})()
|
})()
|
||||||
)} onToggledOn={() => wifi.set_enabled(true)}
|
)} onToggledOn={() => wifi.set_enabled(true)}
|
||||||
onToggledOff={() => wifi.set_enabled(false)}
|
onToggledOff={() => wifi.set_enabled(false)}
|
||||||
onClickMore={() => TilesPages?.toggle(PageNetwork())}
|
onClickMore={() => TilesPages?.toggle(PageNetwork)}
|
||||||
icon={"network-wireless-signal-excellent-symbolic"}
|
icon={"network-wireless-signal-excellent-symbolic"}
|
||||||
toggleState={createBinding(wifi, "enabled")}
|
toggleState={createBinding(wifi, "enabled")}
|
||||||
/>
|
/>
|
||||||
@@ -50,7 +50,7 @@ export const TileNetwork = () => <Gtk.Box>
|
|||||||
})}
|
})}
|
||||||
onToggledOn={() => execAsync("nmcli n on")}
|
onToggledOn={() => execAsync("nmcli n on")}
|
||||||
onToggledOff={() => execAsync("nmcli n off")}
|
onToggledOff={() => execAsync("nmcli n off")}
|
||||||
onClickMore={() => TilesPages?.toggle(PageNetwork())}
|
onClickMore={() => TilesPages?.toggle(PageNetwork)}
|
||||||
icon={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) => {
|
icon={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) => {
|
||||||
switch(internet) {
|
switch(internet) {
|
||||||
case AstalNetwork.Internet.CONNECTED:
|
case AstalNetwork.Internet.CONNECTED:
|
||||||
@@ -74,7 +74,7 @@ export const TileNetwork = () => <Gtk.Box>
|
|||||||
description={tr("disconnected")}
|
description={tr("disconnected")}
|
||||||
onToggledOn={() => execAsync("nmcli n on")}
|
onToggledOn={() => execAsync("nmcli n on")}
|
||||||
onToggledOff={() => execAsync("nmcli n off")}
|
onToggledOff={() => execAsync("nmcli n off")}
|
||||||
onClickMore={() => TilesPages?.toggle(PageNetwork())}
|
onClickMore={() => TilesPages?.toggle(PageNetwork)}
|
||||||
icon={"network-wired-disconnected-symbolic"}
|
icon={"network-wired-disconnected-symbolic"}
|
||||||
iconSize={16}
|
iconSize={16}
|
||||||
toggleState={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) =>
|
toggleState={createBinding(wired, "internet").as((internet: AstalNetwork.Internet) =>
|
||||||
|
|||||||
@@ -20,6 +20,6 @@ export const TileNightLight = () =>
|
|||||||
onToggledOff={() => NightLight.getDefault().identity = true}
|
onToggledOff={() => NightLight.getDefault().identity = true}
|
||||||
onToggledOn={() => NightLight.getDefault().identity = false}
|
onToggledOn={() => NightLight.getDefault().identity = false}
|
||||||
enableOnClickMore={true}
|
enableOnClickMore={true}
|
||||||
onClickMore={() => TilesPages?.toggle(PageNightLight())}
|
onClickMore={() => TilesPages?.toggle(PageNightLight)}
|
||||||
toggleState={createBinding(NightLight.getDefault(), "identity").as(identity => !identity)}
|
toggleState={createBinding(NightLight.getDefault(), "identity").as(identity => !identity)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { Recording } from "../../../scripts/recording";
|
|||||||
import { tr } from "../../../i18n/intl";
|
import { tr } from "../../../i18n/intl";
|
||||||
import { isInstalled, time } from "../../../scripts/utils";
|
import { isInstalled, time } from "../../../scripts/utils";
|
||||||
import { createBinding, createComputed } from "ags";
|
import { createBinding, createComputed } from "ags";
|
||||||
import { Gtk } from "ags/gtk4";
|
|
||||||
|
|
||||||
|
|
||||||
export const TileRecording = () =>
|
export const TileRecording = () =>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export type TileProps = {
|
|||||||
description?: string | Accessor<string>;
|
description?: string | Accessor<string>;
|
||||||
toggleState?: boolean | Accessor<boolean>;
|
toggleState?: boolean | Accessor<boolean>;
|
||||||
enableOnClickMore?: boolean | Accessor<boolean>;
|
enableOnClickMore?: boolean | Accessor<boolean>;
|
||||||
onDestroy?: (self: Gtk.Box) => void;
|
onUnmap?: (self: Gtk.Box) => void;
|
||||||
onToggledOn: () => void;
|
onToggledOn: () => void;
|
||||||
onToggledOff: () => void;
|
onToggledOff: () => void;
|
||||||
onClickMore?: () => void;
|
onClickMore?: () => void;
|
||||||
@@ -35,7 +35,8 @@ export function Tile(props: TileProps): Gtk.Widget {
|
|||||||
|
|
||||||
onCleanup(() => subs.forEach(s => s()));
|
onCleanup(() => subs.forEach(s => s()));
|
||||||
|
|
||||||
return <Gtk.Box hexpand visible={props.visible} onDestroy={props.onDestroy} class={
|
return <Gtk.Box hexpand visible={props.visible} onUnmap={props.onUnmap}
|
||||||
|
canFocus focusable={false} class={
|
||||||
(props.class instanceof Accessor) ?
|
(props.class instanceof Accessor) ?
|
||||||
createComputed([props.class, toggled], (clss, isToggled) =>
|
createComputed([props.class, toggled], (clss, isToggled) =>
|
||||||
`tile ${clss} ${isToggled ? "toggled" : ""} ${
|
`tile ${clss} ${isToggled ? "toggled" : ""} ${
|
||||||
@@ -47,7 +48,7 @@ export function Tile(props: TileProps): Gtk.Widget {
|
|||||||
props.onClickMore ? "has-more" : ""
|
props.onClickMore ? "has-more" : ""
|
||||||
}`
|
}`
|
||||||
)
|
)
|
||||||
}>
|
}>
|
||||||
<Gtk.Button class={"toggle-button"} onClicked={() => {
|
<Gtk.Button class={"toggle-button"} onClicked={() => {
|
||||||
if(toggled.get()) {
|
if(toggled.get()) {
|
||||||
setToggled(false);
|
setToggled(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user