mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-19 11:43:35 +00:00
Clean up Relay Card and onboarding data
This commit is contained in:
parent
c22e4e76a9
commit
6c0eab5214
@ -1,6 +1,6 @@
|
||||
# Current
|
||||
|
||||
- [ ] Check on RelayCard, it should automatically do the right thing for anon/pubkey
|
||||
- [ ] Details on note in modal is broken
|
||||
- [ ] Remember message/chat status
|
||||
- [ ] Image classification
|
||||
- https://github.com/bhky/opennsfw2
|
||||
|
@ -94,6 +94,13 @@ const Meta = {
|
||||
|
||||
const forceUrls = (import.meta.env.VITE_FORCE_RELAYS || "").split(",").filter(identity)
|
||||
|
||||
const defaultUrls = [
|
||||
"wss://nostr-pub.wellorder.net",
|
||||
"wss://nostr.zebedee.cloud",
|
||||
"wss://nos.lol",
|
||||
"wss://brb.io",
|
||||
]
|
||||
|
||||
const getUrls = relays => {
|
||||
if (relays.length === 0) {
|
||||
error(`Attempted to connect to zero urls`)
|
||||
@ -370,6 +377,7 @@ export default {
|
||||
Config,
|
||||
Meta,
|
||||
forceUrls,
|
||||
defaultUrls,
|
||||
disconnect,
|
||||
getQuality,
|
||||
publish,
|
||||
|
@ -185,6 +185,11 @@ export const sampleRelays = (relays, scale = 1) => {
|
||||
relays = relays.concat(shuffle(getUserReadRelays()).slice(0, limit - relays.length))
|
||||
}
|
||||
|
||||
// And if we still have nothing, add a default
|
||||
if (relays.length === 0) {
|
||||
relays = [{url: pool.forceUrls[0] || pool.defaultUrls[0]}]
|
||||
}
|
||||
|
||||
return uniqByUrl(relays)
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,13 @@ import {Tags} from "src/util/nostr"
|
||||
import {getPersonWithFallback} from "src/agent/db"
|
||||
import user from "src/agent/user"
|
||||
|
||||
export const defaultFollows = [
|
||||
"97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322", // hodlbod
|
||||
"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d", // fiatjaf
|
||||
"82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2", // jack
|
||||
"6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93", // Gigi
|
||||
]
|
||||
|
||||
export const getFollows = pubkey =>
|
||||
Tags.wrap(getPersonWithFallback(pubkey).petnames).type("p").values().all()
|
||||
|
||||
|
@ -88,6 +88,7 @@ export default {
|
||||
petnames,
|
||||
getPetnames: () => profileCopy.petnames,
|
||||
petnamePubkeys: derived(petnames, map(nth(1))) as Readable<Array<string>>,
|
||||
getPetnamePubkeys: () => profileCopy.petnames.map(nth(1)),
|
||||
updatePetnames(f) {
|
||||
const $petnames = f(profileCopy.petnames)
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
||||
{/if}
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each $relays as relay (relay.url)}
|
||||
<RelayCard showActions {relay} />
|
||||
<RelayCard {relay} />
|
||||
{:else}
|
||||
<div class="flex flex-col items-center gap-4 my-8">
|
||||
<div class="text-xl flex gap-2 items-center">
|
||||
@ -45,7 +45,7 @@
|
||||
</div>
|
||||
<RelaySearch>
|
||||
<div slot="item" let:relay>
|
||||
<RelayCard showActions {relay} />
|
||||
<RelayCard {relay} />
|
||||
</div>
|
||||
</RelaySearch>
|
||||
</Content>
|
||||
|
@ -312,7 +312,7 @@
|
||||
<p>This note was found on {quantify(note.seen_on.length, "relay")} below.</p>
|
||||
<div class="flex flex-col gap-2">
|
||||
{#each note.seen_on as url}
|
||||
<RelayCard theme="black" relay={{url}} />
|
||||
<RelayCard relay={{url}} />
|
||||
{/each}
|
||||
</div>
|
||||
<h1 class="staatliches text-2xl">Details</h1>
|
||||
|
@ -14,9 +14,9 @@
|
||||
export let person
|
||||
export let hasPetname = null
|
||||
|
||||
export let removePetname = ({pubkey}) => user.removePetname(pubkey)
|
||||
const removePetname = ({pubkey}) => user.removePetname(pubkey)
|
||||
|
||||
export let addPetname = ({pubkey}) => {
|
||||
const addPetname = ({pubkey}) => {
|
||||
const [{url}] = sampleRelays(getPubkeyWriteRelays(pubkey))
|
||||
|
||||
user.addPetname(pubkey, url, displayPerson(person))
|
||||
|
@ -16,9 +16,7 @@
|
||||
<div class="pt-8 text-center">No relays found</div>
|
||||
{:else}
|
||||
{#each relays as relay (relay.url)}
|
||||
{#if relay.write !== "!"}
|
||||
<RelayCard {relay} />
|
||||
{/if}
|
||||
<RelayCard {relay} />
|
||||
{/each}
|
||||
{/if}
|
||||
</Content>
|
||||
|
@ -14,7 +14,7 @@
|
||||
export let relay
|
||||
export let theme = "gray-8"
|
||||
export let showStatus = false
|
||||
export let showActions = false
|
||||
export let hideActions = false
|
||||
export let showControls = false
|
||||
|
||||
const {relays, canPublish} = user
|
||||
@ -23,11 +23,11 @@
|
||||
let quality = null
|
||||
let message = null
|
||||
|
||||
export let hasRelay = r => Boolean(find(propEq("url", r.url), $relays))
|
||||
$: hasRelay = Boolean(find(propEq("url", relay.url), $relays))
|
||||
|
||||
export let removeRelay = r => user.removeRelay(r.url)
|
||||
const removeRelay = r => user.removeRelay(r.url)
|
||||
|
||||
export let addRelay = r => {
|
||||
const addRelay = r => {
|
||||
user.addRelay(r.url)
|
||||
|
||||
const pubkey = user.getPubkey()
|
||||
@ -79,17 +79,16 @@
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{#if showActions}
|
||||
{#if !hideActions}
|
||||
<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)}
|
||||
{#if !hasRelay}
|
||||
<button class="flex items-center gap-3 text-gray-1" on:click={() => addRelay(relay)}>
|
||||
<i class="fa fa-right-to-bracket" /> Join
|
||||
</button>
|
||||
{:else if $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}
|
||||
</slot>
|
||||
{/if}
|
||||
@ -97,7 +96,8 @@
|
||||
{#if relay.description}
|
||||
<p>{relay.description}</p>
|
||||
{/if}
|
||||
{#if hasRelay(relay) && showControls && $canPublish}
|
||||
{#if hasRelay && showControls && $canPublish}
|
||||
<div class="-mx-6 my-1 h-px bg-gray-7" />
|
||||
<div class="flex justify-between gap-2">
|
||||
<span>Publish to this relay?</span>
|
||||
<Toggle
|
||||
|
@ -122,7 +122,7 @@
|
||||
{#each Object.values(currentRelays) as relay}
|
||||
<div class="h-12">
|
||||
{#if relay}
|
||||
<RelayCard relay={{...relay, description: null}} />
|
||||
<RelayCard hideActions relay={{...relay, description: null}} />
|
||||
{/if}
|
||||
</div>
|
||||
{/each}
|
||||
|
@ -151,7 +151,7 @@
|
||||
</div>
|
||||
<RelaySearch bind:q limit={3} hideIfEmpty>
|
||||
<div slot="item" let:relay>
|
||||
<RelayCard {relay} showActions>
|
||||
<RelayCard {relay}>
|
||||
<button
|
||||
slot="actions"
|
||||
class="underline"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {uniq, objOf} from "ramda"
|
||||
import {uniq} from "ramda"
|
||||
import {onMount} from "svelte"
|
||||
import {generatePrivateKey} from "nostr-tools"
|
||||
import {fly} from "svelte/transition"
|
||||
@ -11,11 +11,10 @@
|
||||
import OnboardingRelays from "src/app/views/OnboardingRelays.svelte"
|
||||
import OnboardingFollows from "src/app/views/OnboardingFollows.svelte"
|
||||
import OnboardingComplete from "src/app/views/OnboardingComplete.svelte"
|
||||
import {getFollows} from "src/agent/social"
|
||||
import {getFollows, defaultFollows} from "src/agent/social"
|
||||
import {getPubkeyWriteRelays, sampleRelays} from "src/agent/relays"
|
||||
import {getPersonWithFallback} from "src/agent/db"
|
||||
import network from "src/agent/network"
|
||||
import pool from "src/agent/pool"
|
||||
import user from "src/agent/user"
|
||||
import keys from "src/agent/keys"
|
||||
import {loadAppData} from "src/app/state"
|
||||
@ -23,39 +22,15 @@
|
||||
|
||||
export let stage
|
||||
|
||||
const {relays: userRelays, petnamePubkeys} = user
|
||||
|
||||
let relays = []
|
||||
if ($userRelays.length > 0) {
|
||||
relays = $userRelays
|
||||
} else if (pool.forceUrls.length > 0) {
|
||||
relays = pool.forceUrls.map(objOf("url"))
|
||||
} else {
|
||||
relays = [
|
||||
{url: "wss://nostr-pub.wellorder.net", write: true},
|
||||
{url: "wss://nostr.zebedee.cloud", write: true},
|
||||
{url: "wss://nos.lol", write: true},
|
||||
{url: "wss://brb.io", write: true},
|
||||
]
|
||||
}
|
||||
|
||||
let follows =
|
||||
$petnamePubkeys.length > 0
|
||||
? $petnamePubkeys
|
||||
: [
|
||||
"97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322", // hodlbod
|
||||
"3bf0c63fcb93463407af97a5e5ee64fa883d107ef9e558472c4eb9aaaefa459d", // fiatjaf
|
||||
"82341f882b6eabcd2ba7f1ef90aad961cf074af15b9ef44a09f9d2a8fbfbe6a2", // jack
|
||||
"6e468422dfb74a5738702a8823b9b28168abab8655faacb6853cd0ee15deee93", // Gigi
|
||||
]
|
||||
|
||||
const privkey = generatePrivateKey()
|
||||
|
||||
const signup = async () => {
|
||||
await keys.login("privkey", privkey)
|
||||
await user.updateRelays(() => relays)
|
||||
|
||||
// Re-save preferences now that we have a key
|
||||
await user.updateRelays(() => user.getRelays())
|
||||
await user.updatePetnames(() =>
|
||||
follows.map(pubkey => {
|
||||
user.getPetnamePubkeys().map(pubkey => {
|
||||
const [{url}] = sampleRelays(getPubkeyWriteRelays(pubkey))
|
||||
const name = displayPerson(getPersonWithFallback(pubkey))
|
||||
|
||||
@ -65,12 +40,15 @@
|
||||
|
||||
loadAppData(user.getPubkey())
|
||||
|
||||
modal.pop()
|
||||
modal.clear()
|
||||
navigate("/notes")
|
||||
}
|
||||
|
||||
// Prime our people cache for hardcoded follows and a sample of people they follow
|
||||
onMount(async () => {
|
||||
const relays = sampleRelays(user.getRelays())
|
||||
const follows = user.getPetnamePubkeys().concat(defaultFollows)
|
||||
|
||||
await network.loadPeople(follows, {relays})
|
||||
|
||||
const others = shuffle(uniq(follows.flatMap(getFollows))).slice(0, 256)
|
||||
@ -86,9 +64,9 @@
|
||||
{:else if stage === "key"}
|
||||
<OnboardingKey {privkey} />
|
||||
{:else if stage === "relays"}
|
||||
<OnboardingRelays bind:relays />
|
||||
<OnboardingRelays />
|
||||
{:else if stage === "follows"}
|
||||
<OnboardingFollows bind:follows />
|
||||
<OnboardingFollows />
|
||||
{:else}
|
||||
<OnboardingComplete {signup} />
|
||||
{/if}
|
||||
|
@ -1,34 +1,33 @@
|
||||
<script lang="ts">
|
||||
import {without, always} from "ramda"
|
||||
import {fuzzy} from "src/util/misc"
|
||||
import {reject} from "ramda"
|
||||
import {displayPerson} from "src/util/nostr"
|
||||
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 PersonInfo from "src/app/shared/PersonInfo.svelte"
|
||||
import {getPersonWithFallback} from "src/agent/db"
|
||||
import {watch} from "src/agent/db"
|
||||
import {getPersonWithFallback, searchPeople} from "src/agent/db"
|
||||
import {defaultFollows} from "src/agent/social"
|
||||
import {sampleRelays, getPubkeyWriteRelays} from "src/agent/relays"
|
||||
import {modal} from "src/partials/state"
|
||||
import user from "src/agent/user"
|
||||
|
||||
export let follows
|
||||
const {petnamePubkeys} = user
|
||||
|
||||
if ($petnamePubkeys.length === 0) {
|
||||
user.updatePetnames(() =>
|
||||
defaultFollows.map(pubkey => {
|
||||
const [{url}] = sampleRelays(getPubkeyWriteRelays(pubkey))
|
||||
const name = displayPerson(getPersonWithFallback(pubkey))
|
||||
|
||||
return ["p", pubkey, url, name]
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
let q = ""
|
||||
let search
|
||||
|
||||
const knownPeople = watch("people", t => t.all({"kind0.name": {$type: "string"}}))
|
||||
|
||||
$: search = fuzzy(
|
||||
$knownPeople.filter(p => !follows.includes(p.pubkey)),
|
||||
{keys: ["kind0.name", "kind0.about", "pubkey"]}
|
||||
)
|
||||
|
||||
const removePetname = ({pubkey}) => {
|
||||
follows = without([pubkey], follows)
|
||||
}
|
||||
|
||||
const addPetname = ({pubkey}) => {
|
||||
follows = follows.concat(pubkey)
|
||||
}
|
||||
$: results = reject(p => $petnamePubkeys.includes(p.pubkey), $searchPeople(q))
|
||||
</script>
|
||||
|
||||
<Content>
|
||||
@ -40,7 +39,7 @@
|
||||
</p>
|
||||
<Anchor
|
||||
type="button-accent"
|
||||
on:click={() => modal.push({type: "onboarding", stage: "complete"})}>
|
||||
on:click={() => modal.replace({type: "onboarding", stage: "complete"})}>
|
||||
Continue
|
||||
</Anchor>
|
||||
</Content>
|
||||
@ -48,17 +47,14 @@
|
||||
<i class="fa fa-user-astronaut fa-lg" />
|
||||
<h2 class="staatliches text-2xl">Your follows</h2>
|
||||
</div>
|
||||
{#if follows.length === 0}
|
||||
{#if $petnamePubkeys.length === 0}
|
||||
<div class="mt-8 flex items-center justify-center gap-2 text-center">
|
||||
<i class="fa fa-triangle-exclamation" />
|
||||
<span>No follows selected</span>
|
||||
</div>
|
||||
{:else}
|
||||
{#each follows as pubkey}
|
||||
<PersonInfo
|
||||
person={getPersonWithFallback(pubkey)}
|
||||
hasPetname={always(true)}
|
||||
{removePetname} />
|
||||
{#each $petnamePubkeys as pubkey}
|
||||
<PersonInfo person={getPersonWithFallback(pubkey)} />
|
||||
{/each}
|
||||
{/if}
|
||||
<div class="flex items-center gap-2">
|
||||
@ -68,7 +64,7 @@
|
||||
<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 person (person.pubkey)}
|
||||
<PersonInfo {person} hasPetname={always(false)} {addPetname} />
|
||||
{#each results.slice(0, 50) as person (person.pubkey)}
|
||||
<PersonInfo {person} />
|
||||
{/each}
|
||||
</Content>
|
||||
|
@ -19,7 +19,7 @@
|
||||
When you’re ready to dive in, click below and we’ll guide you through the process of creating an
|
||||
account.
|
||||
</p>
|
||||
<Anchor type="button-accent" on:click={() => modal.push({type: "onboarding", stage: "key"})}>
|
||||
<Anchor type="button-accent" on:click={() => modal.replace({type: "onboarding", stage: "key"})}>
|
||||
Let's go!
|
||||
</Anchor>
|
||||
</Content>
|
||||
|
@ -32,7 +32,7 @@
|
||||
</Input>
|
||||
<Anchor
|
||||
type="button-accent"
|
||||
on:click={() => modal.push({type: "onboarding", stage: nextStage})}>
|
||||
on:click={() => modal.replace({type: "onboarding", stage: nextStage})}>
|
||||
Log in
|
||||
</Anchor>
|
||||
</div>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import {reject, always, pluck, propEq} from "ramda"
|
||||
import {pluck} from "ramda"
|
||||
import {fuzzy} from "src/util/misc"
|
||||
import {modal} from "src/partials/state"
|
||||
import Input from "src/partials/Input.svelte"
|
||||
@ -8,23 +8,26 @@
|
||||
import Content from "src/partials/Content.svelte"
|
||||
import RelayCard from "src/app/shared/RelayCard.svelte"
|
||||
import {watch} from "src/agent/db"
|
||||
import pool from "src/agent/pool"
|
||||
import user from "src/agent/user"
|
||||
|
||||
export let relays
|
||||
const {relays} = user
|
||||
|
||||
if ($relays.length === 0) {
|
||||
user.updateRelays(() =>
|
||||
(pool.forceUrls.length > 0 ? pool.forceUrls : pool.defaultUrls).map(url => ({
|
||||
url,
|
||||
write: true,
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
||||
let q = ""
|
||||
let search
|
||||
|
||||
const knownRelays = watch("relays", t => t.all())
|
||||
|
||||
const removeRelay = r => {
|
||||
relays = reject(propEq("url", r.url), relays)
|
||||
}
|
||||
|
||||
const addRelay = r => {
|
||||
relays = relays.concat({...r, write: true})
|
||||
}
|
||||
|
||||
$: joined = new Set(pluck("url", relays))
|
||||
$: joined = new Set(pluck("url", $relays))
|
||||
$: search = fuzzy(
|
||||
$knownRelays.filter(r => !joined.has(r.url)),
|
||||
{keys: ["name", "description", "url"]}
|
||||
@ -32,32 +35,33 @@
|
||||
</script>
|
||||
|
||||
<Content>
|
||||
<Content class="text-center">
|
||||
<div class="text-center">
|
||||
<Heading>Get Connected</Heading>
|
||||
<p>
|
||||
Nostr is a protocol, not a platform. This means that <i>you</i> choose where to store your data.
|
||||
Select your preferred storage relays below, or click "continue" to use some reasonable defaults.
|
||||
You can change your selection any time.
|
||||
</p>
|
||||
<Anchor
|
||||
type="button-accent"
|
||||
on:click={() => modal.push({type: "onboarding", stage: "follows"})}>
|
||||
Continue
|
||||
</Anchor>
|
||||
</Content>
|
||||
</div>
|
||||
<Anchor
|
||||
type="button-accent"
|
||||
class="text-center"
|
||||
on:click={() => modal.replace({type: "onboarding", stage: "follows"})}>
|
||||
Continue
|
||||
</Anchor>
|
||||
<div class="flex items-center gap-2">
|
||||
<i class="fa fa-server fa-lg" />
|
||||
<h2 class="staatliches text-2xl">Your relays</h2>
|
||||
</div>
|
||||
{#if relays.length === 0}
|
||||
{#if $relays.length === 0}
|
||||
<div class="mt-8 flex items-center justify-center gap-2 text-center">
|
||||
<i class="fa fa-triangle-exclamation" />
|
||||
<span>No relays connected</span>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
{#each relays as relay (relay.url)}
|
||||
<RelayCard {relay} hasRelay={always(true)} {removeRelay} />
|
||||
{#each $relays as relay (relay.url)}
|
||||
<RelayCard {relay} />
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
@ -69,10 +73,10 @@
|
||||
<i slot="before" class="fa-solid fa-search" />
|
||||
</Input>
|
||||
{#each (search(q) || []).slice(0, 50) as relay (relay.url)}
|
||||
<RelayCard {relay} hasRelay={always(false)} {addRelay} />
|
||||
<RelayCard {relay} />
|
||||
{/each}
|
||||
<small class="text-center">
|
||||
Showing {Math.min($knownRelays.length - relays.length, 50)}
|
||||
of {$knownRelays.length - relays.length} known relays
|
||||
Showing {Math.min($knownRelays.length - $relays.length, 50)}
|
||||
of {$knownRelays.length - $relays.length} known relays
|
||||
</small>
|
||||
</Content>
|
||||
|
@ -35,7 +35,7 @@
|
||||
{/if}
|
||||
<div class="grid grid-cols-1 gap-4">
|
||||
{#each $relays as relay (relay.url)}
|
||||
<RelayCard showActions showControls {relay} />
|
||||
<RelayCard showControls {relay} />
|
||||
{/each}
|
||||
</div>
|
||||
<div class="flex flex-col gap-6" in:fly={{y: 20}}>
|
||||
@ -48,11 +48,7 @@
|
||||
Coracle automatically discovers relays as you browse the network. Adding more relays will
|
||||
generally make things quicker to load, at the expense of higher data usage.
|
||||
</p>
|
||||
<RelaySearch>
|
||||
<div slot="item" let:relay>
|
||||
<RelayCard showActions {relay} />
|
||||
</div>
|
||||
</RelaySearch>
|
||||
<RelaySearch />
|
||||
</div>
|
||||
</Content>
|
||||
</div>
|
||||
|
Loading…
Reference in New Issue
Block a user