feat(ags): use experimental clipboard manager
This commit is contained in:
parent
5fd6448ba2
commit
f4618c3271
10 changed files with 243 additions and 112 deletions
|
@ -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;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -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);
|
|
||||||
}
|
|
19
modules/ags/clipboard/default.nix
Normal file
19
modules/ags/clipboard/default.nix
Normal 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
45
modules/ags/clipboard/script.sh
Executable 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
|
64
modules/ags/config/scss/wim-widgets/clipboard.scss
Normal file
64
modules/ags/config/scss/wim-widgets/clipboard.scss
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,3 +21,4 @@ undershoot {
|
||||||
@import "./wim-widgets/applauncher";
|
@import "./wim-widgets/applauncher";
|
||||||
@import "./wim-widgets/osd";
|
@import "./wim-widgets/osd";
|
||||||
@import "./wim-widgets/osk";
|
@import "./wim-widgets/osk";
|
||||||
|
@import "./wim-widgets/clipboard";
|
||||||
|
|
110
modules/ags/config/ts/clipboard/main.ts
Normal file
110
modules/ags/config/ts/clipboard/main.ts
Normal 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],
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
};
|
|
@ -3,6 +3,7 @@ import AppLauncher from './ts/applauncher/main.ts';
|
||||||
import Bar from './ts/bar/wim.ts';
|
import Bar from './ts/bar/wim.ts';
|
||||||
import BgFade from './ts/misc/background-fade.ts';
|
import BgFade from './ts/misc/background-fade.ts';
|
||||||
import Calendar from './ts/date.ts';
|
import Calendar from './ts/date.ts';
|
||||||
|
import Clipboard from './ts/clipboard/main.ts';
|
||||||
import Corners from './ts/corners/main.ts';
|
import Corners from './ts/corners/main.ts';
|
||||||
import { NotifPopups, NotifCenter } from './ts/notifications/wim.ts';
|
import { NotifPopups, NotifCenter } from './ts/notifications/wim.ts';
|
||||||
import OSD from './ts/osd/main.ts';
|
import OSD from './ts/osd/main.ts';
|
||||||
|
@ -23,6 +24,7 @@ App.config({
|
||||||
|
|
||||||
AppLauncher(),
|
AppLauncher(),
|
||||||
Calendar(),
|
Calendar(),
|
||||||
|
Clipboard(),
|
||||||
NotifCenter(),
|
NotifCenter(),
|
||||||
OSD(),
|
OSD(),
|
||||||
OSK(),
|
OSK(),
|
||||||
|
|
|
@ -107,6 +107,7 @@ in {
|
||||||
dart-sass
|
dart-sass
|
||||||
bun
|
bun
|
||||||
playerctl
|
playerctl
|
||||||
|
(callPackage ./clipboard {})
|
||||||
|
|
||||||
## gui
|
## gui
|
||||||
pavucontrol # TODO: replace with ags widget
|
pavucontrol # TODO: replace with ags widget
|
||||||
|
|
|
@ -17,7 +17,6 @@ in {
|
||||||
../../home/foot.nix
|
../../home/foot.nix
|
||||||
../../home/mpv
|
../../home/mpv
|
||||||
../../home/obs.nix
|
../../home/obs.nix
|
||||||
../../home/wofi
|
|
||||||
|
|
||||||
({config, ...}: let
|
({config, ...}: let
|
||||||
symlink = config.lib.file.mkOutOfStoreSymlink;
|
symlink = config.lib.file.mkOutOfStoreSymlink;
|
||||||
|
@ -115,7 +114,6 @@ in {
|
||||||
];
|
];
|
||||||
|
|
||||||
windowrule = [
|
windowrule = [
|
||||||
"noborder,^(wofi)$"
|
|
||||||
"tile,^(libreoffice)$"
|
"tile,^(libreoffice)$"
|
||||||
"float,^(org.gnome.Calculator)$"
|
"float,^(org.gnome.Calculator)$"
|
||||||
"float,^(com.gabm.satty)$"
|
"float,^(com.gabm.satty)$"
|
||||||
|
@ -133,7 +131,7 @@ in {
|
||||||
"$mainMod, Q, exec, foot"
|
"$mainMod, Q, exec, foot"
|
||||||
|
|
||||||
# Clipboard History
|
# 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"
|
" , Print, exec, screenshot"
|
||||||
"$mainMod, Print, exec, grim -g \"$(slurp)\" - | satty -f - --output-filename \"screenshot-$(date --iso-8601=seconds)\""
|
"$mainMod, Print, exec, grim -g \"$(slurp)\" - | satty -f - --output-filename \"screenshot-$(date --iso-8601=seconds)\""
|
||||||
|
|
Loading…
Reference in a new issue