nixos-configs/modules/ags/config/greeter.ts
matt1432 5c64b5bd42
All checks were successful
Discord / discord commits (push) Has been skipped
refactor(greetd): change some ags code
2024-02-08 14:24:33 -05:00

140 lines
3.1 KiB
TypeScript

/* eslint no-magic-numbers: 0 */
const { Box, Button, Entry, Label, Menu, MenuItem, Window } = Widget;
const { execAsync, idle, readFileAsync } = Utils;
const greetd = await Service.import('greetd');
const { Gdk } = imports.gi;
const DEFAULT_NAME = 'matt';
// Types
type User = {
name: string;
uid: number;
gid: number;
desc: string;
home: string;
shell: string;
};
// Run Wallpaper daemon here to not cause issues at startup
execAsync(['swww', 'init', '--no-cache']).then(() => {
execAsync([
'swww', 'img', '-t', 'none',
`${App.configDir}/.wallpaper`,
]).catch(print);
}).catch(print);
// Put ref of Label here to change it easily later
const name = Label(DEFAULT_NAME);
// Initiate menu here to not have garbage collection take it away
// TODO: figure out type
let menu;
const parsePasswd = (fileContent: string) => {
const splitUsers = fileContent.split('\n');
const parsedUsers = splitUsers.map((u) => {
const user = u.split(':');
return {
name: user[0],
uid: Number(user[2]),
gid: Number(user[3]),
desc: user[4],
home: user[5],
shell: user[6],
};
});
// Filter out system users, nixbld users and nobody
return parsedUsers.filter((u) => {
return u.uid >= 1000 &&
!u.name.includes('nixbld') &&
u.name !== 'nobody';
});
};
// FIXME: make menu scrollable
const DropdownMenu = (users: User[]) => Menu({
attach_widget: dropdown,
children: users.map((u) => MenuItem({
on_activate: () => {
name.label = u.name;
},
child: Label({
label: u.name,
justification: 'center',
css: `min-width: ${dropdown.get_allocated_width() / 2}px;`,
}),
})),
});
const dropdown = Button({
child: name,
setup: () => {
idle(() => {
readFileAsync('/etc/passwd').then((out) => {
const users = parsePasswd(out);
menu = DropdownMenu(users);
}).catch(print);
});
},
on_primary_click_release: (self, event) => {
menu.popup_at_widget(
self,
Gdk.Gravity.SOUTH,
Gdk.Gravity.NORTH,
event,
);
},
});
const password = Entry({
placeholder_text: 'Password',
visibility: false,
on_accept: () => {
greetd.login(
name.label || '',
password.text || '',
'Hyprland',
).catch((error) => {
response.label = JSON.stringify(error);
});
},
}).on('realize', (entry) => entry.grab_focus());
const response = Label();
const win = Window({
name: 'greeter',
css: 'background-color: transparent;',
anchor: ['top', 'left', 'right', 'bottom'],
keymode: 'on-demand',
child: Box({
vertical: true,
hpack: 'center',
vpack: 'center',
hexpand: true,
vexpand: true,
children: [
dropdown,
password,
response,
],
}),
});
export default { windows: [win] };