|
|
|
|
@ -1,18 +1,10 @@
@@ -1,18 +1,10 @@
|
|
|
|
|
<script lang="ts"> |
|
|
|
|
import Header from '../../lib/components/layout/Header.svelte'; |
|
|
|
|
import FeedPage from '../../lib/modules/feed/FeedPage.svelte'; |
|
|
|
|
import UnifiedSearch from '../../lib/components/layout/UnifiedSearch.svelte'; |
|
|
|
|
import FeedPost from '../../lib/modules/feed/FeedPost.svelte'; |
|
|
|
|
import ProfileBadge from '../../lib/components/layout/ProfileBadge.svelte'; |
|
|
|
|
import { nostrClient } from '../../lib/services/nostr/nostr-client.js'; |
|
|
|
|
import { KIND } from '../../lib/types/kind-lookup.js'; |
|
|
|
|
import type { NostrEvent } from '../../lib/types/nostr.js'; |
|
|
|
|
import { onMount } from 'svelte'; |
|
|
|
|
import Icon from '../../lib/components/ui/Icon.svelte'; |
|
|
|
|
|
|
|
|
|
let filterResult = $state<{ type: 'event' | 'pubkey' | 'text' | null; value: string | null }>({ type: null, value: null }); |
|
|
|
|
let searchResults = $state<{ events: NostrEvent[]; profiles: string[] }>({ events: [], profiles: [] }); |
|
|
|
|
let unifiedSearchComponent: { triggerSearch: () => void } | null = $state(null); |
|
|
|
|
let feedPageComponent: { |
|
|
|
|
loadOlderEvents: () => Promise<void>; |
|
|
|
|
loadingMore: boolean; |
|
|
|
|
@ -21,20 +13,6 @@
@@ -21,20 +13,6 @@
|
|
|
|
|
loadWaitingRoomEvents: () => void; |
|
|
|
|
} | null = $state(null); |
|
|
|
|
|
|
|
|
|
function handleFilterChange(result: { type: 'event' | 'pubkey' | 'text' | null; value: string | null }) { |
|
|
|
|
filterResult = result; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function handleSearchResults(results: { events: NostrEvent[]; profiles: string[] }) { |
|
|
|
|
searchResults = results; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function handleSearch() { |
|
|
|
|
if (unifiedSearchComponent) { |
|
|
|
|
unifiedSearchComponent.triggerSearch(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
onMount(async () => { |
|
|
|
|
await nostrClient.initialize(); |
|
|
|
|
}); |
|
|
|
|
@ -52,19 +30,8 @@
@@ -52,19 +30,8 @@
|
|
|
|
|
</a> |
|
|
|
|
</div> |
|
|
|
|
<div class="feed-controls"> |
|
|
|
|
<div class="search-section"> |
|
|
|
|
<UnifiedSearch |
|
|
|
|
mode="search" |
|
|
|
|
bind:this={unifiedSearchComponent} |
|
|
|
|
allowedKinds={[KIND.SHORT_TEXT_NOTE]} |
|
|
|
|
hideDropdownResults={true} |
|
|
|
|
onSearchResults={handleSearchResults} |
|
|
|
|
onFilterChange={handleFilterChange} |
|
|
|
|
placeholder="Search kind 1 events by pubkey, p, q tags, or content..." |
|
|
|
|
/> |
|
|
|
|
</div> |
|
|
|
|
<div class="feed-header-buttons"> |
|
|
|
|
{#if feedPageComponent && feedPageComponent.waitingRoomEvents.length > 0 && !searchResults.events.length && !searchResults.profiles.length} |
|
|
|
|
{#if feedPageComponent && feedPageComponent.waitingRoomEvents.length > 0} |
|
|
|
|
<button |
|
|
|
|
onclick={() => feedPageComponent?.loadWaitingRoomEvents()} |
|
|
|
|
class="see-new-events-btn-header" |
|
|
|
|
@ -72,7 +39,7 @@
@@ -72,7 +39,7 @@
|
|
|
|
|
See {feedPageComponent.waitingRoomEvents.length} new event{feedPageComponent.waitingRoomEvents.length === 1 ? '' : 's'} |
|
|
|
|
</button> |
|
|
|
|
{/if} |
|
|
|
|
{#if feedPageComponent && feedPageComponent.hasMoreEvents && !searchResults.events.length && !searchResults.profiles.length} |
|
|
|
|
{#if feedPageComponent && feedPageComponent.hasMoreEvents} |
|
|
|
|
<button |
|
|
|
|
onclick={() => feedPageComponent?.loadOlderEvents()} |
|
|
|
|
disabled={feedPageComponent.loadingMore || !feedPageComponent.hasMoreEvents} |
|
|
|
|
@ -85,39 +52,7 @@
@@ -85,39 +52,7 @@
|
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
|
|
|
|
|
{#if searchResults.events.length > 0 || searchResults.profiles.length > 0} |
|
|
|
|
<div class="search-results-section"> |
|
|
|
|
<h2 class="results-title">Search Results</h2> |
|
|
|
|
|
|
|
|
|
{#if searchResults.profiles.length > 0} |
|
|
|
|
<div class="results-group"> |
|
|
|
|
<h3>Profiles</h3> |
|
|
|
|
<div class="profile-results"> |
|
|
|
|
{#each searchResults.profiles as pubkey} |
|
|
|
|
<a href="/profile/{pubkey}" class="profile-result-card"> |
|
|
|
|
<ProfileBadge pubkey={pubkey} /> |
|
|
|
|
</a> |
|
|
|
|
{/each} |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
{/if} |
|
|
|
|
|
|
|
|
|
{#if searchResults.events.length > 0} |
|
|
|
|
<div class="results-group"> |
|
|
|
|
<h3>Events ({searchResults.events.length})</h3> |
|
|
|
|
<div class="event-results"> |
|
|
|
|
{#each searchResults.events as event} |
|
|
|
|
<a href="/event/{event.id}" class="event-result-card"> |
|
|
|
|
<FeedPost post={event} fullView={false} /> |
|
|
|
|
</a> |
|
|
|
|
{/each} |
|
|
|
|
</div> |
|
|
|
|
</div> |
|
|
|
|
{/if} |
|
|
|
|
</div> |
|
|
|
|
{:else} |
|
|
|
|
<FeedPage filterResult={filterResult} bind:this={feedPageComponent} /> |
|
|
|
|
{/if} |
|
|
|
|
<FeedPage bind:this={feedPageComponent} /> |
|
|
|
|
</div> |
|
|
|
|
</main> |
|
|
|
|
|
|
|
|
|
@ -161,33 +96,14 @@
@@ -161,33 +96,14 @@
|
|
|
|
|
|
|
|
|
|
.feed-controls { |
|
|
|
|
display: flex; |
|
|
|
|
justify-content: space-between; |
|
|
|
|
justify-content: flex-end; |
|
|
|
|
align-items: center; |
|
|
|
|
gap: 1rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@media (max-width: 640px) { |
|
|
|
|
.feed-controls { |
|
|
|
|
flex-direction: column; |
|
|
|
|
align-items: stretch; |
|
|
|
|
gap: 0.75rem; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.search-section { |
|
|
|
|
flex: 1; |
|
|
|
|
min-width: 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@media (max-width: 640px) { |
|
|
|
|
.search-section { |
|
|
|
|
width: 100%; |
|
|
|
|
flex: none; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.search-section :global(.unified-search-container) { |
|
|
|
|
max-width: 100%; |
|
|
|
|
width: 100%; |
|
|
|
|
justify-content: flex-start; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -266,108 +182,4 @@
@@ -266,108 +182,4 @@
|
|
|
|
|
border-color: var(--fog-dark-accent, #64748b); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.search-results-section { |
|
|
|
|
margin-top: 2rem; |
|
|
|
|
border: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
border-radius: 0.5rem; |
|
|
|
|
padding: 2rem; |
|
|
|
|
background: var(--fog-post, #ffffff); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .search-results-section { |
|
|
|
|
border-color: var(--fog-dark-border, #374151); |
|
|
|
|
background: var(--fog-dark-post, #1f2937); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.results-title { |
|
|
|
|
margin: 0 0 1.5rem 0; |
|
|
|
|
font-size: 1.25rem; |
|
|
|
|
font-weight: 600; |
|
|
|
|
color: var(--fog-text, #475569); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .results-title { |
|
|
|
|
color: var(--fog-dark-text, #cbd5e1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.results-group { |
|
|
|
|
margin-bottom: 2rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.results-group:last-child { |
|
|
|
|
margin-bottom: 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.results-group h3 { |
|
|
|
|
margin: 0 0 1rem 0; |
|
|
|
|
font-size: 1rem; |
|
|
|
|
font-weight: 500; |
|
|
|
|
color: var(--fog-text-light, #52667a); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .results-group h3 { |
|
|
|
|
color: var(--fog-dark-text-light, #a8b8d0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.profile-results { |
|
|
|
|
display: flex; |
|
|
|
|
flex-direction: column; |
|
|
|
|
gap: 1rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.profile-result-card { |
|
|
|
|
padding: 1rem; |
|
|
|
|
border: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
border-radius: 0.375rem; |
|
|
|
|
background: var(--fog-post, #ffffff); |
|
|
|
|
text-decoration: none; |
|
|
|
|
transition: all 0.2s; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .profile-result-card { |
|
|
|
|
border-color: var(--fog-dark-border, #374151); |
|
|
|
|
background: var(--fog-dark-post, #1f2937); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.profile-result-card:hover { |
|
|
|
|
border-color: var(--fog-accent, #64748b); |
|
|
|
|
transform: translateY(-1px); |
|
|
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .profile-result-card:hover { |
|
|
|
|
border-color: var(--fog-dark-accent, #94a3b8); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.event-results { |
|
|
|
|
display: flex; |
|
|
|
|
flex-direction: column; |
|
|
|
|
gap: 1rem; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.event-result-card { |
|
|
|
|
display: block; |
|
|
|
|
border: 1px solid var(--fog-border, #e5e7eb); |
|
|
|
|
border-radius: 0.375rem; |
|
|
|
|
background: var(--fog-post, #ffffff); |
|
|
|
|
overflow: hidden; |
|
|
|
|
transition: all 0.2s; |
|
|
|
|
text-decoration: none; |
|
|
|
|
color: inherit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .event-result-card { |
|
|
|
|
border-color: var(--fog-dark-border, #374151); |
|
|
|
|
background: var(--fog-dark-post, #1f2937); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
.event-result-card:hover { |
|
|
|
|
border-color: var(--fog-accent, #64748b); |
|
|
|
|
transform: translateY(-1px); |
|
|
|
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
:global(.dark) .event-result-card:hover { |
|
|
|
|
border-color: var(--fog-dark-accent, #94a3b8); |
|
|
|
|
} |
|
|
|
|
</style> |
|
|
|
|
|