feat(agsV2): add clipboard
All checks were successful
Discord / discord commits (push) Has been skipped
All checks were successful
Discord / discord commits (push) Has been skipped
This commit is contained in:
parent
cd8384a556
commit
171ff9629c
6 changed files with 213 additions and 0 deletions
|
@ -8,6 +8,7 @@ import AppLauncher from './widgets/applauncher/main';
|
||||||
import Bar from './widgets/bar/wim';
|
import Bar from './widgets/bar/wim';
|
||||||
import BgFade from './widgets/bg-fade/main';
|
import BgFade from './widgets/bg-fade/main';
|
||||||
import Calendar from './widgets/date/main';
|
import Calendar from './widgets/date/main';
|
||||||
|
import Clipboard from './widgets/clipboard/main';
|
||||||
import Corners from './widgets/corners/main';
|
import Corners from './widgets/corners/main';
|
||||||
import IconBrowser from './widgets/icon-browser/main';
|
import IconBrowser from './widgets/icon-browser/main';
|
||||||
import { NotifPopups, NotifCenter } from './widgets/notifs/main';
|
import { NotifPopups, NotifCenter } from './widgets/notifs/main';
|
||||||
|
@ -59,6 +60,7 @@ switch (CONF) {
|
||||||
Bar();
|
Bar();
|
||||||
BgFade();
|
BgFade();
|
||||||
Calendar();
|
Calendar();
|
||||||
|
Clipboard();
|
||||||
Corners();
|
Corners();
|
||||||
IconBrowser();
|
IconBrowser();
|
||||||
NotifPopups();
|
NotifPopups();
|
||||||
|
|
|
@ -40,6 +40,7 @@ progressbar {
|
||||||
|
|
||||||
@import 'widgets/applauncher/style.scss';
|
@import 'widgets/applauncher/style.scss';
|
||||||
@import 'widgets/bar/style.scss';
|
@import 'widgets/bar/style.scss';
|
||||||
|
@import 'widgets/clipboard/style.scss';
|
||||||
@import 'widgets/date/style.scss';
|
@import 'widgets/date/style.scss';
|
||||||
@import 'widgets/icon-browser/style.scss';
|
@import 'widgets/icon-browser/style.scss';
|
||||||
@import 'widgets/lockscreen/style.scss';
|
@import 'widgets/lockscreen/style.scss';
|
||||||
|
|
96
nixosModules/ags/v2/widgets/clipboard/clip-item.tsx
Normal file
96
nixosModules/ags/v2/widgets/clipboard/clip-item.tsx
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
import { execAsync } from 'astal';
|
||||||
|
import { register } from 'astal/gobject';
|
||||||
|
import { Gtk, Widget } from 'astal/gtk3';
|
||||||
|
|
||||||
|
export interface EntryObject {
|
||||||
|
id: number
|
||||||
|
content: string
|
||||||
|
entry: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const SCALE = 150;
|
||||||
|
const BINARY_DATA = /\[\[ binary data (\d+) (KiB|MiB) (\w+) (\d+)x(\d+) \]\]/;
|
||||||
|
|
||||||
|
export const CLIP_SCRIPT = `${SRC}/widgets/clipboard/cliphist.sh`;
|
||||||
|
|
||||||
|
@register()
|
||||||
|
export class ClipItem extends Widget.Box {
|
||||||
|
declare id: number;
|
||||||
|
declare content: string;
|
||||||
|
|
||||||
|
public show_image(file: string, width: string | number, height: string | number) {
|
||||||
|
this.children[2].destroy();
|
||||||
|
|
||||||
|
const initCss = () => {
|
||||||
|
const _widthPx = Number(width);
|
||||||
|
const heightPx = Number(height);
|
||||||
|
const maxWidth = 400;
|
||||||
|
const widthPx = (_widthPx / heightPx) * SCALE;
|
||||||
|
|
||||||
|
let css = `background-image: url("${file}");`;
|
||||||
|
|
||||||
|
if (widthPx > maxWidth) {
|
||||||
|
const newHeightPx = (SCALE / widthPx) * maxWidth;
|
||||||
|
|
||||||
|
css += `min-height: ${newHeightPx}px; min-width: ${maxWidth}px;`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
css += `min-height: 150px; min-width: ${widthPx}px;`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return css;
|
||||||
|
};
|
||||||
|
|
||||||
|
const icon = (
|
||||||
|
<box
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
css={initCss()}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
this.children = [...this.children, icon];
|
||||||
|
};
|
||||||
|
|
||||||
|
constructor({ item }: { item: EntryObject }) {
|
||||||
|
super({
|
||||||
|
children: [
|
||||||
|
<label
|
||||||
|
label={item.id.toString()}
|
||||||
|
xalign={0}
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
/>,
|
||||||
|
<label
|
||||||
|
label="・"
|
||||||
|
xalign={0}
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
/>,
|
||||||
|
<label
|
||||||
|
label={item.content}
|
||||||
|
xalign={0}
|
||||||
|
valign={Gtk.Align.CENTER}
|
||||||
|
truncate
|
||||||
|
/>,
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
this.id = item.id;
|
||||||
|
this.content = item.content;
|
||||||
|
|
||||||
|
const matches = this.content.match(BINARY_DATA);
|
||||||
|
|
||||||
|
if (matches) {
|
||||||
|
// const size = matches[1];
|
||||||
|
const format = matches[3];
|
||||||
|
const width = matches[4];
|
||||||
|
const height = matches[5];
|
||||||
|
|
||||||
|
if (format === 'png') {
|
||||||
|
execAsync(`${CLIP_SCRIPT} --save-by-id ${this.id}`)
|
||||||
|
.then((file) => {
|
||||||
|
this.show_image(file, width, height);
|
||||||
|
})
|
||||||
|
.catch(print);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
44
nixosModules/ags/v2/widgets/clipboard/cliphist.sh
Executable file
44
nixosModules/ags/v2/widgets/clipboard/cliphist.sh
Executable file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# https://github.com/koeqaife/hyprland-material-you/blob/d23cf9d524522c8c215664c2c3334c2b51609cae/ags/scripts/cliphist.sh
|
||||||
|
|
||||||
|
get() {
|
||||||
|
cliphist list | iconv -f "$(locale charmap)" -t UTF-8 -c
|
||||||
|
}
|
||||||
|
|
||||||
|
copy_by_id() {
|
||||||
|
id=$1
|
||||||
|
cliphist decode "$id" | wl-copy
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
cliphist wipe
|
||||||
|
}
|
||||||
|
|
||||||
|
save_cache_file() {
|
||||||
|
id=$1
|
||||||
|
|
||||||
|
output_file="/tmp/ags/cliphist/$id.png"
|
||||||
|
|
||||||
|
if [[ ! -f "$output_file" ]]; then
|
||||||
|
mkdir -p "/tmp/ags/cliphist/"
|
||||||
|
cliphist decode "$id" >"$output_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$output_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_tmp() {
|
||||||
|
rm "/tmp/ags/cliphist/*"
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "$1" == "--get" ]]; then
|
||||||
|
get
|
||||||
|
elif [[ "$1" == "--copy-by-id" ]]; then
|
||||||
|
{ copy_by_id "$2"; }
|
||||||
|
elif [[ "$1" == "--save-by-id" ]]; then
|
||||||
|
{ save_cache_file "$2"; }
|
||||||
|
elif [[ "$1" == "--clear-cache" ]]; then
|
||||||
|
clear_tmp
|
||||||
|
elif [[ "$1" == "--clear" ]]; then
|
||||||
|
clear
|
||||||
|
fi
|
66
nixosModules/ags/v2/widgets/clipboard/main.tsx
Normal file
66
nixosModules/ags/v2/widgets/clipboard/main.tsx
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
import { execAsync } from 'astal';
|
||||||
|
import { App } from 'astal/gtk3';
|
||||||
|
|
||||||
|
import SortedList from '../misc/sorted-list';
|
||||||
|
|
||||||
|
import { CLIP_SCRIPT, ClipItem, EntryObject } from './clip-item';
|
||||||
|
|
||||||
|
|
||||||
|
export default () => SortedList<EntryObject>({
|
||||||
|
name: 'clipboard',
|
||||||
|
|
||||||
|
create_list: async() => {
|
||||||
|
const output = await execAsync(`${CLIP_SCRIPT} --get`)
|
||||||
|
.then((str) => str)
|
||||||
|
.catch((err) => {
|
||||||
|
print(err);
|
||||||
|
|
||||||
|
return '';
|
||||||
|
});
|
||||||
|
|
||||||
|
return output
|
||||||
|
.split('\n')
|
||||||
|
.filter((line) => line.trim() !== '')
|
||||||
|
.map((entry) => {
|
||||||
|
const [id, ...content] = entry.split('\t');
|
||||||
|
|
||||||
|
return { id: parseInt(id.trim()), content: content.join(' ').trim(), entry };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
create_row: (item) => new ClipItem({ item }),
|
||||||
|
|
||||||
|
fzf_options: {
|
||||||
|
selector: (item) => item.content,
|
||||||
|
},
|
||||||
|
|
||||||
|
compare_props: ['id'],
|
||||||
|
|
||||||
|
on_row_activated: (row) => {
|
||||||
|
const clip = row.get_children()[0] as ClipItem;
|
||||||
|
|
||||||
|
execAsync(`${CLIP_SCRIPT} --copy-by-id ${clip.id}`);
|
||||||
|
App.get_window('win-clipboard')?.set_visible(false);
|
||||||
|
},
|
||||||
|
|
||||||
|
sort_func: (a, b, entry, fzfResults) => {
|
||||||
|
const row1 = a.get_children()[0] as ClipItem;
|
||||||
|
const row2 = b.get_children()[0] as ClipItem;
|
||||||
|
|
||||||
|
if (entry.text === '' || entry.text === '-') {
|
||||||
|
a.set_visible(true);
|
||||||
|
b.set_visible(true);
|
||||||
|
|
||||||
|
return row2.id - row1.id;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const s1 = fzfResults.find((r) => r.item.id === row1.id)?.score ?? 0;
|
||||||
|
const s2 = fzfResults.find((r) => r.item.id === row2.id)?.score ?? 0;
|
||||||
|
|
||||||
|
a.set_visible(s1 !== 0);
|
||||||
|
b.set_visible(s2 !== 0);
|
||||||
|
|
||||||
|
return s2 - s1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
4
nixosModules/ags/v2/widgets/clipboard/style.scss
Normal file
4
nixosModules/ags/v2/widgets/clipboard/style.scss
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
.clipboard .list row box {
|
||||||
|
margin: 20px;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
Loading…
Reference in a new issue