- merge.py: keep private activities in _merged/index.json instead of
stripping them; privacy filtering is now done client-side
- ActivityFeed: detect logged-in user via bincio:me event; show private
activities only when viewing your own profile; private cards get a lock
badge
This commit is contained in:
@@ -43,8 +43,20 @@
|
||||
let loading = true;
|
||||
let error = '';
|
||||
let mounted = false;
|
||||
/** Logged-in handle — resolved async via bincio:me event. */
|
||||
let me: string = '';
|
||||
|
||||
$: filtered = sport === 'all' ? all : all.filter(a => a.sport === sport);
|
||||
// Show private activities only to their owner.
|
||||
// On a profile page (filterHandle set): show private if me === filterHandle.
|
||||
// On the global feed: show private only for the logged-in user's own activities.
|
||||
$: isOwner = filterHandle !== '' && me === filterHandle;
|
||||
$: withPrivacy = all.filter(a => {
|
||||
if (a.privacy === 'private') {
|
||||
return filterHandle ? isOwner : (me !== '' && (a as any).handle === me);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
$: filtered = sport === 'all' ? withPrivacy : withPrivacy.filter(a => a.sport === sport);
|
||||
$: visible = filtered.slice(0, shown);
|
||||
$: hasMore = shown < filtered.length;
|
||||
|
||||
@@ -60,18 +72,26 @@
|
||||
onMount(async () => {
|
||||
sport = (new URLSearchParams(window.location.search).get('sport') as Sport | 'all') ?? 'all';
|
||||
mounted = true;
|
||||
|
||||
// Resolve the logged-in handle so we can show the owner their private activities.
|
||||
if ((window as any).__bincioMe !== undefined) {
|
||||
me = (window as any).__bincioMe;
|
||||
} else {
|
||||
window.addEventListener('bincio:me', (e: Event) => { me = (e as CustomEvent).detail; }, { once: true });
|
||||
}
|
||||
|
||||
try {
|
||||
const indexUrl = profileIndexUrl
|
||||
? `${base}data/${profileIndexUrl}`
|
||||
: `${base}data/index.json`;
|
||||
const index = await loadIndex(base, indexUrl);
|
||||
let activities = index.activities.filter(a => a.privacy !== 'private');
|
||||
let activities = index.activities;
|
||||
// filterHandle only applies when loading the root manifest (multi-user feed).
|
||||
// When profileIndexUrl is set we already loaded the right user's shard directly —
|
||||
// activities from a direct shard fetch have no handle tag, so the filter would
|
||||
// remove everything.
|
||||
if (filterHandle && !profileIndexUrl) {
|
||||
activities = activities.filter(a => a.handle === filterHandle);
|
||||
activities = activities.filter(a => (a as any).handle === filterHandle);
|
||||
}
|
||||
all = activities;
|
||||
} catch (e: any) {
|
||||
@@ -140,10 +160,13 @@
|
||||
>@{a.handle}</a>{/if}
|
||||
</p>
|
||||
<!-- stretched link covers the whole card; sits below the handle link -->
|
||||
<h3 class="font-semibold text-white truncate group-hover:text-[--accent] transition-colors">
|
||||
<h3 class="font-semibold text-white truncate group-hover:text-[--accent] transition-colors flex items-center gap-1.5">
|
||||
{#if a.privacy === 'private'}
|
||||
<span class="text-zinc-500 shrink-0" title="Private">🔒</span>
|
||||
{/if}
|
||||
<a
|
||||
href={a.detail_url ? `${import.meta.env.BASE_URL}activity/${a.id}/` : `${import.meta.env.BASE_URL}activity/local/?id=${a.id}`}
|
||||
class="before:absolute before:inset-0 before:content-['']"
|
||||
class="before:absolute before:inset-0 before:content-[''] truncate"
|
||||
>{a.title}</a>
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user