Re-work relays page
This commit is contained in:
+10
-6
@@ -51,16 +51,20 @@
|
|||||||
--secondary: oklch(var(--s));
|
--secondary: oklch(var(--s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.bg-alt, .bg-alt .bg-alt .bg-alt {
|
||||||
|
@apply bg-base-100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bg-alt .bg-alt, .bg-alt .bg-alt .bg-alt .bg-alt {
|
||||||
|
@apply bg-base-300;
|
||||||
|
}
|
||||||
|
|
||||||
.card2 {
|
.card2 {
|
||||||
@apply text-ellipsis rounded-box bg-base-100 p-6 text-base-content;
|
@apply text-ellipsis rounded-box p-6 text-base-content;
|
||||||
}
|
}
|
||||||
|
|
||||||
.card2.card2-sm {
|
.card2.card2-sm {
|
||||||
@apply rounded-box bg-base-100 p-4 text-base-content;
|
@apply p-4 text-base-content;
|
||||||
}
|
|
||||||
|
|
||||||
.card2.card2-alt {
|
|
||||||
@apply bg-base-300;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.column {
|
.column {
|
||||||
|
|||||||
+16
-2
@@ -1,5 +1,5 @@
|
|||||||
import {uniqBy, sleep, chunk, equals, choice} from "@welshman/lib"
|
import {uniqBy, sleep, chunk, equals, choice, append} from "@welshman/lib"
|
||||||
import {DELETE, REACTION, getPubkeyTagValues, createEvent, displayProfile} from "@welshman/util"
|
import {DELETE, MUTES, FOLLOWS, REACTION, getPubkeyTagValues, createEvent, displayProfile} from "@welshman/util"
|
||||||
import type {TrustedEvent} from "@welshman/util"
|
import type {TrustedEvent} from "@welshman/util"
|
||||||
import type {SubscribeRequestWithHandlers} from "@welshman/net"
|
import type {SubscribeRequestWithHandlers} from "@welshman/net"
|
||||||
import {
|
import {
|
||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
loadMutes,
|
loadMutes,
|
||||||
getFollows,
|
getFollows,
|
||||||
tagEvent,
|
tagEvent,
|
||||||
|
tagPubkey,
|
||||||
tagReactionTo,
|
tagReactionTo,
|
||||||
} from "@welshman/app"
|
} from "@welshman/app"
|
||||||
import {tagRoom, MEMBERSHIPS, INDEXER_RELAYS} from "@app/state"
|
import {tagRoom, MEMBERSHIPS, INDEXER_RELAYS} from "@app/state"
|
||||||
@@ -110,6 +111,19 @@ export const removeSpaceMembership = (url: string) =>
|
|||||||
export const removeRoomMembership = (url: string, room: string) =>
|
export const removeRoomMembership = (url: string, room: string) =>
|
||||||
updateList(MEMBERSHIPS, (tags: string[][]) => tags.filter(t => !equals(tagRoom(room, url), t)))
|
updateList(MEMBERSHIPS, (tags: string[][]) => tags.filter(t => !equals(tagRoom(room, url), t)))
|
||||||
|
|
||||||
|
|
||||||
|
export const unfollowPerson = (pubkey: string) =>
|
||||||
|
updateList(FOLLOWS, tags => tags.filter(t => t[1] !== pubkey))
|
||||||
|
|
||||||
|
export const followPerson = (pubkey: string) =>
|
||||||
|
updateList(FOLLOWS, tags => append(tagPubkey(pubkey), tags))
|
||||||
|
|
||||||
|
export const unmutePerson = (pubkey: string) =>
|
||||||
|
updateList(MUTES, tags => tags.filter(t => t[1] !== pubkey))
|
||||||
|
|
||||||
|
export const mutePerson = (pubkey: string) =>
|
||||||
|
updateList(MUTES, tags => append(tagPubkey(pubkey), tags))
|
||||||
|
|
||||||
// Actions
|
// Actions
|
||||||
|
|
||||||
export const publishReaction = ({relays, event, content, tags = []}: {
|
export const publishReaction = ({relays, event, content, tags = []}: {
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {onMount} from 'svelte'
|
|
||||||
import {getAddress, Address} from "@welshman/util"
|
import {getAddress, Address} from "@welshman/util"
|
||||||
import Spinner from "@lib/components/Spinner.svelte"
|
import Spinner from "@lib/components/Spinner.svelte"
|
||||||
import NoteCard from "@app/components/NoteCard.svelte"
|
import NoteCard from "@app/components/NoteCard.svelte"
|
||||||
@@ -13,25 +12,18 @@
|
|||||||
const event = deriveEvent(idOrAddress, relays)
|
const event = deriveEvent(idOrAddress, relays)
|
||||||
|
|
||||||
let element: Element
|
let element: Element
|
||||||
let bgClass = "bg-base-300"
|
|
||||||
|
|
||||||
$: address = $event ? getAddress($event) : ""
|
$: address = $event ? getAddress($event) : ""
|
||||||
$: isGroup = address.match(/^(34550|35834):/)
|
$: isGroup = address.match(/^(34550|35834):/)
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
if (element.closest('.bg-base-300')) {
|
|
||||||
bgClass = 'bg-base-100'
|
|
||||||
}
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<button class="block text-left my-2 max-w-full" bind:this={element} on:click|stopPropagation>
|
<button class="block text-left my-2 max-w-full" bind:this={element} on:click|stopPropagation>
|
||||||
{#if $event}
|
{#if $event}
|
||||||
<NoteCard event={$event} class="p-4 rounded-box {bgClass}">
|
<NoteCard event={$event} class="p-4 rounded-box bg-alt">
|
||||||
<slot name="note-content" event={$event} {depth} />
|
<slot name="note-content" event={$event} {depth} />
|
||||||
</NoteCard>
|
</NoteCard>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="p-4 rounded-box {bgClass}">
|
<div class="p-4 rounded-box">
|
||||||
<Spinner loading>Loading event...</Spinner>
|
<Spinner loading>Loading event...</Spinner>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {onMount} from 'svelte'
|
||||||
|
import type {Readable} from 'svelte/store'
|
||||||
|
import {relaySearch} from "@welshman/app"
|
||||||
|
import {createScroller} from "@lib/html"
|
||||||
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
|
import Button from "@lib/components/Button.svelte"
|
||||||
|
import RelayItem from "@app/components/RelayItem.svelte"
|
||||||
|
import {discoverRelays} from "@app/state"
|
||||||
|
|
||||||
|
export let mode: string
|
||||||
|
export let relays: Readable<string[]>
|
||||||
|
|
||||||
|
const addRelay = (url: string) => null
|
||||||
|
|
||||||
|
let term = ""
|
||||||
|
let limit = 20
|
||||||
|
let element: Element
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
const sub = discoverRelays()
|
||||||
|
const scroller = createScroller({
|
||||||
|
delay: 300,
|
||||||
|
element: element.closest('.modal-box')!,
|
||||||
|
onScroll: () => {
|
||||||
|
limit += 20
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
sub.close()
|
||||||
|
scroller.stop()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="column gap-2" bind:this={element}>
|
||||||
|
<label class="input input-bordered flex w-full items-center gap-2">
|
||||||
|
<Icon icon="magnifer" />
|
||||||
|
<input bind:value={term} class="grow" type="text" placeholder="Search for relays..." />
|
||||||
|
</label>
|
||||||
|
{#each $relaySearch.searchValues(term).filter(url => !$relays.includes(url)).slice(0, limit) as url (url)}
|
||||||
|
<RelayItem {url}>
|
||||||
|
<Button class="btn btn-outline btn-sm flex items-center" on:click={() => addRelay(url)}>
|
||||||
|
<Icon icon="add-circle" />
|
||||||
|
Add Relay
|
||||||
|
</Button>
|
||||||
|
</RelayItem>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
|
import Link from "@lib/components/Link.svelte"
|
||||||
|
import {displayUrl} from '@welshman/lib'
|
||||||
|
import {displayRelayUrl} from '@welshman/util'
|
||||||
|
import {deriveRelay} from '@welshman/app'
|
||||||
|
|
||||||
|
export let url
|
||||||
|
|
||||||
|
const relay = deriveRelay(url)
|
||||||
|
|
||||||
|
$: connections = $relay?.stats?.connect_count || 0
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="card2 card2-sm bg-alt column gap-2">
|
||||||
|
<div class="flex items-center justify-between">
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<Icon icon="remote-controller-minimalistic" />
|
||||||
|
{displayRelayUrl(url)}
|
||||||
|
</div>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
{#if $relay?.profile?.description}
|
||||||
|
<p>{$relay?.profile.description}</p>
|
||||||
|
{/if}
|
||||||
|
<span class="flex items-center gap-1 text-sm">
|
||||||
|
{#if $relay?.profile?.contact}
|
||||||
|
<Link external class="underline" href={$relay.profile.contact}
|
||||||
|
>{displayUrl($relay.profile.contact)}</Link>
|
||||||
|
•
|
||||||
|
{/if}
|
||||||
|
{#if $relay?.profile?.supported_nips}
|
||||||
|
<span class="cursor-pointer underline tooltip" data-tip="NIPs supported: {$relay.profile.supported_nips.join(", ")}">
|
||||||
|
{$relay.profile.supported_nips.length} NIPs
|
||||||
|
</span>
|
||||||
|
•
|
||||||
|
{/if}
|
||||||
|
Connected {connections} {connections === 1 ? 'time' : 'times'}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M19 15L12 9L5 15" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 215 B |
@@ -0,0 +1,4 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M2 12C2 7.28595 2 4.92893 3.46447 3.46447C4.92893 2 7.28595 2 12 2C16.714 2 19.0711 2 20.5355 3.46447C22 4.92893 22 7.28595 22 12C22 16.714 22 19.0711 20.5355 20.5355C19.0711 22 16.714 22 12 22C7.28595 22 4.92893 22 3.46447 20.5355C2 19.0711 2 16.714 2 12Z" stroke="#1C274C" stroke-width="1.5"/>
|
||||||
|
<path d="M2 13H5.16026C6.06543 13 6.51802 13 6.91584 13.183C7.31367 13.3659 7.60821 13.7096 8.19729 14.3968L8.80271 15.1032C9.39179 15.7904 9.68633 16.1341 10.0842 16.317C10.482 16.5 10.9346 16.5 11.8397 16.5H12.1603C13.0654 16.5 13.518 16.5 13.9158 16.317C14.3137 16.1341 14.6082 15.7904 15.1973 15.1032L15.8027 14.3968C16.3918 13.7096 16.6863 13.3659 17.0842 13.183C17.482 13 17.9346 13 18.8397 13H22" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 873 B |
@@ -0,0 +1,6 @@
|
|||||||
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M10.5 22V20M14.5 22V20" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
<path d="M11 20V20.75H11.75V20H11ZM14 19.25C13.5858 19.25 13.25 19.5858 13.25 20C13.25 20.4142 13.5858 20.75 14 20.75V19.25ZM17.5 5.25C17.0858 5.25 16.75 5.58579 16.75 6C16.75 6.41421 17.0858 6.75 17.5 6.75V5.25ZM7 5.25C6.58579 5.25 6.25 5.58579 6.25 6C6.25 6.41421 6.58579 6.75 7 6.75V5.25ZM9 19.25C8.58579 19.25 8.25 19.5858 8.25 20C8.25 20.4142 8.58579 20.75 9 20.75V19.25ZM15 20.75C15.4142 20.75 15.75 20.4142 15.75 20C15.75 19.5858 15.4142 19.25 15 19.25V20.75ZM10.25 11.25V20H11.75V11.25H10.25ZM11 19.25H4.23256V20.75H11V19.25ZM2.75 17.3953V11.25H1.25V17.3953H2.75ZM4.23256 19.25C3.51806 19.25 2.75 18.5323 2.75 17.3953H1.25C1.25 19.1354 2.48104 20.75 4.23256 20.75V19.25ZM6.5 6.75C8.46677 6.75 10.25 8.65209 10.25 11.25H11.75C11.75 8.04892 9.50379 5.25 6.5 5.25V6.75ZM6.5 5.25C3.49621 5.25 1.25 8.04892 1.25 11.25H2.75C2.75 8.65209 4.53323 6.75 6.5 6.75V5.25ZM21.25 11.25V17.4253H22.75V11.25H21.25ZM19.7931 19.25H14V20.75H19.7931V19.25ZM21.25 17.4253C21.25 18.5457 20.4934 19.25 19.7931 19.25V20.75C21.5305 20.75 22.75 19.1488 22.75 17.4253H21.25ZM22.75 11.25C22.75 8.04892 20.5038 5.25 17.5 5.25V6.75C19.4668 6.75 21.25 8.65209 21.25 11.25H22.75ZM7 6.75H18V5.25H7V6.75ZM9 20.75H15V19.25H9V20.75Z" fill="#1C274C"/>
|
||||||
|
<path d="M5 16H8" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
<path d="M16 9.88432V5.41121M16 5.41121V2.63519C16 2.39905 16.1676 2.19612 16.3994 2.15144L16.8855 2.05779C17.4738 1.94443 18.0821 1.99855 18.6412 2.214L18.7203 2.24451C19.2746 2.4581 19.8807 2.498 20.4582 2.35891C20.7343 2.2924 21 2.50168 21 2.78573V5.00723C21 5.2442 20.8376 5.45031 20.6073 5.5058L20.5407 5.52184C19.9095 5.67387 19.247 5.63026 18.6412 5.39679C18.0821 5.18135 17.4738 5.12722 16.8855 5.24058L16 5.41121Z" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.9 KiB |
@@ -0,0 +1,27 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import {slide} from '@lib/transition'
|
||||||
|
import Icon from '@lib/components/Icon.svelte'
|
||||||
|
|
||||||
|
const toggle = () => {
|
||||||
|
isOpen = !isOpen
|
||||||
|
}
|
||||||
|
|
||||||
|
let isOpen = false
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex flex-col gap-4 relative {$$props.class}">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
class="absolute top-8 right-8 cursor-pointer w-4 h-4 transition-all"
|
||||||
|
class:rotate-90={!isOpen}
|
||||||
|
on:click={toggle}>
|
||||||
|
<Icon icon="alt-arrow-down" />
|
||||||
|
</button>
|
||||||
|
<slot name="title" />
|
||||||
|
<slot name="description" />
|
||||||
|
{#if isOpen}
|
||||||
|
<div transition:slide>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
import AddCircle from "@assets/icons/Add Circle.svg?dataurl"
|
import AddCircle from "@assets/icons/Add Circle.svg?dataurl"
|
||||||
import AltArrowDown from "@assets/icons/Alt Arrow Down.svg?dataurl"
|
import AltArrowDown from "@assets/icons/Alt Arrow Down.svg?dataurl"
|
||||||
import AltArrowRight from "@assets/icons/Alt Arrow Right.svg?dataurl"
|
import AltArrowRight from "@assets/icons/Alt Arrow Right.svg?dataurl"
|
||||||
|
import AltArrowUp from "@assets/icons/Alt Arrow Up.svg?dataurl"
|
||||||
import AltArrowLeft from "@assets/icons/Alt Arrow Left.svg?dataurl"
|
import AltArrowLeft from "@assets/icons/Alt Arrow Left.svg?dataurl"
|
||||||
import ArrowRight from "@assets/icons/Arrow Right.svg?dataurl"
|
import ArrowRight from "@assets/icons/Arrow Right.svg?dataurl"
|
||||||
import Bag from "@assets/icons/Bag.svg?dataurl"
|
import Bag from "@assets/icons/Bag.svg?dataurl"
|
||||||
@@ -41,6 +42,7 @@
|
|||||||
import Hashtag from "@assets/icons/Hashtag.svg?dataurl"
|
import Hashtag from "@assets/icons/Hashtag.svg?dataurl"
|
||||||
import HandPills from "@assets/icons/Hand Pills.svg?dataurl"
|
import HandPills from "@assets/icons/Hand Pills.svg?dataurl"
|
||||||
import HomeSmile from "@assets/icons/Home Smile.svg?dataurl"
|
import HomeSmile from "@assets/icons/Home Smile.svg?dataurl"
|
||||||
|
import Inbox from "@assets/icons/Inbox.svg?dataurl"
|
||||||
import InfoCircle from "@assets/icons/Info Circle.svg?dataurl"
|
import InfoCircle from "@assets/icons/Info Circle.svg?dataurl"
|
||||||
import InfoSquare from "@assets/icons/Info Square.svg?dataurl"
|
import InfoSquare from "@assets/icons/Info Square.svg?dataurl"
|
||||||
import Key from "@assets/icons/Key.svg?dataurl"
|
import Key from "@assets/icons/Key.svg?dataurl"
|
||||||
@@ -48,6 +50,7 @@
|
|||||||
import Login from "@assets/icons/Login.svg?dataurl"
|
import Login from "@assets/icons/Login.svg?dataurl"
|
||||||
import Login2 from "@assets/icons/Login 2.svg?dataurl"
|
import Login2 from "@assets/icons/Login 2.svg?dataurl"
|
||||||
import Magnifer from "@assets/icons/Magnifer.svg?dataurl"
|
import Magnifer from "@assets/icons/Magnifer.svg?dataurl"
|
||||||
|
import Mailbox from "@assets/icons/Mailbox.svg?dataurl"
|
||||||
import MapPoint from "@assets/icons/Map Point.svg?dataurl"
|
import MapPoint from "@assets/icons/Map Point.svg?dataurl"
|
||||||
import MenuDots from "@assets/icons/Menu Dots.svg?dataurl"
|
import MenuDots from "@assets/icons/Menu Dots.svg?dataurl"
|
||||||
import NotesMinimalistic from "@assets/icons/Notes Minimalistic.svg?dataurl"
|
import NotesMinimalistic from "@assets/icons/Notes Minimalistic.svg?dataurl"
|
||||||
@@ -86,6 +89,7 @@
|
|||||||
"add-circle": AddCircle,
|
"add-circle": AddCircle,
|
||||||
"alt-arrow-down": AltArrowDown,
|
"alt-arrow-down": AltArrowDown,
|
||||||
"alt-arrow-right": AltArrowRight,
|
"alt-arrow-right": AltArrowRight,
|
||||||
|
"alt-arrow-up": AltArrowUp,
|
||||||
"alt-arrow-left": AltArrowLeft,
|
"alt-arrow-left": AltArrowLeft,
|
||||||
"arrow-right": ArrowRight,
|
"arrow-right": ArrowRight,
|
||||||
bag: Bag,
|
bag: Bag,
|
||||||
@@ -108,6 +112,7 @@
|
|||||||
hashtag: Hashtag,
|
hashtag: Hashtag,
|
||||||
"hand-pills": HandPills,
|
"hand-pills": HandPills,
|
||||||
"home-smile": HomeSmile,
|
"home-smile": HomeSmile,
|
||||||
|
"inbox": Inbox,
|
||||||
"info-circle": InfoCircle,
|
"info-circle": InfoCircle,
|
||||||
"info-square": InfoSquare,
|
"info-square": InfoSquare,
|
||||||
key: Key,
|
key: Key,
|
||||||
@@ -115,6 +120,7 @@
|
|||||||
login: Login,
|
login: Login,
|
||||||
"login-2": Login2,
|
"login-2": Login2,
|
||||||
magnifer: Magnifer,
|
magnifer: Magnifer,
|
||||||
|
mailbox: Mailbox,
|
||||||
"map-point": MapPoint,
|
"map-point": MapPoint,
|
||||||
"menu-dots": MenuDots,
|
"menu-dots": MenuDots,
|
||||||
"notes-minimalistic": NotesMinimalistic,
|
"notes-minimalistic": NotesMinimalistic,
|
||||||
|
|||||||
@@ -5,6 +5,6 @@
|
|||||||
export let props = {}
|
export let props = {}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="modal-box" transition:fly={{duration: 100}}>
|
<div class="modal-box bg-alt" transition:fly={{duration: 100}}>
|
||||||
<svelte:component this={component} {...props} />
|
<svelte:component this={component} {...props} />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,92 +1,114 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {onMount} from "svelte"
|
|
||||||
import {derived} from "svelte/store"
|
import {derived} from "svelte/store"
|
||||||
import {uniq} from "@welshman/lib"
|
import type {Readable} from 'svelte/store'
|
||||||
import {displayRelayUrl} from "@welshman/util"
|
|
||||||
import {relaySearch, getRelayUrls, userRelaySelections, userInboxRelaySelections, getReadRelayUrls, getWriteRelayUrls} from "@welshman/app"
|
import {relaySearch, getRelayUrls, userRelaySelections, userInboxRelaySelections, getReadRelayUrls, getWriteRelayUrls} from "@welshman/app"
|
||||||
import Button from "@lib/components/Button.svelte"
|
|
||||||
import Icon from "@lib/components/Icon.svelte"
|
import Icon from "@lib/components/Icon.svelte"
|
||||||
import {INDEXER_RELAYS, discoverRelays} from "@app/state"
|
import Button from "@lib/components/Button.svelte"
|
||||||
|
import Collapse from "@lib/components/Collapse.svelte"
|
||||||
|
import RelayItem from "@app/components/RelayItem.svelte"
|
||||||
|
import RelayAdd from "@app/components/RelayAdd.svelte"
|
||||||
|
import {pushModal} from '@app/modal'
|
||||||
|
|
||||||
const readRelayUrls = derived(userRelaySelections, getReadRelayUrls)
|
const readRelayUrls = derived(userRelaySelections, getReadRelayUrls)
|
||||||
const writeRelayUrls = derived(userRelaySelections, getWriteRelayUrls)
|
const writeRelayUrls = derived(userRelaySelections, getWriteRelayUrls)
|
||||||
const inboxRelayUrls = derived(userInboxRelaySelections, getRelayUrls)
|
const inboxRelayUrls = derived(userInboxRelaySelections, getRelayUrls)
|
||||||
|
|
||||||
const removeRelay = (url: string) => null
|
const addRelay = (mode: string, relays: Readable<string[]>) =>
|
||||||
|
pushModal(RelayAdd, {mode, relays})
|
||||||
|
|
||||||
const addRelay = (url: string) => null
|
const removeReadRelay = (url: string) => null
|
||||||
|
|
||||||
let term = ""
|
const removeWriteRelay = (url: string) => null
|
||||||
let currentRelayUrls: string[] = []
|
|
||||||
|
|
||||||
$: currentRelayUrls = uniq([
|
const removeInboxRelay = (url: string) => null
|
||||||
...currentRelayUrls,
|
|
||||||
...getRelayUrls($userRelaySelections),
|
|
||||||
...getRelayUrls($userInboxRelaySelections),
|
|
||||||
]).sort()
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
const sub = discoverRelays()
|
|
||||||
|
|
||||||
return () => sub.close()
|
|
||||||
})
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="content column gap-4">
|
<div class="content column gap-4">
|
||||||
<h1 class="superheading mt-20">Relays</h1>
|
<Collapse class="card2 bg-alt column gap-4">
|
||||||
<p class="text-center">Get connected with the nostr network</p>
|
<h2 slot="title" class="text-xl flex items-center gap-3">
|
||||||
{#each currentRelayUrls as url}
|
<Icon icon="earth" />
|
||||||
{@const read = $readRelayUrls.includes(url)}
|
Broadcast Relays
|
||||||
{@const write = $writeRelayUrls.includes(url)}
|
</h2>
|
||||||
{@const inbox = $inboxRelayUrls.includes(url)}
|
<p slot="description" class="text-sm">
|
||||||
<div class="card2 card2-sm flex flex-col gap-2 overflow-visible">
|
These relays will be advertised on your profile as places where you send your public
|
||||||
<div class="flex items-center justify-between">
|
notes. Be sure to select relays that will accept your notes, and which will let people
|
||||||
<div class="flex items-center gap-2">
|
who follow you read them.
|
||||||
<Icon icon="remote-controller-minimalistic" />
|
</p>
|
||||||
{displayRelayUrl(url)}
|
<div class="column gap-2">
|
||||||
</div>
|
{#each $writeRelayUrls.sort() as url (url)}
|
||||||
<Button class="flex items-center" on:click={() => removeRelay(url)}>
|
<RelayItem {url}>
|
||||||
<Icon icon="close-circle" />
|
<Button
|
||||||
</Button>
|
class="flex items-center tooltip"
|
||||||
</div>
|
data-tip="Stop using this relay"
|
||||||
<div class="flex gap-3">
|
on:click={() => removeWriteRelay(url)}>
|
||||||
<div
|
<Icon icon="close-circle" />
|
||||||
class="tooltip tooltip-right"
|
|
||||||
data-tip="Notes for you will {read ? '' : 'not'} be sent here.">
|
|
||||||
<Button class="btn btn-sm btn-{read ? 'primary' : 'neutral'}">
|
|
||||||
Read
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</RelayItem>
|
||||||
<div
|
{:else}
|
||||||
class="tooltip tooltip-right"
|
<p class="text-center text-sm">No relays found</p>
|
||||||
data-tip="Notes you publish will {write ? '' : 'not'} be sent here.">
|
{/each}
|
||||||
<Button class="btn btn-sm btn-{write ? 'primary' : 'neutral'}">
|
<Button class="btn btn-primary mt-2" on:click={() => addRelay('write', writeRelayUrls)}>
|
||||||
Write
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="tooltip tooltip-right"
|
|
||||||
data-tip="Direct messages will {inbox ? '' : 'not'} be sent here.">
|
|
||||||
<Button class="btn btn-sm btn-{inbox ? 'primary' : 'neutral'}">
|
|
||||||
Inbox
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
<label class="input input-bordered flex w-full items-center gap-2">
|
|
||||||
<Icon icon="magnifer" />
|
|
||||||
<input bind:value={term} class="grow" type="text" placeholder="Search for relays..." />
|
|
||||||
</label>
|
|
||||||
{#each $relaySearch.searchValues(term).filter(url => !currentRelayUrls.includes(url)) as url (url)}
|
|
||||||
<div class="card2 card2-sm flex items-center justify-between">
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<Icon icon="remote-controller-minimalistic" />
|
|
||||||
{displayRelayUrl(url)}
|
|
||||||
</div>
|
|
||||||
<Button class="flex items-center" on:click={() => addRelay(url)}>
|
|
||||||
<Icon icon="add-circle" />
|
<Icon icon="add-circle" />
|
||||||
|
Add Relay
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
</Collapse>
|
||||||
|
<Collapse class="card2 bg-alt column gap-4">
|
||||||
|
<h2 slot="title" class="text-xl flex items-center gap-3">
|
||||||
|
<Icon icon="inbox" />
|
||||||
|
Inbox Relays
|
||||||
|
</h2>
|
||||||
|
<p slot="description" class="text-sm">
|
||||||
|
These relays will be advertised on your profile as places where other people should
|
||||||
|
send notes intended for you. Be sure to select relays that will accept notes that
|
||||||
|
tag you.
|
||||||
|
</p>
|
||||||
|
<div class="column gap-2">
|
||||||
|
{#each $readRelayUrls.sort() as url (url)}
|
||||||
|
<RelayItem {url}>
|
||||||
|
<Button
|
||||||
|
class="flex items-center tooltip"
|
||||||
|
data-tip="Stop using this relay"
|
||||||
|
on:click={() => removeReadRelay(url)}>
|
||||||
|
<Icon icon="close-circle" />
|
||||||
|
</Button>
|
||||||
|
</RelayItem>
|
||||||
|
{:else}
|
||||||
|
<p class="text-center text-sm">No relays found</p>
|
||||||
|
{/each}
|
||||||
|
<Button class="btn btn-primary mt-2" on:click={() => addRelay('read', readRelayUrls)}>
|
||||||
|
<Icon icon="add-circle" />
|
||||||
|
Add Relay
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Collapse>
|
||||||
|
<Collapse class="card2 bg-alt column gap-4">
|
||||||
|
<h2 slot="title" class="text-xl flex items-center gap-3">
|
||||||
|
<Icon icon="mailbox" />
|
||||||
|
Messaging Relays
|
||||||
|
</h2>
|
||||||
|
<p slot="description" class="text-sm">
|
||||||
|
These relays will be advertised on your profile as places you use to send and
|
||||||
|
receive direct messages. Be sure to select relays that will accept your messages
|
||||||
|
and messages from people you'd like to be in contact with.
|
||||||
|
</p>
|
||||||
|
<div class="column gap-2">
|
||||||
|
{#each $inboxRelayUrls.sort() as url (url)}
|
||||||
|
<RelayItem {url}>
|
||||||
|
<Button
|
||||||
|
class="flex items-center tooltip"
|
||||||
|
data-tip="Stop using this relay"
|
||||||
|
on:click={() => removeInboxRelay(url)}>
|
||||||
|
<Icon icon="close-circle" />
|
||||||
|
</Button>
|
||||||
|
</RelayItem>
|
||||||
|
{:else}
|
||||||
|
<p class="text-center text-sm">No relays found</p>
|
||||||
|
{/each}
|
||||||
|
<Button class="btn btn-primary mt-2" on:click={() => addRelay('inbox', inboxRelayUrls)}>
|
||||||
|
<Icon icon="add-circle" />
|
||||||
|
Add Relay
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Collapse>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user