fix(ags): clipboard logic

This commit is contained in:
Franek 2025-04-27 15:35:41 +02:00
parent 54b69f0aac
commit 97130dbe27
5 changed files with 124 additions and 101 deletions

View File

@ -1,26 +1,26 @@
// SCSS Variables
// Generated by 'wal'
$wallpaper: "/home/sadorowo/images/wallpapers/youtube_Sheri_142.jpg";
$wallpaper: "/home/sadorowo/images/wallpapers/youtube_Sheri_170.jpg";
// Special
$background: #f9f7f5;
$foreground: #4C3A47;
$cursor: #4C3A47;
$background: #f9f6f3;
$foreground: #251F23;
$cursor: #251F23;
// Colors
$color0: #f9f7f5;
$color1: #B77E8E;
$color2: #6E8EAF;
$color3: #138DCF;
$color4: #609DD4;
$color5: #A196AD;
$color6: #D6ABA7;
$color7: #4C3A47;
$color8: #847974;
$color9: #B77E8E;
$color10: #6E8EAF;
$color11: #138DCF;
$color12: #609DD4;
$color13: #A196AD;
$color14: #D6ABA7;
$color15: #4C3A47;
$color0: #f9f6f3;
$color1: #AB8772;
$color2: #D69768;
$color3: #727188;
$color4: #897A85;
$color5: #79869C;
$color6: #A29597;
$color7: #251F23;
$color8: #82766c;
$color9: #AB8772;
$color10: #D69768;
$color11: #727188;
$color12: #897A85;
$color13: #79869C;
$color14: #A29597;
$color15: #251F23;

View File

@ -14,6 +14,14 @@
}
}
.entry.primary {
background: $color3;
&:hover>.content {
color: $color3;
}
}
.entry {
padding: 10px;
background: $color5;
@ -23,18 +31,17 @@
&:hover {
background: $color0;
box>.content {
>.content {
color: $color5;
}
}
box {
.content {
color: $color0;
font-size: 14px;
font-weight: 600;
}
}
}
.not-found {
background: $color5;

View File

@ -23,7 +23,8 @@
&:hover {
background: $color0;
box>.name, box>.description {
box>.name,
box>.description {
color: $color5;
}
}
@ -32,7 +33,6 @@
margin-right: 12px;
}
box {
.name {
color: $color0;
font-size: 14px;
@ -44,7 +44,6 @@
font-size: 12px;
}
}
}
.not-found {
background: $color5;

View File

@ -17,43 +17,45 @@ function ClipboardEntry({ id, content }: Entry) {
execAsync([SHELL, "-c", `cliphist decode ${id} | wl-copy`]);
}}
>
<box>
<label
cssClasses={["content"]}
xalign={0}
label={content}
/>
</box>
</button>
}
async function getClipboardHistory() {
async function getClipboardHistory(history: Variable<Entry[]>) {
try {
const ids = await execAsync([SHELL, "-c", "cliphist list | awk '{print $1}'"])
.then(it => it.split("\n"));
const contents = await execAsync([SHELL, "-c", "cliphist list | awk '{$1=\"\"; print}'"])
.then(it => it.split("\n"));
return ids
history.set(ids
.map((id, index) => ({ id, content: contents[index] }))
.filter(({ content }) => content && content.length > 0);
.filter(({ content }) => content && content.length > 0));
} catch {
return [];
history.set([]);
}
}
export default async function Clipboard(_monitor_id: number) {
const { TOP, BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor;
const history = await getClipboardHistory();
const hypr = Hyprland.get_default();
const history: Variable<Entry[]> = Variable([]);
const toSkip = Variable(0);
const list = bind(toSkip).as(count => limit(
const list = Variable.derive([
bind(history),
bind(toSkip)
], (history, count) => limit(
skip(history, count),
10
));
const isEmpty = bind(list).as(list => list.length === 0);
const onScroll = (dy: number) => {
const value = toSkip.get();
@ -61,11 +63,15 @@ export default async function Clipboard(_monitor_id: number) {
if ((value - 10) < 0) return;
toSkip.set(value - 10)
} else {
if ((value + 10) > history.length) return;
if ((value + 10) > history.get().length) return;
toSkip.set(value + 10)
}
};
const setup = (self: Gtk.Window) => self.connect('notify::visible', async () => {
await getClipboardHistory(history)
})
return <window
visible={false}
monitor={bind(hypr, "focusedMonitor").as(monitor => monitor.id)}
@ -74,23 +80,36 @@ export default async function Clipboard(_monitor_id: number) {
keymode={Astal.Keymode.EXCLUSIVE}
anchor={TOP | BOTTOM | LEFT | RIGHT}
onKeyPressed={hideWindow}
application={App}>
<box hexpand={false} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
<box cssClasses={["clipboard"]} vertical>
application={App}
setup={setup}>
<box hexpand={false} cssClasses={["clipboard"]} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
<box spacing={6} vertical onScroll={(_, __, dy) => onScroll(dy)}>
{list.as(list => list.map(({ id, content }) => (
{bind(list).as(list => list.map(({ id, content }) => (
<ClipboardEntry id={id} content={content} />
)))}
<button
cssClasses={["entry", "primary"]}
visible={isEmpty.as(empty => !empty)}
onClicked={() => {
execAsync([SHELL, "-c", "cliphist wipe"])
history.set([])
}}
>
<label
cssClasses={["content"]}
xalign={0}
label="Wipe clipboard history"
/>
</button>
</box>
<box
halign={Gtk.Align.CENTER}
cssClasses={["not-found"]}
vertical
visible={list.as(it => it.length === 0)}>
visible={isEmpty}>
<image iconName="system-search-symbolic" />
<label label="No match found" />
</box>
</box>
</box>
</window>
}

View File

@ -56,8 +56,7 @@ export default function Launcher(_monitor_id: number) {
anchor={TOP | BOTTOM | LEFT | RIGHT}
onKeyPressed={hideWindow}
application={App}>
<box hexpand={false} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
<box cssClasses={["launcher"]} vertical>
<box hexpand={false} cssClasses={["launcher"]} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
<entry
placeholderText="Search"
onChanged={self => query.set(self.text)}
@ -77,6 +76,5 @@ export default function Launcher(_monitor_id: number) {
<label label="No match found" />
</box>
</box>
</box>
</window>
}