add user profile details via a svelte store this sets a standard for abstracting ui from data wrappers even when multiple calls are neededmaster
|
After Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 54 KiB |
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 25 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
@ -0,0 +1,86 @@ |
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP |
||||||
|
|
||||||
|
exports[`Users/Header default smoke-test 1`] = ` |
||||||
|
<div class="flex my-2"> |
||||||
|
<div class="avatar flex-none"> |
||||||
|
<div class="w-8 h-8 rounded"> |
||||||
|
<img class="my-0" |
||||||
|
src="../test-profile-image.jpg" |
||||||
|
alt="DanConwayDev" |
||||||
|
> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="flex-auto pl-3 m-auto"> |
||||||
|
DanConwayDev |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`Users/Header displayName without name smoke-test 1`] = ` |
||||||
|
<div class="flex my-2"> |
||||||
|
<div class="avatar flex-none"> |
||||||
|
<div class="w-8 h-8 rounded"> |
||||||
|
<img class="my-0" |
||||||
|
src="../test-profile-image.jpg" |
||||||
|
alt="DanConwayDev" |
||||||
|
> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="flex-auto pl-3 m-auto"> |
||||||
|
DanConwayDev |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`Users/Header loading smoke-test 1`] = ` |
||||||
|
<div class="flex my-2"> |
||||||
|
<div class="avatar flex-none"> |
||||||
|
<div class="w-8 h-8 rounded skeleton"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="flex-auto pl-3 m-auto"> |
||||||
|
<div class="w-24 h-4 skeleton"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`Users/Header name and displayName shows name smoke-test 1`] = ` |
||||||
|
<div class="flex my-2"> |
||||||
|
<div class="avatar flex-none"> |
||||||
|
<div class="w-8 h-8 rounded"> |
||||||
|
<img class="my-0" |
||||||
|
src="../test-profile-image.jpg" |
||||||
|
alt="Dan" |
||||||
|
> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="flex-auto pl-3 m-auto"> |
||||||
|
Dan |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`Users/Header no image smoke-test 1`] = ` |
||||||
|
<div class="flex my-2"> |
||||||
|
<div class="avatar flex-none"> |
||||||
|
<div class="w-8 h-8 rounded bg-neutral"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="flex-auto pl-3 m-auto"> |
||||||
|
DanConwayDev |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
|
|
||||||
|
exports[`Users/Header not found smoke-test 1`] = ` |
||||||
|
<div class="flex my-2"> |
||||||
|
<div class="avatar flex-none"> |
||||||
|
<div class="w-8 h-8 rounded bg-neutral"> |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
<div class="flex-auto pl-3 m-auto"> |
||||||
|
npub18669... |
||||||
|
</div> |
||||||
|
</div> |
||||||
|
`; |
||||||
@ -1,31 +1,11 @@ |
|||||||
<script lang="ts" context="module"> |
<script lang="ts" context="module"> |
||||||
import type { NDKUserProfile } from "@nostr-dev-kit/ndk"; |
import type { NDKUserProfile } from "@nostr-dev-kit/ndk"; |
||||||
|
|
||||||
export interface Args { |
|
||||||
repo_id: string; |
|
||||||
name: string; |
|
||||||
description: string; |
|
||||||
git_server: string; |
|
||||||
tags: string[]; |
|
||||||
maintainers: User[]; |
|
||||||
relays: string[]; |
|
||||||
loading?: boolean; |
|
||||||
} |
|
||||||
export const defaults: Args = { |
|
||||||
repo_id: "", |
|
||||||
name: "", |
|
||||||
description: "", |
|
||||||
git_server: "", |
|
||||||
tags: [], |
|
||||||
maintainers: [], |
|
||||||
relays: [], |
|
||||||
loading: true, |
|
||||||
}; |
|
||||||
</script> |
</script> |
||||||
|
|
||||||
<script lang="ts"> |
<script lang="ts"> |
||||||
import type { User } from "./users/type"; |
import type { User } from "$lib/components/users/type"; |
||||||
import UserHeader from "./users/UserHeader.svelte"; |
import UserHeader from "$lib/components/users/UserHeader.svelte"; |
||||||
|
import { defaults } from "./type"; |
||||||
|
|
||||||
export let { |
export let { |
||||||
repo_id, |
repo_id, |
||||||
@ -0,0 +1,22 @@ |
|||||||
|
import type { User } from "../users/type"; |
||||||
|
|
||||||
|
export interface Repo { |
||||||
|
repo_id: string; |
||||||
|
name: string; |
||||||
|
description: string; |
||||||
|
git_server: string; |
||||||
|
tags: string[]; |
||||||
|
maintainers: User[]; |
||||||
|
relays: string[]; |
||||||
|
loading: boolean; |
||||||
|
} |
||||||
|
export const defaults: Repo = { |
||||||
|
repo_id: "", |
||||||
|
name: "", |
||||||
|
description: "", |
||||||
|
git_server: "", |
||||||
|
tags: [], |
||||||
|
maintainers: [], |
||||||
|
relays: [], |
||||||
|
loading: true, |
||||||
|
}; |
||||||
@ -0,0 +1,76 @@ |
|||||||
|
import { NDKUser } from "@nostr-dev-kit/ndk"; |
||||||
|
import { writable, type Unsubscriber, type Writable } from "svelte/store" |
||||||
|
import { ndk } from "./ndk"; |
||||||
|
import type { Repo } from "$lib/components/repo/type"; |
||||||
|
import { defaults } from "$lib/components/repo/type"; |
||||||
|
import type { User } from "$lib/components/users/type"; |
||||||
|
import { ensureUser, users } from "./users"; |
||||||
|
|
||||||
|
|
||||||
|
let repo_kind: number = 30317; |
||||||
|
|
||||||
|
export let selected_repo: Writable<Repo> = writable({ ...defaults }); |
||||||
|
let selected_repo_id: string = ""; |
||||||
|
|
||||||
|
let maintainers_unsubscribers: Unsubscriber[] = []; |
||||||
|
|
||||||
|
export let ensureSelectedRepo = (repo_id: string) => { |
||||||
|
if (selected_repo_id == repo_id) return selected_repo; |
||||||
|
selected_repo_id = repo_id; |
||||||
|
let sub = ndk.subscribe({ |
||||||
|
kinds: [repo_kind], |
||||||
|
'#d': [repo_id], |
||||||
|
limit: 1, |
||||||
|
}); |
||||||
|
|
||||||
|
sub.on("event", (event) => { |
||||||
|
try { |
||||||
|
if (event.kind == repo_kind && event.tagValue("d") == repo_id) { |
||||||
|
selected_repo.set({ |
||||||
|
loading: false, |
||||||
|
repo_id: event.replaceableDTag(), |
||||||
|
name: event.tagValue("name") || "", |
||||||
|
description: event.tagValue("description") || "", |
||||||
|
git_server: event.tagValue("git_server") || "", |
||||||
|
tags: event.getMatchingTags("t") || [], |
||||||
|
maintainers: event.getMatchingTags("p").map( |
||||||
|
(t: string[]) => |
||||||
|
({ |
||||||
|
hexpubkey: t[1], |
||||||
|
loading: true, |
||||||
|
npub: "", |
||||||
|
}) as User, |
||||||
|
), |
||||||
|
relays: event |
||||||
|
.getMatchingTags("relay") |
||||||
|
.map((t: string[]) => t[1]), |
||||||
|
}); |
||||||
|
let old_unsubscribers = maintainers_unsubscribers; |
||||||
|
maintainers_unsubscribers = event |
||||||
|
.getMatchingTags("p") |
||||||
|
.map((t: string[]) => { |
||||||
|
return ensureUser(t[1]).subscribe((u: User) => { |
||||||
|
selected_repo.update((repo) => { |
||||||
|
return { |
||||||
|
...repo, |
||||||
|
maintainers: repo.maintainers.map((m) => { |
||||||
|
if (m.hexpubkey == u.hexpubkey) return { ...u }; |
||||||
|
else return { ...m }; |
||||||
|
}), |
||||||
|
}; |
||||||
|
}); |
||||||
|
}) |
||||||
|
}); |
||||||
|
old_unsubscribers.forEach((unsubscriber) => unsubscriber()); |
||||||
|
} |
||||||
|
} catch { } |
||||||
|
}); |
||||||
|
sub.on("eose", () => { |
||||||
|
selected_repo.update((repo) => { |
||||||
|
return { |
||||||
|
...repo, |
||||||
|
loading: false, |
||||||
|
} |
||||||
|
}) |
||||||
|
}); |
||||||
|
} |
||||||
@ -0,0 +1,36 @@ |
|||||||
|
import type { User } from "$lib/components/users/type"; |
||||||
|
import { NDKUser } from "@nostr-dev-kit/ndk"; |
||||||
|
import { writable, type Writable } from "svelte/store" |
||||||
|
import { ndk } from "./ndk"; |
||||||
|
|
||||||
|
export let users: { [hexpubkey: string]: Writable<User>; } = {}; |
||||||
|
|
||||||
|
export let ensureUser = (hexpubkey: string): Writable<User> => { |
||||||
|
if (!users[hexpubkey]) { |
||||||
|
let u = ndk.getUser({ hexpubkey }); |
||||||
|
|
||||||
|
let base: User = { |
||||||
|
loading: false, |
||||||
|
hexpubkey, |
||||||
|
npub: u.npub, |
||||||
|
}; |
||||||
|
|
||||||
|
users[hexpubkey] = writable(base); |
||||||
|
u.fetchProfile().then( |
||||||
|
(p) => { |
||||||
|
users[hexpubkey].update((u) => ({ |
||||||
|
...u, |
||||||
|
loading: false, |
||||||
|
profile: p === null ? undefined : p, |
||||||
|
})); |
||||||
|
}, |
||||||
|
() => { |
||||||
|
users[hexpubkey].update((u) => ({ |
||||||
|
...u, |
||||||
|
loading: false, |
||||||
|
})); |
||||||
|
} |
||||||
|
); |
||||||
|
} |
||||||
|
return users[hexpubkey]; |
||||||
|
} |
||||||
@ -1,39 +1,10 @@ |
|||||||
<script lang="ts"> |
<script lang="ts"> |
||||||
import type { Args } from "$lib/components/RepoDetails.svelte"; |
import RepoDetails from "$lib/components/repo/RepoDetails.svelte"; |
||||||
import { defaults } from "$lib/components/RepoDetails.svelte"; |
import { ensureSelectedRepo, selected_repo } from "$lib/stores/repo"; |
||||||
import RepoDetails from "$lib/components/RepoDetails.svelte"; |
|
||||||
import { ndk } from "$lib/stores/ndk"; |
|
||||||
|
|
||||||
export let repo_id = ""; |
export let repo_id = ""; |
||||||
|
|
||||||
let repo: Args = { ...defaults }; |
ensureSelectedRepo(repo_id); |
||||||
let loading: boolean = true; |
|
||||||
let kind: number = 30317; |
|
||||||
let sub = ndk.subscribe({ |
|
||||||
kinds: [kind], |
|
||||||
limit: 1, |
|
||||||
}); |
|
||||||
sub.on("event", (event) => { |
|
||||||
try { |
|
||||||
if (event.kind == kind && event.tagValue("d") == repo_id) |
|
||||||
repo = { |
|
||||||
repo_id: event.replaceableDTag(), |
|
||||||
name: event.tagValue("name") || "", |
|
||||||
description: event.tagValue("description") || "", |
|
||||||
git_server: event.tagValue("git_server") || "", |
|
||||||
tags: event.getMatchingTags("t") || [], |
|
||||||
maintainers: event |
|
||||||
.getMatchingTags("p") |
|
||||||
.map((t: string[]) => t[1]), |
|
||||||
relays: event |
|
||||||
.getMatchingTags("relay") |
|
||||||
.map((t: string[]) => t[1]), |
|
||||||
}; |
|
||||||
} catch {} |
|
||||||
}); |
|
||||||
sub.on("eose", () => { |
|
||||||
if (loading == true) loading = false; |
|
||||||
}); |
|
||||||
</script> |
</script> |
||||||
|
|
||||||
<RepoDetails {...repo} {loading} /> |
<RepoDetails {...$selected_repo} /> |
||||||
|
|||||||