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

View file

@ -1,17 +0,0 @@
{...}: {
programs = {
wofi = {
enable = true;
settings = {
prompt = "";
allow_images = true;
normal_window = true;
image_size = "48";
matching = "fuzzy";
insensitive = true;
no_actions = true;
};
style = builtins.readFile ./style.css;
};
};
}

View file

@ -1,92 +0,0 @@
/* https://github.com/dracula/wofi/blob/master/style.css */
* {
font-size: 16px;
}
window,
undershoot {
all: unset;
}
#input {
all: unset;
border-radius: 9px;
color: #f8f8f2;
background-color: rgba(#44475a, 0.6);
border: 1px solid #44475a;
padding: 8px;
margin: 16.2px;
margin-bottom: 0;
}
#outer-box {
all: unset;
box-shadow: 0 0 4.5px 0 rgba(0, 0, 0, 0.6);
border: 2px solid rgba(189, 147, 249, 0.8);
border-radius: 25px;
background-color: rgba(40, 42, 54, 0.8);
color: #f8f8f2;
padding: 16.2px;
}
#inner-box {
padding: 16.2px;
min-width: 500px;
min-height: 450px;
}
#scroll scrollbar, #scroll scrollbar * {
all: unset;
}
#scroll scrollbar {
transition: 200ms;
background-color: rgba(23, 23, 23, 0.3);
&:hover {
background-color: rgba(23, 23, 23, 0.7);
}
}
#scroll scrollbar.vertical:hover slider {
background-color: rgba(238, 238, 238, 0.7);
min-width: .6em;
}
#scroll scrollbar.horizontal:hover slider {
background-color: rgba(238, 238, 238, 0.7);
min-height: .6em;
}
#scroll .vertical slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-width: .4em;
min-height: 2em;
transition: 200ms;
}
#scroll .horizontal slider {
background-color: rgba(238, 238, 238, 0.5);
border-radius: 9px;
min-height: .4em;
min-width: 2em;
transition: 200ms;
}
#entry {
all: unset;
padding: 9px;
}
#entry image, #entry label {
all: unset;
}
#entry image {
margin-right: 9px;
}
#entry:selected {
background-color: rgba(189, 147, 249, 0.5);
border-radius: 9px;
box-shadow: inset 0 0 0 3px rgba(238, 238, 238, 0.03);
}
#entry:selected image {
-gtk-icon-shadow: 3px 3px rgba(0, 0, 0, 0.8);
}

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

View file

@ -17,7 +17,6 @@ in {
../../home/foot.nix
../../home/mpv
../../home/obs.nix
../../home/wofi
({config, ...}: let
symlink = config.lib.file.mkOutOfStoreSymlink;
@ -115,7 +114,6 @@ in {
];
windowrule = [
"noborder,^(wofi)$"
"tile,^(libreoffice)$"
"float,^(org.gnome.Calculator)$"
"float,^(com.gabm.satty)$"
@ -133,7 +131,7 @@ in {
"$mainMod, Q, exec, foot"
# Clipboard History
"$mainMod, V, exec, killall -r wofi || cliphist list | wofi --dmenu | cliphist decode | wl-copy"
"$mainMod, V, exec, ags -t win-clipboard"
" , Print, exec, screenshot"
"$mainMod, Print, exec, grim -g \"$(slurp)\" - | satty -f - --output-filename \"screenshot-$(date --iso-8601=seconds)\""