Why Nostr? What is Njump?
2024-08-28 14:57:00
in reply to

DanConwayDev on Nostr: I just zapped this commit using amethyst: ...

I just zapped this commit using amethyst:
From ef62256d050161fdfccafd2111005ab46c4f49dd Mon Sep 17 00:00:00 2001
From: Alejandro Gómez
Date: Mon, 22 Apr 2024 12:54:38 +0200
Subject: [PATCH] repo bookmarking

---
src/lib/components/AsyncButton.svelte | 21 +++++++++++++++++++++
src/lib/components/repo/RepoDetails.svelte | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
src/lib/components/stars/icons.ts | 11 +++++++++++
src/lib/components/stars/type.ts | 13 +++++++++++++
src/lib/kinds.ts | 2 ++
src/lib/promise.ts | 3 +++
src/lib/stores/Issues.ts | 2 +-
src/lib/stores/Proposal.ts | 2 +-
src/lib/stores/Stargazers.ts | 74 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/lib/wrappers/RepoMenu.svelte | 33 ++++++++++++++++++++++++++++++++-
src/lib/wrappers/RepoPageWrapper.svelte | 2 ++
src/routes/repo/[repo_id]/stargazers/+page.svelte | 34 ++++++++++++++++++++++++++++++++++
src/routes/repo/[repo_id]/stargazers/+page.ts | 5 +++++
13 files changed, 317 insertions(+), 5 deletions(-)
create mode 100644 src/lib/components/AsyncButton.svelte
create mode 100644 src/lib/components/stars/icons.ts
create mode 100644 src/lib/components/stars/type.ts
create mode 100644 src/lib/promise.ts
create mode 100644 src/lib/stores/Stargazers.ts
create mode 100644 src/routes/repo/[repo_id]/stargazers/+page.svelte
create mode 100644 src/routes/repo/[repo_id]/stargazers/+page.ts

diff --git a/src/lib/components/AsyncButton.svelte b/src/lib/components/AsyncButton.svelte
new file mode 100644
index 0000000..a750834
--- /dev/null
+++ b/src/lib/components/AsyncButton.svelte
@@ -0,0 +1,21 @@
+
+
+
diff --git a/src/lib/components/repo/RepoDetails.svelte b/src/lib/components/repo/RepoDetails.svelte
index 9be1f41..287ed68 100644
--- a/src/lib/components/repo/RepoDetails.svelte
+++ b/src/lib/components/repo/RepoDetails.svelte
@@ -1,6 +1,14 @@


-

+

+

+

{#if name == identifier}
{#if loading}

@@ -66,6 +156,32 @@

{identifier}


{/if}
{/if}
+

+ {#if ref}
+
+ + xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 16 16"
+ class={`w-4 h-4 mr-2 ${isStarred ? "fill-yellow-500" : "fill-gray-400"}`}
+ >
+ {#if isStarred}
+ {#each star_icon_path.filled as p}
+
+ {/each}
+ {:else}
+ {#each star_icon_path.outline as p}
+
+ {/each}
+ {/if}
+
+ {#if isStarred}
+ Unstar
+ {:else}
+ Star
+ {/if}
+

+ {/if}
+

{#if loading}


diff --git a/src/lib/components/stars/icons.ts b/src/lib/components/stars/icons.ts
new file mode 100644
index 0000000..73c465a
--- /dev/null
+++ b/src/lib/components/stars/icons.ts
@@ -0,0 +1,11 @@
+// icon are MIT licenced
+export const star_icon_path = {
+ // https://icon-sets.iconify.design/gravity-ui/star/
+ outline: [
+ "m9.194 5l.351.873l.94.064l3.197.217l-2.46 2.055l-.722.603l.23.914l.782 3.108l-2.714-1.704L8 10.629l-.798.5l-2.714 1.705l.782-3.108l.23-.914l-.723-.603l-2.46-2.055l3.198-.217l.94-.064l.35-.874L8 2.025zm-7.723-.292l3.943-.268L6.886.773C7.29-.231 8.71-.231 9.114.773l1.472 3.667l3.943.268c1.08.073 1.518 1.424.688 2.118L12.185 9.36l.964 3.832c.264 1.05-.886 1.884-1.802 1.31L8 12.4l-3.347 2.101c-.916.575-2.066-.26-1.802-1.309l.964-3.832L.783 6.826c-.83-.694-.391-2.045.688-2.118",
+ ],
+ // https://icon-sets.iconify.design/gravity-ui/star-fill/
+ filled: [
+ "M6.886.773C7.29-.231 8.71-.231 9.114.773l1.472 3.667l3.943.268c1.08.073 1.518 1.424.688 2.118L12.185 9.36l.964 3.832c.264 1.05-.886 1.884-1.802 1.31L8 12.4l-3.347 2.101c-.916.575-2.066-.26-1.802-1.309l.964-3.832L.783 6.826c-.83-.694-.391-2.045.688-2.118l3.943-.268z",
+ ],
+}
diff --git a/src/lib/components/stars/type.ts b/src/lib/components/stars/type.ts
new file mode 100644
index 0000000..f076086
--- /dev/null
+++ b/src/lib/components/stars/type.ts
@@ -0,0 +1,13 @@
+import type { NDKEvent } from '@nostr-dev-kit/ndk'
+
+export interface Stargazers {
+ id: string | undefined
+ events: NDKEvent[]
+ loading: boolean;
+}
+
+export const stars_defaults: Stargazers = {
+ id: '',
+ events: [],
+ loading: true,
+}
diff --git a/src/lib/kinds.ts b/src/lib/kinds.ts
index fd65cf2..06cd21b 100644
--- a/src/lib/kinds.ts
+++ b/src/lib/kinds.ts
@@ -27,3 +27,5 @@ export const repo_kind: number = 30617
export const patch_kind: number = 1617

export const issue_kind: number = 1621
+
+export const bookmarks_kind: number = 10617
diff --git a/src/lib/promise.ts b/src/lib/promise.ts
new file mode 100644
index 0000000..1577059
--- /dev/null
+++ b/src/lib/promise.ts
@@ -0,0 +1,3 @@
+export function timeout(ms: number) {
+ return new Promise((resolve) => setTimeout(resolve, ms))
+}
diff --git a/src/lib/stores/Issues.ts b/src/lib/stores/Issues.ts
index 23b6023..ba229fb 100644
--- a/src/lib/stores/Issues.ts
+++ b/src/lib/stores/Issues.ts
@@ -34,7 +34,7 @@ let selected_repo_id: string | undefined = ''
let sub: NDKSubscription

export const ensureIssueSummaries = async (repo_id: string | undefined) => {
- if (selected_repo_id == repo_id) return
+ if (selected_repo_id === repo_id) return
issue_summaries.set({
id: repo_id,
summaries: [],
diff --git a/src/lib/stores/Proposal.ts b/src/lib/stores/Proposal.ts
index c92d5f7..7aad603 100644
--- a/src/lib/stores/Proposal.ts
+++ b/src/lib/stores/Proposal.ts
@@ -109,7 +109,7 @@ export const ensureProposalFull = (
created_at: event.created_at,
comments: 0,
author: {
- hexpubkey: event.pubkey,
+ pubkey: event.pubkey,
loading: true,
npub: '',
},
diff --git a/src/lib/stores/Stargazers.ts b/src/lib/stores/Stargazers.ts
new file mode 100644
index 0000000..fbf5a11
--- /dev/null
+++ b/src/lib/stores/Stargazers.ts
@@ -0,0 +1,74 @@
+import {
+ NDKRelaySet,
+ type NDKEvent,
+ NDKSubscription,
+ type NDKFilter,
+} from '@nostr-dev-kit/ndk'
+import { writable, type Writable } from 'svelte/store'
+import { awaitSelectedRepoCollection } from './repo'
+import { selectRepoFromCollection } from '$lib/components/repo/utils'
+import { base_relays, ndk } from './ndk'
+import { repo_kind, bookmarks_kind } from '$lib/kinds'
+import { stars_defaults, type Stargazers } from '$lib/components/stars/type'
+
+export const stargazers: Writable = writable(stars_defaults)
+
+let selected_repo_id: string | undefined = ''
+
+let sub: NDKSubscription
+
+export async function fetchStargazers(repo_id: string | undefined) {
+ if (selected_repo_id === repo_id) return
+ selected_repo_id = repo_id;
+ stargazers.set({
+ id: repo_id,
+ events: [],
+ loading: true,
+ })
+ if (sub) sub.stop()
+ if (repo_id) {
+ const repo_collection = await awaitSelectedRepoCollection(repo_id)
+ const repo = selectRepoFromCollection(repo_collection)
+ if (!repo) {
+ // TODO: display error info bar
+ return
+ }
+ const relays_to_use =
+ repo.relays.length > 3
+ ? repo.relays
+ : [...base_relays].concat(repo.relays)
+
+ // todo: relays usually return max 500 results, if a repo is very popular, we may need to paginate
+ const filter = {
+ kinds: [bookmarks_kind],
+ '#a': repo.maintainers.map((m) => `${repo_kind}:${m}:${repo.identifier}`),
+ }
+
+ sub = ndk.subscribe(
+ filter,
+ {
+ closeOnEose: false,
+ },
+ NDKRelaySet.fromRelayUrls(relays_to_use, ndk)
+ )
+
+ sub.on('event', (event: NDKEvent) => {
+ stargazers.update((stars) => {
+ return {
+ ...stars,
+ events: stars.events.concat([event]),
+ loading: false,
+ }
+ })
+ })
+
+ sub.on('eose', () => {
+ stargazers.update((stars) => {
+ return {
+ ...stars,
+ loading: false,
+ }
+ })
+ })
+ }
+}
diff --git a/src/lib/wrappers/RepoMenu.svelte b/src/lib/wrappers/RepoMenu.svelte
index a5958be..df9e477 100644
--- a/src/lib/wrappers/RepoMenu.svelte
+++ b/src/lib/wrappers/RepoMenu.svelte
@@ -1,17 +1,23 @@


-

+


{#if !$selected_repo_readme.failed}
@@ -66,6 +72,31 @@

{/if}

+ + href={`/repo/${identifier}/stargazers`}
+ class="tab"
+ class:tab-active={selected_tab === 'stargazers'}
+ >
+ + xmlns="http://www.w3.org/2000/svg"
+ viewBox="0 0 16 16"
+ class={`mb-1 mr-1 h-4 w-4 flex-none fill-base-content pt-1 ${isStarred ? "fill-yellow-500" : "opacity-50"}`}
+ >
+ {#if isStarred}
+ {#each star_icon_path.filled as p}
+
+ {/each}
+ {:else}
+ {#each star_icon_path.outline as p}
+
+ {/each}
+ {/if}
+
+ Stars
+
+ {$stargazers.events.length}
+

+



diff --git a/src/lib/wrappers/RepoPageWrapper.svelte b/src/lib/wrappers/RepoPageWrapper.svelte
index 76107b8..d9618cd 100644
--- a/src/lib/wrappers/RepoPageWrapper.svelte
+++ b/src/lib/wrappers/RepoPageWrapper.svelte
@@ -9,6 +9,7 @@
import Container from '$lib/components/Container.svelte'
import { ensureProposalSummaries } from '$lib/stores/Proposals'
import { ensureIssueSummaries } from '$lib/stores/Issues'
+ import { fetchStargazers } from '$lib/stores/Stargazers'
import type { RepoPage } from '$lib/components/repo/type'

export let identifier = ''
@@ -18,6 +19,7 @@
ensureSelectedRepoCollection(identifier)
ensureProposalSummaries(identifier)
ensureIssueSummaries(identifier)
+ fetchStargazers(identifier)

let repo_error = false

diff --git a/src/routes/repo/[repo_id]/stargazers/+page.svelte b/src/routes/repo/[repo_id]/stargazers/+page.svelte
new file mode 100644
index 0000000..e77188d
--- /dev/null
+++ b/src/routes/repo/[repo_id]/stargazers/+page.svelte
@@ -0,0 +1,34 @@
+
+
+
+ {#if !$stargazers.loading }
+

+ {#if $stargazers.events.length === 0}
+

+ there aren't any stargazers yet
+

+ {:else}
+

+ {#each $stargazers.events as event}
+
+ {/each}
+

+ {/if}
+

+ {/if}
+

diff --git a/src/routes/repo/[repo_id]/stargazers/+page.ts b/src/routes/repo/[repo_id]/stargazers/+page.ts
new file mode 100644
index 0000000..c70bf13
--- /dev/null
+++ b/src/routes/repo/[repo_id]/stargazers/+page.ts
@@ -0,0 +1,5 @@
+export const load = ({ params }: { params: { repo_id: string } }) => {
+ return {
+ repo_id: decodeURIComponent(params.repo_id),
+ }
+}
--
libgit2 1.7.2

Author Public Key
npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr