[AGS] Launcher: Prepare
This commit is contained in:
parent
02861efcae
commit
afe25a322a
@ -1,22 +1,23 @@
|
||||
import { Variable } from "astal";
|
||||
import { App, Astal, Gdk, Gtk } from "astal/gtk4";
|
||||
import { App, Astal, Gdk, Gtk, hook } from "astal/gtk4";
|
||||
import AstalApps from "gi://AstalApps";
|
||||
import AppList from "./modules/Apps";
|
||||
|
||||
const MAX_ITEMS = 8;
|
||||
const prefixes = ['='];
|
||||
|
||||
function hide() {
|
||||
App.get_window("launcher")!.hide();
|
||||
App.get_window("launcher")!.hide();
|
||||
}
|
||||
|
||||
const Launcher = () => {
|
||||
const { CENTER } = Gtk.Align;
|
||||
const apps = new AstalApps.Apps();
|
||||
const width = Variable(1000);
|
||||
const height = Variable(1000);
|
||||
|
||||
const text = Variable("");
|
||||
const visible = Variable(false);
|
||||
const list = text((text) => apps.fuzzy_query(text).slice(0, MAX_ITEMS));
|
||||
const onEnter = () => {
|
||||
// TODO handle custom stuff
|
||||
apps.fuzzy_query(text.get())?.[0].launch();
|
||||
hide();
|
||||
};
|
||||
@ -29,13 +30,58 @@ const Launcher = () => {
|
||||
application={App}
|
||||
onShow={(self) => {
|
||||
width.set(self.get_current_monitor().geometry.width);
|
||||
height.set(self.get_current_monitor().geometry.height);
|
||||
}}
|
||||
onKeyPressed={(self, keyval) => {
|
||||
if (keyval === Gdk.KEY_Escape) self.hide();
|
||||
}}
|
||||
child={
|
||||
<box></box>
|
||||
<box
|
||||
vertical
|
||||
cssClasses={["app-launcher-wrapper"]}
|
||||
widthRequest={width()}
|
||||
heightRequest={height()}
|
||||
valign={Gtk.Align.CENTER}
|
||||
>
|
||||
<button onClicked={hide} visible={false} />
|
||||
<box
|
||||
vertical
|
||||
cssClasses={["app-launcher"]}
|
||||
valign={Gtk.Align.CENTER}
|
||||
halign={Gtk.Align.CENTER}
|
||||
widthRequest={500}
|
||||
>
|
||||
<button onClicked={hide} visible={false}></button>
|
||||
<box cssClasses={["search"]}>
|
||||
<image iconName={"system-search-symbolic"}></image>
|
||||
<entry
|
||||
placeholderText={"Search..."}
|
||||
text={text.get()}
|
||||
setup={self => {
|
||||
hook(self, App, 'window-toggled', (_, win) => {
|
||||
if (win.name == 'launcher') {
|
||||
self.set_text('');
|
||||
self.grab_focus();
|
||||
}
|
||||
})
|
||||
}}
|
||||
onNotifyText={self => text.set(self.text)}
|
||||
primaryIconSensitive
|
||||
onActivate={onEnter}
|
||||
hexpand></entry>
|
||||
</box>
|
||||
<AppList
|
||||
hide={hide}
|
||||
query={text}
|
||||
visible={text(v => {
|
||||
return !prefixes.includes(v.slice(0, 1));
|
||||
})}
|
||||
></AppList>
|
||||
</box>
|
||||
</box>
|
||||
}
|
||||
>
|
||||
</window>
|
||||
}
|
||||
|
||||
export default Launcher;
|
||||
|
16
config/astal/components/launcher/launcher.scss
Normal file
16
config/astal/components/launcher/launcher.scss
Normal file
@ -0,0 +1,16 @@
|
||||
@use '../../util/colours.scss' as *;
|
||||
|
||||
window {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
box.app-launcher-wrapper {
|
||||
background-color: $shadow-color;
|
||||
|
||||
>box.app-launcher {
|
||||
background-color: $bg-color;
|
||||
border-radius: 30px;
|
||||
padding: 20px;
|
||||
border: 1px solid $accent-color-2;
|
||||
}
|
||||
}
|
59
config/astal/components/launcher/modules/Apps.tsx
Normal file
59
config/astal/components/launcher/modules/Apps.tsx
Normal file
@ -0,0 +1,59 @@
|
||||
import { Binding, Variable } from "astal";
|
||||
import { Gtk } from "astal/gtk4";
|
||||
import AstalApps from "gi://AstalApps";
|
||||
import Pango from "gi://Pango?version=1.0";
|
||||
|
||||
const MAX_ITEMS = 8;
|
||||
|
||||
const AppList = ({ hide, query, visible }: { hide: () => void, query: Variable<string>, visible: Binding<Boolean> }) => {
|
||||
const apps = new AstalApps.Apps();
|
||||
const list = query((text) => apps.fuzzy_query(text).slice(0, MAX_ITEMS));
|
||||
return <box>
|
||||
<box
|
||||
spacing={6}
|
||||
vertical
|
||||
cssClasses={["app-list"]}
|
||||
visible={list.as(l => l.length > 0)}
|
||||
>
|
||||
{list.as(l => l.map(app => <AppButton app={app} hide={hide}></AppButton>))}
|
||||
</box>
|
||||
<box
|
||||
halign={Gtk.Align.CENTER}
|
||||
cssClasses={["list-empty"]}
|
||||
vertical
|
||||
visible={list.as(l => l.length === 0)}
|
||||
>
|
||||
<image iconName={"system-search-symbolic"}></image>
|
||||
<label label={"No match found"}></label>
|
||||
</box>
|
||||
</box>
|
||||
}
|
||||
|
||||
const AppButton = ({ app, hide }: { app: AstalApps.Application, hide: () => void }) => {
|
||||
return <button
|
||||
onClicked={() => {
|
||||
hide();
|
||||
app.launch();
|
||||
}}
|
||||
child={
|
||||
<box>
|
||||
<image iconName={app.iconName}></image>
|
||||
<box valign={Gtk.Align.CENTER} vertical>
|
||||
<label
|
||||
cssClasses={["title-2"]}
|
||||
ellipsize={Pango.EllipsizeMode.END}
|
||||
maxWidthChars={40}
|
||||
xalign={0}
|
||||
label={app.name}
|
||||
></label>
|
||||
<label
|
||||
wrap xalign={0}
|
||||
label={app.description}
|
||||
></label>
|
||||
</box>
|
||||
</box>
|
||||
}>
|
||||
</button>
|
||||
}
|
||||
|
||||
export default AppList;
|
Loading…
x
Reference in New Issue
Block a user