fix: mark-as-read for items from orphan channels
Items from channels with userId: null (created during earlier setup) appeared in the unified timeline but had no _channelUid, causing the mark-read JS handler to silently abort. Fall back to channelId (MongoDB ObjectId) when channelUid is unavailable, and resolve it server-side via getChannelById. Confab-Link: http://localhost:8080/sessions/4d40ef89-a713-48c1-b4ed-0ffafca25677
This commit is contained in:
@@ -6,7 +6,7 @@
|
|||||||
import { IndiekitError } from "@indiekit/error";
|
import { IndiekitError } from "@indiekit/error";
|
||||||
|
|
||||||
import { proxyItemImages } from "../media/proxy.js";
|
import { proxyItemImages } from "../media/proxy.js";
|
||||||
import { getChannel } from "../storage/channels.js";
|
import { getChannel, getChannelById } from "../storage/channels.js";
|
||||||
import {
|
import {
|
||||||
getTimelineItems,
|
getTimelineItems,
|
||||||
markItemsRead,
|
markItemsRead,
|
||||||
@@ -72,8 +72,16 @@ export async function action(request, response) {
|
|||||||
|
|
||||||
validateChannel(channel);
|
validateChannel(channel);
|
||||||
|
|
||||||
// Verify channel exists
|
// Verify channel exists — try by UID first, fall back to ObjectId
|
||||||
const channelDocument = await getChannel(application, channel, userId);
|
// (timeline view may send ObjectId string for items from orphan channels)
|
||||||
|
let channelDocument = await getChannel(application, channel, userId);
|
||||||
|
if (!channelDocument) {
|
||||||
|
try {
|
||||||
|
channelDocument = await getChannelById(application, channel);
|
||||||
|
} catch {
|
||||||
|
// Invalid ObjectId format — channel string is not a valid ObjectId
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!channelDocument) {
|
if (!channelDocument) {
|
||||||
throw new IndiekitError("Channel not found", {
|
throw new IndiekitError("Channel not found", {
|
||||||
status: 404,
|
status: 404,
|
||||||
|
|||||||
@@ -203,6 +203,7 @@
|
|||||||
data-action="mark-read"
|
data-action="mark-read"
|
||||||
data-item-id="{{ item._id }}"
|
data-item-id="{{ item._id }}"
|
||||||
{% if item._channelUid %}data-channel-uid="{{ item._channelUid }}"{% endif %}
|
{% if item._channelUid %}data-channel-uid="{{ item._channelUid }}"{% endif %}
|
||||||
|
{% if item._channelId %}data-channel-id="{{ item._channelId }}"{% endif %}
|
||||||
title="Mark as read">
|
title="Mark as read">
|
||||||
{{ icon("checkboxChecked") }}
|
{{ icon("checkboxChecked") }}
|
||||||
<span class="visually-hidden">Mark read</span>
|
<span class="visually-hidden">Mark read</span>
|
||||||
|
|||||||
+3
-2
@@ -108,7 +108,8 @@
|
|||||||
|
|
||||||
const itemId = button.dataset.itemId;
|
const itemId = button.dataset.itemId;
|
||||||
const channelUid = button.dataset.channelUid;
|
const channelUid = button.dataset.channelUid;
|
||||||
if (!itemId || !channelUid) return;
|
const channelId = button.dataset.channelId;
|
||||||
|
if (!itemId || (!channelUid && !channelId)) return;
|
||||||
|
|
||||||
button.disabled = true;
|
button.disabled = true;
|
||||||
|
|
||||||
@@ -116,7 +117,7 @@
|
|||||||
const formData = new URLSearchParams();
|
const formData = new URLSearchParams();
|
||||||
formData.append('action', 'timeline');
|
formData.append('action', 'timeline');
|
||||||
formData.append('method', 'mark_read');
|
formData.append('method', 'mark_read');
|
||||||
formData.append('channel', channelUid);
|
formData.append('channel', channelUid || channelId);
|
||||||
formData.append('entry', itemId);
|
formData.append('entry', itemId);
|
||||||
|
|
||||||
const response = await fetch(microsubApiUrl, {
|
const response = await fetch(microsubApiUrl, {
|
||||||
|
|||||||
Reference in New Issue
Block a user