feat(ags clipboard): hide long clips past 5 lines
All checks were successful
Discord / discord commits (push) Has been skipped

This commit is contained in:
matt1432 2024-08-01 21:09:38 -04:00
parent 1928a74e90
commit 59675a6d1f
5 changed files with 137 additions and 66 deletions

View file

@ -46,15 +46,17 @@
all: unset;
transition: 200ms;
border-radius: 9px;
box {
padding: 10px;
}
padding: 10px;
}
*:selected .item,
.item:hover,
.item:focus {
*:hover .item,
*:focus .item {
background-color: #363449;
}
.down-arrow {
transition: all 500ms;
opacity: 0.5;
}
}

View file

@ -47,15 +47,17 @@
all: unset;
transition: 200ms;
border-radius: 9px;
box {
padding: 10px;
}
padding: 10px;
}
*:selected .item,
.item:hover,
.item:focus {
*:hover .item,
*:focus .item {
background-color: #363449;
}
.down-arrow {
transition: all 500ms;
opacity: 0.5;
}
}

View file

@ -32,7 +32,7 @@ class Clipboard extends Service {
// Public Class Methods
public copyOldItem(key: string | number): void {
execAsync([
'bash', '-c', `cliphist list | grep ${key} | cliphist decode | wl-copy`,
'bash', '-c', `cliphist list | grep '^${key}' | cliphist decode | wl-copy`,
]);
}
@ -63,9 +63,28 @@ class Clipboard extends Service {
}
}
private _getHistory(n = Clipboard._MAX_CLIPS) {
this._clips = new Map();
private _addClip(newClip: [number, { clip: string, isImage: boolean }]) {
if (
![...this.clips.values()]
.map((c) => c.clip)
.includes(newClip[1].clip)
) {
this._clips.set(...newClip);
this.emit('clip-added', newClip);
}
else {
const oldClip = [...this.clips.entries()]
.find(([_, { clip }]) => clip === newClip[1].clip);
if (oldClip && oldClip[0] < newClip[0]) {
this.clips.delete(oldClip[0]);
this._clips.set(...newClip);
this.emit('clip-added', newClip);
}
}
}
private _getHistory(n = Clipboard._MAX_CLIPS) {
// FIXME: this is necessary when not putting a cap on clip amount
// exec(`prlimit --pid ${exec('pgrep ags')} --nofile=10024:`);
@ -91,8 +110,7 @@ class Clipboard extends Service {
},
];
this._clips.set(...newClip);
this.emit('clip-added', newClip);
this._addClip(newClip);
}
else {
const decodedClip = await this._decodeItem(clip);
@ -106,8 +124,7 @@ class Clipboard extends Service {
},
];
this._clips.set(...newClip);
this.emit('clip-added', newClip);
this._addClip(newClip);
}
}
});

View file

@ -0,0 +1,80 @@
const { Box, Button, Icon, Label, Revealer } = Widget;
const ImageClip = (key: number, val: string) => Box({
class_name: 'item',
name: key.toString(),
child: Icon({
icon: val.replace('img:', ''),
size: 100 * 2,
}),
});
const TextClip = (key: number, val: string) => {
const lines = val.split('\n');
if (lines.length <= 5) {
return Box({
class_name: 'item',
name: key.toString(),
child: Label({
label: val,
truncate: 'end',
max_width_chars: 100,
}),
});
}
else {
const revText = Revealer({
hpack: 'start',
child: Label({
label: lines.slice(2, lines.length).join('\n'),
truncate: 'end',
max_width_chars: 100,
}),
});
return Box({
class_name: 'item',
name: key.toString(),
vertical: true,
children: [
Label({
label: lines.slice(0, 2).join('\n'),
truncate: 'end',
max_width_chars: 100,
hpack: 'start',
}),
revText,
Button({
child: Icon({
class_name: 'down-arrow',
icon: 'down-large-symbolic',
size: 24,
}),
on_primary_click_release: (self) => {
const state = !revText.reveal_child;
revText.reveal_child = state;
self.child.setCss(`
-gtk-icon-transform: rotate(${state ? '180' : '0'}deg);
`);
},
}),
],
});
}
};
export default ({
key = 0,
isImage = false,
val = '',
}) => isImage ? ImageClip(key, val) : TextClip(key, val);

View file

@ -1,55 +1,17 @@
const { Box, Icon, Label } = Widget;
import { Fzf, FzfResultItem } from 'fzf';
import Gtk from 'gi://Gtk?version=3.0';
import Clipboard from '../../services/clipboard.ts';
import CursorBox from '../misc/cursorbox.ts';
import SortedList from '../misc/sorted-list.ts';
import ClipWidget from './clip.ts';
const getKey = (r: Gtk.ListBoxRow): number => parseInt(r.get_child()?.name ?? '0');
export default () => {
const makeItem = (
list: Gtk.ListBox,
key: number,
val: string,
isImage: boolean,
): void => {
const widget = CursorBox({
class_name: 'item',
name: key.toString(),
on_primary_click_release: () => {
Clipboard.copyOldItem(key);
App.closeWindow('win-clipboard');
},
child: Box({
children: [
isImage ?
Icon({
icon: val.replace('img:', ''),
size: 100 * 2,
}) :
Label({
label: val,
truncate: 'end',
max_width_chars: 100,
}),
],
}),
});
list.add(widget);
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',
class_name: 'clipboard',
@ -61,18 +23,23 @@ export default () => {
},
setup_list: (list, entry) => {
list.cursor = 'pointer';
const CONNECT_ID = Clipboard.connect('history-searched', () => {
// Do every clip that existed before this widget
list.get_children().forEach((row) => {
row.destroy();
});
Clipboard.clips.forEach((clip, key) => {
makeItem(list, key, clip.clip, clip.isImage);
const widget = ClipWidget({ key, isImage: clip.isImage, val: clip.clip });
list.add(widget);
widget.show_all();
});
// Setup connection for new clips
Clipboard.connect('clip-added', (_, [key, clip]) => {
makeItem(list, key, clip.clip, clip.isImage);
const widget = ClipWidget({ key, isImage: clip.isImage, val: clip.clip });
list.add(widget);
widget.show_all();
});
list.set_sort_func((a, b) => {
@ -93,6 +60,9 @@ export default () => {
}
});
// Trigger on_text_change after init
entry.text = '-';
Clipboard.disconnect(CONNECT_ID);
});
},