<script lang="ts">
import type { BaseUrl, NodeIdentity, NodeStats } from "@http-client";
import * as utils from "@app/lib/utils";
import Button from "@app/components/Button.svelte";
import Command from "@app/components/Command.svelte";
import ExternalLink from "@app/components/ExternalLink.svelte";
import Icon from "@app/components/Icon.svelte";
import Id from "@app/components/Id.svelte";
import Layout from "@app/components/Layout.svelte";
import Link from "@app/components/Link.svelte";
import Popover from "@app/components/Popover.svelte";
import Separator from "@app/views/repos/Separator.svelte";
import UserAddress from "@app/views/users/UserAddress.svelte";
import UserAvatar from "@app/components/UserAvatar.svelte";
import UserReposView from "./UserReposView.svelte";
export let baseUrl: BaseUrl;
export let node: NodeIdentity;
export let did: { prefix: string; pubkey: string };
export let nodeAvatarUrl: string | undefined;
export let stats: NodeStats;
</script>
<style>
.sidebar {
padding: 1rem;
}
.sidebar-content {
gap: 1rem;
display: flex;
flex-direction: column;
}
.node-address {
display: flex;
align-items: center;
gap: 0.5rem;
margin-top: 0.5rem;
min-width: 0;
max-width: 100%;
}
.node-alias {
font: var(--txt-body-m-regular);
color: var(--color-text-tertiary);
border: 1px solid var(--color-border-alpha-subtle);
border-radius: var(--border-radius-sm);
padding: 0.25rem 0.5rem;
white-space: nowrap;
display: flex;
align-items: center;
gap: 0.25rem;
}
.follow-label {
display: block;
font: var(--txt-body-m-regular);
margin-bottom: 0.75rem;
}
.breadcrumbs {
display: flex;
align-items: center;
column-gap: 0.25rem;
font: var(--txt-body-m-regular);
white-space: nowrap;
flex-wrap: wrap;
}
.breadcrumb {
display: flex;
align-items: center;
gap: 0.25rem;
}
.breadcrumb :global(a:hover) {
color: var(--color-text-brand);
}
.avatar {
border-radius: var(--border-radius-md);
}
</style>
<Layout>
<svelte:fragment slot="breadcrumbs">
<div class="breadcrumbs">
<span class="breadcrumb">
<Link
style="display: flex; align-items: center; gap: 0.5rem;"
route={{
resource: "nodes",
params: {
baseUrl,
repoPageIndex: 0,
},
}}>
{#if nodeAvatarUrl}
<img
width="24"
height="24"
class="avatar"
alt="Node avatar"
src={nodeAvatarUrl} />
{:else}
<UserAvatar nodeId={baseUrl.hostname} styleWidth="1.5rem" />
{/if}
{baseUrl.hostname}
</Link>
</span>
<Separator />
<span class="breadcrumb">
<Link
ariaLabel="Home"
route={{
resource: "users",
baseUrl: baseUrl,
did: utils.formatDid(did),
}}>
{node.alias || utils.formatNodeId(did.pubkey)}
</Link>
</span>
</div>
</svelte:fragment>
<div slot="sidebar">
<!-- Banner/Avatar at top -->
{#if nodeAvatarUrl}
<img style:width="100%" alt="User banner" src={nodeAvatarUrl} />
{:else}
<UserAvatar nodeId={did.pubkey} styleWidth="100%" />
{/if}
<div class="sidebar">
<div class="sidebar-content">
<!-- User Alias -->
<div
class="global-flex-item"
style:width="100%"
style:justify-content="space-between">
<div
class="txt-heading-s txt-overflow"
style:flex="1"
style:min-width="0">
{node.alias || utils.formatNodeId(did.pubkey)}
</div>
<Popover popoverPositionTop="2.5rem" popoverPositionRight="0">
<Button
slot="toggle"
let:toggle
on:click={toggle}
variant="outline">
<div class="global-flex-item">
<Icon name="plus" />
<span>Follow</span>
</div>
</Button>
<div slot="popover" style:width="16rem">
<span class="follow-label">
Use the <ExternalLink href="https://radicle.dev">
Radicle CLI
</ExternalLink> to start following this user.
</span>
<span class="follow-label">
Following a user ensures that their contributions are fetched
onto your device.
</span>
<Command command={`rad follow ${did.pubkey}`} />
</div>
</Popover>
</div>
<div
style:flex-direction="column"
style:align-items="flex-start"
style:overflow="visible"
style:width="100%">
<div
style:flex-direction="column"
style:align-items="flex-start"
style:width="100%">
<div class="node-address">
<div class="node-alias">
<Icon name="key" />{node.alias || "user"}
</div>
<UserAddress {did} />
</div>
</div>
<div class="node-address">
<div class="node-alias">
<Icon name="key" />SSH Key
</div>
<Id styleWidth="fit-content" id={node.ssh.full}>
<div class="txt-overflow">
{node.ssh.full.substring(0, 10)}…{node.ssh.full.slice(-10)}
</div>
</Id>
</div>
<div class="node-address">
<div class="node-alias">
<Icon name="key" />SSH Hash
</div>
<Id styleWidth="fit-content" id={node.ssh.hash}>
<div class="txt-overflow">
{node.ssh.hash.substring(0, 10)}…{node.ssh.hash.slice(-10)}
</div>
</Id>
</div>
</div>
</div>
</div>
</div>
<div slot="center">
<UserReposView {baseUrl} {stats} user={node} {did} />
</div>
</Layout>