--- /dev/null
+<!doctype html>
+<html>
+ <head>
+ <title>News River</title>
+ <meta charset="utf-8">
+ <link rel="stylesheet" href="style.css">
+ <script src="https://unpkg.com/htmx.org@1.7.0"></script>
+ <base target="_blank">
+ </head>
+ <body class="app">
+ <div id="feed-pane" valign="top" hx-get="/feeds" hx-trigger="load, newFeed from:body, every 900s" hx-target="#feed-list">
+ <h1>Feed List</h1>
+ <div id="feed-list"></div>
+ <div id="add-feed">
+ <form hx-post="/feeds">
+ <input type="url" name="link" placeholder="Link to RSS Feed">
+ <button type="submit" class="btn">Add</button>
+ </form>
+ </div>
+ </div>
+ <div id="list-pane"></div>
+ <div id="reading-pane"></div>
+ <div id="status-bar">
+ A project by <a href="https://xangelo.ca">xangelo</a> that is still in active <a href="https://git.xangelo.ca/?p=rss-reader.git;a=summary">development</a> (2022)
+ </div>
+ </body>
+ <script>
+ function $(sel, root, opts) {
+ const el = (root || document).querySelectorAll(sel);
+ if(opts && opts.array) {
+ return Array.from(el);
+ }
+ if(el.length === 1) {
+ return el[0];
+ }
+ else {
+ return Array.from(el);
+ }
+ }
+
+function activeMarker(e) {
+ // clear sibling active class.
+ if(e.target.parentElement.tagName === 'LI') {
+ const parent = e.target.parentElement.parentElement;
+ $('a.active', parent, {array: true}).forEach(el => {
+ el.classList.remove('active');
+ });
+ }
+
+ e.target.classList.add('active');
+}
+
+ $('body').addEventListener('click', e => {
+ const actions = e.target.getAttribute('data-actions');
+ if(actions && actions.split(' ').includes('activate')) {
+ activeMarker(e);
+ }
+ if (e.target.classList.contains('unread') && e.target.getAttribute('data-feed-item-id') !== null) {
+ e.target.classList.remove('unread');
+ // ok it was unread.. so we should figure out the id that it belongs
+ // to and decr the counter for that!
+ const feedId = e.target.getAttribute('data-feed-id');
+ const el = $(`#feed-list a[data-feed-id="${feedId}"] .unread-count`);
+ if(el) {
+ if(el.innerHTML.length) {
+ let count = parseInt(el.innerHTML.split('(')[1].split(')')[0]);
+ count--;
+ if(count < 1) {
+ el.innerHTML = '';
+ el.parentElement.classList.remove('unread');
+ }
+ else {
+ el.innerHTML = `(${count})`;
+ }
+ }
+ }
+ }
+ });
+ </script>
+</html>
apiWrapper('delete', endpoint, fn, view);
}
+apiPost('/login', async (req, res): Promise<any> => {
+});
+
apiPost('/feeds', async (req, res): Promise<any> => {
// get info about the feed
const url = req.body.link;
<ul class="scrollable list" id="feed-item-list">
${feedData.items.map((item: any, index: number) => {
const read = !!item.read_at;
+ const first = index === 0;
return `<li>
- <a href="#" class="${index === 0 ? 'active': ''} ${read ? '': 'unread'}" data-actions="activate" hx-get="/feeds/${item.feed_id}/items/${item.id}" hx-trigger="${index === 0 ? 'load,': ''}click" hx-target="#reading-pane" data-feed-item-id="${item.id}" data-feed-id="${item.feed_id}">${item.title}
+ <a href="#" class="${first ? 'active': ''} ${read ? '': 'unread'}" data-actions="activate" hx-get="/feeds/${item.feed_id}/items/${item.id}" hx-trigger="click" hx-target="#reading-pane" data-feed-item-id="${item.id}" data-feed-id="${item.feed_id}">${item.title}
<span class="date">${reasonable(new Date(item.pub_date * 1000))}</span>
</a>
</li>