mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-19 11:43:35 +00:00
Try opening feeds filtered by relay in a modal
This commit is contained in:
parent
5d6d3b1b6f
commit
dbbbec4d07
@ -1,13 +1,14 @@
|
||||
# Current
|
||||
|
||||
- [ ] Fix scrolling with embedded modals by registering open modals in the component
|
||||
- [ ] Relays bounty
|
||||
- [x] Ability to click into a relay's global feed
|
||||
- [ ] Ability to filter feeds by relay
|
||||
- Global Mutes? Global Whitelist?
|
||||
- Open in modal with "here's what this feed would look like with only this relay"
|
||||
- [x] Ability to filter feeds by relay
|
||||
- [-] Global Mutes? Global Whitelist?
|
||||
- [x] Open in modal with "here's what this feed would look like with only this relay"
|
||||
- [ ] Fix scrolling with embedded modals by registering open modals in the component
|
||||
- [ ] Ability to create custom feeds
|
||||
- [ ] Fix tag-style event mentions. Probably transform all mentions into entities in parse
|
||||
- [ ] Some lnurls aren't working npub1y3k2nheva29y9ej8a22e07epuxrn04rvgy28wvs54y57j7vsxxuq0gvp4j
|
||||
- [ ] Fix performance issues
|
||||
- [ ] https://github.com/techfort/LokiJS
|
||||
- Use indexed adapter github.com/techfort/LokiJS/blob/master/tutorials/Persistence%20Adapters.md and partitioning adapter
|
||||
|
@ -24,7 +24,7 @@
|
||||
import user from "src/agent/user"
|
||||
import {loadAppData} from "src/app"
|
||||
import {theme, getThemeVariables} from "src/app/ui"
|
||||
import {modal, routes, menuIsOpen, logUsage} from "src/app/ui"
|
||||
import {modal, openModals, routes, menuIsOpen, logUsage} from "src/app/ui"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
@ -97,11 +97,16 @@
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
// Keep scroll position on body, but don't allow scrolling
|
||||
// Log modals
|
||||
const unsubModal = modal.subscribe($modal => {
|
||||
if ($modal) {
|
||||
logUsage(btoa(["modal", $modal.type].join(":")))
|
||||
}
|
||||
})
|
||||
|
||||
// Keep scroll position on body, but don't allow scrolling
|
||||
const unsubOpenModals = openModals.subscribe(n => {
|
||||
if (n > 0) {
|
||||
// This is not idempotent, so don't duplicate it
|
||||
if (document.body.style.position !== "fixed") {
|
||||
scrollY = window.scrollY
|
||||
@ -133,6 +138,7 @@
|
||||
return () => {
|
||||
unsubHistory()
|
||||
unsubModal()
|
||||
unsubOpenModals()
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -118,7 +118,7 @@ export const getRelaysForEventParent = event => {
|
||||
// to read from the current user's network's read relays instead.
|
||||
export const getRelaysForEventChildren = event => {
|
||||
return uniqByUrl(
|
||||
getPubkeyReadRelays(event.pubkey).concat(event.seen_on.map(url => ({url, score: 1})))
|
||||
getPubkeyReadRelays(event.pubkey).concat((event.seen_on || []).map(url => ({url, score: 1})))
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,7 @@ export const routes = new Table("routes", "id", {
|
||||
listener.connect()
|
||||
|
||||
export const getPersonWithFallback = pubkey => people.get(pubkey) || {pubkey}
|
||||
export const getRelayWithFallback = url => relays.get(url) || {url}
|
||||
|
||||
const ready = derived(pluck("ready", Object.values(registry)), all(identity))
|
||||
|
||||
|
@ -6,7 +6,7 @@ import {navigate} from "svelte-routing"
|
||||
import {nip19} from "nostr-tools"
|
||||
import {writable, get} from "svelte/store"
|
||||
import {globalHistory} from "svelte-routing/src/history"
|
||||
import {sleep, WritableList, synced, hash} from "src/util/misc"
|
||||
import {sleep, synced, hash} from "src/util/misc"
|
||||
import {warn} from "src/util/logger"
|
||||
import user from "src/agent/user"
|
||||
|
||||
@ -48,6 +48,8 @@ export const menuIsOpen = writable(false)
|
||||
|
||||
// Modals
|
||||
|
||||
export const openModals = writable(0)
|
||||
|
||||
export const modal = {
|
||||
history: [],
|
||||
set: data => {
|
||||
|
@ -1,9 +1,19 @@
|
||||
<script>
|
||||
import {onMount, onDestroy} from "svelte"
|
||||
import {fly, fade} from "svelte/transition"
|
||||
import {openModals} from "src/app/ui"
|
||||
|
||||
export let onEscape = null
|
||||
|
||||
let root, content
|
||||
|
||||
onMount(() => {
|
||||
openModals.update(n => n + 1)
|
||||
})
|
||||
|
||||
onDestroy(() => {
|
||||
openModals.update(n => n - 1)
|
||||
})
|
||||
</script>
|
||||
|
||||
<svelte:body
|
||||
|
@ -9,6 +9,7 @@
|
||||
export let triggerType = "click"
|
||||
export let placement = "top"
|
||||
export let interactive = true
|
||||
export let arrow = false
|
||||
|
||||
let trigger
|
||||
let tooltip
|
||||
@ -17,6 +18,7 @@
|
||||
onMount(() => {
|
||||
instance = tippy(trigger, {
|
||||
theme,
|
||||
arrow,
|
||||
placement: placement as Placement,
|
||||
appendTo: () => document.body,
|
||||
allowHTML: true,
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {objOf} from "ramda"
|
||||
import {objOf, last} from "ramda"
|
||||
import {onMount} from "svelte"
|
||||
import {nip19} from "nostr-tools"
|
||||
import {warn} from "src/util/logger"
|
||||
@ -10,6 +10,8 @@
|
||||
|
||||
export let entity
|
||||
|
||||
entity = last(entity.split(":"))
|
||||
|
||||
let type, data, relays
|
||||
|
||||
onMount(() => {
|
||||
|
@ -1,10 +1,9 @@
|
||||
<script lang="ts">
|
||||
import {displayRelay} from "src/util/nostr"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Feed from "src/views/feed/Feed.svelte"
|
||||
import RelayTitle from "src/views/relays/RelayTitle.svelte"
|
||||
import RelayJoin from "src/views/relays/RelayJoin.svelte"
|
||||
import RelayActions from "src/views/relays/RelayActions.svelte"
|
||||
import {relays} from "src/agent/tables"
|
||||
|
||||
export let url
|
||||
@ -17,7 +16,7 @@
|
||||
<Content>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<RelayTitle {relay} />
|
||||
<RelayJoin {relay} />
|
||||
<RelayActions {relay} />
|
||||
</div>
|
||||
{#if relay.description}
|
||||
<p>{relay.description}</p>
|
||||
|
@ -125,7 +125,7 @@ export const poll = (t, cb) => {
|
||||
}
|
||||
}
|
||||
|
||||
export const createScroller = (loadMore, {reverse = false} = {}) => {
|
||||
export const createScroller = (loadMore, {reverse = false, element = document.body} = {}) => {
|
||||
const THRESHOLD = 2000
|
||||
|
||||
// NOTE TO FUTURE SELF
|
||||
@ -136,10 +136,11 @@ export const createScroller = (loadMore, {reverse = false} = {}) => {
|
||||
const check = async () => {
|
||||
// While we have empty space, fill it
|
||||
const {scrollY, innerHeight} = window
|
||||
const {scrollHeight} = document.body
|
||||
const {scrollHeight, scrollTop} = element
|
||||
const offset = scrollTop || scrollY
|
||||
const shouldLoad = reverse
|
||||
? scrollY < THRESHOLD
|
||||
: scrollY + innerHeight + THRESHOLD > scrollHeight
|
||||
? offset < THRESHOLD
|
||||
: offset + innerHeight + THRESHOLD > scrollHeight
|
||||
|
||||
// Only trigger loading the first time we reach the threshold
|
||||
if (shouldLoad) {
|
||||
|
@ -1,15 +1,14 @@
|
||||
<script lang="ts">
|
||||
import {onMount} from "svelte"
|
||||
import {find, partition, always, propEq, uniqBy, sortBy, prop} from "ramda"
|
||||
import {partition, always, propEq, uniqBy, sortBy, prop} from "ramda"
|
||||
import {fly} from "svelte/transition"
|
||||
import {quantify} from "hurdak/lib/hurdak"
|
||||
import {createScroller, now, timedelta, Cursor} from "src/util/misc"
|
||||
import {asDisplayEvent, mergeFilter, displayRelay} from "src/util/nostr"
|
||||
import {asDisplayEvent, mergeFilter} from "src/util/nostr"
|
||||
import Spinner from "src/partials/Spinner.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import RelayTitle from "src/views/relays/RelayTitle.svelte"
|
||||
import RelayJoin from "src/views/relays/RelayJoin.svelte"
|
||||
import RelayFeed from "src/views/feed/RelayFeed.svelte"
|
||||
import Note from "src/views/notes/Note.svelte"
|
||||
import user from "src/agent/user"
|
||||
import network from "src/agent/network"
|
||||
@ -25,6 +24,7 @@
|
||||
let notes = []
|
||||
let notesBuffer = []
|
||||
let feedRelay = null
|
||||
let feedScroller = null
|
||||
|
||||
// Add a short buffer so we can get the most possible results for recent notes
|
||||
const since = now()
|
||||
@ -34,6 +34,15 @@
|
||||
|
||||
const setFeedRelay = relay => {
|
||||
feedRelay = relay
|
||||
|
||||
setTimeout(() => {
|
||||
feedScroller?.stop()
|
||||
feedScroller = !relay
|
||||
? null
|
||||
: createScroller(loadMore, {
|
||||
element: document.querySelector(".modal-content"),
|
||||
})
|
||||
}, 300)
|
||||
}
|
||||
|
||||
const loadBufferedNotes = () => {
|
||||
@ -95,14 +104,7 @@
|
||||
notes = uniqBy(prop("id"), notes.concat(bottom))
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
const sub = network.listen({
|
||||
relays,
|
||||
filter: mergeFilter(filter, {since}),
|
||||
onChunk,
|
||||
})
|
||||
|
||||
const scroller = createScroller(async () => {
|
||||
const loadMore = async () => {
|
||||
if ($modal) {
|
||||
return
|
||||
}
|
||||
@ -116,10 +118,20 @@
|
||||
|
||||
// Update our cursor
|
||||
cursor.update(notes)
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
const sub = network.listen({
|
||||
relays,
|
||||
filter: mergeFilter(filter, {since}),
|
||||
onChunk,
|
||||
})
|
||||
|
||||
const scroller = createScroller(loadMore)
|
||||
|
||||
return () => {
|
||||
scroller.stop()
|
||||
feedScroller?.stop()
|
||||
sub.then(s => s?.unsub())
|
||||
}
|
||||
})
|
||||
@ -141,7 +153,7 @@
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
{#each notes as note (note.id)}
|
||||
<Note depth={2} {note} setFeedRelay={setFeedRelay} />
|
||||
<Note depth={2} {note} {feedRelay} {setFeedRelay} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@ -149,26 +161,7 @@
|
||||
</Content>
|
||||
|
||||
{#if feedRelay}
|
||||
<Modal onEscape={() => setFeedRelay(null)}>
|
||||
<Content>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<RelayTitle relay={feedRelay} />
|
||||
<RelayJoin relay={feedRelay} />
|
||||
</div>
|
||||
{#if feedRelay.description}
|
||||
<p>{feedRelay.description}</p>
|
||||
{/if}
|
||||
<p class="text-gray-4">
|
||||
<i class="fa fa-info-circle" />
|
||||
Below is your current feed including only notes seen on {displayRelay(feedRelay)}
|
||||
</p>
|
||||
<div class="flex flex-col gap-4">
|
||||
{#each notes as note (note.id)}
|
||||
{#if note.seen_on.includes(feedRelay.url)}
|
||||
<Note depth={2} {note} />
|
||||
{/if}
|
||||
{/each}
|
||||
</div>
|
||||
</Content>
|
||||
</Modal>
|
||||
<Modal onEscape={() => setFeedRelay(null)}>
|
||||
<RelayFeed {feedRelay} {notes} depth={2} />
|
||||
</Modal>
|
||||
{/if}
|
||||
|
39
src/views/feed/RelayFeed.svelte
Normal file
39
src/views/feed/RelayFeed.svelte
Normal file
@ -0,0 +1,39 @@
|
||||
<script lang="ts">
|
||||
import {displayRelay} from "src/util/nostr"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Spinner from "src/partials/Spinner.svelte"
|
||||
import RelayTitle from "src/views/relays/RelayTitle.svelte"
|
||||
import RelayActions from "src/views/relays/RelayActions.svelte"
|
||||
import Note from "src/views/notes/Note.svelte"
|
||||
|
||||
export let depth
|
||||
export let showContext = false
|
||||
export let feedRelay
|
||||
export let notes
|
||||
|
||||
$: filteredNotes = notes.filter(n => n.seen_on.includes(feedRelay.url))
|
||||
</script>
|
||||
|
||||
<Content>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<RelayTitle relay={feedRelay} />
|
||||
<RelayActions relay={feedRelay} />
|
||||
</div>
|
||||
{#if feedRelay.description}
|
||||
<p>{feedRelay.description}</p>
|
||||
{/if}
|
||||
<p class="text-gray-4">
|
||||
<i class="fa fa-info-circle" />
|
||||
Below is your current feed including only notes seen on {displayRelay(feedRelay)}
|
||||
</p>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<!-- If someone clicks on a child note that was seen on a relay the parent was not
|
||||
seen on, we get nothing, so just show everything - but pass down the filter -->
|
||||
{#each filteredNotes.length > 0 ? filteredNotes : notes as note (note.id)}
|
||||
<Note invertColors {depth} {note} {feedRelay} {showContext} />
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<Spinner />
|
||||
</Content>
|
@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import {fly} from "svelte/transition"
|
||||
import user from "src/agent/user"
|
||||
import {modal} from "src/app/ui"
|
||||
|
||||
|
@ -50,7 +50,8 @@
|
||||
import NoteContent from "src/views/notes/NoteContent.svelte"
|
||||
|
||||
export let note
|
||||
export let setFeedRelay
|
||||
export let feedRelay
|
||||
export let setFeedRelay = null
|
||||
export let depth = 0
|
||||
export let anchorId = null
|
||||
export let showParent = true
|
||||
@ -134,8 +135,15 @@
|
||||
$: $likesCount = likes.length
|
||||
$: $zapsTotal = sum(zaps.map(zap => zap.invoiceAmount)) / 1000
|
||||
$: $repliesCount = note.replies.length
|
||||
$: visibleNotes = note.replies.filter(r => (showContext ? true : !r.isContext))
|
||||
$: canZap = $person?.zapper && $person?.pubkey !== user.getPubkey()
|
||||
$: visibleNotes = note.replies.filter(r => {
|
||||
if (feedRelay && !r.seen_on.includes(feedRelay.url)) {
|
||||
return false
|
||||
}
|
||||
|
||||
return showContext ? true : !r.isContext
|
||||
})
|
||||
|
||||
$: {
|
||||
actions = []
|
||||
|
||||
@ -393,7 +401,7 @@
|
||||
<div slot="trigger">
|
||||
<Anchor
|
||||
type="unstyled"
|
||||
class="flex items-center gap-2 text-lg font-bold"
|
||||
class="flex items-center gap-2 pr-16 text-lg font-bold sm:pr-0"
|
||||
href={isMobile ? null : routes.person($person.pubkey)}>
|
||||
<span>{displayPerson($person)}</span>
|
||||
{#if $person.verified_as}
|
||||
@ -465,18 +473,31 @@
|
||||
</div>
|
||||
<div on:click|stopPropagation class="flex items-center">
|
||||
{#if pool.forceUrls.length === 0}
|
||||
<!-- Mobile version -->
|
||||
<div
|
||||
class={cx("absolute top-0 right-0 m-3 sm:relative sm:m-0", {
|
||||
"hidden group-hover:flex": !showEntire,
|
||||
flex: showEntire,
|
||||
style="transform: scale(-1, 1)"
|
||||
class="absolute top-0 right-0 m-3 grid grid-cols-3 gap-2 sm:hidden">
|
||||
{#each note.seen_on as url, i}
|
||||
<div class={`cursor-pointer order-${3 - (i % 3)}`}>
|
||||
<div
|
||||
class="h-3 w-3 rounded-full border border-solid border-gray-6"
|
||||
style={`background: ${hsl(stringToHue(url))}`}
|
||||
on:click={() => setFeedRelay?.({url})} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<!-- Desktop version -->
|
||||
<div
|
||||
class={cx("hidden sm:flex transition-opacity", {
|
||||
"opacity-0 group-hover:opacity-100": !showEntire,
|
||||
})}>
|
||||
{#each note.seen_on as url}
|
||||
{#each note.seen_on as url, i}
|
||||
<Popover triggerType="mouseenter" interactive={false}>
|
||||
<div slot="trigger" class="cursor-pointer p-1">
|
||||
<div
|
||||
class="h-3 w-3 rounded-full border border-solid border-gray-6"
|
||||
style={`background: ${hsl(stringToHue(url))}`}
|
||||
on:click={() => setFeedRelay({url})} />
|
||||
on:click={() => setFeedRelay?.({url})} />
|
||||
</div>
|
||||
<div slot="tooltip">{displayRelay({url})}</div>
|
||||
</Popover>
|
||||
@ -596,6 +617,8 @@
|
||||
showParent={false}
|
||||
note={r}
|
||||
depth={depth - 1}
|
||||
{feedRelay}
|
||||
{setFeedRelay}
|
||||
{invertColors}
|
||||
{anchorId}
|
||||
{showContext} />
|
||||
|
@ -6,6 +6,8 @@
|
||||
import {log} from "src/util/logger"
|
||||
import {asDisplayEvent} from "src/util/nostr"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import RelayFeed from "src/views/feed/RelayFeed.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
import Spinner from "src/partials/Spinner.svelte"
|
||||
import Note from "src/views/notes/Note.svelte"
|
||||
import user from "src/agent/user"
|
||||
@ -18,6 +20,11 @@
|
||||
|
||||
let sub = null
|
||||
let loading = true
|
||||
let feedRelay = null
|
||||
|
||||
const setFeedRelay = relay => {
|
||||
feedRelay = relay
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
if (!note.pubkey) {
|
||||
@ -56,10 +63,23 @@
|
||||
</div>
|
||||
{:else if note.pubkey}
|
||||
<div in:fly={{y: 20}} class="m-auto flex w-full max-w-2xl flex-col gap-4 p-4">
|
||||
<Note showContext depth={6} anchorId={note.id} note={asDisplayEvent(note)} {invertColors} />
|
||||
<Note
|
||||
showContext
|
||||
depth={6}
|
||||
anchorId={note.id}
|
||||
note={asDisplayEvent(note)}
|
||||
{invertColors}
|
||||
{feedRelay}
|
||||
{setFeedRelay} />
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if loading}
|
||||
<Spinner />
|
||||
{/if}
|
||||
|
||||
{#if feedRelay}
|
||||
<Modal onEscape={() => setFeedRelay(null)}>
|
||||
<RelayFeed {feedRelay} notes={[note]} depth={6} showContext />
|
||||
</Modal>
|
||||
{/if}
|
||||
|
56
src/views/relays/RelayActions.svelte
Normal file
56
src/views/relays/RelayActions.svelte
Normal file
@ -0,0 +1,56 @@
|
||||
<script lang="ts">
|
||||
import {find, last, propEq} from "ramda"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Popover from "src/partials/Popover.svelte"
|
||||
import OverflowMenu from "src/partials/OverflowMenu.svelte"
|
||||
import user from "src/agent/user"
|
||||
import {getRelayWithFallback} from "src/agent/tables"
|
||||
|
||||
export let relay
|
||||
|
||||
relay = getRelayWithFallback(relay.url)
|
||||
|
||||
const {relays: userRelays} = user
|
||||
|
||||
let actions = []
|
||||
|
||||
$: joined = find(propEq("url", relay.url), $userRelays)
|
||||
$: {
|
||||
actions = []
|
||||
|
||||
if (!joined) {
|
||||
actions.push({
|
||||
onClick: () => user.addRelay(relay.url),
|
||||
label: "Join",
|
||||
icon: "right-to-bracket",
|
||||
})
|
||||
} else if ($userRelays.length > 1) {
|
||||
actions.push({
|
||||
onClick: () => user.removeRelay(relay.url),
|
||||
label: "Leave",
|
||||
icon: "right-from-bracket",
|
||||
})
|
||||
}
|
||||
|
||||
if (relay.contact) {
|
||||
actions.push({
|
||||
onClick: () => window.open("mailto:" + last(relay.contact.split(":"))),
|
||||
label: "Contact",
|
||||
icon: "envelope",
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if actions.length > 0}
|
||||
{#if actions.length === 1}
|
||||
<Popover triggerType="mouseenter">
|
||||
<Anchor slot="trigger" type="button-circle" on:click={actions[0].onClick}>
|
||||
<i class={`fa fa-${actions[0].icon}`} />
|
||||
</Anchor>
|
||||
<p slot="tooltip">{actions[0].label}</p>
|
||||
</Popover>
|
||||
{:else}
|
||||
<OverflowMenu {actions} />
|
||||
{/if}
|
||||
{/if}
|
@ -1,36 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {find, propEq} from "ramda"
|
||||
import Anchor from 'src/partials/Anchor.svelte'
|
||||
import user from "src/agent/user"
|
||||
|
||||
export let relay
|
||||
|
||||
const {relays: userRelays} = user
|
||||
|
||||
$: joined = find(propEq("url", relay.url), $userRelays)
|
||||
</script>
|
||||
|
||||
<div class="flex flex-wrap items-center gap-3 whitespace-nowrap">
|
||||
{#if relay.contact}
|
||||
<Anchor type="button-circle" href={`mailto:${relay.contact}`}>
|
||||
<i class="fa fa-envelope" />
|
||||
</Anchor>
|
||||
{/if}
|
||||
{#if joined}
|
||||
{#if $userRelays.length > 1}
|
||||
<Anchor
|
||||
type="button"
|
||||
class="flex items-center gap-2 rounded-full"
|
||||
on:click={() => user.removeRelay(relay.url)}>
|
||||
<i class="fa fa-right-from-bracket" /> Leave
|
||||
</Anchor>
|
||||
{/if}
|
||||
{:else}
|
||||
<Anchor
|
||||
type="button"
|
||||
class="flex items-center gap-2 rounded-full"
|
||||
on:click={() => user.addRelay(relay.url)}>
|
||||
<i class="fa fa-right-to-bracket" /> Join
|
||||
</Anchor>
|
||||
{/if}
|
||||
</div>
|
@ -3,7 +3,8 @@
|
||||
import {between} from "hurdak/lib/hurdak"
|
||||
import {displayRelay} from "src/util/nostr"
|
||||
import {poll, stringToHue, hsl} from "src/util/misc"
|
||||
import pool from 'src/agent/pool'
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import pool from "src/agent/pool"
|
||||
|
||||
export let relay
|
||||
|
||||
@ -20,9 +21,13 @@
|
||||
|
||||
<div class="flex items-center gap-2 text-xl">
|
||||
<i class={relay.url.startsWith("wss") ? "fa fa-lock" : "fa fa-unlock"} />
|
||||
<span class="border-b border-solid" style={`border-color: ${hsl(stringToHue(relay.url))}`}>
|
||||
<Anchor
|
||||
type="unstyled"
|
||||
href={`/relays/${btoa(relay.url)}`}
|
||||
class="border-b border-solid"
|
||||
style={`border-color: ${hsl(stringToHue(relay.url))}`}>
|
||||
{displayRelay(relay)}
|
||||
</span>
|
||||
</Anchor>
|
||||
<span
|
||||
on:mouseout={() => {
|
||||
showStatus = false
|
||||
|
Loading…
Reference in New Issue
Block a user