Merge pull request #12 from ayoayco/feat/use-cache-api

feat: save to library
This commit is contained in:
Ayo Ayco 2023-06-04 15:48:43 +02:00 committed by GitHub
commit 6c3cff1b66
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 106 additions and 12 deletions

View file

@ -10,9 +10,9 @@ Cozy is your modern-day reading assistant.
## Roadmap ## Roadmap
| Feature | Status | | Feature | Status |
| --- | --- | | --- | --- |
| Remove distractions| Done | | Remove distractions| ✅ DONE |
| Save to a Reading Library | In-Progress | | Save to a Reading Library | ✅ DONE |
| PWA: Offline access to library | | | PWA: Offline access to library | 🛠️ In-progress |
| AI insights | | | AI insights | |
| Browser Extensions | | | Browser Extensions | |

View file

@ -0,0 +1,65 @@
---
export interface Props {
postDivSelector: string
}
const {postDivSelector} = Astro.props;
---
<div id="library">
<ul id="post-list"></ul>
</div>
<input value={postDivSelector} name="postDivSelector" id="postDivSelector" hidden />
<script>
const cache = await caches.open('cozy-reader');
const url = new URL(window.location.href);
const response = await cache.match(url)
if (!response) {
await cache.add(url);
}
const postDivSelector = document.getElementById('postDivSelector') as HTMLInputElement;
const postDiv = document.querySelector(postDivSelector?.value);
const cachedResponses = await cache.keys();
const list = document.querySelector('#post-list');
cachedResponses
.filter(request => {
const urlObj = new URL(request.url);
return urlObj.search !== '';
})
.forEach(async (request) => {
const {url} = request;
const link = document.createElement('a');
let responseText;
const fullResponse = await cache.match(url)
fullResponse?.text().then(data => {
responseText = data;
const html = document.createElement('html');
html.innerHTML = responseText;
const title = html.querySelector('title');
link.innerText = (title?.innerText || url).replace('Cozy 🧸 | ', '');
});
link.href = url;
link.onclick = async (e) => {
e.preventDefault();
const html = document.createElement('html');
html.innerHTML = responseText;
const newPost = html.querySelector('body')?.querySelector('#post');
if (postDiv && newPost?.innerHTML) {
postDiv.innerHTML = (newPost.innerHTML)
}
}
const item = document.createElement('li');
item.appendChild(link);
list?.appendChild(item);
});
</script>

View file

@ -11,7 +11,7 @@ const datePublished =
{ {
article && ( article && (
<div class="post"> <div id="post">
{article.source && <span class="source">{article.source}</span>} {article.source && <span class="source">{article.source}</span>}
{article.title && <h1 class="title">{article.title}</h1>} {article.title && <h1 class="title">{article.title}</h1>}
{(article.author || datePublished) && ( {(article.author || datePublished) && (
@ -26,11 +26,6 @@ const datePublished =
} }
<style is:inline> <style is:inline>
div.post {
max-width: 600px;
margin: 1em auto;
padding: 1em;
}
@counter-style publish-icons { @counter-style publish-icons {
system: cyclic; system: cyclic;
symbols: "️✍️" "🗓️"; symbols: "️✍️" "🗓️";

View file

@ -16,10 +16,33 @@ const { title } = Astro.props;
<title>{appTitle} {title && `| ${title}`}</title> <title>{appTitle} {title && `| ${title}`}</title>
</head> </head>
<body> <body>
<slot /> <slot name="address-bar" />
<div id="main-content">
<div id="post-wrapper">
<slot name="post" />
</div>
<div id="library-wrapper">
<slot name="library" />
</div>
</div>
</body> </body>
</html> </html>
<style>
#main-content {
display: flex;
padding: 1em;
max-width: 1000px;
margin: 0 auto;
}
#post-wrapper, #library-wrapper {
flex: 1
}
#post-wrapper {
flex-grow: 2;
}
</style>
<style is:global> <style is:global>
:root { :root {
--system-ui: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, --system-ui: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,

View file

@ -3,6 +3,7 @@ import { extract } from "@extractus/article-extractor";
import AddressBar from "../components/AddressBar.astro"; import AddressBar from "../components/AddressBar.astro";
import Post from "../components/Post.astro"; import Post from "../components/Post.astro";
import Layout from "../layouts/Layout.astro"; import Layout from "../layouts/Layout.astro";
import Library from "../components/Library.astro";
const params = Astro.url.searchParams; const params = Astro.url.searchParams;
const url = params.get('url') || ''; const url = params.get('url') || '';
@ -16,8 +17,18 @@ try {
content: "<p>The article extractor did not get any result.</p>", content: "<p>The article extractor did not get any result.</p>",
}; };
} }
if (url === '') {
article = {
title: "Welcome to Cozy 🧸",
author: "Ayo Ayco",
content: "<p>Enter a URL in the address bar above to get started.</p>",
};
}
--- ---
<Layout title={url !== "" ? article?.title : "Your modern-day reading assistant"}> <Layout title={url !== "" ? article?.title : "Your modern-day reading assistant"}>
<AddressBar url={url} /> <AddressBar slot="address-bar" url={url} />
{url && <Post article={article} />} <Post slot="post" article={article} />
<Library slot="library" postDivSelector="#post" />
</Layout> </Layout>