Browse Source

Added a checkbox to the landing page, so that the currently logged-in user can easily find their own publications, both as "p" tag and as "pubkey".

master
silberengel 7 months ago
parent
commit
74598a1d3c
  1. 112
      src/lib/components/publications/PublicationFeed.svelte
  2. 22
      src/routes/+page.svelte

112
src/lib/components/publications/PublicationFeed.svelte

@ -13,9 +13,11 @@
import { searchCache } from "$lib/utils/searchCache"; import { searchCache } from "$lib/utils/searchCache";
import { indexEventCache } from "$lib/utils/indexEventCache"; import { indexEventCache } from "$lib/utils/indexEventCache";
import { isValidNip05Address } from "$lib/utils/search_utility"; import { isValidNip05Address } from "$lib/utils/search_utility";
import { userStore } from "$lib/stores/userStore.ts";
const props = $props<{ const props = $props<{
searchQuery?: string; searchQuery?: string;
showOnlyMyPublications?: boolean;
onEventCountUpdate?: (counts: { displayed: number; total: number }) => void; onEventCountUpdate?: (counts: { displayed: number; total: number }) => void;
}>(); }>();
@ -55,9 +57,16 @@
// Update the view immediately when column count changes // Update the view immediately when column count changes
if (allIndexEvents.length > 0) { if (allIndexEvents.length > 0) {
const source = props.searchQuery?.trim() let source = allIndexEvents;
? filterEventsBySearch(allIndexEvents)
: allIndexEvents; // Apply user filter first
source = filterEventsByUser(source);
// Then apply search filter if query exists
if (props.searchQuery?.trim()) {
source = filterEventsBySearch(source);
}
eventsInView = source.slice(0, publicationsToDisplay); eventsInView = source.slice(0, publicationsToDisplay);
endOfFeed = eventsInView.length >= source.length; endOfFeed = eventsInView.length >= source.length;
} }
@ -282,6 +291,47 @@
loading = false; loading = false;
} }
// Function to filter events by current user's pubkey
const filterEventsByUser = (events: NDKEvent[]) => {
if (!props.showOnlyMyPublications) return events;
const currentUser = $userStore;
if (!currentUser.signedIn || !currentUser.pubkey) {
console.debug("[PublicationFeed] User not signed in or no pubkey, showing all events");
return events;
}
const userPubkey = currentUser.pubkey.toLowerCase();
console.debug("[PublicationFeed] Filtering events for user:", userPubkey);
const filtered = events.filter((event) => {
// Check if user is the author of the event
const eventPubkey = event.pubkey.toLowerCase();
const isAuthor = eventPubkey === userPubkey;
// Check if user is listed in "p" tags (participants/contributors)
const pTags = getMatchingTags(event, "p");
const isInPTags = pTags.some(tag => tag[1]?.toLowerCase() === userPubkey);
const matches = isAuthor || isInPTags;
if (matches) {
console.debug("[PublicationFeed] Event matches user filter:", {
id: event.id,
eventPubkey,
userPubkey,
isAuthor,
isInPTags,
pTags: pTags.map(tag => tag[1])
});
}
return matches;
});
console.debug("[PublicationFeed] Events after user filtering:", filtered.length);
return filtered;
};
// Function to filter events based on search query // Function to filter events based on search query
const filterEventsBySearch = (events: NDKEvent[]) => { const filterEventsBySearch = (events: NDKEvent[]) => {
if (!props.searchQuery) return events; if (!props.searchQuery) return events;
@ -364,21 +414,37 @@
// Debounced search function // Debounced search function
const debouncedSearch = debounceAsync(async (query: string) => { const debouncedSearch = debounceAsync(async (query: string) => {
console.debug("[PublicationFeed] Search query changed:", query); console.debug("[PublicationFeed] Search query or user filter changed:", query);
let filtered = allIndexEvents;
// Apply user filter first
filtered = filterEventsByUser(filtered);
// Then apply search filter if query exists
if (query && query.trim()) { if (query && query.trim()) {
const filtered = filterEventsBySearch(allIndexEvents); filtered = filterEventsBySearch(filtered);
eventsInView = filtered.slice(0, publicationsToDisplay);
endOfFeed = filtered.length <= publicationsToDisplay;
} else {
eventsInView = allIndexEvents.slice(0, publicationsToDisplay);
endOfFeed = allIndexEvents.length <= publicationsToDisplay;
} }
eventsInView = filtered.slice(0, publicationsToDisplay);
endOfFeed = filtered.length <= publicationsToDisplay;
}, 300); }, 300);
// AI-NOTE: Watch for changes in search query and user filter
$effect(() => { $effect(() => {
// Trigger search when either search query or user filter changes
// Also watch for changes in user store to update filter when user logs in/out
debouncedSearch(props.searchQuery); debouncedSearch(props.searchQuery);
}); });
// AI-NOTE: Watch for changes in the user filter checkbox
$effect(() => {
// Trigger filtering when the user filter checkbox changes
// Access both props to ensure the effect runs when either changes
const searchQuery = props.searchQuery;
const showOnlyMyPublications = props.showOnlyMyPublications;
debouncedSearch(searchQuery);
});
// Emit event count updates // Emit event count updates
$effect(() => { $effect(() => {
if (props.onEventCountUpdate) { if (props.onEventCountUpdate) {
@ -392,9 +458,16 @@
async function loadMorePublications() { async function loadMorePublications() {
loadingMore = true; loadingMore = true;
const current = eventsInView.length; const current = eventsInView.length;
let source = props.searchQuery.trim() let source = allIndexEvents;
? filterEventsBySearch(allIndexEvents)
: allIndexEvents; // Apply user filter first
source = filterEventsByUser(source);
// Then apply search filter if query exists
if (props.searchQuery.trim()) {
source = filterEventsBySearch(source);
}
eventsInView = source.slice(0, current + publicationsToDisplay); eventsInView = source.slice(0, current + publicationsToDisplay);
endOfFeed = eventsInView.length >= source.length; endOfFeed = eventsInView.length >= source.length;
loadingMore = false; loadingMore = false;
@ -448,9 +521,16 @@
// Update the view immediately when column count changes // Update the view immediately when column count changes
if (allIndexEvents.length > 0) { if (allIndexEvents.length > 0) {
const source = props.searchQuery?.trim() let source = allIndexEvents;
? filterEventsBySearch(allIndexEvents)
: allIndexEvents; // Apply user filter first
source = filterEventsByUser(source);
// Then apply search filter if query exists
if (props.searchQuery?.trim()) {
source = filterEventsBySearch(source);
}
eventsInView = source.slice(0, publicationsToDisplay); eventsInView = source.slice(0, publicationsToDisplay);
endOfFeed = eventsInView.length >= source.length; endOfFeed = eventsInView.length >= source.length;
} }

22
src/routes/+page.svelte

@ -1,8 +1,10 @@
<script lang="ts"> <script lang="ts">
import { Input } from "flowbite-svelte"; import { Input, Checkbox } from "flowbite-svelte";
import PublicationFeed from "$lib/components/publications/PublicationFeed.svelte"; import PublicationFeed from "$lib/components/publications/PublicationFeed.svelte";
import { userStore } from "$lib/stores/userStore.ts";
let searchQuery = $state(""); let searchQuery = $state("");
let showOnlyMyPublications = $state(false);
let eventCount = $state({ displayed: 0, total: 0 }); let eventCount = $state({ displayed: 0, total: 0 });
function handleEventCountUpdate(counts: { displayed: number; total: number }) { function handleEventCountUpdate(counts: { displayed: number; total: number }) {
@ -22,13 +24,27 @@
</div> </div>
{#if eventCount.total > 0} {#if eventCount.total > 0}
<div class="text-center text-sm text-gray-600 dark:text-gray-400"> <div class="flex items-center justify-center gap-4 text-sm text-gray-600 dark:text-gray-400">
Showing {eventCount.displayed} of {eventCount.total} events. <span>Showing {eventCount.displayed} of {eventCount.total} events.</span>
<!-- AI-NOTE: Show filter checkbox only when user is logged in -->
{#if $userStore.signedIn}
<div class="flex items-center gap-2">
<Checkbox
bind:checked={showOnlyMyPublications}
id="show-my-publications"
/>
<label for="show-my-publications" class="text-sm cursor-pointer">
Show only my publications
</label>
</div>
{/if}
</div> </div>
{/if} {/if}
<PublicationFeed <PublicationFeed
{searchQuery} {searchQuery}
{showOnlyMyPublications}
onEventCountUpdate={handleEventCountUpdate} onEventCountUpdate={handleEventCountUpdate}
/> />
</main> </main>

Loading…
Cancel
Save