mirror of
https://github.com/coracle-social/coracle.git
synced 2024-10-06 11:43:30 +00:00
Consolidate RelayCard
This commit is contained in:
parent
260328b757
commit
08d6195880
@ -7,6 +7,7 @@
|
||||
|
||||
- [ ] Relays bounty
|
||||
- [ ] Ability to create custom feeds
|
||||
- [ ] Add global/following/network tabs to relay detail
|
||||
- [ ] Fix tag-style event mentions. Probably transform all mentions into entities in parse
|
||||
- [ ] Some lnurls aren't working npub1y3k2nheva29y9ej8a22e07epuxrn04rvgy28wvs54y57j7vsxxuq0gvp4j
|
||||
- [ ] Fix performance issues
|
||||
|
@ -1,57 +1,108 @@
|
||||
<script lang="ts">
|
||||
import {find, propEq} from "ramda"
|
||||
import cx from "classnames"
|
||||
import {find, last, propEq} from "ramda"
|
||||
import {between} from "hurdak/lib/hurdak"
|
||||
import {onMount} from "svelte"
|
||||
import {poll} from "src/util/misc"
|
||||
import {fly} from "svelte/transition"
|
||||
import {poll, stringToHue, hsl} from "src/util/misc"
|
||||
import Toggle from "src/partials/Toggle.svelte"
|
||||
import RelayCard from "src/partials/RelayCard.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import pool from "src/agent/pool"
|
||||
import user from "src/agent/user"
|
||||
import keys from "src/agent/keys"
|
||||
import {loadAppData} from "src/app"
|
||||
|
||||
export let relay
|
||||
export let theme = "gray-8"
|
||||
export let showStatus = false
|
||||
export let showActions = false
|
||||
export let showControls = false
|
||||
|
||||
const {relays, canPublish} = user
|
||||
|
||||
let statusHover = false
|
||||
let quality = null
|
||||
let message = null
|
||||
let joined = false
|
||||
|
||||
const {relays, canPublish} = user
|
||||
const {method} = keys
|
||||
const isPubkeyLogin = $method === "pubkey"
|
||||
export let hasRelay = r => Boolean(find(propEq("url", r.url), $relays))
|
||||
|
||||
$: joined = find(propEq("url", relay.url), $relays)
|
||||
export let removeRelay = r => user.removeRelay(r.url)
|
||||
|
||||
const removeRelay = ({url}) => user.removeRelay(url)
|
||||
export let addRelay = r => {
|
||||
user.addRelay(r.url).then(() => {
|
||||
const pubkey = user.getPubkey()
|
||||
const profile = user.getProfile()
|
||||
|
||||
const addRelay = async ({url}) => {
|
||||
await user.addRelay(url)
|
||||
|
||||
if (!user.getProfile()?.kind0) {
|
||||
loadAppData(user.getPubkey())
|
||||
}
|
||||
if (pubkey && !profile?.kind0) {
|
||||
loadAppData(pubkey)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
return poll(10_000, async () => {
|
||||
;[quality, message] = await pool.getQuality(relay.url)
|
||||
return poll(10_000, () => {
|
||||
;[quality, message] = pool.getQuality(relay.url)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<RelayCard
|
||||
{relay}
|
||||
{theme}
|
||||
addRelay={!joined && !isPubkeyLogin ? addRelay : null}
|
||||
removeRelay={joined && $relays.length > 1 && !isPubkeyLogin ? removeRelay : null}>
|
||||
<div
|
||||
slot="controls"
|
||||
class="flex justify-between gap-2"
|
||||
class:hidden={!showControls || !$canPublish}>
|
||||
<span>Publish to this relay?</span>
|
||||
<Toggle
|
||||
value={relay.write}
|
||||
on:change={() => user.setRelayWriteCondition(relay.url, !relay.write)} />
|
||||
<div
|
||||
class={cx(
|
||||
`bg-${theme}`,
|
||||
"flex flex-col justify-between gap-3 rounded border border-l-2 border-solid border-gray-6 py-3 px-6 shadow"
|
||||
)}
|
||||
style={`border-left-color: ${hsl(stringToHue(relay.url))}`}
|
||||
in:fly={{y: 20}}>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="flex items-center gap-2 text-xl">
|
||||
<i class={relay.url.startsWith("wss") ? "fa fa-lock" : "fa fa-unlock"} />
|
||||
<Anchor type="unstyled" href={`/relays/${btoa(relay.url)}`}>
|
||||
{last(relay.url.split("://"))}
|
||||
</Anchor>
|
||||
{#if showStatus}
|
||||
<span
|
||||
on:mouseout={() => {
|
||||
statusHover = false
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
statusHover = true
|
||||
}}
|
||||
class="h-2 w-2 cursor-pointer rounded-full bg-gray-6"
|
||||
class:bg-gray-6={message === "Not connected"}
|
||||
class:bg-danger={quality <= 0.3 && message !== "Not connected"}
|
||||
class:bg-warning={between(0.3, 0.7, quality)}
|
||||
class:bg-success={quality > 0.7} />
|
||||
<p
|
||||
class="hidden text-sm text-gray-1 transition-all sm:block"
|
||||
class:opacity-0={!statusHover}
|
||||
class:opacity-1={statusHover}>
|
||||
{message}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{#if $canPublish && showActions}
|
||||
<slot name="actions">
|
||||
{#if hasRelay(relay) && $relays.length > 1}
|
||||
<button class="flex items-center gap-3 text-gray-1" on:click={() => removeRelay(relay)}>
|
||||
<i class="fa fa-right-from-bracket" /> Leave
|
||||
</button>
|
||||
{/if}
|
||||
{#if !hasRelay(relay)}
|
||||
<button class="flex items-center gap-3 text-gray-1" on:click={() => addRelay(relay)}>
|
||||
<i class="fa fa-right-to-bracket" /> Join
|
||||
</button>
|
||||
{/if}
|
||||
</slot>
|
||||
{/if}
|
||||
</div>
|
||||
</RelayCard>
|
||||
{#if relay.description}
|
||||
<p>{relay.description}</p>
|
||||
{/if}
|
||||
{#if hasRelay(relay) && showControls && $canPublish}
|
||||
<div class="flex justify-between gap-2">
|
||||
<span>Publish to this relay?</span>
|
||||
<Toggle
|
||||
value={relay.write}
|
||||
on:change={() => user.setRelayWriteCondition(relay.url, !relay.write)} />
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -6,12 +6,15 @@
|
||||
import {watch} from "src/agent/storage"
|
||||
import user from "src/agent/user"
|
||||
|
||||
let q = ""
|
||||
export let q = ""
|
||||
export let limit = 50
|
||||
export let relays = user.relays
|
||||
export let placeholder = "Search known relays"
|
||||
export let hideIfEmpty = false
|
||||
|
||||
let search
|
||||
let knownRelays = watch("relays", t => t.all())
|
||||
|
||||
const {relays} = user
|
||||
|
||||
$: {
|
||||
const joined = new Set(pluck("url", $relays))
|
||||
|
||||
@ -22,13 +25,19 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Input bind:value={q} type="text" wrapperClass="flex-grow" placeholder="Type to search">
|
||||
<i slot="before" class="fa-solid fa-search" />
|
||||
</Input>
|
||||
{#each (search(q) || []).slice(0, 50) as relay (relay.url)}
|
||||
<RelayCard {relay} />
|
||||
{/each}
|
||||
<small class="text-center">
|
||||
Showing {Math.min(($knownRelays || []).length - $relays.length, 50)}
|
||||
of {($knownRelays || []).length - $relays.length} known relays
|
||||
</small>
|
||||
<div class="flex flex-col gap-2">
|
||||
<Input bind:value={q} type="text" wrapperClass="flex-grow" {placeholder}>
|
||||
<i slot="before" class="fa-solid fa-search" />
|
||||
</Input>
|
||||
{#each !q && hideIfEmpty ? [] : search(q).slice(0, limit) as relay (relay.url)}
|
||||
<slot name="item" {relay}>
|
||||
<RelayCard {relay} />
|
||||
</slot>
|
||||
{/each}
|
||||
<slot name="footer">
|
||||
<small class="text-center">
|
||||
Showing {Math.min(($knownRelays || []).length - $relays.length, 50)}
|
||||
of {($knownRelays || []).length - $relays.length} known relays
|
||||
</small>
|
||||
</slot>
|
||||
</div>
|
||||
|
@ -9,9 +9,9 @@
|
||||
import Spinner from "src/partials/Spinner.svelte"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import Heading from "src/partials/Heading.svelte"
|
||||
import RelayCardSimple from "src/partials/RelayCardSimple.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
import RelayCard from "src/app2/shared/RelayCard.svelte"
|
||||
import {watch} from "src/agent/storage"
|
||||
import network from "src/agent/network"
|
||||
import user from "src/agent/user"
|
||||
@ -122,7 +122,7 @@
|
||||
{#each Object.values(currentRelays) as relay}
|
||||
<div class="h-12">
|
||||
{#if relay}
|
||||
<RelayCardSimple relay={{...relay, description: null}} />
|
||||
<RelayCard relay={{...relay, description: null}} />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
@ -4,20 +4,20 @@
|
||||
import {quantify} from "hurdak/lib/hurdak"
|
||||
import {last, reject, pluck, propEq} from "ramda"
|
||||
import {fly} from "svelte/transition"
|
||||
import {fuzzy, annotateMedia} from "src/util/misc"
|
||||
import {writable} from "svelte/store"
|
||||
import {annotateMedia} from "src/util/misc"
|
||||
import {displayPerson} from "src/util/nostr"
|
||||
import Button from "src/partials/Button.svelte"
|
||||
import Compose from "src/partials/Compose.svelte"
|
||||
import ImageInput from "src/partials/ImageInput.svelte"
|
||||
import Media from "src/partials/Media.svelte"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import RelayCardSimple from "src/partials/RelayCardSimple.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
import Heading from "src/partials/Heading.svelte"
|
||||
import RelayCard from "src/app2/shared/RelayCard.svelte"
|
||||
import RelaySearch from "src/app2/shared/RelaySearch.svelte"
|
||||
import {getUserWriteRelays} from "src/agent/relays"
|
||||
import {getPersonWithFallback} from "src/agent/tables"
|
||||
import {watch} from "src/agent/storage"
|
||||
import cmd from "src/agent/cmd"
|
||||
import user from "src/agent/user"
|
||||
import {toast, modal} from "src/app/ui"
|
||||
@ -26,23 +26,11 @@
|
||||
export let pubkey = null
|
||||
export let nevent = null
|
||||
|
||||
let q = ""
|
||||
let image = null
|
||||
let compose = null
|
||||
let relays = getUserWriteRelays()
|
||||
let showSettings = false
|
||||
let q = ""
|
||||
let search
|
||||
|
||||
const knownRelays = watch("relays", t => t.all())
|
||||
|
||||
$: {
|
||||
const joined = new Set(pluck("url", relays))
|
||||
|
||||
search = fuzzy(
|
||||
$knownRelays.filter(r => !joined.has(r.url)),
|
||||
{keys: ["name", "description", "url"]}
|
||||
)
|
||||
}
|
||||
let relays = writable(getUserWriteRelays())
|
||||
|
||||
const onSubmit = async () => {
|
||||
let {content, mentions, topics} = compose.parse()
|
||||
@ -53,7 +41,7 @@
|
||||
|
||||
if (content) {
|
||||
const thunk = cmd.createNote(content.trim(), mentions, topics)
|
||||
const [event, promise] = await publishWithToast(relays, thunk)
|
||||
const [event, promise] = await publishWithToast($relays, thunk)
|
||||
|
||||
promise.then(() =>
|
||||
setTimeout(
|
||||
@ -66,7 +54,7 @@
|
||||
"/" +
|
||||
nip19.neventEncode({
|
||||
id: event.id,
|
||||
relays: pluck("url", relays.slice(0, 3)),
|
||||
relays: pluck("url", $relays.slice(0, 3)),
|
||||
}),
|
||||
},
|
||||
}),
|
||||
@ -85,11 +73,11 @@
|
||||
|
||||
const addRelay = relay => {
|
||||
q = ""
|
||||
relays = relays.concat(relay)
|
||||
relays.update($r => $r.concat(relay))
|
||||
}
|
||||
|
||||
const removeRelay = relay => {
|
||||
relays = reject(propEq("url", relay.url), relays)
|
||||
relays.update(reject(propEq("url", relay.url)))
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
@ -134,7 +122,7 @@
|
||||
on:click={() => {
|
||||
showSettings = true
|
||||
}}>
|
||||
<span>Publishing to {quantify(relays.length, "relay")}</span>
|
||||
<span>Publishing to {quantify($relays.length, "relay")}</span>
|
||||
<i class="fa fa-edit" />
|
||||
</small>
|
||||
</div>
|
||||
@ -150,7 +138,7 @@
|
||||
</div>
|
||||
<div>Select which relays to publish to:</div>
|
||||
<div>
|
||||
{#each relays as relay}
|
||||
{#each $relays as relay}
|
||||
<div
|
||||
class="mr-1 mb-2 inline-block rounded-full border border-solid border-gray-1 py-1 px-2">
|
||||
<button
|
||||
@ -161,17 +149,21 @@
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<Input bind:value={q} placeholder="Search for other relays">
|
||||
<i slot="before" class="fa fa-search" />
|
||||
</Input>
|
||||
{#each (q ? search(q) : []).slice(0, 3) as relay (relay.url)}
|
||||
<RelayCardSimple {relay}>
|
||||
<button slot="actions" class="underline" on:click={() => addRelay(relay)}>
|
||||
Add relay
|
||||
</button>
|
||||
</RelayCardSimple>
|
||||
{/each}
|
||||
<Button type="submit" class="text-center">Done</Button>
|
||||
<RelaySearch bind:q limit={3} hideIfEmpty>
|
||||
<div slot="item" let:relay>
|
||||
<RelayCard {relay} showActions>
|
||||
<button
|
||||
slot="actions"
|
||||
class="underline"
|
||||
on:click|preventDefault={() => addRelay(relay)}>
|
||||
Add relay
|
||||
</button>
|
||||
</RelayCard>
|
||||
</div>
|
||||
<div slot="footer">
|
||||
<Button type="submit" class="w-full text-center">Done</Button>
|
||||
</div>
|
||||
</RelaySearch>
|
||||
</Content>
|
||||
</form>
|
||||
</Modal>
|
||||
|
@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import {reject, pluck, whereEq} from "ramda"
|
||||
import {reject, always, pluck, propEq} from "ramda"
|
||||
import {fuzzy} from "src/util/misc"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import Heading from "src/partials/Heading.svelte"
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import RelayCard from "src/partials/RelayCard.svelte"
|
||||
import RelayCard from "src/app2/shared/RelayCard.svelte"
|
||||
import {watch} from "src/agent/storage"
|
||||
import {modal} from "src/app/ui"
|
||||
|
||||
@ -16,22 +16,19 @@
|
||||
|
||||
const knownRelays = watch("relays", t => t.all())
|
||||
|
||||
$: {
|
||||
const joined = new Set(pluck("url", relays))
|
||||
|
||||
search = fuzzy(
|
||||
$knownRelays.filter(r => !joined.has(r.url)),
|
||||
{keys: ["name", "description", "url"]}
|
||||
)
|
||||
const removeRelay = r => {
|
||||
relays = reject(propEq("url", r.url), relays)
|
||||
}
|
||||
|
||||
const removeRelay = ({url}) => {
|
||||
relays = reject(whereEq({url}), relays)
|
||||
const addRelay = r => {
|
||||
relays = relays.concat({...r, write: true})
|
||||
}
|
||||
|
||||
const addRelay = relay => {
|
||||
relays = relays.concat({...relay, write: true})
|
||||
}
|
||||
$: joined = new Set(pluck("url", relays))
|
||||
$: search = fuzzy(
|
||||
$knownRelays.filter(r => !joined.has(r.url)),
|
||||
{keys: ["name", "description", "url"]}
|
||||
)
|
||||
</script>
|
||||
|
||||
<Content>
|
||||
@ -58,7 +55,7 @@
|
||||
{:else}
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
{#each relays as relay (relay.url)}
|
||||
<RelayCard {relay} {removeRelay} />
|
||||
<RelayCard {relay} hasRelay={always(true)} {removeRelay} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
@ -70,7 +67,7 @@
|
||||
<i slot="before" class="fa-solid fa-search" />
|
||||
</Input>
|
||||
{#each (search(q) || []).slice(0, 50) as relay (relay.url)}
|
||||
<RelayCard {relay} {addRelay} />
|
||||
<RelayCard {relay} hasRelay={always(false)} {addRelay} />
|
||||
{/each}
|
||||
<small class="text-center">
|
||||
Showing {Math.min($knownRelays.length - relays.length, 50)}
|
||||
|
@ -1,74 +0,0 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {last} from "ramda"
|
||||
import {onMount} from "svelte"
|
||||
import {poll, stringToHue, hsl} from "src/util/misc"
|
||||
import {between} from "hurdak/lib/hurdak"
|
||||
import {fly} from "svelte/transition"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import pool from "src/agent/pool"
|
||||
|
||||
export let relay
|
||||
export let theme = "gray-8"
|
||||
export let removeRelay = null
|
||||
export let addRelay = null
|
||||
|
||||
let quality = null
|
||||
let message = null
|
||||
let showStatus = false
|
||||
|
||||
onMount(() => {
|
||||
return poll(10_000, async () => {
|
||||
;[quality, message] = pool.getQuality(relay.url)
|
||||
})
|
||||
})
|
||||
</script>
|
||||
|
||||
<div
|
||||
class={cx(
|
||||
`bg-${theme}`,
|
||||
"flex flex-col justify-between gap-3 rounded border border-l-2 border-solid border-gray-6 py-3 px-6 shadow"
|
||||
)}
|
||||
style={`border-left-color: ${hsl(stringToHue(relay.url))}`}
|
||||
in:fly={{y: 20}}>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="flex items-center gap-2 text-xl">
|
||||
<i class={relay.url.startsWith("wss") ? "fa fa-lock" : "fa fa-unlock"} />
|
||||
<Anchor type="unstyled" href={`/relays/${btoa(relay.url)}`}>
|
||||
{last(relay.url.split("://"))}
|
||||
</Anchor>
|
||||
<span
|
||||
on:mouseout={() => {
|
||||
showStatus = false
|
||||
}}
|
||||
on:mouseover={() => {
|
||||
showStatus = true
|
||||
}}
|
||||
class="h-2 w-2 cursor-pointer rounded-full bg-gray-6"
|
||||
class:bg-gray-6={message === "Not connected"}
|
||||
class:bg-danger={quality <= 0.3 && message !== "Not connected"}
|
||||
class:bg-warning={between(0.3, 0.7, quality)}
|
||||
class:bg-success={quality > 0.7} />
|
||||
<p
|
||||
class="hidden text-sm text-gray-1 transition-all sm:block"
|
||||
class:opacity-0={!showStatus}
|
||||
class:opacity-1={showStatus}>
|
||||
{message}
|
||||
</p>
|
||||
</div>
|
||||
{#if removeRelay}
|
||||
<button class="flex items-center gap-3 text-gray-1" on:click={() => removeRelay(relay)}>
|
||||
<i class="fa fa-right-from-bracket" /> Leave
|
||||
</button>
|
||||
{/if}
|
||||
{#if addRelay}
|
||||
<button class="flex items-center gap-3 text-gray-1" on:click={() => addRelay(relay)}>
|
||||
<i class="fa fa-right-to-bracket" /> Join
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{#if relay.description}
|
||||
<p>{relay.description}</p>
|
||||
{/if}
|
||||
<slot name="controls" />
|
||||
</div>
|
@ -1,24 +0,0 @@
|
||||
<script lang="ts">
|
||||
import {last} from "ramda"
|
||||
import {fly} from "svelte/transition"
|
||||
import {stringToHue, hsl} from "src/util/misc"
|
||||
|
||||
export let relay
|
||||
</script>
|
||||
|
||||
<div
|
||||
class="flex flex-col justify-between gap-3 rounded border border-l-2 border-solid
|
||||
border-gray-6 py-3 px-6 shadow"
|
||||
style={`border-left-color: ${hsl(stringToHue(relay.url))}`}
|
||||
in:fly={{y: 20}}>
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="flex items-center gap-2 text-xl">
|
||||
<i class={relay.url.startsWith("wss") ? "fa fa-lock" : "fa fa-unlock"} />
|
||||
<span>{last(relay.url.split("://"))}</span>
|
||||
</div>
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
{#if relay.description}
|
||||
<p>{relay.description}</p>
|
||||
{/if}
|
||||
</div>
|
Loading…
Reference in New Issue
Block a user