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 BgFade from './widgets/bg-fade/main';
|
||||
import Calendar from './widgets/date/main';
|
||||
import Clipboard from './widgets/clipboard/main';
|
||||
import Corners from './widgets/corners/main';
|
||||
import IconBrowser from './widgets/icon-browser/main';
|
||||
import { NotifPopups, NotifCenter } from './widgets/notifs/main';
|
||||
|
@ -59,6 +60,7 @@ switch (CONF) {
|
|||
Bar();
|
||||
BgFade();
|
||||
Calendar();
|
||||
Clipboard();
|
||||
Corners();
|
||||
IconBrowser();
|
||||
NotifPopups();
|
||||
|
|
|
@ -40,6 +40,7 @@ progressbar {
|
|||
|
||||
@import 'widgets/applauncher/style.scss';
|
||||
@import 'widgets/bar/style.scss';
|
||||
@import 'widgets/clipboard/style.scss';
|
||||
@import 'widgets/date/style.scss';
|
||||
@import 'widgets/icon-browser/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