Add profile and note to onboarding

This commit is contained in:
Jonathan Staab 2023-04-27 10:31:03 -05:00
parent dcdac88b75
commit 97d37eaca0
10 changed files with 130 additions and 43 deletions

View File

@ -1,5 +1,7 @@
# Current
- [ ] Enable global view via env var
- [ ] Ask for name/image, first post on signup
- [ ] Image classification
- https://github.com/bhky/opennsfw2

View File

@ -7,6 +7,8 @@ export const defaultFollows = (import.meta.env.VITE_DEFAULT_FOLLOWS || "")
.split(",")
.filter(identity)
console.log(defaultFollows)
export const getFollows = pubkey =>
Tags.wrap(getPersonWithFallback(pubkey).petnames).type("p").values().all()

View File

@ -7,10 +7,11 @@
import {shuffle} from "src/util/misc"
import {displayPerson} from "src/util/nostr"
import OnboardingIntro from "src/app/views/OnboardingIntro.svelte"
import OnboardingProfile from "src/app/views/OnboardingProfile.svelte"
import OnboardingKey from "src/app/views/OnboardingKey.svelte"
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 OnboardingNote from "src/app/views/OnboardingNote.svelte"
import {getFollows, defaultFollows} from "src/agent/social"
import {getPubkeyWriteRelays, sampleRelays} from "src/agent/relays"
import {getPersonWithFallback} from "src/agent/db"
@ -18,13 +19,14 @@
import user from "src/agent/user"
import pool from "src/agent/pool"
import keys from "src/agent/keys"
import cmd from "src/agent/cmd"
import {loadAppData} from "src/app/state"
import {modal} from "src/partials/state"
export let stage
const privkey = generatePrivateKey()
const profile = {}
const {relays} = user
if ($relays.length === 0) {
@ -36,19 +38,23 @@
)
}
const signup = async () => {
const signup = async note => {
await keys.login("privkey", privkey)
// Re-save preferences now that we have a key
await user.updateRelays(() => user.getRelays())
await user.updatePetnames(() =>
user.getPetnamePubkeys().map(pubkey => {
const [{url}] = sampleRelays(getPubkeyWriteRelays(pubkey))
const name = displayPerson(getPersonWithFallback(pubkey))
await Promise.all([
user.updateRelays(() => user.getRelays()),
cmd.updateUser(profile).publish(user.getRelays()),
note && cmd.createNote(note.content, note.mentions, note.topics).publish(user.getRelays()),
user.updatePetnames(() =>
user.getPetnamePubkeys().map(pubkey => {
const [{url}] = sampleRelays(getPubkeyWriteRelays(pubkey))
const name = displayPerson(getPersonWithFallback(pubkey))
return ["p", pubkey, url, name]
})
)
return ["p", pubkey, url, name]
})
),
])
loadAppData(user.getPubkey())
@ -73,14 +79,16 @@
<div in:fly={{y: 20}}>
{#if stage === "intro"}
<OnboardingIntro />
{:else if stage === "profile"}
<OnboardingProfile {profile} />
{:else if stage === "key"}
<OnboardingKey {privkey} />
{:else if stage === "relays"}
<OnboardingRelays />
{:else if stage === "follows"}
<OnboardingFollows />
{:else}
<OnboardingComplete {signup} />
{:else if stage === "note"}
<OnboardingNote {signup} />
{/if}
</div>
{/key}

View File

@ -1,27 +0,0 @@
<script lang="ts">
import Anchor from "src/partials/Anchor.svelte"
import Heading from "src/partials/Heading.svelte"
import Content from "src/partials/Content.svelte"
import Spinner from "src/partials/Spinner.svelte"
export let signup
let loading = false
const startSignup = () => {
loading = true
signup()
}
</script>
<Content size="lg" class="text-center">
<Heading>Welcome to Nostr</Heading>
<p>
Youre all set! If have any questions, or need any help, just ask. Your fellow nostriches are
always happy to lend a hand.
</p>
<Anchor {loading} type="button-accent" on:click={startSignup}>Get on Nostr</Anchor>
{#if loading}
<Spinner />
{/if}
</Content>

View File

@ -39,7 +39,7 @@
</p>
<Anchor
type="button-accent"
on:click={() => modal.replace({type: "onboarding", stage: "complete"})}>
on:click={() => modal.replace({type: "onboarding", stage: "note"})}>
Continue
</Anchor>
</Content>

View File

@ -19,7 +19,9 @@
When youre ready to dive in, click below and well guide you through the process of creating an
account.
</p>
<Anchor type="button-accent" on:click={() => modal.replace({type: "onboarding", stage: "key"})}>
<Anchor
type="button-accent"
on:click={() => modal.replace({type: "onboarding", stage: "profile"})}>
Let's go!
</Anchor>
</Content>

View File

@ -33,7 +33,7 @@
<Anchor
type="button-accent"
on:click={() => modal.replace({type: "onboarding", stage: nextStage})}>
Log in
Got it
</Anchor>
</div>
<p>If you don't want to save your keys now, you can find them later in {appName}'s settings.</p>

View File

@ -0,0 +1,36 @@
<script lang="ts">
import {onMount} from "svelte"
import Compose from "src/partials/Compose.svelte"
import Anchor from "src/partials/Anchor.svelte"
import Heading from "src/partials/Heading.svelte"
import Content from "src/partials/Content.svelte"
export let signup
let compose = null
const onSubmit = () => {
signup(compose.parse())
}
const skip = () => signup()
onMount(() => {
compose.write("Hello world! #introductions")
})
</script>
<Content size="lg">
<Heading class="text-center">Welcome to Nostr</Heading>
<p class="text-center">
Your're all set! If have any questions, just ask! People around these parts are always ready to
lend a hand.
</p>
<div class="border-l-2 border-solid border-gray-6 pl-4">
<Compose bind:this={compose} {onSubmit} />
</div>
<Anchor type="button-accent" class="flex-grow text-center" on:click={onSubmit}>Say Hello!</Anchor>
<Anchor type="unstyled" class="text-center" on:click={skip}>
Skip and see your feed <i class="fa fa-arrow-right" />
</Anchor>
</Content>

View File

@ -0,0 +1,46 @@
<script lang="ts">
import {modal} from "src/partials/state"
import Input from "src/partials/Input.svelte"
import Textarea from "src/partials/Textarea.svelte"
import ImageInput from "src/partials/ImageInput.svelte"
import Anchor from "src/partials/Anchor.svelte"
import Heading from "src/partials/Heading.svelte"
import Content from "src/partials/Content.svelte"
export let profile
</script>
<Content size="lg">
<Heading class="text-center">Introduce Yourself</Heading>
<p class="text-center">
Give other people something to go on. Remember that "privacy is the power to selectively reveal
oneself to the world".
</p>
<div class="flex flex-col gap-2">
<div class="flex flex-col gap-1">
<strong>Your Name</strong>
<Input type="text" name="name" wrapperClass="flex-grow" bind:value={profile.name}>
<i slot="before" class="fa-solid fa-user-astronaut" />
</Input>
</div>
<div class="flex flex-col gap-1">
<strong>About You</strong>
<Textarea name="about" bind:value={profile.about} />
</div>
<div class="flex flex-col gap-1">
<strong>Profile Picture</strong>
<ImageInput
bind:value={profile.picture}
icon="image-portrait"
maxWidth={480}
maxHeight={480} />
<p class="text-sm text-gray-1">Please be mindful of others and only use small images.</p>
</div>
</div>
<Anchor
type="button-accent"
class="text-center"
on:click={() => modal.replace({type: "onboarding", stage: "key"})}>
Continue
</Anchor>
</Content>

View File

@ -170,6 +170,24 @@
selection.collapse(input, 0)
}
export const write = text => {
const selection = window.getSelection()
const textNode = document.createTextNode(text)
selection.getRangeAt(0).insertNode(textNode)
selection.collapse(textNode, text.length)
autocomplete()
}
export const newlines = n => {
const selection = window.getSelection()
const newLines = createNewLines(2)
selection.getRangeAt(0).insertNode(newLines)
selection.collapse(newLines, 2)
}
export const parse = () => {
let {content, annotations} = contenteditable.parse()
const topics = pluck("value", annotations.filter(propEq("prefix", "#")))