feat(ags): use experimental clipboard manager

This commit is contained in:
matt1432 2024-05-01 10:21:28 -04:00
parent 5fd6448ba2
commit f4618c3271
10 changed files with 243 additions and 112 deletions
modules/ags

View file

@ -0,0 +1,19 @@
{
cliphist,
gawk,
imagemagick,
ripgrep,
writeShellApplication,
...
}:
writeShellApplication {
name = "clipboard-manager";
runtimeInputs = [
cliphist
gawk
imagemagick
ripgrep
];
text = builtins.readFile ./script.sh;
}

45
modules/ags/clipboard/script.sh Executable file
View file

@ -0,0 +1,45 @@
set +o errexit
# Modified from https://github.com/sentriz/cliphist/blob/master/contrib/cliphist-wofi-img
# set up thumbnail directory
thumb_dir="/tmp/cliphist/thumbs"
mkdir -p "$thumb_dir"
cliphist_list="$(cliphist list)"
# delete thumbnails in cache but not in cliphist
for thumb in "$thumb_dir"/*; do
clip_id="${thumb##*/}"
clip_id="${clip_id%.*}"
check=$(rg <<< "$cliphist_list" "^$clip_id\s")
if [ -z "$check" ]; then
>&2 rm -v "$thumb"
fi
done
# create thumbnail if image not processed already
read -r -d '' prog <<EOF
/^[0-9]+\s<meta http-equiv=/ { next }
match(\$0, /^([0-9]+)\s(\[\[\s)?binary.*(jpg|jpeg|png|bmp)/, grp) {
image = grp[1]"."grp[3]
system("[ -f $thumb_dir/"image" ] || echo " grp[1] "\\\\\t | cliphist decode | convert - -resize '256x256>' $thumb_dir/"image )
print "img:$thumb_dir/"image
next
}
1
EOF
output=$(gawk <<< "$cliphist_list" "$prog")
# Use a while loop with read to iterate over each line
echo "$output" | while IFS= read -r line; do
if [[ ! $line =~ ^img:/tmp/cliphist/thumbs ]]; then
[[ $line =~ ([0-9]+) ]]
line=${BASH_REMATCH[1]}
fi
echo "$line"
done

View file

@ -0,0 +1,64 @@
.clipboard {
all: unset;
border: 2px solid $contrast-bg;
border-radius: 25px;
background-color: $bg;
color: #f8f8f2;
padding: 2px;
* {
font-size: 16px;
}
list, row {
all: unset;
}
scrolledwindow {
padding: 10px;
padding-bottom: 0;
min-width: 900px;
min-height: 750px;
scrollbar, scrollbar * {
all: unset;
}
scrollbar.vertical {
transition: 200ms;
background-color: rgba(23, 23, 23, 0.3);
margin: 20px 0;
&:hover {
background-color: rgba(23, 23, 23, 0.7);
slider {
background-color: rgba(238, 238, 238, 0.7);
min-width: .6em;
}
}
slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-width: .4em;
min-height: 2em;
transition: 200ms;
}
}
}
.item {
all: unset;
transition: 200ms;
border-radius: 9px;
box {
padding: 10px;
}
}
*:selected, .item:hover, .item:focus {
background-color: #363449;
}
}

View file

@ -21,3 +21,4 @@ undershoot {
@import "./wim-widgets/applauncher";
@import "./wim-widgets/osd";
@import "./wim-widgets/osk";
@import "./wim-widgets/clipboard";

View file

@ -0,0 +1,110 @@
const { Box, Icon, Label, ListBox, Scrollable } = Widget;
const { execAsync } = Utils;
import Gtk from 'gi://Gtk?version=3.0';
import CursorBox from '../misc/cursorbox.ts';
import PopupWindow from '../misc/popup.ts';
const N_ITEMS = 30;
export default () => {
const list = ListBox();
list.set_sort_func((row1, row2) => {
const getKey = (r: Gtk.ListBoxRow) => parseInt(r.get_child()?.name ?? '');
return getKey(row2) - getKey(row1);
});
const updateItems = () => {
(list.get_children() as Gtk.ListBoxRow[]).forEach((r) => {
r.changed();
});
};
const makeItem = (key: string, val: string) => {
const widget = CursorBox({
class_name: 'item',
name: key,
on_primary_click_release: () => {
execAsync([
'bash', '-c', `cliphist list | grep ${key} | cliphist decode | wl-copy`,
]).then(() => {
App.closeWindow('win-clipboard');
});
},
child: Box({
children: [
val.startsWith('img:') ?
Icon({
icon: val.replace('img:', ''),
size: 100 * 2,
}) :
Label({
label: val,
truncate: 'end',
max_width_chars: 100,
}),
],
}),
});
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);
});
};
const on_open = () => {
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((items[i].match('[0-9]+') ?? [''])[0], items[i]);
}
else {
decodeItem(items[i]);
}
}
}).catch(console.log);
};
on_open();
return PopupWindow({
name: 'clipboard',
on_open,
child: Box({
class_name: 'clipboard',
children: [
Scrollable({
hscroll: 'never',
vscroll: 'automatic',
child: Box({
vertical: true,
children: [list],
}),
}),
],
}),
});
};

View file

@ -3,6 +3,7 @@ import AppLauncher from './ts/applauncher/main.ts';
import Bar from './ts/bar/wim.ts';
import BgFade from './ts/misc/background-fade.ts';
import Calendar from './ts/date.ts';
import Clipboard from './ts/clipboard/main.ts';
import Corners from './ts/corners/main.ts';
import { NotifPopups, NotifCenter } from './ts/notifications/wim.ts';
import OSD from './ts/osd/main.ts';
@ -23,6 +24,7 @@ App.config({
AppLauncher(),
Calendar(),
Clipboard(),
NotifCenter(),
OSD(),
OSK(),

View file

@ -107,6 +107,7 @@ in {
dart-sass
bun
playerctl
(callPackage ./clipboard {})
## gui
pavucontrol # TODO: replace with ags widget