From 1928a74e90e48951fe82c04c39d03c1bc00f2d5a Mon Sep 17 00:00:00 2001
From: matt1432 <matt@nelim.org>
Date: Thu, 1 Aug 2024 17:21:52 -0400
Subject: [PATCH] feat(ags): cleanup sorted list and hide not matching clips

---
 modules/ags/config/ts/applauncher/main.ts | 75 ++++++++++-------------
 modules/ags/config/ts/clipboard/main.ts   | 54 +++++++++-------
 modules/ags/config/ts/misc/sorted-list.ts | 20 +++---
 3 files changed, 74 insertions(+), 75 deletions(-)

diff --git a/modules/ags/config/ts/applauncher/main.ts b/modules/ags/config/ts/applauncher/main.ts
index 8b331788..cda40e68 100644
--- a/modules/ags/config/ts/applauncher/main.ts
+++ b/modules/ags/config/ts/applauncher/main.ts
@@ -8,13 +8,12 @@ import AppItem from './app-item.ts';
 import { launchApp } from './launch.ts';
 
 /* 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';
 
 
 export default () => {
-    let fzfResults: FzfResultItem<Application>[];
+    let fzfResults = [] as FzfResultItem<Application>[];
 
     return SortedList({
         name: 'applauncher',
@@ -26,23 +25,38 @@ export default () => {
             launchApp((r.get_child() as AgsAppItem).attribute.app);
         },
 
-        init_rows: (list) => {
-            const rows = list.get_children() as ListBoxRow[];
+        setup_list: (list, entry) => {
+            Applications.query('')
+                .flatMap((app) => AppItem(app))
+                .forEach((ch) => {
+                    list.add(ch);
+                });
 
-            rows.forEach((ch) => {
-                ch.destroy();
-            });
-
-            const children = Applications.query('')
-                .flatMap((app) => AppItem(app));
-
-            children.forEach((ch) => {
-                list.add(ch);
-            });
             list.show_all();
+
+            list.set_sort_func((a, b) => {
+                const row1 = (a.get_children()[0] as AgsAppItem).attribute.app;
+                const row2 = (b.get_children()[0] as AgsAppItem).attribute.app;
+
+                if (entry.text === '' || entry.text === '-') {
+                    a.set_visible(true);
+                    b.set_visible(true);
+
+                    return row2.frequency - row1.frequency;
+                }
+                else {
+                    const s1 = fzfResults.find((r) => r.item.name === row1.name)?.score ?? 0;
+                    const s2 = fzfResults.find((r) => r.item.name === row2.name)?.score ?? 0;
+
+                    a.set_visible(s1 !== 0);
+                    b.set_visible(s2 !== 0);
+
+                    return s2 - s1;
+                }
+            });
         },
 
-        set_sort: (text, list, placeholder) => {
+        on_text_change: (text, list, placeholder) => {
             const fzf = new Fzf(Applications.list, {
                 selector: (app) => app.name + app.executable,
 
@@ -52,37 +66,10 @@ export default () => {
             });
 
             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;
+            list.invalidate_sort();
 
-                const s1 = fzfResults.find((r) => r.item.name === row1)?.score ?? 0;
-                const s2 = fzfResults.find((r) => r.item.name === row2)?.score ?? 0;
+            const visibleApps = list.get_children().filter((row) => row.visible).length;
 
-                return s2 - s1;
-            });
-
-            let visibleApps = 0;
-
-            const rows = list.get_children() as ListBoxRow[];
-
-            rows.forEach((row) => {
-                row.changed();
-
-                const item = row.get_children()[0] as AgsAppItem;
-
-                if (item.attribute.app) {
-                    const isMatching = fzfResults.some((r) => {
-                        return r.item.name === item.attribute.app.name;
-                    });
-
-                    row.visible = isMatching;
-
-                    if (isMatching) {
-                        ++visibleApps;
-                    }
-                }
-            });
             placeholder.reveal_child = visibleApps <= 0;
         },
     });
diff --git a/modules/ags/config/ts/clipboard/main.ts b/modules/ags/config/ts/clipboard/main.ts
index 1defdea6..b2f8dd52 100644
--- a/modules/ags/config/ts/clipboard/main.ts
+++ b/modules/ags/config/ts/clipboard/main.ts
@@ -9,10 +9,6 @@ import SortedList from '../misc/sorted-list.ts';
 
 
 export default () => {
-    let fzfResults: FzfResultItem<[number, { clip: string, isImage: boolean }]>[];
-
-    const getKey = (r: Gtk.ListBoxRow): number => parseInt(r.get_child()?.name ?? '0');
-
     const makeItem = (
         list: Gtk.ListBox,
         key: number,
@@ -49,6 +45,10 @@ export default () => {
         widget.show_all();
     };
 
+    let fzfResults = [] as FzfResultItem<[number, { clip: string, isImage: boolean }]>[];
+
+    const getKey = (r: Gtk.ListBoxRow): number => parseInt(r.get_child()?.name ?? '0');
+
 
     return SortedList({
         name: 'clipboard',
@@ -60,7 +60,7 @@ export default () => {
             App.closeWindow('win-clipboard');
         },
 
-        setup_list: (list) => {
+        setup_list: (list, entry) => {
             const CONNECT_ID = Clipboard.connect('history-searched', () => {
                 // Do every clip that existed before this widget
                 list.get_children().forEach((row) => {
@@ -75,29 +75,41 @@ export default () => {
                     makeItem(list, key, clip.clip, clip.isImage);
                 });
 
+                list.set_sort_func((a, b) => {
+                    if (entry.text === '' || entry.text === '-') {
+                        a.set_visible(true);
+                        b.set_visible(true);
+
+                        return getKey(b) - getKey(a);
+                    }
+                    else {
+                        const ROW_1 = fzfResults.find((f) => f.item[0] === getKey(a))?.score ?? 0;
+                        const ROW_2 = fzfResults.find((f) => f.item[0] === getKey(b))?.score ?? 0;
+
+                        a.set_visible(ROW_1 !== 0);
+                        b.set_visible(ROW_2 !== 0);
+
+                        return ROW_2 - ROW_1;
+                    }
+                });
+
                 Clipboard.disconnect(CONNECT_ID);
             });
         },
 
-        set_sort: (text, list) => {
-            if (text === '' || text === '-') {
-                list.set_sort_func((row1, row2) => getKey(row2) - getKey(row1));
-            }
-            else {
-                const fzf = new Fzf([...Clipboard.clips.entries()], {
-                    selector: ([_key, { clip }]) => clip,
+        on_text_change: (text, list, placeholder) => {
+            const fzf = new Fzf([...Clipboard.clips.entries()], {
+                selector: ([_key, { clip }]) => clip,
 
-                    tiebreakers: [(a, b) => b[0] - a[0]],
-                });
+                tiebreakers: [(a, b) => b[0] - a[0]],
+            });
 
-                fzfResults = fzf.find(text);
-                list.set_sort_func((a, b) => {
-                    const ROW_1 = fzfResults.find((f) => f.item[0] === getKey(a))?.score ?? 0;
-                    const ROW_2 = fzfResults.find((f) => f.item[0] === getKey(b))?.score ?? 0;
+            fzfResults = fzf.find(text);
+            list.invalidate_sort();
 
-                    return ROW_2 - ROW_1;
-                });
-            }
+            const visibleApps = list.get_children().filter((row) => row.visible).length;
+
+            placeholder.reveal_child = visibleApps <= 0;
         },
     });
 };
diff --git a/modules/ags/config/ts/misc/sorted-list.ts b/modules/ags/config/ts/misc/sorted-list.ts
index f58dc4bc..8541c6f0 100644
--- a/modules/ags/config/ts/misc/sorted-list.ts
+++ b/modules/ags/config/ts/misc/sorted-list.ts
@@ -17,14 +17,14 @@ type MakeChild = ReturnType<typeof makeChild>;
 
 type SortedListProps<Attr = unknown, Self = SortedList<Attr>> =
   PopupWindowProps<MakeChild['child'], Attr, Self> & {
-      on_select: (row: ListBoxRow) => void
+      on_select?: (row: ListBoxRow) => void
       init_rows?: (list: MakeChild['list']) => void
-      set_sort: (
+      on_text_change?: (
           text: string,
           list: MakeChild['list'],
           placeholder: MakeChild['placeholder'],
       ) => void
-      setup_list?: (list: MakeChild['list']) => void
+      setup_list?: (list: MakeChild['list'], entry: MakeChild['entry']) => void
   };
 
 
@@ -127,7 +127,7 @@ export class SortedList<
     private _scrollable: MakeChild['scrollable'];
     private _on_select: (row: ListBoxRow) => void;
     private _init_rows: (list: MakeChild['list']) => void;
-    private _set_sort: (
+    private _on_text_change: (
         text: string,
         list: MakeChild['list'],
         placeholder: MakeChild['placeholder'],
@@ -148,9 +148,9 @@ export class SortedList<
     }
 
     constructor({
-        on_select,
+        on_select = () => { /**/ },
         init_rows = () => { /**/ },
-        set_sort,
+        on_text_change = () => { /**/ },
         setup_list = () => { /**/ },
         on_open = () => { /**/ },
         class_name = '',
@@ -171,7 +171,7 @@ export class SortedList<
         // SortedList
         this._on_select = on_select;
         this._init_rows = init_rows;
-        this._set_sort = set_sort;
+        this._on_text_change = on_text_change;
 
         this._placeholder = makeChildResult.placeholder;
         this._scrollable = makeChildResult.scrollable;
@@ -185,14 +185,14 @@ export class SortedList<
 
         this._entry.on_change = ({ text }) => {
             if (text !== null || typeof text === 'string') {
-                this._set_sort(text, this._list, this._placeholder);
+                this._on_text_change(text, this._list, this._placeholder);
             }
         };
         // TODO: add on_accept where it just selects the first visible one
 
-        setup_list(this._list);
+        setup_list(this._list, this._entry);
         this._init_rows(this._list);
-        this._set_sort('', this._list, this._placeholder);
+        this._on_text_change('', this._list, this._placeholder);
     }
 }