Merge pull request #12 from ayoayco/feat/use-cache-api
feat: save to library
This commit is contained in:
commit
6c3cff1b66
5 changed files with 106 additions and 12 deletions
|
@ -10,9 +10,9 @@ Cozy is your modern-day reading assistant.
|
|||
## Roadmap
|
||||
| Feature | Status |
|
||||
| --- | --- |
|
||||
| Remove distractions| Done |
|
||||
| Save to a Reading Library | In-Progress |
|
||||
| PWA: Offline access to library | |
|
||||
| Remove distractions| ✅ DONE |
|
||||
| Save to a Reading Library | ✅ DONE |
|
||||
| PWA: Offline access to library | 🛠️ In-progress |
|
||||
| AI insights | |
|
||||
| Browser Extensions | |
|
||||
|
||||
|
|
65
src/components/Library.astro
Normal file
65
src/components/Library.astro
Normal 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>
|
|
@ -11,7 +11,7 @@ const datePublished =
|
|||
|
||||
{
|
||||
article && (
|
||||
<div class="post">
|
||||
<div id="post">
|
||||
{article.source && <span class="source">{article.source}</span>}
|
||||
{article.title && <h1 class="title">{article.title}</h1>}
|
||||
{(article.author || datePublished) && (
|
||||
|
@ -26,11 +26,6 @@ const datePublished =
|
|||
}
|
||||
|
||||
<style is:inline>
|
||||
div.post {
|
||||
max-width: 600px;
|
||||
margin: 1em auto;
|
||||
padding: 1em;
|
||||
}
|
||||
@counter-style publish-icons {
|
||||
system: cyclic;
|
||||
symbols: "️✍️" "🗓️";
|
||||
|
|
|
@ -16,10 +16,33 @@ const { title } = Astro.props;
|
|||
<title>{appTitle} {title && `| ${title}`}</title>
|
||||
</head>
|
||||
<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>
|
||||
</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>
|
||||
:root {
|
||||
--system-ui: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
|
||||
|
|
|
@ -3,6 +3,7 @@ import { extract } from "@extractus/article-extractor";
|
|||
import AddressBar from "../components/AddressBar.astro";
|
||||
import Post from "../components/Post.astro";
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
import Library from "../components/Library.astro";
|
||||
|
||||
const params = Astro.url.searchParams;
|
||||
const url = params.get('url') || '';
|
||||
|
@ -16,8 +17,18 @@ try {
|
|||
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"}>
|
||||
<AddressBar url={url} />
|
||||
{url && <Post article={article} />}
|
||||
<AddressBar slot="address-bar" url={url} />
|
||||
<Post slot="post" article={article} />
|
||||
<Library slot="library" postDivSelector="#post" />
|
||||
</Layout>
|
||||
|
|
Loading…
Reference in a new issue