mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-18 19:23:40 +00:00
Add profile and note to onboarding
This commit is contained in:
parent
dcdac88b75
commit
97d37eaca0
@ -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
|
||||
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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}
|
||||
|
@ -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>
|
||||
You’re 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>
|
@ -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>
|
||||
|
@ -19,7 +19,9 @@
|
||||
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.replace({type: "onboarding", stage: "key"})}>
|
||||
<Anchor
|
||||
type="button-accent"
|
||||
on:click={() => modal.replace({type: "onboarding", stage: "profile"})}>
|
||||
Let's go!
|
||||
</Anchor>
|
||||
</Content>
|
||||
|
@ -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>
|
||||
|
36
src/app/views/OnboardingNote.svelte
Normal file
36
src/app/views/OnboardingNote.svelte
Normal 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>
|
46
src/app/views/OnboardingProfile.svelte
Normal file
46
src/app/views/OnboardingProfile.svelte
Normal 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>
|
@ -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", "#")))
|
||||
|
Loading…
Reference in New Issue
Block a user