fix(ags): clipboard logic
This commit is contained in:
parent
54b69f0aac
commit
97130dbe27
@ -1,26 +1,26 @@
|
|||||||
// SCSS Variables
|
// SCSS Variables
|
||||||
// Generated by 'wal'
|
// Generated by 'wal'
|
||||||
$wallpaper: "/home/sadorowo/images/wallpapers/youtube_Sheri_142.jpg";
|
$wallpaper: "/home/sadorowo/images/wallpapers/youtube_Sheri_170.jpg";
|
||||||
|
|
||||||
// Special
|
// Special
|
||||||
$background: #f9f7f5;
|
$background: #f9f6f3;
|
||||||
$foreground: #4C3A47;
|
$foreground: #251F23;
|
||||||
$cursor: #4C3A47;
|
$cursor: #251F23;
|
||||||
|
|
||||||
// Colors
|
// Colors
|
||||||
$color0: #f9f7f5;
|
$color0: #f9f6f3;
|
||||||
$color1: #B77E8E;
|
$color1: #AB8772;
|
||||||
$color2: #6E8EAF;
|
$color2: #D69768;
|
||||||
$color3: #138DCF;
|
$color3: #727188;
|
||||||
$color4: #609DD4;
|
$color4: #897A85;
|
||||||
$color5: #A196AD;
|
$color5: #79869C;
|
||||||
$color6: #D6ABA7;
|
$color6: #A29597;
|
||||||
$color7: #4C3A47;
|
$color7: #251F23;
|
||||||
$color8: #847974;
|
$color8: #82766c;
|
||||||
$color9: #B77E8E;
|
$color9: #AB8772;
|
||||||
$color10: #6E8EAF;
|
$color10: #D69768;
|
||||||
$color11: #138DCF;
|
$color11: #727188;
|
||||||
$color12: #609DD4;
|
$color12: #897A85;
|
||||||
$color13: #A196AD;
|
$color13: #79869C;
|
||||||
$color14: #D6ABA7;
|
$color14: #A29597;
|
||||||
$color15: #4C3A47;
|
$color15: #251F23;
|
||||||
|
@ -14,6 +14,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.entry.primary {
|
||||||
|
background: $color3;
|
||||||
|
|
||||||
|
&:hover>.content {
|
||||||
|
color: $color3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.entry {
|
.entry {
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
background: $color5;
|
background: $color5;
|
||||||
@ -23,18 +31,17 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
background: $color0;
|
background: $color0;
|
||||||
|
|
||||||
box>.content {
|
>.content {
|
||||||
color: $color5;
|
color: $color5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
box {
|
|
||||||
.content {
|
.content {
|
||||||
color: $color0;
|
color: $color0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.not-found {
|
.not-found {
|
||||||
background: $color5;
|
background: $color5;
|
||||||
|
@ -23,7 +23,8 @@
|
|||||||
&:hover {
|
&:hover {
|
||||||
background: $color0;
|
background: $color0;
|
||||||
|
|
||||||
box>.name, box>.description {
|
box>.name,
|
||||||
|
box>.description {
|
||||||
color: $color5;
|
color: $color5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -32,7 +33,6 @@
|
|||||||
margin-right: 12px;
|
margin-right: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
box {
|
|
||||||
.name {
|
.name {
|
||||||
color: $color0;
|
color: $color0;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@ -44,7 +44,6 @@
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.not-found {
|
.not-found {
|
||||||
background: $color5;
|
background: $color5;
|
||||||
|
@ -17,43 +17,45 @@ function ClipboardEntry({ id, content }: Entry) {
|
|||||||
execAsync([SHELL, "-c", `cliphist decode ${id} | wl-copy`]);
|
execAsync([SHELL, "-c", `cliphist decode ${id} | wl-copy`]);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<box>
|
|
||||||
<label
|
<label
|
||||||
cssClasses={["content"]}
|
cssClasses={["content"]}
|
||||||
xalign={0}
|
xalign={0}
|
||||||
label={content}
|
label={content}
|
||||||
/>
|
/>
|
||||||
</box>
|
|
||||||
</button>
|
</button>
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getClipboardHistory() {
|
async function getClipboardHistory(history: Variable<Entry[]>) {
|
||||||
try {
|
try {
|
||||||
const ids = await execAsync([SHELL, "-c", "cliphist list | awk '{print $1}'"])
|
const ids = await execAsync([SHELL, "-c", "cliphist list | awk '{print $1}'"])
|
||||||
.then(it => it.split("\n"));
|
.then(it => it.split("\n"));
|
||||||
const contents = await execAsync([SHELL, "-c", "cliphist list | awk '{$1=\"\"; print}'"])
|
const contents = await execAsync([SHELL, "-c", "cliphist list | awk '{$1=\"\"; print}'"])
|
||||||
.then(it => it.split("\n"));
|
.then(it => it.split("\n"));
|
||||||
|
|
||||||
return ids
|
history.set(ids
|
||||||
.map((id, index) => ({ id, content: contents[index] }))
|
.map((id, index) => ({ id, content: contents[index] }))
|
||||||
.filter(({ content }) => content && content.length > 0);
|
.filter(({ content }) => content && content.length > 0));
|
||||||
} catch {
|
} catch {
|
||||||
return [];
|
history.set([]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function Clipboard(_monitor_id: number) {
|
export default async function Clipboard(_monitor_id: number) {
|
||||||
const { TOP, BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor;
|
const { TOP, BOTTOM, LEFT, RIGHT } = Astal.WindowAnchor;
|
||||||
|
|
||||||
const history = await getClipboardHistory();
|
|
||||||
const hypr = Hyprland.get_default();
|
const hypr = Hyprland.get_default();
|
||||||
|
|
||||||
|
const history: Variable<Entry[]> = Variable([]);
|
||||||
const toSkip = Variable(0);
|
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),
|
skip(history, count),
|
||||||
10
|
10
|
||||||
));
|
));
|
||||||
|
|
||||||
|
const isEmpty = bind(list).as(list => list.length === 0);
|
||||||
const onScroll = (dy: number) => {
|
const onScroll = (dy: number) => {
|
||||||
const value = toSkip.get();
|
const value = toSkip.get();
|
||||||
|
|
||||||
@ -61,11 +63,15 @@ export default async function Clipboard(_monitor_id: number) {
|
|||||||
if ((value - 10) < 0) return;
|
if ((value - 10) < 0) return;
|
||||||
toSkip.set(value - 10)
|
toSkip.set(value - 10)
|
||||||
} else {
|
} else {
|
||||||
if ((value + 10) > history.length) return;
|
if ((value + 10) > history.get().length) return;
|
||||||
toSkip.set(value + 10)
|
toSkip.set(value + 10)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setup = (self: Gtk.Window) => self.connect('notify::visible', async () => {
|
||||||
|
await getClipboardHistory(history)
|
||||||
|
})
|
||||||
|
|
||||||
return <window
|
return <window
|
||||||
visible={false}
|
visible={false}
|
||||||
monitor={bind(hypr, "focusedMonitor").as(monitor => monitor.id)}
|
monitor={bind(hypr, "focusedMonitor").as(monitor => monitor.id)}
|
||||||
@ -74,23 +80,36 @@ export default async function Clipboard(_monitor_id: number) {
|
|||||||
keymode={Astal.Keymode.EXCLUSIVE}
|
keymode={Astal.Keymode.EXCLUSIVE}
|
||||||
anchor={TOP | BOTTOM | LEFT | RIGHT}
|
anchor={TOP | BOTTOM | LEFT | RIGHT}
|
||||||
onKeyPressed={hideWindow}
|
onKeyPressed={hideWindow}
|
||||||
application={App}>
|
application={App}
|
||||||
<box hexpand={false} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
|
setup={setup}>
|
||||||
<box cssClasses={["clipboard"]} vertical>
|
<box hexpand={false} cssClasses={["clipboard"]} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
|
||||||
<box spacing={6} vertical onScroll={(_, __, dy) => onScroll(dy)}>
|
<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} />
|
<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>
|
||||||
<box
|
<box
|
||||||
halign={Gtk.Align.CENTER}
|
halign={Gtk.Align.CENTER}
|
||||||
cssClasses={["not-found"]}
|
cssClasses={["not-found"]}
|
||||||
vertical
|
vertical
|
||||||
visible={list.as(it => it.length === 0)}>
|
visible={isEmpty}>
|
||||||
<image iconName="system-search-symbolic" />
|
<image iconName="system-search-symbolic" />
|
||||||
<label label="No match found" />
|
<label label="No match found" />
|
||||||
</box>
|
</box>
|
||||||
</box>
|
</box>
|
||||||
</box>
|
|
||||||
</window>
|
</window>
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,7 @@ export default function Launcher(_monitor_id: number) {
|
|||||||
anchor={TOP | BOTTOM | LEFT | RIGHT}
|
anchor={TOP | BOTTOM | LEFT | RIGHT}
|
||||||
onKeyPressed={hideWindow}
|
onKeyPressed={hideWindow}
|
||||||
application={App}>
|
application={App}>
|
||||||
<box hexpand={false} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
|
<box hexpand={false} cssClasses={["launcher"]} vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER}>
|
||||||
<box cssClasses={["launcher"]} vertical>
|
|
||||||
<entry
|
<entry
|
||||||
placeholderText="Search"
|
placeholderText="Search"
|
||||||
onChanged={self => query.set(self.text)}
|
onChanged={self => query.set(self.text)}
|
||||||
@ -77,6 +76,5 @@ export default function Launcher(_monitor_id: number) {
|
|||||||
<label label="No match found" />
|
<label label="No match found" />
|
||||||
</box>
|
</box>
|
||||||
</box>
|
</box>
|
||||||
</box>
|
|
||||||
</window>
|
</window>
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user