Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrating to ags v2 #112

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .config/ags/.gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.vscode
types
@girs

!assets/

Expand Down
11 changes: 11 additions & 0 deletions .config/ags/app.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { App } from "astal/gtk3"
import Bar from "./widgets/bar/Bar"
import { getCssPath } from "./utils/scss"

App.start({
css: getCssPath(),
main()
{
App.get_monitors().map(Bar)
},
})
21 changes: 21 additions & 0 deletions .config/ags/env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
const SRC: string

declare module "inline:*" {
const content: string
export default content
}

declare module "*.scss" {
const content: string
export default content
}

declare module "*.blp" {
const content: string
export default content
}

declare module "*.css" {
const content: string
export default content
}
134 changes: 63 additions & 71 deletions .config/ags/services/brightness.ts
Original file line number Diff line number Diff line change
@@ -1,88 +1,80 @@
class BrightnessService extends Service
{
// every subclass of GObject.Object has to register itself
static {
// takes three arguments
// the class itself
// an object defining the signals
// an object defining its properties
Service.register(
this,
{
// 'name-of-signal': [type as a string from GObject.TYPE_<type>],
"screen-changed": ["float"],
},
{
// 'kebab-cased-name': [type as a string from GObject.TYPE_<type>, 'r' | 'w' | 'rw']
// 'r' means readable
// 'w' means writable
// guess what 'rw' means
"screen-value": ["float", "rw"],
}
);
}

// this Service assumes only one device with backlight
#interface = Utils.exec("sh -c 'ls -w1 /sys/class/backlight | head -1'");

// # prefix means private in JS
#screenValue = 0;
#max = Number(Utils.exec("brightnessctl max"));
import GObject, { register, property } from "astal/gobject"
import { monitorFile, readFileAsync } from "astal/file"
import { exec, execAsync } from "astal/process"

// the getter has to be in snake_case
get screen_value()
{
return this.#screenValue;
}
const get = (args: string) => Number(exec(`brightnessctl ${args}`))
const screen = exec(`bash -c "ls -w1 /sys/class/backlight | head -1"`)
const kbd = exec(`bash -c "ls -w1 /sys/class/leds | head -1"`)

// the setter has to be in snake_case too
set screen_value(percent)
@register({ GTypeName: "Brightness" })
export default class Brightness extends GObject.Object
{
static instance: Brightness
static get_default()
{
if (percent < 0.2) percent = 0.2;

// if (percent > 1) percent = 1;
if (!this.instance)
this.instance = new Brightness()

Utils.execAsync(`brightnessctl set ${percent * 100}% -q`).catch(err => print(err));
// the file monitor will handle the rest
return this.instance
}

constructor()
{
super();
#kbdMax = get(`--device ${kbd} max`)
#kbd = get(`--device ${kbd} get`)
#screenMax = get("max")
#screen = get("get") / (get("max") || 1)

// setup monitor
const brightness = `/sys/class/backlight/${this.#interface}/brightness`;
Utils.monitorFile(brightness, () => this.#onChange());
@property(Number)
get kbd() { return this.#kbd }

// initialize
this.#onChange();
set kbd(value)
{
if (value < 0 || value > this.#kbdMax)
return

execAsync(`brightnessctl -d ${kbd} s ${value} -q`).then(() =>
{
this.#kbd = value
this.notify("kbd")
})
}

#onChange()
{
this.#screenValue = Number(Utils.exec("brightnessctl get")) / this.#max;
@property(Number)
get screen() { return this.#screen }

// signals have to be explicitly emitted
// this.emit("changed"); // emits "changed"
// this.notify("screen-value"); // emits "notify::screen-value"
set screen(percent)
{
if (percent < 0)
percent = 0

// or use Service.changed(propName: string) which does the above two
this.changed('screen-value');
if (percent > 1)
percent = 1

// emit screen-changed with the percent as a parameter
this.emit("screen-changed", this.#screenValue);
execAsync(`brightnessctl set ${Math.floor(percent * 100)}% -q`).then(() =>
{
this.#screen = percent
this.notify("screen")
})
}

// overwriting the connect method, let's you
// change the default event that widgets connect to
connect(event = "screen-changed", callback)
constructor()
{
return super.connect(event, callback);
super()

const screenPath = `/sys/class/backlight/${screen}/brightness`
const kbdPath = `/sys/class/leds/${kbd}/brightness`

monitorFile(screenPath, async f =>
{
const v = await readFileAsync(f)
this.#screen = Number(v) / this.#screenMax
this.notify("screen")
})

monitorFile(kbdPath, async f =>
{
const v = await readFileAsync(f)
this.#kbd = Number(v) / this.#kbdMax
this.notify("kbd")
})
}
}

// the singleton instance
const service = new BrightnessService();

// export to use in other modules
export default service;
}
38 changes: 21 additions & 17 deletions .config/ags/tsconfig.json
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "ES2022",
"lib": [
"ES2022"
],
"allowJs": true,
"checkJs": true,
"strict": true,
"noImplicitAny": false,
"baseUrl": ".",
"typeRoots": [
"./types"
],
"skipLibCheck": true
}
}
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"experimentalDecorators": true,
"strict": true,
"target": "ES2022",
"module": "ES2022",
"moduleResolution": "Bundler",
// "checkJs": true,
// "allowJs": true,
"jsx": "react-jsx",
"jsxImportSource": "/usr/share/astal/gjs/gtk3",
"paths": {
"astal": [
"/usr/share/astal/gjs"
],
"astal/*": [
"/usr/share/astal/gjs/*"
]
},
}
}
3 changes: 2 additions & 1 deletion .config/ags/utils/image.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { exec } from "../../../../../usr/share/astal/gjs";

export function getDominantColor(imagePath: string)
{
Expand All @@ -9,6 +10,6 @@ export function getDominantColor(imagePath: string)
// }).catch(err => { print("err", err); return "" });
// print("imagePath : ", imagePath)
// return "black"
return Utils.exec(`bash ${App.configDir}/scripts/get-image-color.sh ${imagePath}`)
return exec(`bash ./scripts/get-image-color.sh ${imagePath}`)
// return color
}
10 changes: 6 additions & 4 deletions .config/ags/utils/json.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import { exec, readFile, writeFile } from "../../../../../usr/share/astal/gjs";

export function readJSONFile(filePath: string): any
{
if (Utils.readFile(filePath) == '') return {};
if (readFile(filePath) == '') return {};
try {
const data = Utils.readFile(filePath);
const data = readFile(filePath);
return data.trim() ? JSON.parse(data) : {};
} catch (e) {
console.error('Error:', e);
Expand All @@ -22,9 +24,9 @@ export function readJson(string: string)

export function writeJSONFile(filePath: string, data: any)
{
if (Utils.readFile(filePath) == '') Utils.exec(`mkdir -p ${filePath.split('/').slice(0, -1).join('/')}`);
if (readFile(filePath) == '') exec(`mkdir -p ${filePath.split('/').slice(0, -1).join('/')}`);
try {
Utils.writeFile(JSON.stringify(data, null, 4), filePath);
writeFile(JSON.stringify(data, null, 4), filePath);
} catch (e) {
console.error('Error:', e);
}
Expand Down
29 changes: 16 additions & 13 deletions .config/ags/utils/scss.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,38 @@
import { globalOpacity } from "variables"

import { App } from "../../../../../usr/share/astal/gjs/gtk3"
import { exec, monitorFile } from "../../../../../usr/share/astal/gjs"
import Astal from "gi://Astal?version=3.0"
// import { globalOpacity } from "../variables"

// target css file
const tmpCss = `/tmp/tmp-style.css`
const tmpScss = `/tmp/tmp-style.scss`
const scss_dir = `${App.configDir}/scss`
const scss_dir = `./scss`

const walColors = `${App.configDir}/../../.cache/wal/colors.scss`
const defaultColors = `${App.configDir}/scss/defaultColors.scss`
const walColors = `./../../.cache/wal/colors.scss`
const defaultColors = `./scss/defaultColors.scss`

export const getCssPath = () => tmpCss

export function refreshCss()
{
// main scss file
const scss = `${App.configDir}/scss/style.scss`
const scss = `./scss/style.scss`

const response = Utils.exec(`bash -c "echo '$OPACITY: ${globalOpacity.value};' | cat - ${defaultColors} ${walColors} ${scss} > ${tmpScss} && sassc ${tmpScss} ${tmpCss} -I ${scss_dir}"`)
if (response != "") Utils.notify(response)
const response = exec(`bash -c "echo '$OPACITY: ${1};' | cat - ${defaultColors} ${walColors} ${scss} > ${tmpScss} && sassc ${tmpScss} ${tmpCss} -I ${scss_dir}"`)
// if (response != "") notify(response)

App.resetCss()
App.applyCss(tmpCss)
App.apply_css(tmpCss)
}

Utils.monitorFile(
monitorFile(
// directory that contains the scss files
`${App.configDir}/scss`,
`./scss`,
() => refreshCss()
)

Utils.monitorFile(
monitorFile(
// directory that contains pywal colors
`${App.configDir}/../../.cache/wal/colors.scss`,
`./../../.cache/wal/colors.scss`,
() => refreshCss()
)
23 changes: 12 additions & 11 deletions .config/ags/utils/settings.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { execAsync, Variable } from "../../../../../usr/share/astal/gjs";
import { readJSONFile, writeJSONFile } from "./json";

const settingsPath = App.configDir + "/assets/settings/settings.json";
const settingsPath = "./assets/settings/settings.json";

const defaultSettings: Settings = {
hyprsunset: {
Expand Down Expand Up @@ -72,32 +73,32 @@ function deepMerge(target: any, source: any): any

// Settings are stored in a json file, containing all the settings, check if it exists, if not, create it
if (Object.keys(readJSONFile(settingsPath)).length !== 0) {
globalSettings.value = deepMerge(defaultSettings, readJSONFile(settingsPath));
globalSettings.set(deepMerge(defaultSettings, readJSONFile(settingsPath)))
} else {
writeJSONFile(settingsPath, globalSettings.value);
writeJSONFile(settingsPath, globalSettings.get());
}

// When the settings change, write them to the json file
globalSettings.connect('changed', ({ value }) =>
{
writeJSONFile(settingsPath, value);
});
// globalSettings.watch('changed', ({ self }) =>
// {
// writeJSONFile(settingsPath, value);
// });


export function setSetting(key: string, value: any): any
{
let o = globalSettings.value;
let o: any = globalSettings.get();
key.split('.').reduce((o, k, i, arr) =>
o[k] = (i === arr.length - 1 ? value : o[k] || {}), o);
globalSettings.setValue(o);
globalSettings.set(o);
}

export function getSetting(key: string): any
{
return key.split('.').reduce((o, k) => o?.[k], globalSettings.value);
return key.split('.').reduce((o: any, k) => o?.[k], globalSettings.get());
}

export function exportSettings()
{
Utils.execAsync(`bash -c 'cat ${settingsPath} | wl-copy'`)
execAsync(`bash -c 'cat ${settingsPath} | wl-copy'`)
}
Loading