You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

120 lines
3.6 KiB

<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 RelayInfo from '../../../../lib/components/relay/RelayInfo.svelte';
import { nostrClient } from '../../../../lib/services/nostr/nostr-client.js';
import { onMount } from 'svelte';
import { page } from '$app/stores';
let decodedRelay = $state<string | null>(null);
let error = $state<string | null>(null);
function decodeRelayUrl(encoded: string): string | null {
try {
// The relay parameter might be just the domain or might include protocol and port
let relayUrl = encoded.trim();
// If it already has a protocol, use it as-is
if (relayUrl.startsWith('ws://') || relayUrl.startsWith('wss://')) {
return relayUrl;
}
// Check if it's prefixed with ws- to indicate ws:// protocol
if (relayUrl.startsWith('ws-')) {
relayUrl = relayUrl.substring(3); // Remove ws- prefix
return `ws://${relayUrl}`;
}
// Validate it looks like a domain (may include port)
if (!relayUrl || relayUrl.includes('/')) {
return null;
}
// Check if port is included (format: hostname:port)
const hasPort = relayUrl.includes(':') && !relayUrl.startsWith('localhost') && !relayUrl.startsWith('127.0.0.1') && !relayUrl.startsWith('192.168.') && !relayUrl.startsWith('10.') && !relayUrl.startsWith('172.');
const portMatch = relayUrl.match(/^([^:]+):(\d+)$/);
// Construct URL (preserve ws:// for localhost/127.0.0.1/local IPs, use wss:// for others)
// Preserve port if it was in the encoded string
if (relayUrl.startsWith('localhost') || relayUrl.startsWith('127.0.0.1') || relayUrl.startsWith('192.168.') || relayUrl.startsWith('10.') || relayUrl.startsWith('172.')) {
relayUrl = `ws://${relayUrl}`;
} else {
relayUrl = `wss://${relayUrl}`;
}
return relayUrl;
} catch (e) {
console.error('Error decoding relay URL:', e);
return null;
}
}
onMount(async () => {
await nostrClient.initialize();
if ($page.params.relay) {
const decoded = decodeRelayUrl($page.params.relay);
if (decoded) {
decodedRelay = decoded;
} else {
error = 'Invalid relay domain.';
}
} else {
error = 'No relay specified.';
}
});
$effect(() => {
if ($page.params.relay) {
const decoded = decodeRelayUrl($page.params.relay);
if (decoded) {
decodedRelay = decoded;
error = null;
} else {
error = 'Invalid relay domain.';
decodedRelay = null;
}
}
});
</script>
<Header />
<main class="container mx-auto px-4 py-8">
<div class="relay-feed-content">
<div class="search-section mb-6">
<UnifiedSearch mode="search" />
</div>
{#if error}
<div class="error-state">
<p class="text-fog-text dark:text-fog-dark-text">{error}</p>
</div>
{:else if decodedRelay}
<RelayInfo relayUrl={decodedRelay} />
<FeedPage singleRelay={decodedRelay} />
{:else}
<div class="loading-state">
<p class="text-fog-text dark:text-fog-dark-text">Loading relay feed...</p>
</div>
{/if}
</div>
</main>
<style>
.relay-feed-content {
max-width: var(--content-width);
margin: 0 auto;
}
.search-section {
padding: 0 1rem;
}
.error-state,
.loading-state {
padding: 2rem;
text-align: center;
}
</style>