forked from coracle/flotilla
Add profile detail modal
This commit is contained in:
@@ -11,16 +11,16 @@
|
||||
import {isMobile} from "@lib/html"
|
||||
import LongPress from "@lib/components/LongPress.svelte"
|
||||
import Avatar from "@lib/components/Avatar.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Content from "@app/components/Content.svelte"
|
||||
import ThunkStatus from "@app/components/ThunkStatus.svelte"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
import ReactionSummary from "@app/components/ReactionSummary.svelte"
|
||||
import ChannelMessageEmojiButton from "@app/components/ChannelMessageEmojiButton.svelte"
|
||||
import ChannelMessageMenuButton from "@app/components/ChannelMessageMenuButton.svelte"
|
||||
import ChannelMessageMenuMobile from "@app/components/ChannelMessageMenuMobile.svelte"
|
||||
import {colors, tagRoom, pubkeyLink, PROTECTED} from "@app/state"
|
||||
import {colors, tagRoom, PROTECTED} from "@app/state"
|
||||
import {publishDelete, publishReaction} from "@app/commands"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
@@ -39,6 +39,8 @@
|
||||
|
||||
const onLongPress = () => pushModal(ChannelMessageMenuMobile, {url, event})
|
||||
|
||||
const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey})
|
||||
|
||||
const onReactionClick = (content: string, events: TrustedEvent[]) => {
|
||||
const reaction = events.find(e => e.pubkey === $pubkey)
|
||||
|
||||
@@ -61,22 +63,18 @@
|
||||
class="group relative flex w-full cursor-default flex-col p-2 pb-3 text-left">
|
||||
<div class="flex w-full gap-3 overflow-auto">
|
||||
{#if showPubkey}
|
||||
<Link external href={pubkeyLink(event.pubkey)} class="flex items-start">
|
||||
<Button on:click={openProfile} class="flex items-start">
|
||||
<Avatar src={$profile?.picture} class="border border-solid border-base-content" size={8} />
|
||||
</Link>
|
||||
</Button>
|
||||
{:else}
|
||||
<div class="w-8 min-w-8 max-w-8" />
|
||||
{/if}
|
||||
<div class="min-w-0 flex-grow pr-1">
|
||||
{#if showPubkey}
|
||||
<div class="flex items-center gap-2">
|
||||
<Link
|
||||
external
|
||||
href={pubkeyLink(event.pubkey)}
|
||||
class="text-sm font-bold"
|
||||
style="color: {colorValue}">
|
||||
<Button on:click={openProfile} class="text-sm font-bold" style="color: {colorValue}">
|
||||
{$profileDisplay}
|
||||
</Link>
|
||||
</Button>
|
||||
<span class="text-xs opacity-50">{formatTimestampAsTime(event.created_at)}</span>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -32,10 +32,11 @@
|
||||
import ProfileName from "@app/components/ProfileName.svelte"
|
||||
import ProfileCircle from "@app/components/ProfileCircle.svelte"
|
||||
import ProfileCircles from "@app/components/ProfileCircles.svelte"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
import ProfileList from "@app/components/ProfileList.svelte"
|
||||
import ChatMessage from "@app/components/ChatMessage.svelte"
|
||||
import ChatCompose from "@app/components/ChannelCompose.svelte"
|
||||
import {userSettingValues, deriveChat, splitChatId, PLATFORM_NAME, pubkeyLink} from "@app/state"
|
||||
import {userSettingValues, deriveChat, splitChatId, PLATFORM_NAME} from "@app/state"
|
||||
import {pushModal} from "@app/modal"
|
||||
import {sendWrapped} from "@app/commands"
|
||||
|
||||
@@ -125,10 +126,11 @@
|
||||
<div slot="title" class="flex flex-col gap-1 sm:flex-row sm:gap-2">
|
||||
{#if others.length === 1}
|
||||
{@const pubkey = others[0]}
|
||||
<Link external href={pubkeyLink(pubkey)} class="row-2">
|
||||
{@const onClick = () => pushModal(ProfileDetail, {pubkey})}
|
||||
<Button on:click={onClick} class="row-2">
|
||||
<ProfileCircle {pubkey} size={5} />
|
||||
<ProfileName {pubkey} />
|
||||
</Link>
|
||||
</Button>
|
||||
{:else}
|
||||
<div class="flex items-center gap-2">
|
||||
<ProfileCircles pubkeys={others} size={5} />
|
||||
|
||||
@@ -11,16 +11,17 @@
|
||||
} from "@welshman/app"
|
||||
import {isMobile} from "@lib/html"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Tippy from "@lib/components/Tippy.svelte"
|
||||
import LongPress from "@lib/components/LongPress.svelte"
|
||||
import Avatar from "@lib/components/Avatar.svelte"
|
||||
import Content from "@app/components/Content.svelte"
|
||||
import ReactionSummary from "@app/components/ReactionSummary.svelte"
|
||||
import ThunkStatus from "@app/components/ThunkStatus.svelte"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
import ChatMessageMenu from "@app/components/ChatMessageMenu.svelte"
|
||||
import ChatMessageMenuMobile from "@app/components/ChatMessageMenuMobile.svelte"
|
||||
import {colors, pubkeyLink} from "@app/state"
|
||||
import {colors} from "@app/state"
|
||||
import {makeDelete, makeReaction, sendWrapped} from "@app/commands"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
@@ -42,6 +43,8 @@
|
||||
await sendWrapped({template, pubkeys})
|
||||
}
|
||||
|
||||
const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey})
|
||||
|
||||
const showMobileMenu = () => pushModal(ChatMessageMenuMobile, {event, pubkeys})
|
||||
|
||||
const togglePopover = () => {
|
||||
@@ -94,21 +97,20 @@
|
||||
{#if showPubkey}
|
||||
<div class="flex items-center gap-2">
|
||||
{#if !isOwn}
|
||||
<Link external href={pubkeyLink(event.pubkey)} class="flex items-center gap-1">
|
||||
<Button on:click={openProfile} class="flex items-center gap-1">
|
||||
<Avatar
|
||||
src={$profile?.picture}
|
||||
class="border border-solid border-base-content"
|
||||
size={4} />
|
||||
<div class="flex items-center gap-2">
|
||||
<Link
|
||||
external
|
||||
href={pubkeyLink(event.pubkey)}
|
||||
<Button
|
||||
on:click={openProfile}
|
||||
class="text-sm font-bold"
|
||||
style="color: {colorValue}">
|
||||
{$profileDisplay}
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</Link>
|
||||
</Button>
|
||||
{/if}
|
||||
<span class="text-xs opacity-50">{formatTimestampAsTime(event.created_at)}</span>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
<script lang="ts">
|
||||
import {displayProfile} from "@welshman/util"
|
||||
import {deriveProfile} from "@welshman/app"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import {pubkeyLink} from "@app/state"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
export let value
|
||||
|
||||
const profile = deriveProfile(value.pubkey)
|
||||
|
||||
const openProfile = () => pushModal(ProfileDetail, {pubkey: value.pubkey})
|
||||
</script>
|
||||
|
||||
<Link external href={pubkeyLink(value.pubkey)} class="link-content">
|
||||
<Button on:click={openProfile} class="link-content">
|
||||
@{displayProfile($profile)}
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
@@ -90,7 +90,7 @@
|
||||
<PrimaryNavItem title="Search" href="/people">
|
||||
<Avatar icon="magnifer" class="!h-10 !w-10" />
|
||||
</PrimaryNavItem>
|
||||
<PrimaryNavItem title="Notes" href="/notes">
|
||||
<PrimaryNavItem title="Notes" on:click={openNotes}>
|
||||
<Avatar icon="notes-minimalistic" class="!h-10 !w-10" />
|
||||
</PrimaryNavItem>
|
||||
<PrimaryNavItem
|
||||
|
||||
@@ -9,10 +9,11 @@
|
||||
displayHandle,
|
||||
deriveProfileDisplay,
|
||||
} from "@welshman/app"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Avatar from "@lib/components/Avatar.svelte"
|
||||
import WotScore from "@lib/components/WotScore.svelte"
|
||||
import {pubkeyLink} from "@app/state"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
export let pubkey
|
||||
|
||||
@@ -21,19 +22,21 @@
|
||||
const handle = deriveHandleForPubkey(pubkey)
|
||||
const score = deriveUserWotScore(pubkey)
|
||||
|
||||
const openProfile = () => pushModal(ProfileDetail, {pubkey})
|
||||
|
||||
$: following =
|
||||
pubkey === $session!.pubkey || getPubkeyTagValues(getListTags($userFollows)).includes(pubkey)
|
||||
</script>
|
||||
|
||||
<div class="flex max-w-full gap-3">
|
||||
<Link external href={pubkeyLink(pubkey)} class="py-1">
|
||||
<Button on:click={openProfile} class="py-1">
|
||||
<Avatar src={$profile?.picture} size={10} />
|
||||
</Link>
|
||||
</Button>
|
||||
<div class="flex min-w-0 flex-col">
|
||||
<div class="flex items-center gap-2">
|
||||
<Link external href={pubkeyLink(pubkey)} class="text-bold overflow-hidden text-ellipsis">
|
||||
<Button on:click={openProfile} class="text-bold overflow-hidden text-ellipsis">
|
||||
{$profileDisplay}
|
||||
</Link>
|
||||
</Button>
|
||||
<WotScore score={$score} active={following} />
|
||||
</div>
|
||||
<div class="overflow-hidden text-ellipsis text-sm opacity-75">
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
<script lang="ts">
|
||||
import {goto} from "$app/navigation"
|
||||
import {displayPubkey, getPubkeyTagValues, getListTags} from "@welshman/util"
|
||||
import {
|
||||
session,
|
||||
userFollows,
|
||||
deriveUserWotScore,
|
||||
deriveProfile,
|
||||
deriveHandleForPubkey,
|
||||
displayHandle,
|
||||
deriveProfileDisplay,
|
||||
} from "@welshman/app"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Avatar from "@lib/components/Avatar.svelte"
|
||||
import WotScore from "@lib/components/WotScore.svelte"
|
||||
import ModalFooter from "@lib/components/ModalFooter.svelte"
|
||||
import ProfileInfo from "@app/components/ProfileInfo.svelte"
|
||||
import ChatEnable from "@app/components/ChatEnable.svelte"
|
||||
import {canDecrypt, pubkeyLink} from "@app/state"
|
||||
import {pushModal} from "@app/modal"
|
||||
import {makeChatPath} from "@app/routes"
|
||||
|
||||
export let pubkey
|
||||
|
||||
const profile = deriveProfile(pubkey)
|
||||
const profileDisplay = deriveProfileDisplay(pubkey)
|
||||
const handle = deriveHandleForPubkey(pubkey)
|
||||
const score = deriveUserWotScore(pubkey)
|
||||
|
||||
const back = () => history.back()
|
||||
|
||||
const chatPath = makeChatPath([pubkey])
|
||||
|
||||
const openChat = () => ($canDecrypt ? goto(chatPath) : pushModal(ChatEnable, {next: chatPath}))
|
||||
|
||||
$: following =
|
||||
pubkey === $session!.pubkey || getPubkeyTagValues(getListTags($userFollows)).includes(pubkey)
|
||||
</script>
|
||||
|
||||
<div class="column gap-4">
|
||||
<div class="flex max-w-full gap-3">
|
||||
<span class="py-1">
|
||||
<Avatar src={$profile?.picture} size={10} />
|
||||
</span>
|
||||
<div class="flex min-w-0 flex-col">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="text-bold overflow-hidden text-ellipsis">
|
||||
{$profileDisplay}
|
||||
</span>
|
||||
<WotScore score={$score} active={following} />
|
||||
</div>
|
||||
<div class="overflow-hidden text-ellipsis text-sm opacity-75">
|
||||
{$handle ? displayHandle($handle) : displayPubkey(pubkey)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ProfileInfo {pubkey} />
|
||||
<ModalFooter>
|
||||
<Button on:click={back} class="btn btn-link">
|
||||
<Icon icon="alt-arrow-left" />
|
||||
Go back
|
||||
</Button>
|
||||
<div class="flex gap-2">
|
||||
<Link external href={pubkeyLink(pubkey)} class="btn btn-neutral">
|
||||
<Icon icon="user-circle" />
|
||||
See Complete Profile
|
||||
</Link>
|
||||
<Button on:click={openChat} class="btn btn-primary">
|
||||
<Icon icon="letter" />
|
||||
Open Chat
|
||||
</Button>
|
||||
</div>
|
||||
</ModalFooter>
|
||||
</div>
|
||||
@@ -5,12 +5,12 @@
|
||||
import {profileSearch} from "@welshman/app"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Tippy from "@lib/components/Tippy.svelte"
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Suggestions from "@lib/editor/Suggestions.svelte"
|
||||
import SuggestionProfile from "@lib/editor/SuggestionProfile.svelte"
|
||||
import ProfileName from "@app/components/ProfileName.svelte"
|
||||
import {pubkeyLink} from "@app/state"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
export let value: string[]
|
||||
export let autofocus = false
|
||||
@@ -48,13 +48,14 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
<div>
|
||||
{#each value as pubkey (pubkey)}
|
||||
{@const onClick = () => pushModal(ProfileDetail, {pubkey})}
|
||||
<div class="flex-inline badge badge-neutral mr-1 gap-1">
|
||||
<Button class="flex items-center" on:click={() => removePubkey(pubkey)}>
|
||||
<Icon icon="close-circle" size={4} class="-ml-1 mt-px" />
|
||||
</Button>
|
||||
<Link external href={pubkeyLink(pubkey)}>
|
||||
<Button on:click={onClick}>
|
||||
<ProfileName {pubkey} />
|
||||
</Link>
|
||||
</Button>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
@@ -4,15 +4,18 @@
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Content from "@app/components/Content.svelte"
|
||||
import ProfileName from "@app/components/ProfileName.svelte"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
import ThreadActions from "@app/components/ThreadActions.svelte"
|
||||
import {makeThreadPath} from "@app/routes"
|
||||
import {pubkeyLink} from "@app/state"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
export let url
|
||||
export let event
|
||||
export let hideActions = false
|
||||
|
||||
const title = event.tags.find(nthEq(0, "title"))?.[1]
|
||||
|
||||
const openProfile = () => pushModal(ProfileDetail, {pubkey: event.pubkey})
|
||||
</script>
|
||||
|
||||
<Link class="col-2 card2 bg-alt w-full cursor-pointer" href={makeThreadPath(url, event.id)}>
|
||||
@@ -32,9 +35,9 @@
|
||||
<div class="flex w-full flex-col items-end justify-between gap-2 sm:flex-row">
|
||||
<span class="whitespace-nowrap py-1 text-sm opacity-75">
|
||||
Posted by
|
||||
<Link external href={pubkeyLink(event.pubkey)} class="link-content">
|
||||
<button type="button" on:click|preventDefault={openProfile} class="link-content">
|
||||
@<ProfileName pubkey={event.pubkey} />
|
||||
</Link>
|
||||
</button>
|
||||
</span>
|
||||
{#if !hideActions}
|
||||
<ThreadActions showActivity {url} {event} />
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
<script lang="ts">
|
||||
import Link from "@lib/components/Link.svelte"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import {PLATFORM_NAME, pubkeyLink} from "@app/state"
|
||||
import ProfileDetail from "@app/components/ProfileDetail.svelte"
|
||||
import {PLATFORM_NAME} from "@app/state"
|
||||
import {pushModal} from "@app/modal"
|
||||
|
||||
const pubkey = "97c70a44366a6535c145b333f973ea86dfdc2d7a99da618c40c64705ad98e322"
|
||||
|
||||
const openProfile = () => pushModal(ProfileDetail, {pubkey})
|
||||
</script>
|
||||
|
||||
<div class="mt-8 min-h-screen bg-base-200 sm:hero">
|
||||
@@ -34,7 +39,7 @@
|
||||
<p class="text-sm">
|
||||
Built with 💜 by
|
||||
<span class="text-primary">
|
||||
@<Link external href={pubkeyLink(pubkey)} class="link">hodlbod</Link>
|
||||
@<Button on:click={openProfile} class="link">hodlbod</Button>
|
||||
</span>
|
||||
</p>
|
||||
<p class="text-xs">
|
||||
|
||||
@@ -120,8 +120,8 @@
|
||||
</div>
|
||||
<div class="grid grid-cols-3 gap-2">
|
||||
<Link href={threadsPath} class="btn btn-primary">
|
||||
<Icon icon="notes-minimalistic" />
|
||||
<div class="relative">
|
||||
<div class="relative flex items-center gap-2">
|
||||
<Icon icon="notes-minimalistic" />
|
||||
Threads
|
||||
{#if $notifications.has(threadsPath)}
|
||||
<div
|
||||
@@ -133,12 +133,12 @@
|
||||
{#each $userRooms as room (room)}
|
||||
{@const roomPath = makeRoomPath(url, room)}
|
||||
<Link href={roomPath} class="btn btn-neutral">
|
||||
{#if channelIsLocked($channelsById.get(makeChannelId(url, room)))}
|
||||
<Icon icon="lock" size={4} />
|
||||
{:else}
|
||||
<Icon icon="hashtag" />
|
||||
{/if}
|
||||
<div class="relative">
|
||||
<div class="relative flex min-w-0 items-center gap-2 overflow-hidden">
|
||||
{#if channelIsLocked($channelsById.get(makeChannelId(url, room)))}
|
||||
<Icon icon="lock" size={4} />
|
||||
{:else}
|
||||
<Icon icon="hashtag" />
|
||||
{/if}
|
||||
<ChannelName {url} {room} />
|
||||
{#if $notifications.has(roomPath)}
|
||||
<div
|
||||
@@ -150,12 +150,14 @@
|
||||
{/each}
|
||||
{#each $otherRooms as room (room)}
|
||||
<Link href={makeRoomPath(url, room)} class="btn btn-neutral">
|
||||
{#if channelIsLocked($channelsById.get(makeChannelId(url, room)))}
|
||||
<Icon icon="lock" size={4} />
|
||||
{:else}
|
||||
<Icon icon="hashtag" />
|
||||
{/if}
|
||||
<ChannelName {url} {room} />
|
||||
<div class="relative flex min-w-0 items-center gap-2 overflow-hidden">
|
||||
{#if channelIsLocked($channelsById.get(makeChannelId(url, room)))}
|
||||
<Icon icon="lock" size={4} />
|
||||
{:else}
|
||||
<Icon icon="hashtag" />
|
||||
{/if}
|
||||
<ChannelName {url} {room} />
|
||||
</div>
|
||||
</Link>
|
||||
{/each}
|
||||
<Button on:click={addRoom} class="btn btn-neutral">
|
||||
|
||||
Reference in New Issue
Block a user