sidebar: package news module
This commit is contained in:
parent
93f1dd5131
commit
5d89f8a8d5
5 changed files with 162 additions and 2 deletions
|
|
@ -704,4 +704,44 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.news {
|
||||||
|
min-height: lib.s(200);
|
||||||
|
|
||||||
|
.empty {
|
||||||
|
margin-top: lib.s(40);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list {
|
||||||
|
@include lib.spacing(10, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
.article {
|
||||||
|
@include lib.rounded(20);
|
||||||
|
@include lib.element-decel;
|
||||||
|
|
||||||
|
background-color: color.change(scheme.$surface1, $alpha: 0.4);
|
||||||
|
padding: lib.s(10) lib.s(15);
|
||||||
|
|
||||||
|
@include lib.spacing(5);
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: lib.s(28);
|
||||||
|
|
||||||
|
&:not(:last-child) {
|
||||||
|
margin-right: lib.s(12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.sublabel {
|
||||||
|
font-size: lib.s(14);
|
||||||
|
color: scheme.$subtext0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.body {
|
||||||
|
margin-top: lib.s(10);
|
||||||
|
font-size: lib.s(14);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import Audio from "./audio";
|
||||||
import Connectivity from "./connectivity";
|
import Connectivity from "./connectivity";
|
||||||
import Dashboard from "./dashboard";
|
import Dashboard from "./dashboard";
|
||||||
import NotifPane from "./notifpane";
|
import NotifPane from "./notifpane";
|
||||||
|
import Packages from "./packages";
|
||||||
|
|
||||||
@register()
|
@register()
|
||||||
export default class SideBar extends Widget.Window {
|
export default class SideBar extends Widget.Window {
|
||||||
|
|
@ -22,7 +23,7 @@ export default class SideBar extends Widget.Window {
|
||||||
visible: false,
|
visible: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const panes = [<Dashboard />, <Audio />, <Connectivity />, <NotifPane />];
|
const panes = [<Dashboard />, <Audio />, <Connectivity />, <Packages />, <NotifPane />];
|
||||||
this.shown = Variable(panes[0].name);
|
this.shown = Variable(panes[0].name);
|
||||||
|
|
||||||
this.add(
|
this.add(
|
||||||
|
|
|
||||||
110
src/modules/sidebar/modules/news.tsx
Normal file
110
src/modules/sidebar/modules/news.tsx
Normal file
|
|
@ -0,0 +1,110 @@
|
||||||
|
import Palette from "@/services/palette";
|
||||||
|
import Updates from "@/services/updates";
|
||||||
|
import { setupCustomTooltip } from "@/utils/widgets";
|
||||||
|
import { bind, Variable } from "astal";
|
||||||
|
import { Gtk } from "astal/gtk3";
|
||||||
|
|
||||||
|
const countNews = (news: string) => news.match(/^([0-9]{4}-[0-9]{2}-[0-9]{2} .+)$/gm)?.length ?? 0;
|
||||||
|
|
||||||
|
const News = ({ header, body }: { header: string; body: string }) => {
|
||||||
|
const expanded = Variable(false);
|
||||||
|
|
||||||
|
body = body
|
||||||
|
.slice(0, -5) // Remove last unopened \x1b[0m
|
||||||
|
.replaceAll("\x1b[0m", "</span>"); // Replace reset code with end span
|
||||||
|
|
||||||
|
return (
|
||||||
|
<box vertical className="article">
|
||||||
|
<button
|
||||||
|
className="wrapper"
|
||||||
|
cursor="pointer"
|
||||||
|
onClicked={() => expanded.set(!expanded.get())}
|
||||||
|
setup={self => setupCustomTooltip(self, header)}
|
||||||
|
>
|
||||||
|
<box hexpand className="header">
|
||||||
|
<label className="icon" label="newspaper" />
|
||||||
|
<box vertical>
|
||||||
|
<label xalign={0} label={header.split(" ")[0]} />
|
||||||
|
<label
|
||||||
|
truncate
|
||||||
|
xalign={0}
|
||||||
|
className="sublabel"
|
||||||
|
label={header.replace(/[0-9]{4}-[0-9]{2}-[0-9]{2} /, "")}
|
||||||
|
/>
|
||||||
|
</box>
|
||||||
|
<label className="icon" label={bind(expanded).as(e => (e ? "expand_less" : "expand_more"))} />
|
||||||
|
</box>
|
||||||
|
</button>
|
||||||
|
<revealer
|
||||||
|
revealChild={bind(expanded)}
|
||||||
|
transitionType={Gtk.RevealerTransitionType.SLIDE_DOWN}
|
||||||
|
transitionDuration={200}
|
||||||
|
>
|
||||||
|
<label
|
||||||
|
wrap
|
||||||
|
useMarkup
|
||||||
|
xalign={0}
|
||||||
|
className="body"
|
||||||
|
label={bind(Palette.get_default(), "teal").as(
|
||||||
|
c => body.replaceAll("\x1b[36m", `<span foreground="${c}">`) // Replace colour codes with html spans
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</revealer>
|
||||||
|
</box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const List = () => (
|
||||||
|
<box vertical valign={Gtk.Align.START} className="list">
|
||||||
|
{bind(Updates.get_default(), "news").as(n => {
|
||||||
|
const children = [];
|
||||||
|
const news = n.split(/^([0-9]{4}-[0-9]{2}-[0-9]{2} .+)$/gm);
|
||||||
|
for (let i = 1; i < news.length - 1; i += 2)
|
||||||
|
children.push(<News header={news[i].trim()} body={news[i + 1].trim()} />);
|
||||||
|
return children;
|
||||||
|
})}
|
||||||
|
</box>
|
||||||
|
);
|
||||||
|
|
||||||
|
const NoNews = () => (
|
||||||
|
<box homogeneous name="empty">
|
||||||
|
<box vertical halign={Gtk.Align.CENTER} valign={Gtk.Align.CENTER} className="empty">
|
||||||
|
<label className="icon" label="breaking_news_alt_1" />
|
||||||
|
<label label="No Arch news!" />
|
||||||
|
</box>
|
||||||
|
</box>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<box vertical className="news">
|
||||||
|
<box className="header-bar">
|
||||||
|
<label
|
||||||
|
label={bind(Updates.get_default(), "news")
|
||||||
|
.as(countNews)
|
||||||
|
.as(n => `${n} news article${n === 1 ? "" : "s"}`)}
|
||||||
|
/>
|
||||||
|
<box hexpand />
|
||||||
|
<button
|
||||||
|
className={bind(Updates.get_default(), "loading").as(l => (l ? "enabled" : ""))}
|
||||||
|
sensitive={bind(Updates.get_default(), "loading").as(l => !l)}
|
||||||
|
cursor="pointer"
|
||||||
|
onClicked={() => Updates.get_default().getUpdates()}
|
||||||
|
label={bind(Updates.get_default(), "loading").as(l => (l ? " Loading" : " Reload"))}
|
||||||
|
/>
|
||||||
|
</box>
|
||||||
|
<stack
|
||||||
|
transitionType={Gtk.StackTransitionType.CROSSFADE}
|
||||||
|
transitionDuration={200}
|
||||||
|
shown={bind(Updates.get_default(), "news").as(n => (n ? "list" : "empty"))}
|
||||||
|
>
|
||||||
|
<NoNews />
|
||||||
|
<scrollable
|
||||||
|
expand={bind(Updates.get_default(), "news").as(n => !!n)}
|
||||||
|
hscroll={Gtk.PolicyType.NEVER}
|
||||||
|
name="list"
|
||||||
|
>
|
||||||
|
<List />
|
||||||
|
</scrollable>
|
||||||
|
</stack>
|
||||||
|
</box>
|
||||||
|
);
|
||||||
|
|
@ -82,7 +82,7 @@ export default () => (
|
||||||
sensitive={bind(Calendar.get_default(), "loading").as(l => !l)}
|
sensitive={bind(Calendar.get_default(), "loading").as(l => !l)}
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
onClicked={() => Calendar.get_default().updateCalendars().catch(console.error)}
|
onClicked={() => Calendar.get_default().updateCalendars().catch(console.error)}
|
||||||
label=" Reload"
|
label={bind(Calendar.get_default(), "loading").as(l => (l ? " Loading" : " Reload"))}
|
||||||
/>
|
/>
|
||||||
</box>
|
</box>
|
||||||
<stack
|
<stack
|
||||||
|
|
|
||||||
9
src/modules/sidebar/packages.tsx
Normal file
9
src/modules/sidebar/packages.tsx
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
import News from "./modules/news";
|
||||||
|
import Updates from "./modules/updates";
|
||||||
|
|
||||||
|
export default () => (
|
||||||
|
<box vertical className="pane packages" name="packages">
|
||||||
|
<box className="separator" />
|
||||||
|
<News />
|
||||||
|
</box>
|
||||||
|
);
|
||||||
Loading…
Add table
Reference in a new issue