nixos-configs/modules/ags/config/greeter.ts

146 lines
3.1 KiB
TypeScript
Raw Normal View History

2024-02-07 14:22:19 -05:00
/* eslint no-magic-numbers: 0 */
const { Box, Button, Entry, Label, Menu, MenuItem, Window } = Widget;
2024-02-06 16:03:45 -05:00
const { execAsync, idle, readFileAsync } = Utils;
2024-02-05 12:00:25 -05:00
const greetd = await Service.import('greetd');
const { Gdk } = imports.gi;
const DEFAULT_NAME = 'matt';
2024-02-06 16:03:45 -05:00
2024-02-07 14:22:19 -05:00
// Types
type User = {
name: string;
uid: number;
gid: number;
desc: string;
home: string;
shell: string;
};
2024-02-06 16:03:45 -05:00
2024-02-07 14:22:19 -05:00
// Run Wallpaper daemon here to not cause issues at startup
2024-02-06 16:03:45 -05:00
execAsync(['swww', 'init', '--no-cache']).then(() => {
execAsync([
'swww', 'img', '-t', 'none',
`${App.configDir}/.wallpaper`,
]).catch(print);
}).catch(print);
2024-02-07 14:22:19 -05:00
// Put ref of Label here to change it easily later
const name = Label(DEFAULT_NAME);
2024-02-07 14:22:19 -05:00
// Initiate menu here to not have garbage collection take it away
// TODO: figure out type
let menu;
2024-02-07 14:22:19 -05:00
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,
2024-02-07 14:22:19 -05:00
setup: () => {
idle(() => {
readFileAsync('/etc/passwd').then((out) => {
2024-02-07 14:22:19 -05:00
const users = parsePasswd(out);
menu = DropdownMenu(users);
}).catch(print);
});
},
2024-02-07 14:22:19 -05:00
on_primary_click_release: (self, event) => {
menu.popup_at_widget(
2024-02-07 14:22:19 -05:00
self,
Gdk.Gravity.SOUTH,
Gdk.Gravity.NORTH,
event,
);
},
});
2024-02-05 12:00:25 -05:00
const password = Entry({
2024-02-05 12:00:25 -05:00
placeholder_text: 'Password',
visibility: false,
2024-02-07 14:22:19 -05:00
2024-02-05 12:00:25 -05:00
on_accept: () => {
2024-02-06 13:31:36 -05:00
greetd.login(
name.label || '',
2024-02-06 13:31:36 -05:00
password.text || '',
'Hyprland',
).catch((err) => {
response.label = JSON.stringify(err);
});
2024-02-05 12:00:25 -05:00
},
});
2024-02-05 12:00:25 -05:00
const response = Label();
2024-02-05 12:00:25 -05:00
const win = Window({
2024-02-06 13:31:36 -05:00
name: 'greeter',
2024-02-05 12:00:25 -05:00
css: 'background-color: transparent;',
anchor: ['top', 'left', 'right', 'bottom'],
2024-02-06 13:31:36 -05:00
keymode: 'exclusive',
setup: () => {
idle(() => {
password.grab_focus();
});
},
child: Box({
2024-02-05 12:00:25 -05:00
vertical: true,
hpack: 'center',
vpack: 'center',
hexpand: true,
vexpand: true,
2024-02-07 14:22:19 -05:00
2024-02-05 12:00:25 -05:00
children: [
dropdown,
2024-02-05 12:00:25 -05:00
password,
response,
],
}),
});
export default { windows: [win] };