forked from coracle/flotilla
Add profile page
This commit is contained in:
@@ -2,11 +2,19 @@
|
||||
|
||||
A discord-like nostr client based on the idea of "relays as groups". WIP.
|
||||
|
||||
# Notes
|
||||
# Todo
|
||||
|
||||
- [ ] NIP 17 dms/chats
|
||||
- [ ] Hook up donate buttons
|
||||
- [ ] Profile settings
|
||||
- [ ] Relay settings
|
||||
|
||||
------
|
||||
|
||||
- [ ] If the user isn't following anyone, show warning/fallback on people/notes pages
|
||||
- [ ] Add person drawer with info and recent notes, where you can follow/mute them. Maybe same stuff as person search
|
||||
- [ ] If the user isn't following anyone, show warning/fallback on people/notes pages
|
||||
- [ ] Add react/reply to notes
|
||||
- [ ] Indicate cut-off images, allow user to expand
|
||||
- [ ] Sort/migrate repository data to keep important events
|
||||
- Get rid of stuff from spaces the user isn't currently a member of
|
||||
- [ ] Apply mutes
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<script lang="ts">
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
</script>
|
||||
|
||||
<div class="column gap-4">
|
||||
<div class="py-2">
|
||||
<h1 class="heading">What is a nostr address?</h1>
|
||||
</div>
|
||||
<p>
|
||||
Flotilla hosts spaces on the <Link external href="https://nostr.com/" class="underline">Nostr protocol</Link>.
|
||||
Nostr uses "nostr addresses" to make it easier for people to find you, without having to
|
||||
memorize your public key (your user id).
|
||||
</p>
|
||||
<p>
|
||||
There are several providers of nostr addresses, including several clients. You can find a
|
||||
list and more information on <Link external href="https://nostr.how/en/guides/get-verified" class="underline">nostr.how</Link>.
|
||||
</p>
|
||||
<Button class="btn btn-primary" on:click={() => history.back()}>Got it</Button>
|
||||
</div>
|
||||
@@ -8,7 +8,7 @@
|
||||
<h1 class="heading">What is a relay?</h1>
|
||||
</div>
|
||||
<p>
|
||||
Flotilla hosts spaces on the <Link external href="https://nostr.com/">Nostr protocol</Link>.
|
||||
Flotilla hosts spaces on the <Link external href="https://nostr.com/" class="underline">Nostr protocol</Link>.
|
||||
Nostr uses "relays" to host data, which are special-purpose servers that speak nostr's language.
|
||||
This means that anyone can host their own data, making the web more decentralized and resilient.
|
||||
</p>
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M22 10.5V12C22 16.714 22 19.0711 20.5355 20.5355C19.0711 22 16.714 22 12 22C7.28595 22 4.92893 22 3.46447 20.5355C2 19.0711 2 16.714 2 12C2 7.28595 2 4.92893 3.46447 3.46447C4.92893 2 7.28595 2 12 2H13.5" stroke="#1C274C" stroke-width="1.5" stroke-linecap="round"/>
|
||||
<path d="M16.652 3.45506L17.3009 2.80624C18.3759 1.73125 20.1188 1.73125 21.1938 2.80624C22.2687 3.88124 22.2687 5.62415 21.1938 6.69914L20.5449 7.34795M16.652 3.45506C16.652 3.45506 16.7331 4.83379 17.9497 6.05032C19.1662 7.26685 20.5449 7.34795 20.5449 7.34795M16.652 3.45506L10.6872 9.41993C10.2832 9.82394 10.0812 10.0259 9.90743 10.2487C9.70249 10.5114 9.52679 10.7957 9.38344 11.0965C9.26191 11.3515 9.17157 11.6225 8.99089 12.1646L8.41242 13.9M20.5449 7.34795L14.5801 13.3128C14.1761 13.7168 13.9741 13.9188 13.7513 14.0926C13.4886 14.2975 13.2043 14.4732 12.9035 14.6166C12.6485 14.7381 12.3775 14.8284 11.8354 15.0091L10.1 15.5876M10.1 15.5876L8.97709 15.9619C8.71035 16.0508 8.41626 15.9814 8.21744 15.7826C8.01862 15.5837 7.9492 15.2897 8.03811 15.0229L8.41242 13.9M10.1 15.5876L8.41242 13.9" stroke="#1C274C" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -14,6 +14,7 @@
|
||||
import Document from "@assets/icons/Document.svg?dataurl"
|
||||
import Earth from "@assets/icons/Earth.svg?dataurl"
|
||||
import Pen from "@assets/icons/Pen.svg?dataurl"
|
||||
import PenNewSquare from "@assets/icons/Pen New Square.svg?dataurl"
|
||||
import HeadphonesRound from "@assets/icons/Headphones Round.svg?dataurl"
|
||||
import AddCircle from "@assets/icons/Add Circle.svg?dataurl"
|
||||
import AltArrowDown from "@assets/icons/Alt Arrow Down.svg?dataurl"
|
||||
@@ -80,6 +81,7 @@
|
||||
document: Document,
|
||||
earth: Earth,
|
||||
pen: Pen,
|
||||
'pen-new-square': PenNewSquare,
|
||||
"headphones-round": HeadphonesRound,
|
||||
"add-circle": AddCircle,
|
||||
"alt-arrow-down": AltArrowDown,
|
||||
|
||||
@@ -15,20 +15,25 @@
|
||||
<SecondaryNavSection>
|
||||
<div in:fly|local>
|
||||
<SecondaryNavItem href="/settings">
|
||||
<Icon icon="user-circle" /> Profile
|
||||
<Icon icon="settings" /> Settings
|
||||
</SecondaryNavItem>
|
||||
</div>
|
||||
<div in:fly|local={{delay: 50}}>
|
||||
<SecondaryNavItem href="/settings/profile">
|
||||
<Icon icon="user-circle" /> Profile
|
||||
</SecondaryNavItem>
|
||||
</div>
|
||||
<div in:fly|local={{delay: 100}}>
|
||||
<SecondaryNavItem href="/settings/relays">
|
||||
<Icon icon="remote-controller-minimalistic" /> Relays
|
||||
</SecondaryNavItem>
|
||||
</div>
|
||||
<div in:fly|local={{delay: 100}}>
|
||||
<div in:fly|local={{delay: 150}}>
|
||||
<SecondaryNavItem href="/settings/about">
|
||||
<Icon icon="info-square" /> About
|
||||
</SecondaryNavItem>
|
||||
</div>
|
||||
<div in:fly|local={{delay: 150}}>
|
||||
<div in:fly|local={{delay: 200}}>
|
||||
<SecondaryNavItem class="text-error hover:text-error" on:click={logout}>
|
||||
<Icon icon="exit" /> Log Out
|
||||
</SecondaryNavItem>
|
||||
|
||||
@@ -22,10 +22,7 @@
|
||||
<div class="card2 flex flex-col gap-2 text-center shadow-2xl">
|
||||
<h3 class="text-2xl sm:h-12">Get in touch</h3>
|
||||
<p class="sm:h-16">Having problems? Let us know by filing an issue.</p>
|
||||
<Link
|
||||
external
|
||||
class="btn btn-primary"
|
||||
href="https://github.com/coracle-social/flotilla/issues/new">
|
||||
<Link class="btn btn-primary" href="/home/97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322">
|
||||
Open an Issue
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
<script lang="ts">
|
||||
import {nip19} from 'nostr-tools'
|
||||
import {last, ctx} from "@welshman/lib"
|
||||
import {PROFILE, createEvent, displayPubkey, displayProfile, makeProfile, editProfile, createProfile, isPublishedProfile} from "@welshman/util"
|
||||
import {pubkey, getProfile, displayHandle, makeThunk, publishThunk} from "@welshman/app"
|
||||
import {slide} from '@lib/transition'
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Field from '@lib/components/Field.svelte'
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Avatar from "@lib/components/Avatar.svelte"
|
||||
import InputProfilePicture from "@lib/components/InputProfilePicture.svelte"
|
||||
import Content from '@app/components/Content.svelte'
|
||||
import InfoHandle from '@app/components/InfoHandle.svelte'
|
||||
import {pushModal} from "@app/modal"
|
||||
import {pushToast} from "@app/toast"
|
||||
|
||||
const npub = nip19.npubEncode($pubkey!)
|
||||
const pubkeyDisplay = displayPubkey($pubkey!)
|
||||
|
||||
const displayNip05 = (nip05: string) =>
|
||||
nip05?.startsWith("_@") ? last(nip05.split("@")) : nip05
|
||||
|
||||
const toggleEdit = () => {
|
||||
editing = !editing
|
||||
}
|
||||
|
||||
const stopEdit = () => {
|
||||
editing = false
|
||||
profile = getProfile($pubkey!) || makeProfile()
|
||||
}
|
||||
|
||||
const saveEdit = () => {
|
||||
const relays = ctx.app.router.WriteRelays().getUrls()
|
||||
const template = isPublishedProfile(profile) ? editProfile(profile) : createProfile(profile)
|
||||
const event = createEvent(template.kind, template)
|
||||
|
||||
publishThunk(makeThunk({event, relays}))
|
||||
pushToast({message: "Your profile has been updated!"})
|
||||
editing = false
|
||||
}
|
||||
|
||||
let file: File
|
||||
let editing = false
|
||||
let profile = getProfile($pubkey!) || makeProfile()
|
||||
</script>
|
||||
|
||||
<div class="content column gap-4">
|
||||
<div class="card bg-base-100 shadow-xl">
|
||||
<div class="card-body">
|
||||
<div class="flex gap-2 justify-between">
|
||||
<div class="flex gap-3 max-w-full">
|
||||
<div class="py-1">
|
||||
<Avatar src={profile?.picture} size={10} />
|
||||
</div>
|
||||
<div class="flex flex-col min-w-0">
|
||||
<div class="flex gap-2 items-center">
|
||||
<div class="text-bold text-ellipsis overflow-hidden">
|
||||
{displayProfile(profile, pubkeyDisplay)}
|
||||
</div>
|
||||
</div>
|
||||
<div class="text-sm opacity-75 text-ellipsis overflow-hidden">
|
||||
{profile?.nip05 ? displayNip05(profile.nip05) : pubkeyDisplay}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button class="btn btn-neutral btn-circle w-12 h-12 center -mt-4 -mr-4" on:click={toggleEdit}>
|
||||
<Icon icon="pen-new-square" />
|
||||
</Button>
|
||||
</div>
|
||||
{#key profile.about}
|
||||
<Content event={{content: profile.about, tags: []}} hideMedia />
|
||||
{/key}
|
||||
</div>
|
||||
</div>
|
||||
{#if editing}
|
||||
<form class="card bg-base-100 shadow-xl" transition:slide on:submit|preventDefault={saveEdit}>
|
||||
<div class="card-body">
|
||||
<div class="flex justify-center py-2">
|
||||
<InputProfilePicture bind:file bind:url={profile.picture} />
|
||||
</div>
|
||||
<Field>
|
||||
<p slot="label">Username</p>
|
||||
<label class="input input-bordered flex w-full items-center gap-2" slot="input">
|
||||
<Icon icon="user-circle" />
|
||||
<input bind:value={profile.name} class="grow" type="text" />
|
||||
</label>
|
||||
</Field>
|
||||
<Field>
|
||||
<p slot="label">About You</p>
|
||||
<textarea class="textarea textarea-bordered leading-4" rows="3" bind:value={profile.about} slot="input" />
|
||||
</Field>
|
||||
<Field>
|
||||
<p slot="label">Address</p>
|
||||
<label class="input input-bordered flex w-full items-center gap-2" slot="input">
|
||||
<Icon icon="remote-controller-minimalistic" />
|
||||
<input bind:value={profile.nip05} class="grow" type="text" />
|
||||
</label>
|
||||
<p slot="info">
|
||||
<Button class="link" on:click={() => pushModal(InfoHandle)}>What is a nostr address?</Button>
|
||||
</p>
|
||||
</Field>
|
||||
<div class="flex flex-row items-center justify-between gap-4 mt-4">
|
||||
<Button class="btn btn-neutral" on:click={stopEdit}>
|
||||
Discard Changes
|
||||
</Button>
|
||||
<Button type="submit" class="btn btn-primary">
|
||||
Save Changes
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{/if}
|
||||
</div>
|
||||
Reference in New Issue
Block a user