refactor(ags): abstract appL and clip with SortedList
All checks were successful
Discord / discord commits (push) Has been skipped
All checks were successful
Discord / discord commits (push) Has been skipped
This commit is contained in:
parent
384e0c24b3
commit
9a9cfc13f6
7 changed files with 317 additions and 278 deletions
13
modules/ags/config/global-types.d.ts
vendored
13
modules/ags/config/global-types.d.ts
vendored
|
@ -115,22 +115,9 @@ export type CursorBox = CursorBox;
|
|||
export type CursorBoxProps = CursorBoxProps;
|
||||
|
||||
// For PopupWindow
|
||||
export type PopupChild = Binding<
|
||||
Var<Widget>,
|
||||
'is_listening' | 'is_polling' | 'value',
|
||||
Widget[]
|
||||
>;
|
||||
export type HyprTransition = 'slide' | 'slide top' | 'slide bottom' | 'slide left' |
|
||||
'slide right' | 'popin' | 'fade';
|
||||
export type CloseType = 'none' | 'stay' | 'released' | 'clicked';
|
||||
export type PopupWindowProps<Child extends Widget, Attr = unknown> =
|
||||
WindowProps<Child> & {
|
||||
transition?: HyprTransition;
|
||||
on_open?(self: PopupWindow<Child, Attr>): void
|
||||
on_close?(self: PopupWindow<Child, Attr>): void
|
||||
close_on_unfocus?: CloseType
|
||||
anchor?: Array<'top' | 'bottom' | 'right' | 'left'>;
|
||||
};
|
||||
import { PopupWindow } from 'ts/misc/popup';
|
||||
export type PopupWindow = PopupWindow;
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ const { Box, Icon, Label } = Widget;
|
|||
const { lookUpIcon } = Utils;
|
||||
|
||||
import CursorBox from '../misc/cursorbox.ts';
|
||||
import { launchApp } from './launch.ts';
|
||||
|
||||
/* Types */
|
||||
import { Application } from 'types/service/applications.ts';
|
||||
|
@ -54,11 +53,6 @@ export default (app: Application) => {
|
|||
|
||||
attribute: { app },
|
||||
|
||||
on_primary_click_release: () => {
|
||||
App.closeWindow('win-applauncher');
|
||||
launchApp(app);
|
||||
},
|
||||
|
||||
child: Box({
|
||||
children: [
|
||||
icon,
|
||||
|
|
|
@ -1,87 +1,67 @@
|
|||
const Applications = await Service.import('applications');
|
||||
const { Box, Entry, Icon, Label, ListBox, Revealer, Scrollable } = Widget;
|
||||
|
||||
import { Fzf, FzfResultItem } from 'fzf';
|
||||
|
||||
import PopupWindow from '../misc/popup.ts';
|
||||
import SortedList from '../misc/sorted-list.ts';
|
||||
import AppItem from './app-item.ts';
|
||||
|
||||
import { launchApp } from './launch.ts';
|
||||
|
||||
// Types
|
||||
/* Types */
|
||||
import { ListBoxRow } from 'types/@girs/gtk-3.0/gtk-3.0.cjs';
|
||||
import { Application } from 'types/service/applications.ts';
|
||||
import { AgsAppItem } from 'global-types';
|
||||
|
||||
|
||||
const Applauncher = (window_name = 'applauncher') => {
|
||||
export default () => {
|
||||
let fzfResults: FzfResultItem<Application>[];
|
||||
const list = ListBox();
|
||||
|
||||
const setSort = (text: string) => {
|
||||
const fzf = new Fzf(Applications.list, {
|
||||
selector: (app) => app.name + app.executable,
|
||||
return SortedList({
|
||||
name: 'applauncher',
|
||||
class_name: 'applauncher',
|
||||
transition: 'slide top',
|
||||
|
||||
tiebreakers: [
|
||||
(a, b) => b.item.frequency - a.item.frequency,
|
||||
],
|
||||
});
|
||||
|
||||
fzfResults = fzf.find(text);
|
||||
list.set_sort_func((a, b) => {
|
||||
const row1 = (a.get_children()[0] as AgsAppItem).attribute.app.name;
|
||||
const row2 = (b.get_children()[0] as AgsAppItem).attribute.app.name;
|
||||
|
||||
const s1 = fzfResults.find((r) => r.item.name === row1)?.score ?? 0;
|
||||
const s2 = fzfResults.find((r) => r.item.name === row2)?.score ?? 0;
|
||||
|
||||
return s2 - s1;
|
||||
});
|
||||
};
|
||||
|
||||
const makeNewChildren = () => {
|
||||
const rows = list.get_children() as ListBoxRow[];
|
||||
|
||||
rows.forEach((ch) => {
|
||||
ch.destroy();
|
||||
});
|
||||
|
||||
const children = Applications.query('')
|
||||
.flatMap((app) => AppItem(app));
|
||||
|
||||
children.forEach((ch) => {
|
||||
list.add(ch);
|
||||
});
|
||||
list.show_all();
|
||||
};
|
||||
|
||||
makeNewChildren();
|
||||
|
||||
const placeholder = Revealer({
|
||||
child: Label({
|
||||
label: " Couldn't find a match",
|
||||
class_name: 'placeholder',
|
||||
}),
|
||||
});
|
||||
|
||||
const entry = Entry({
|
||||
// Set some text so on-change works the first time
|
||||
text: '-',
|
||||
hexpand: true,
|
||||
|
||||
on_accept: ({ text }) => {
|
||||
const appList = Applications.query(text || '');
|
||||
|
||||
if (appList[0]) {
|
||||
App.closeWindow(`win-${window_name}`);
|
||||
launchApp(appList[0]);
|
||||
}
|
||||
on_select: (r) => {
|
||||
App.closeWindow('win-applauncher');
|
||||
launchApp((r.get_child() as AgsAppItem).attribute.app);
|
||||
},
|
||||
|
||||
on_change: ({ text }) => {
|
||||
if (text === null) {
|
||||
return;
|
||||
}
|
||||
setSort(text);
|
||||
init_rows: (list) => {
|
||||
const rows = list.get_children() as ListBoxRow[];
|
||||
|
||||
rows.forEach((ch) => {
|
||||
ch.destroy();
|
||||
});
|
||||
|
||||
const children = Applications.query('')
|
||||
.flatMap((app) => AppItem(app));
|
||||
|
||||
children.forEach((ch) => {
|
||||
list.add(ch);
|
||||
});
|
||||
list.show_all();
|
||||
},
|
||||
|
||||
set_sort: (text, list, placeholder) => {
|
||||
const fzf = new Fzf(Applications.list, {
|
||||
selector: (app) => app.name + app.executable,
|
||||
|
||||
tiebreakers: [
|
||||
(a, b) => b.item.frequency - a.item.frequency,
|
||||
],
|
||||
});
|
||||
|
||||
fzfResults = fzf.find(text);
|
||||
list.set_sort_func((a, b) => {
|
||||
const row1 = (a.get_children()[0] as AgsAppItem).attribute.app.name;
|
||||
const row2 = (b.get_children()[0] as AgsAppItem).attribute.app.name;
|
||||
|
||||
const s1 = fzfResults.find((r) => r.item.name === row1)?.score ?? 0;
|
||||
const s2 = fzfResults.find((r) => r.item.name === row2)?.score ?? 0;
|
||||
|
||||
return s2 - s1;
|
||||
});
|
||||
|
||||
let visibleApps = 0;
|
||||
|
||||
const rows = list.get_children() as ListBoxRow[];
|
||||
|
@ -106,52 +86,4 @@ const Applauncher = (window_name = 'applauncher') => {
|
|||
placeholder.reveal_child = visibleApps <= 0;
|
||||
},
|
||||
});
|
||||
|
||||
return Box({
|
||||
class_name: 'applauncher',
|
||||
vertical: true,
|
||||
|
||||
setup: (self) => {
|
||||
self.hook(App, (_, name, visible) => {
|
||||
if (name !== `win-${window_name}`) {
|
||||
return;
|
||||
}
|
||||
|
||||
entry.text = '';
|
||||
|
||||
if (visible) {
|
||||
entry.grab_focus();
|
||||
}
|
||||
else {
|
||||
makeNewChildren();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
children: [
|
||||
Box({
|
||||
class_name: 'header',
|
||||
children: [
|
||||
Icon('preferences-system-search-symbolic'),
|
||||
entry,
|
||||
],
|
||||
}),
|
||||
|
||||
Scrollable({
|
||||
hscroll: 'never',
|
||||
vscroll: 'automatic',
|
||||
child: Box({
|
||||
vertical: true,
|
||||
children: [list, placeholder],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
export default () => PopupWindow({
|
||||
name: 'applauncher',
|
||||
transition: 'slide top',
|
||||
keymode: 'on-demand',
|
||||
child: Applauncher(),
|
||||
});
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
const { Box, Entry, Icon, Label, ListBox, Scrollable } = Widget;
|
||||
const { Box, Icon, Label } = Widget;
|
||||
const { execAsync } = Utils;
|
||||
|
||||
const Hyprland = await Service.import('hyprland');
|
||||
|
||||
import { Fzf, FzfResultItem } from 'fzf';
|
||||
import Gtk from 'gi://Gtk?version=3.0';
|
||||
|
||||
import CursorBox from '../misc/cursorbox.ts';
|
||||
import PopupWindow from '../misc/popup.ts';
|
||||
import { Monitor } from 'types/service/hyprland';
|
||||
import SortedList from '../misc/sorted-list.ts';
|
||||
|
||||
|
||||
const N_ITEMS = 30;
|
||||
|
@ -27,39 +24,7 @@ export default () => {
|
|||
|
||||
const getKey = (r: Gtk.ListBoxRow) => parseInt(r.get_child()?.name ?? '');
|
||||
|
||||
const list = ListBox().on('row-activated', (_, row) => {
|
||||
copyOldItem(getKey(row));
|
||||
});
|
||||
|
||||
const updateItems = () => {
|
||||
(list.get_children() as Gtk.ListBoxRow[]).forEach((r) => {
|
||||
r.changed();
|
||||
});
|
||||
};
|
||||
|
||||
const setSort = (text: string) => {
|
||||
if (text === '' || text === '-') {
|
||||
list.set_sort_func((row1, row2) => getKey(row2) - getKey(row1));
|
||||
}
|
||||
else {
|
||||
const fzf = new Fzf(CopiedItems, {
|
||||
selector: (item) => item[0],
|
||||
|
||||
tiebreakers: [(a, b) => b[1] - a[1]],
|
||||
});
|
||||
|
||||
fzfResults = fzf.find(text);
|
||||
list.set_sort_func((a, b) => {
|
||||
const row1 = fzfResults.find((f) => f.item[1] === getKey(a))?.score ?? 0;
|
||||
const row2 = fzfResults.find((f) => f.item[1] === getKey(b))?.score ?? 0;
|
||||
|
||||
return row2 - row1;
|
||||
});
|
||||
}
|
||||
updateItems();
|
||||
};
|
||||
|
||||
const makeItem = (key: string, val: string) => {
|
||||
const makeItem = (list: Gtk.ListBox, key: string, val: string) => {
|
||||
CopiedItems.push([val, parseInt(key)]);
|
||||
|
||||
const widget = CursorBox({
|
||||
|
@ -87,110 +52,67 @@ export default () => {
|
|||
|
||||
list.add(widget);
|
||||
widget.show_all();
|
||||
updateItems();
|
||||
};
|
||||
|
||||
// Decode old item:
|
||||
const decodeItem = (index: string) => {
|
||||
execAsync([
|
||||
'bash', '-c', `cliphist list | grep ${index} | cliphist decode`,
|
||||
]).then((out) => {
|
||||
makeItem(index, out);
|
||||
(list.get_children() as Gtk.ListBoxRow[]).forEach((r) => {
|
||||
r.changed();
|
||||
});
|
||||
};
|
||||
|
||||
const entry = Entry({
|
||||
// Set some text so on-change works the first time
|
||||
text: '-',
|
||||
hexpand: true,
|
||||
// Decode old item:
|
||||
const decodeItem = (list: Gtk.ListBox, index: string) => {
|
||||
execAsync([
|
||||
'bash', '-c', `cliphist list | grep ${index} | cliphist decode`,
|
||||
]).then((out) => {
|
||||
makeItem(list, index, out);
|
||||
});
|
||||
};
|
||||
|
||||
on_change: ({ text }) => {
|
||||
if (text !== null) {
|
||||
setSort(text);
|
||||
return SortedList({
|
||||
name: 'clipboard',
|
||||
class_name: 'clipboard',
|
||||
transition: 'slide top',
|
||||
|
||||
on_select: (r) => copyOldItem(getKey(r)),
|
||||
|
||||
init_rows: (list) => {
|
||||
CopiedItems = [];
|
||||
|
||||
execAsync('clipboard-manager').then((out) => {
|
||||
list.get_children()?.forEach((ch) => {
|
||||
ch.destroy();
|
||||
});
|
||||
|
||||
const items = out.split('\n');
|
||||
|
||||
for (let i = 0; i < N_ITEMS; ++i) {
|
||||
if (items[i].includes('img')) {
|
||||
makeItem(list, (items[i].match('[0-9]+') ?? [''])[0], items[i]);
|
||||
}
|
||||
else {
|
||||
decodeItem(list, items[i]);
|
||||
}
|
||||
}
|
||||
}).catch(console.error);
|
||||
},
|
||||
|
||||
set_sort: (text, list) => {
|
||||
if (text === '' || text === '-') {
|
||||
list.set_sort_func((row1, row2) => getKey(row2) - getKey(row1));
|
||||
}
|
||||
else {
|
||||
const fzf = new Fzf(CopiedItems, {
|
||||
selector: (item) => item[0],
|
||||
|
||||
tiebreakers: [(a, b) => b[1] - a[1]],
|
||||
});
|
||||
|
||||
fzfResults = fzf.find(text);
|
||||
list.set_sort_func((a, b) => {
|
||||
const row1 = fzfResults.find((f) => f.item[1] === getKey(a))?.score ?? 0;
|
||||
const row2 = fzfResults.find((f) => f.item[1] === getKey(b))?.score ?? 0;
|
||||
|
||||
return row2 - row1;
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const on_open = () => {
|
||||
CopiedItems = [];
|
||||
entry.text = '';
|
||||
|
||||
execAsync('clipboard-manager').then(async(out) => {
|
||||
list.get_children()?.forEach((ch) => {
|
||||
ch.destroy();
|
||||
});
|
||||
|
||||
const items = out.split('\n');
|
||||
|
||||
for (let i = 0; i < N_ITEMS; ++i) {
|
||||
if (items[i].includes('img')) {
|
||||
makeItem((items[i].match('[0-9]+') ?? [''])[0], items[i]);
|
||||
}
|
||||
else {
|
||||
decodeItem(items[i]);
|
||||
}
|
||||
}
|
||||
|
||||
let x: number;
|
||||
let y: number;
|
||||
const monitor = (JSON.parse(await Hyprland.messageAsync('j/monitors')) as Monitor[])
|
||||
.find((m) => m.focused) as Monitor;
|
||||
|
||||
switch (monitor.transform) {
|
||||
case 1:
|
||||
x = monitor.x - (monitor.height / 2);
|
||||
y = monitor.y - (monitor.width / 2);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
x = monitor.x - (monitor.width / 2);
|
||||
y = monitor.y - (monitor.height / 2);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
x = monitor.x + (monitor.height / 2);
|
||||
y = monitor.y + (monitor.width / 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
x = monitor.x + (monitor.width / 2);
|
||||
y = monitor.y + (monitor.height / 2);
|
||||
break;
|
||||
}
|
||||
|
||||
await Hyprland.messageAsync(`dispatch movecursor ${x} ${y}`);
|
||||
entry.grab_focus();
|
||||
}).catch(console.log);
|
||||
};
|
||||
|
||||
on_open();
|
||||
|
||||
return PopupWindow({
|
||||
name: 'clipboard',
|
||||
keymode: 'on-demand',
|
||||
on_open,
|
||||
|
||||
child: Box({
|
||||
class_name: 'clipboard',
|
||||
vertical: true,
|
||||
children: [
|
||||
Box({
|
||||
class_name: 'header',
|
||||
children: [
|
||||
Icon('preferences-system-search-symbolic'),
|
||||
entry,
|
||||
],
|
||||
}),
|
||||
|
||||
Scrollable({
|
||||
hscroll: 'never',
|
||||
vscroll: 'automatic',
|
||||
child: Box({
|
||||
vertical: true,
|
||||
children: [list],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
});
|
||||
};
|
||||
|
|
|
@ -3,13 +3,29 @@ const Hyprland = await Service.import('hyprland');
|
|||
|
||||
/* Types */
|
||||
import { Window } from 'resource:///com/github/Aylur/ags/widgets/window.js';
|
||||
import type { WindowProps } from 'types/widgets/window';
|
||||
import type { Widget as AgsWidget } from 'types/widgets/widget';
|
||||
|
||||
import {
|
||||
CloseType,
|
||||
HyprTransition,
|
||||
PopupWindowProps,
|
||||
} from 'global-types';
|
||||
|
||||
export type PopupWindowProps<
|
||||
Child extends Gtk.Widget,
|
||||
Attr = unknown,
|
||||
Self = PopupWindow<Child, Attr>,
|
||||
> = WindowProps<Child, Attr, Self> & {
|
||||
transition?: HyprTransition;
|
||||
on_open?(self: PopupWindow<Child, Attr>): void;
|
||||
on_close?(self: PopupWindow<Child, Attr>): void;
|
||||
close_on_unfocus?: CloseType;
|
||||
anchor?: Array<'top' | 'bottom' | 'right' | 'left'>;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export interface PopupWindow<Child, Attr> extends AgsWidget<Attr> { }
|
||||
|
||||
|
||||
export class PopupWindow<
|
||||
Child extends Gtk.Widget,
|
||||
|
@ -50,7 +66,7 @@ export class PopupWindow<
|
|||
}
|
||||
|
||||
|
||||
private _on_open: (self: PopupWindow<Child, Attr>) => void;
|
||||
protected _on_open: (self: PopupWindow<Child, Attr>) => void;
|
||||
|
||||
get on_open() {
|
||||
return this._on_open;
|
||||
|
@ -114,10 +130,10 @@ export class PopupWindow<
|
|||
this.transition = transition;
|
||||
|
||||
if (isOpen) {
|
||||
this.on_open(this);
|
||||
this._on_open(this);
|
||||
}
|
||||
else {
|
||||
this.on_close(this);
|
||||
this._on_close(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -147,6 +163,6 @@ export class PopupWindow<
|
|||
}
|
||||
}
|
||||
|
||||
export default <Child extends Gtk.Widget, Attr>(
|
||||
export default <Child extends Gtk.Widget, Attr> (
|
||||
props: PopupWindowProps<Child, Attr>,
|
||||
) => new PopupWindow(props);
|
||||
|
|
188
modules/ags/config/ts/misc/sorted-list.ts
Normal file
188
modules/ags/config/ts/misc/sorted-list.ts
Normal file
|
@ -0,0 +1,188 @@
|
|||
const Hyprland = await Service.import('hyprland');
|
||||
|
||||
const { Box, Entry, Icon, Label, ListBox, Revealer, Scrollable } = Widget;
|
||||
|
||||
/* Types */
|
||||
import { PopupWindow, PopupWindowProps } from '../misc/popup.ts';
|
||||
import type { Widget as AgsWidget } from 'types/widgets/widget';
|
||||
import { ListBoxRow } from 'types/@girs/gtk-3.0/gtk-3.0.cjs';
|
||||
import { Monitor } from 'types/service/hyprland';
|
||||
import { Binding } from 'types/service';
|
||||
|
||||
type MakeChild = ReturnType<typeof makeChild>;
|
||||
|
||||
type SortedListProps<Attr = unknown, Self = SortedList<Attr>> =
|
||||
PopupWindowProps<MakeChild['child'], Attr, Self> & {
|
||||
on_select: (row: ListBoxRow) => void;
|
||||
init_rows: (list: MakeChild['list']) => void;
|
||||
set_sort: (
|
||||
text: string,
|
||||
list: MakeChild['list'],
|
||||
placeholder: MakeChild['placeholder'],
|
||||
) => void;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export interface SortedList<Attr> extends AgsWidget<Attr> { }
|
||||
|
||||
|
||||
const centerCursor = async(): Promise<void> => {
|
||||
let x: number;
|
||||
let y: number;
|
||||
const monitor = (JSON.parse(await Hyprland.messageAsync('j/monitors')) as Monitor[])
|
||||
.find((m) => m.focused) as Monitor;
|
||||
|
||||
switch (monitor.transform) {
|
||||
case 1:
|
||||
x = monitor.x - (monitor.height / 2);
|
||||
y = monitor.y - (monitor.width / 2);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
x = monitor.x - (monitor.width / 2);
|
||||
y = monitor.y - (monitor.height / 2);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
x = monitor.x + (monitor.height / 2);
|
||||
y = monitor.y + (monitor.width / 2);
|
||||
break;
|
||||
|
||||
default:
|
||||
x = monitor.x + (monitor.width / 2);
|
||||
y = monitor.y + (monitor.height / 2);
|
||||
break;
|
||||
}
|
||||
|
||||
await Hyprland.messageAsync(`dispatch movecursor ${x} ${y}`);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const makeChild = (class_name: string | Binding<any, any, string>) => {
|
||||
const list = ListBox();
|
||||
|
||||
const placeholder = Revealer({
|
||||
child: Label({
|
||||
label: " Couldn't find a match",
|
||||
class_name: 'placeholder',
|
||||
}),
|
||||
});
|
||||
|
||||
const entry = Entry({
|
||||
// Set some text so on-change works the first time
|
||||
text: '-',
|
||||
hexpand: true,
|
||||
});
|
||||
|
||||
return {
|
||||
list,
|
||||
entry,
|
||||
placeholder,
|
||||
child: Box({
|
||||
class_name,
|
||||
vertical: true,
|
||||
children: [
|
||||
Box({
|
||||
class_name: 'header',
|
||||
children: [
|
||||
Icon('preferences-system-search-symbolic'),
|
||||
entry,
|
||||
],
|
||||
}),
|
||||
|
||||
Scrollable({
|
||||
hscroll: 'never',
|
||||
vscroll: 'automatic',
|
||||
child: Box({
|
||||
vertical: true,
|
||||
children: [list, placeholder],
|
||||
}),
|
||||
}),
|
||||
],
|
||||
}),
|
||||
};
|
||||
};
|
||||
|
||||
export class SortedList<
|
||||
Attr,
|
||||
> extends PopupWindow<MakeChild['child'], Attr> {
|
||||
static {
|
||||
Widget.register(this, {
|
||||
properties: {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private _list: MakeChild['list'];
|
||||
private _entry: MakeChild['entry'];
|
||||
private _placeholder: MakeChild['placeholder'];
|
||||
private _on_select: (row: ListBoxRow) => void;
|
||||
private _init_rows: (list: MakeChild['list']) => void;
|
||||
private _set_sort: (
|
||||
text: string,
|
||||
list: MakeChild['list'],
|
||||
placeholder: MakeChild['placeholder'],
|
||||
) => void;
|
||||
|
||||
set on_open(fun: (self: PopupWindow<MakeChild['child'], Attr>) => void) {
|
||||
this._on_open = () => {
|
||||
this._entry.text = '';
|
||||
fun(this);
|
||||
this._init_rows(this._list);
|
||||
centerCursor();
|
||||
this._entry.grab_focus();
|
||||
};
|
||||
}
|
||||
|
||||
constructor({
|
||||
on_select,
|
||||
init_rows,
|
||||
set_sort,
|
||||
on_open = () => {/**/},
|
||||
class_name = '',
|
||||
keymode = 'on-demand',
|
||||
...rest
|
||||
}: SortedListProps<Attr, PopupWindow<MakeChild['child'], Attr>>) {
|
||||
const makeChildResult = makeChild(class_name);
|
||||
|
||||
// PopupWindow
|
||||
super({
|
||||
child: makeChildResult.child,
|
||||
keymode,
|
||||
...rest,
|
||||
});
|
||||
|
||||
this.on_open = on_open;
|
||||
|
||||
// SortedList
|
||||
this._on_select = on_select;
|
||||
this._init_rows = init_rows;
|
||||
this._set_sort = set_sort;
|
||||
|
||||
this._placeholder = makeChildResult.placeholder;
|
||||
|
||||
this._list = makeChildResult.list;
|
||||
this._list.on('row-activated', (_, row) => {
|
||||
this._on_select(row);
|
||||
});
|
||||
|
||||
this._entry = makeChildResult.entry;
|
||||
|
||||
this._entry.on_change = ({ text }) => {
|
||||
if (text !== null) {
|
||||
this._set_sort(text, this._list, this._placeholder);
|
||||
(this._list.get_children() as ListBoxRow[]).forEach((r) => {
|
||||
r.changed();
|
||||
});
|
||||
}
|
||||
};
|
||||
// TODO: add on_accept where it just selects the first visible one
|
||||
|
||||
this._init_rows(this._list);
|
||||
this._set_sort('', this._list, this._placeholder);
|
||||
}
|
||||
}
|
||||
|
||||
export default <Attr>(
|
||||
props: SortedListProps<Attr, PopupWindow<MakeChild['child'], Attr>>,
|
||||
) => new SortedList(props);
|
|
@ -11,12 +11,12 @@
|
|||
"noImplicitAny": false,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"fzf": ["./node_modules/fzf/dist/types"],
|
||||
"fzf": ["./node_modules/fzf/dist/types"]
|
||||
},
|
||||
"typeRoots": [
|
||||
"./types",
|
||||
"./global-types.d.ts",
|
||||
"./node_modules",
|
||||
"./node_modules"
|
||||
],
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
|
|
Loading…
Reference in a new issue