feat: add save-for-later button to microsub reader

Adds a save icon to the item-card action bar that POSTs to
/readlater/save when the readlater plugin is installed. Button
only renders if application.readlaterEndpoint is set. Includes
JS handlers in both channel and timeline views.
This commit is contained in:
Ricardo
2026-02-27 16:01:47 +01:00
parent d09b293e76
commit 0c1420c1ed
5 changed files with 84 additions and 1 deletions
+6
View File
@@ -421,6 +421,12 @@
margin-left: auto;
}
/* Save for later button */
.item-actions__save-later--saved {
color: var(--color-accent, #4a9eff);
opacity: 0.6;
}
/* ==========================================================================
Single Item View
========================================================================== */
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@rmdes/indiekit-endpoint-microsub",
"version": "1.0.40",
"version": "1.0.41",
"description": "Microsub endpoint for Indiekit. Enables subscribing to feeds and reading content using the Microsub protocol.",
"keywords": [
"indiekit",
+33
View File
@@ -173,6 +173,39 @@
button.disabled = false;
}
});
// Handle save-for-later buttons
timeline.addEventListener('click', async (e) => {
const button = e.target.closest('.item-actions__save-later');
if (!button) return;
e.preventDefault();
e.stopPropagation();
const url = button.dataset.url;
const title = button.dataset.title;
if (!url) return;
button.disabled = true;
try {
const response = await fetch('/readlater/save', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url, title: title || url, source: 'microsub' }),
credentials: 'same-origin'
});
if (response.ok) {
button.classList.add('item-actions__save-later--saved');
button.title = 'Saved';
} else {
button.disabled = false;
}
} catch {
button.disabled = false;
}
});
}
</script>
{% endblock %}
+11
View File
@@ -208,5 +208,16 @@
<span class="visually-hidden">Mark read</span>
</button>
{% endif %}
{% if application.readlaterEndpoint %}
<button type="button"
class="item-actions__button item-actions__save-later"
data-action="save-later"
data-url="{{ item.url }}"
data-title="{{ item.name or '' }}"
title="Save for later">
{{ icon("bookmark") }}
<span class="visually-hidden">Save for later</span>
</button>
{% endif %}
</div>
</article>
+33
View File
@@ -150,6 +150,39 @@
button.disabled = false;
}
});
// Handle save-for-later buttons
timeline.addEventListener('click', async (e) => {
const button = e.target.closest('.item-actions__save-later');
if (!button) return;
e.preventDefault();
e.stopPropagation();
const url = button.dataset.url;
const title = button.dataset.title;
if (!url) return;
button.disabled = true;
try {
const response = await fetch('/readlater/save', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ url, title: title || url, source: 'microsub' }),
credentials: 'same-origin'
});
if (response.ok) {
button.classList.add('item-actions__save-later--saved');
button.title = 'Saved';
} else {
button.disabled = false;
}
} catch {
button.disabled = false;
}
});
}
</script>
{% endblock %}