From 5b221fb72d6b915a56df4c17ecc747bb6f15dee8 Mon Sep 17 00:00:00 2001 From: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com> Date: Wed, 9 Apr 2025 14:21:50 +1000 Subject: feat: news headlines for alerts pane Also handle news api errors Also config num pages --- scss/sidebar.scss | 70 +++++++++++- src/config/defaults.ts | 1 + src/config/types.ts | 1 + src/modules/sidebar/alerts.tsx | 3 + src/modules/sidebar/modules/headlines.tsx | 172 ++++++++++++++++++++++++++++++ src/modules/sidebar/modules/news.tsx | 2 +- src/services/news.ts | 35 ++++-- 7 files changed, 275 insertions(+), 9 deletions(-) create mode 100644 src/modules/sidebar/modules/headlines.tsx diff --git a/scss/sidebar.scss b/scss/sidebar.scss index 9f5bd39..1fea682 100644 --- a/scss/sidebar.scss +++ b/scss/sidebar.scss @@ -752,7 +752,7 @@ min-height: lib.s(200); .expanded { - min-height: lib.s(400); + min-height: lib.s(500); } .empty { @@ -792,6 +792,74 @@ } } + .headlines { + min-height: lib.s(200); + + .expanded { + min-height: lib.s(500); + } + + .empty { + margin-top: lib.s(40); + } + + .list { + @include lib.spacing(10, true); + } + + .category { + @include lib.rounded(20); + @include lib.element-decel; + + background-color: color.change(scheme.$surface0, $alpha: 0.5); + 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); + + @include lib.spacing(8, true); + } + } + + .article { + @include lib.rounded(20); + @include lib.element-decel; + + background-color: color.change(scheme.$surface1, $alpha: 0.3); + padding: lib.s(10) lib.s(15); + + .article-body { + @include font.reading; + @include lib.element-decel; + + font-size: lib.s(15); + margin-top: lib.s(10); + color: scheme.$subtext1; + } + + button:hover .article-body, + button:focus .article-body { + color: color.mix(scheme.$subtext0, scheme.$blue, 60%); + } + } + } + .time-date { padding: lib.s(12) lib.s(8); font-size: lib.s(48); diff --git a/src/config/defaults.ts b/src/config/defaults.ts index d5db290..70a4700 100644 --- a/src/config/defaults.ts +++ b/src/config/defaults.ts @@ -171,5 +171,6 @@ export default { languages: ["en"], // A list of languages codes to filter by domains: [] as string[], // A list of news domains to pull from timezone: "", // A timezone to filter by, e.g. "America/New_York" + pages: 3, // Number of pages to pull (each page is 10 articles) }, }; diff --git a/src/config/types.ts b/src/config/types.ts index 2862612..0e9138d 100644 --- a/src/config/types.ts +++ b/src/config/types.ts @@ -100,4 +100,5 @@ export default { "news.languages": ARR(STR), "news.domains": ARR(STR), "news.timezone": STR, + "news.pages": NUM, } as { [k: string]: string | string[] | number[] }; diff --git a/src/modules/sidebar/alerts.tsx b/src/modules/sidebar/alerts.tsx index 3dd4b5a..b669514 100644 --- a/src/modules/sidebar/alerts.tsx +++ b/src/modules/sidebar/alerts.tsx @@ -1,7 +1,10 @@ +import Headlines from "./modules/headlines"; import Notifications from "./modules/notifications"; export default () => ( + + ); diff --git a/src/modules/sidebar/modules/headlines.tsx b/src/modules/sidebar/modules/headlines.tsx new file mode 100644 index 0000000..924e5b8 --- /dev/null +++ b/src/modules/sidebar/modules/headlines.tsx @@ -0,0 +1,172 @@ +import News, { type IArticle } from "@/services/news"; +import Palette, { type IPalette } from "@/services/palette"; +import { capitalize } from "@/utils/strings"; +import { setupCustomTooltip } from "@/utils/widgets"; +import { bind, execAsync, Variable } from "astal"; +import { Gtk } from "astal/gtk3"; + +const fixGoogleNews = (colours: IPalette, title: string, desc: string) => { + // Add separator, bold and split at domain (domain is at the end of each headline) + const domain = title.split(" - ").at(-1); + if (domain) desc = desc.replaceAll(domain, `— ${domain}\n\n`); + // Add spaces between sentences + desc = desc.replace(/\.([A-Z])/g, ". $1"); + // Split headlines + desc = desc.replace(/(( |\.)[^A-Z][a-z]+)([A-Z])/g, "$1\n\n$3"); + desc = desc.replace(/( [A-Z]+)([A-Z](?![s])[a-z])/g, "$1\n\n$2"); + // Add separator and bold domains + desc = desc.replace(/ ([a-zA-Z.]+)\n\n/g, ` — $1\n\n`); + desc = desc.replace(/ ([a-zA-Z.]+)$/, ` — $1`); // Last domain + return desc.trim(); +}; + +const getCategoryIcon = (category: string) => { + if (category === "business") return "monitoring"; + if (category === "crime") return "speed_camera"; + if (category === "domestic") return "home"; + if (category === "education") return "school"; + if (category === "entertainment") return "tv"; + if (category === "environment") return "eco"; + if (category === "food") return "restaurant"; + if (category === "health") return "health_and_safety"; + if (category === "lifestyle") return "digital_wellbeing"; + if (category === "politics") return "account_balance"; + if (category === "science") return "science"; + if (category === "sports") return "sports_basketball"; + if (category === "technology") return "account_tree"; + if (category === "top") return "breaking_news"; + if (category === "tourism") return "travel"; + if (category === "world") return "public"; + return "newsmode"; +}; + +const Article = ({ title, description, creator, pubDate, source_name, link }: IArticle) => { + const expanded = Variable(false); + + return ( + + + + + + + ); +}; + +const Category = ({ title, articles }: { title: string; articles: IArticle[] }) => { + const expanded = Variable(false); + + return ( + + + + + {articles.map(a => ( +
+ ))} + + + + ); +}; + +const List = () => ( + + {bind(News.get_default(), "categories").as(c => + Object.entries(c).map(([k, v]) => ) + )} + +); + +const NoNews = () => ( + + + + +); + +export default () => ( + + +