diff --git a/src/ags.src.gresource.xml b/src/ags.src.gresource.xml index 4e16607..4064319 100644 --- a/src/ags.src.gresource.xml +++ b/src/ags.src.gresource.xml @@ -6,6 +6,7 @@ client.js utils.js widget.js + service.js widgets/overrides.js widgets/box.js @@ -26,7 +27,7 @@ widgets/window.js service/service.js - service/apps.js + service/applications.js service/audio.js service/battery.js service/bluetooth.js diff --git a/src/main.ts b/src/main.ts index c9d8664..42edd9f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,16 +3,8 @@ import GLib from 'gi://GLib'; import * as Utils from './utils.js'; import App from './app.js'; import client from './client.js'; -import Service from './service/service.js'; +import Service from './service.js'; import Widget from './widget.js'; -import './service/apps.js'; -import './service/audio.js'; -import './service/battery.js'; -import './service/bluetooth.js'; -import './service/hyprland.js'; -import './service/mpris.js'; -import './service/network.js'; -import './service/notifications.js'; const APP_BUS = (name: string) => 'com.github.Aylur.ags.' + name; const APP_PATH = (name: string) => '/com/github/Aylur/ags/' + name; @@ -23,23 +15,14 @@ const help = (bin: string) => `USAGE: OPTIONS: -h, --help Print this help and exit - -v, --version Print version and exit - -q, --quit Kill AGS - -c, --config Path to the config file. Default: ${DEFAULT_CONF} - -b, --bus-name Bus name of the process - -i, --inspector Open up the Gtk debug tool - -t, --toggle-window Show or hide a window - -r, --run-js Evaluate given string as a function and execute it - -p, --run-promise Evaluate and execute function as Promise - --clear-cache Remove ${Utils.CACHE_DIR} EXAMPLES @@ -56,7 +39,7 @@ function isRunning(dbusName: string) { '/org/freedesktop/DBus', 'org.freedesktop.DBus', 'NameHasOwner', - // @ts-ignore + // @ts-expect-error GLib.Variant.new_tuple([new GLib.Variant('s', dbusName)]), new GLib.VariantType('(b)'), Gio.DBusCallFlags.NONE, @@ -141,7 +124,7 @@ export function main(args: string[]) { } } - // @ts-ignore + // @ts-expect-error globalThis.ags = { App, Utils, @@ -168,7 +151,7 @@ export function main(args: string[]) { app.Inspector(); }); - // @ts-ignore + // @ts-expect-error return app.runAsync(null); } else { diff --git a/src/service.ts b/src/service.ts new file mode 100644 index 0000000..23b4d3f --- /dev/null +++ b/src/service.ts @@ -0,0 +1,34 @@ +// @ts-nocheck +import Service from './service/service.js'; +import Applications from './service/applications.js'; +import Audio from './service/audio.js'; +import Battery from './service/battery.js'; +import Bluetooth from './service/bluetooth.js'; +import Hyprland from './service/hyprland.js'; +import Mpris from './service/mpris.js'; +import Network from './service/network.js'; +import Notifications from './service/notifications.js'; + +export { + Applications, + Audio, + Battery, + Bluetooth, + Hyprland, + Mpris, + Network, + Notifications, + Service, +}; + +Service.Applications = Applications; +Service.Audio = Audio; +Service.Battery = Battery; +Service.Bluetooth = Bluetooth; +Service.Hyprland = Hyprland; +Service.Mpris = Mpris; +Service.Network = Network; +Service.Notifications = Notifications; +Service.Service = Service; + +export default Service; diff --git a/src/service/apps.ts b/src/service/applications.ts similarity index 97% rename from src/service/apps.ts rename to src/service/applications.ts index 6466cf6..fea761c 100644 --- a/src/service/apps.ts +++ b/src/service/applications.ts @@ -37,11 +37,11 @@ class Application extends Service { if (!app.get_icon()) return ''; - // @ts-ignore + // @ts-expect-error if (typeof app.get_icon()?.get_names !== 'function') return ''; - // @ts-ignore + // @ts-expect-error const name = app.get_icon()?.get_names()[0]; return name || ''; } @@ -130,7 +130,6 @@ class ApplicationsService extends Service { } export default class Applications { - static { Service.export(this, 'Applications'); } static _instance: ApplicationsService; static get instance() { diff --git a/src/service/audio.ts b/src/service/audio.ts index 355d8aa..05964a7 100644 --- a/src/service/audio.ts +++ b/src/service/audio.ts @@ -3,11 +3,11 @@ import GObject from 'gi://GObject'; import Gvc from 'gi://Gvc'; import { bulkConnect, bulkDisconnect } from '../utils.js'; -class Stream extends GObject.Object { +class Stream extends Service { static { - GObject.registerClass({ - Signals: { 'changed': {}, 'closed': {} }, - }, this); + Service.register(this, { + 'closed': [], + }); } private _stream: Gvc.MixerStream; @@ -156,7 +156,6 @@ class AudioService extends Service { } export default class Audio { - static { Service.export(this, 'Audio'); } static _instance: AudioService; static get instance() { diff --git a/src/service/battery.ts b/src/service/battery.ts index 3f88bf2..60aacc9 100644 --- a/src/service/battery.ts +++ b/src/service/battery.ts @@ -64,7 +64,6 @@ class BatteryService extends Service { } export default class Battery { - static { Service.export(this, 'Battery'); } static _instance: BatteryService; static get instance() { diff --git a/src/service/bluetooth.ts b/src/service/bluetooth.ts index bc5737d..da56f53 100644 --- a/src/service/bluetooth.ts +++ b/src/service/bluetooth.ts @@ -62,7 +62,7 @@ class Device extends GObject.Object { class BluetoothService extends Service { static { Service.register(this); } - // @ts-ignore + // @ts-expect-error private _client: GnomeBluetooth.Client; private _devices: Map; @@ -163,7 +163,6 @@ class BluetoothService extends Service { } export default class Bluetooth { - static { Service.export(this, 'Bluetooth'); } static _instance: BluetoothService; static get instance() { diff --git a/src/service/hyprland.ts b/src/service/hyprland.ts index 380fbde..b02f374 100644 --- a/src/service/hyprland.ts +++ b/src/service/hyprland.ts @@ -202,7 +202,7 @@ class HyprlandService extends Service { case 'changefloating': { const client = this._clients.get(argv[0]); if (client) - // @ts-ignore + // @ts-expect-error client.floating = argv[1] === '1'; break; } @@ -222,7 +222,6 @@ class HyprlandService extends Service { } export default class Hyprland { - static { Service.export(this, 'Hyprland'); } static _instance: HyprlandService; static get instance() { diff --git a/src/service/mpris.ts b/src/service/mpris.ts index eb57bf8..9eafd5b 100644 --- a/src/service/mpris.ts +++ b/src/service/mpris.ts @@ -168,11 +168,8 @@ class MprisPlayer extends GObject.Object { Gio.File.new_for_path(coverPath), Gio.FileCopyFlags.OVERWRITE, GLib.PRIORITY_DEFAULT, - null, - // @ts-ignore - null, - // @ts-ignore - (source, result) => { + // @ts-expect-error + null, null, (source, result) => { try { source.copy_finish(result); this.emit('changed'); @@ -314,7 +311,6 @@ class MprisService extends Service { getPlayer(name: string | ((players: Players) => MprisPlayer) = '') { if (typeof name === 'function') - // @ts-ignore return name(new Map(this._players)) || null; for (const [busName, player] of this._players) { @@ -326,7 +322,6 @@ class MprisService extends Service { } export default class Mpris { - static { Service.export(this, 'Mpris'); } static _instance: MprisService; static get instance() { diff --git a/src/service/network.ts b/src/service/network.ts index 7aad3f9..a0186ec 100644 --- a/src/service/network.ts +++ b/src/service/network.ts @@ -237,7 +237,6 @@ class NetworkService extends Service { } export default class Network { - static { Service.export(this, 'Network'); } static _instance: NetworkService; static get instance() { diff --git a/src/service/notifications.ts b/src/service/notifications.ts index 1e20be2..6216245 100644 --- a/src/service/notifications.ts +++ b/src/service/notifications.ts @@ -260,7 +260,6 @@ class NotificationsService extends Service { } export default class Notifications { - static { Service.export(this, 'Notifications'); } static _instance: NotificationsService; static get instance() { diff --git a/src/service/service.ts b/src/service/service.ts index bbb66df..61cd07e 100644 --- a/src/service/service.ts +++ b/src/service/service.ts @@ -6,6 +6,7 @@ import { type Ctor } from 'gi-types/gobject2.js'; export default class Service extends GObject.Object { static { GObject.registerClass({ + GTypeName: 'AgsService', Signals: { 'changed': {} }, }, this); } @@ -24,7 +25,7 @@ export default class Service extends GObject.Object { Object.keys(signals).forEach(signal => Signals[signal] = { param_types: signals[signal].map(t => - // @ts-ignore + // @ts-expect-error GObject[`TYPE_${t.toUpperCase()}`]), }, ); @@ -34,8 +35,11 @@ export default class Service extends GObject.Object { } static export(api: { instance: object }, name: string) { - // @ts-ignore + // @ts-expect-error Service[name] = api; + console.error('Service.register is DEPRECATED.\n' + + "Simply do Service['YourService'] = YourService\n" + + 'or just export and import your YourService'); } connectWidget( @@ -46,3 +50,4 @@ export default class Service extends GObject.Object { connect(this, widget, callback, event); } } + diff --git a/src/utils.ts b/src/utils.ts index d0e2d59..2a97ea0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -97,8 +97,18 @@ export function connect( const bind = service.connect( event, (_s, ...args: unknown[]) => callback(widget, ...args)); - widget.connect('destroy', () => service.disconnect(bind)); - timeout(10, () => callback(widget)); + widget.connect('destroy', () => { + // @ts-expect-error + widget._destroyed = true; + service.disconnect(bind); + }); + GLib.idle_add(GLib.PRIORITY_DEFAULT_IDLE, () => { + // @ts-expect-error + if (!widget._destroyed) + callback(widget); + + return GLib.SOURCE_REMOVE; + }); } export function interval( diff --git a/src/widget.ts b/src/widget.ts index f743212..10f7076 100644 --- a/src/widget.ts +++ b/src/widget.ts @@ -21,7 +21,7 @@ export default function Widget({ type, ...params }: { type: ctor }) { return constructor(type, params); } -// @ts-ignore +// @ts-expect-error export const Window = (args: object) => constructor(AgsWindow, args); export const Box = (args: object) => constructor(AgsBox, args); export const Button = (args: object) => constructor(AgsButton, args); diff --git a/src/widgets/label.ts b/src/widgets/label.ts index f6c530c..b3dbc64 100644 --- a/src/widgets/label.ts +++ b/src/widgets/label.ts @@ -38,7 +38,7 @@ export default class AgsLabel extends Gtk.Label { return; } - // @ts-ignore + // @ts-expect-error this.ellipsize = Pango.EllipsizeMode[truncate.toUpperCase()]; } @@ -52,7 +52,7 @@ export default class AgsLabel extends Gtk.Label { return; } - // @ts-ignore + // @ts-expect-error this.justify = Gtk.Justification[justify.toUpperCase()]; } } diff --git a/src/widgets/overrides.ts b/src/widgets/overrides.ts index 62943e8..af78953 100644 --- a/src/widgets/overrides.ts +++ b/src/widgets/overrides.ts @@ -66,12 +66,12 @@ Object.defineProperty(Gtk.Widget.prototype, 'style', { }, }); -// @ts-ignore +// @ts-expect-error Gtk.Widget.prototype.setStyle = function(css: string) { setStyle(this, css); }; -// @ts-ignore +// @ts-expect-error Gtk.Widget.prototype.toggleClassName = function(cn: string, condition = true) { toggleClassName(this, cn, condition); }; diff --git a/src/widgets/revealer.ts b/src/widgets/revealer.ts index 21fa6e9..6ab3baf 100644 --- a/src/widgets/revealer.ts +++ b/src/widgets/revealer.ts @@ -31,8 +31,7 @@ export default class AgsRevealer extends Gtk.Revealer { return; } - this.transitionType = - // @ts-ignore - Gtk.RevealerTransitionType[transition.toUpperCase()]; + // @ts-expect-error + this.transitionType = Gtk.RevealerTransitionType[transition.toUpperCase()]; } } diff --git a/src/widgets/scrollable.ts b/src/widgets/scrollable.ts index ab8abb1..310813e 100644 --- a/src/widgets/scrollable.ts +++ b/src/widgets/scrollable.ts @@ -62,9 +62,9 @@ export default class AgsScrollable extends Gtk.ScrolledWindow { policy() { this.set_policy( - // @ts-ignore + // @ts-expect-error Gtk.PolicyType[this._hscroll?.toUpperCase() || 'AUTOMATIC'], - // @ts-ignore + // @ts-expect-error Gtk.PolicyType[this._vscroll?.toUpperCase() || 'AUTOMATIC'], ); } diff --git a/src/widgets/shared.ts b/src/widgets/shared.ts index ebbde63..34dccff 100644 --- a/src/widgets/shared.ts +++ b/src/widgets/shared.ts @@ -1,16 +1,18 @@ import Gtk from 'gi://Gtk?version=3.0'; -import { interval } from '../utils.js'; +import GObject from 'gi://GObject'; +import { connect, interval } from '../utils.js'; export type Command = string | ((...args: unknown[]) => boolean); -interface ServiceAPI { - instance: { - connectWidget: ( - widget: Gtk.Widget, - callback: (widget: Gtk.Widget, ...args: unknown[]) => void, - event?: string - ) => void - } +type ConnectWidget = ( + widget: Gtk.Widget, + callback: (widget: Gtk.Widget, ...args: unknown[]) => void, + event?: string +) => void + +interface Connectable extends GObject.Object { + instance: { connectWidget: ConnectWidget } + connectWidget: ConnectWidget } interface CommonParams { @@ -21,7 +23,7 @@ interface CommonParams { connections?: ( [string, (...args: unknown[]) => unknown] | [number, (...args: unknown[]) => unknown] | - [ServiceAPI, (...args: unknown[]) => unknown, string] + [Connectable, (...args: unknown[]) => unknown, string] )[] properties?: [string, unknown][] setup?: (widget: Gtk.Widget) => void @@ -43,16 +45,16 @@ function parseCommon(widget: Gtk.Widget, { connections, properties, setup, }: CommonParams) { if (className !== undefined) - // @ts-ignore + // @ts-expect-error widget.className = className; if (style !== undefined) - // @ts-ignore + // @ts-expect-error widget.style = style; if (typeof halign === 'string') { - // @ts-ignore + // @ts-expect-error const align = Gtk.Align[halign.toUpperCase()]; if (typeof align !== 'number') console.error('wrong halign value'); @@ -64,7 +66,7 @@ function parseCommon(widget: Gtk.Widget, { widget.halign = halign; if (typeof valign === 'string') { - // @ts-ignore + // @ts-expect-error const align = Gtk.Align[valign.toUpperCase()]; if (typeof align !== 'number') console.error('wrong valign value'); @@ -77,7 +79,7 @@ function parseCommon(widget: Gtk.Widget, { if (properties) { properties.forEach(([key, value]) => { - // @ts-ignore + // @ts-expect-error widget[`_${key}`] = value; }); } @@ -93,8 +95,14 @@ function parseCommon(widget: Gtk.Widget, { else if (typeof s?.instance?.connectWidget === 'function') s.instance.connectWidget(widget, callback, event); + else if (typeof s?.connectWidget === 'function') + s.connectWidget(widget, callback, event); + + else if (typeof s?.connect === 'function') + connect(s, widget, callback, event); + else - logError(new Error(`${s} is not an instanceof Service`)); + logError(new Error(`${s} is not connectable`)); }); } diff --git a/src/widgets/stack.ts b/src/widgets/stack.ts index eeb590c..d41b3a6 100644 --- a/src/widgets/stack.ts +++ b/src/widgets/stack.ts @@ -74,7 +74,7 @@ export default class AgsStack extends Gtk.Stack { return; } - // @ts-ignore + // @ts-expect-error this.transitionType = Gtk.StackTransitionType[transition.toUpperCase()]; } diff --git a/src/widgets/window.ts b/src/widgets/window.ts index 521ba96..b90efd5 100644 --- a/src/widgets/window.ts +++ b/src/widgets/window.ts @@ -115,10 +115,10 @@ export default class AgsWindow extends Gtk.Window { _margin: number[] | number = [0]; - // @ts-ignore + // @ts-expect-error get margin() { return this._margin; } - // @ts-ignore + // @ts-expect-error set margin(margin: number[] | number) { let margins: [side: string, index: number][] = []; if (typeof margin === 'number')