feat: import page separates your repos (Import) from others (Fork to Cospan)

Author: Aaron Steven White
Commit 152049508c758090761bb8662d0c096f434d4ffc
Parent: 90953c07a9
Structural diff unavailable

These commits were pushed via plain git push, so no pre-parsed schemas are available. Install git-remote-cospan and re-push via panproto:// to see scope-level changes, breaking change detection, and semantic diffs.

brew install panproto/tap/git-remote-cospan
1 file changed +101 -84
@@ -8,9 +8,7 @@
88 
99 	let auth = $derived(getAuth());
1010 	let searchQuery = $state('');
11-	let showMineOnly = $state(false);
1211 
13-	// Resolve handles for all repos
1412 	let handles = $state<Record<string, string>>({});
1513 
1614 	onMount(async () => {
@@ -29,15 +27,16 @@
2927 		return handles[did] || (did.startsWith('did:plc:') ? did.slice(8, 18) + '…' : did);
3028 	}
3129 
32-	let filteredRepos = $derived(() => {
33-		let repos = data.repos.items;
30+	let myRepos = $derived(() => {
31+		if (!auth.authenticated || !auth.did) return [];
32+		return data.repos.items.filter((r: Repo) => r.did === auth.did);
33+	});
3434 
35-		// Filter to user's repos
36-		if (showMineOnly && auth.authenticated && auth.did) {
37-			repos = repos.filter((r: Repo) => r.did === auth.did);
35+	let otherRepos = $derived(() => {
36+		let repos = data.repos.items;
37+		if (auth.authenticated && auth.did) {
38+			repos = repos.filter((r: Repo) => r.did !== auth.did);
3839 		}
39-
40-		// Search filter
4140 		if (searchQuery.trim()) {
4241 			const q = searchQuery.toLowerCase();
4342 			repos = repos.filter((r: Repo) =>
@@ -46,7 +45,6 @@
4645 				getHandle(r.did).toLowerCase().includes(q)
4746 			);
4847 		}
49-
5048 		return repos;
5149 	});
5250 
@@ -65,95 +63,114 @@
6563 	<div class="mb-6">
6664 		<h1 class="mb-1 text-lg font-semibold text-ink">Import from Tangled</h1>
6765 		<p class="text-[13px] text-caption">
68-			Browse repositories from the Tangled network and import them into Cospan for schema-aware version control.
66+			Bring your Tangled repositories into Cospan for schema-aware version control.
6967 		</p>
7068 	</div>
7169 
72-	<!-- Search + filters -->
73-	<div class="mb-6 flex flex-wrap items-center gap-3">
74-		<div class="relative flex-1">
70+	<!-- Your repos section -->
71+	{#if auth.authenticated}
72+		{#if myRepos().length > 0}
73+			<div class="mb-8">
74+				<h2 class="mb-3 text-[13px] font-semibold uppercase tracking-wide text-ink">Your Tangled repos</h2>
75+				<div class="divide-y divide-line/40 rounded-lg border border-line/60 bg-ground">
76+					{#each myRepos() as repo (repo.did + '/' + repo.name)}
77+						<div class="flex items-center justify-between gap-4 px-4 py-3">
78+							<div class="min-w-0 flex-1">
79+								<div class="flex items-center gap-2">
80+									<a href="/{repo.did}/{repo.name}" class="font-mono text-[13px] font-medium text-ink hover:text-focus-bright transition-colors">
81+										{repo.name}
82+									</a>
83+									{#if repo.description}
84+										<span class="truncate text-[12px] text-ghost">{repo.description}</span>
85+									{/if}
86+								</div>
87+							</div>
88+							<button class="shrink-0 rounded-md bg-focus/10 border border-focus/30 px-3 py-1.5 text-[12px] font-medium text-focus-bright transition-all hover:bg-focus/15 hover:border-focus">
89+								Import
90+							</button>
91+						</div>
92+					{/each}
93+				</div>
94+			</div>
95+		{:else}
96+			<div class="mb-8 rounded-lg border border-line/40 bg-ground px-4 py-6 text-center">
97+				<p class="text-[13px] text-caption">You don't have any Tangled repositories yet.</p>
98+				<p class="mt-1 text-[12px] text-ghost">Create a repo on <a href="https://tangled.sh" target="_blank" rel="noopener" class="text-focus-bright hover:underline">tangled.sh</a> to import it here.</p>
99+			</div>
100+		{/if}
101+	{:else}
102+		<div class="mb-8 rounded-lg border border-line/40 bg-ground px-4 py-6 text-center">
103+			<p class="text-[13px] text-caption">Sign in to import your Tangled repositories.</p>
104+		</div>
105+	{/if}
106+
107+	<!-- All Tangled repos -->
108+	<div>
109+		<div class="mb-3 flex items-center justify-between gap-3">
110+			<h2 class="text-[13px] font-semibold uppercase tracking-wide text-ink">Browse all</h2>
111+			<span class="text-[11px] text-ghost">{otherRepos().length} repos</span>
112+		</div>
113+
114+		<div class="relative mb-4">
75115 			<svg class="pointer-events-none absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-ghost" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
76116 				<path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z" />
77117 			</svg>
78118 			<input
79119 				type="text"
80120 				bind:value={searchQuery}
81-				placeholder="Search Tangled repos…"
121+				placeholder="Search repos…"
82122 				class="w-full rounded-md border border-line bg-surface py-2 pl-10 pr-3 text-[13px] text-ink placeholder:text-ghost focus:border-focus/50 focus:outline-none transition-colors"
83123 			/>
84124 		</div>
85125 
86-		{#if auth.authenticated}
87-			<button
88-				type="button"
89-				onclick={() => showMineOnly = !showMineOnly}
90-				class="rounded-md px-3 py-2 text-[12px] font-medium transition-all
91-					{showMineOnly ? 'bg-focus/10 text-focus-bright border border-focus/30' : 'bg-surface text-ghost border border-line hover:text-caption'}"
92-			>
93-				My repos
94-			</button>
95-		{/if}
96-
97-		<span class="text-[11px] text-ghost">
98-			{filteredRepos().length} repos
99-		</span>
100-	</div>
101-
102-	<!-- Repo list -->
103-	{#if filteredRepos().length === 0}
104-		<div class="flex flex-col items-center justify-center py-24 text-center">
105-			<div class="mb-4 text-ghost">
106-				<svg class="mx-auto h-10 w-10" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1">
107-					<path stroke-linecap="round" stroke-linejoin="round" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
108-				</svg>
126+		{#if otherRepos().length === 0}
127+			<div class="flex flex-col items-center justify-center py-16 text-center">
128+				{#if searchQuery.trim()}
129+					<p class="text-sm text-caption">No repos matching "{searchQuery}"</p>
130+				{:else}
131+					<div class="mb-4 text-ghost">
132+						<svg class="mx-auto h-10 w-10" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1">
133+							<path stroke-linecap="round" stroke-linejoin="round" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
134+						</svg>
135+					</div>
136+					<p class="text-sm text-caption">No Tangled repositories found yet.</p>
137+					<p class="mt-1 text-xs text-ghost">Repositories are being backfilled from the network.</p>
138+				{/if}
109139 			</div>
110-			{#if searchQuery.trim()}
111-				<p class="text-sm text-caption">No repos matching "{searchQuery}"</p>
112-			{:else if showMineOnly}
113-				<p class="text-sm text-caption">No Tangled repos found for your account.</p>
114-			{:else}
115-				<p class="text-sm text-caption">No Tangled repositories found yet.</p>
116-				<p class="mt-1 text-xs text-ghost">Repositories are being backfilled from the network. Check back soon.</p>
117-			{/if}
118-		</div>
119-	{:else}
120-		<div class="divide-y divide-line/40">
121-			{#each filteredRepos() as repo (repo.did + '/' + repo.name)}
122-				<div class="flex items-start justify-between gap-4 py-4">
123-					<div class="min-w-0 flex-1">
124-						<div class="flex items-center gap-2">
125-							<a href="/{repo.did}/{repo.name}" class="font-mono text-[14px] font-medium text-ink hover:text-focus-bright transition-colors">
126-								{getHandle(repo.did)}/{repo.name}
127-							</a>
128-							{#if repo.protocol}
129-								<span class="text-[11px] text-ghost">{repo.protocol}</span>
130-							{:else}
131-								<span class="text-[11px] text-ghost">git</span>
132-							{/if}
133-						</div>
134-						{#if repo.description}
135-							<p class="mt-1 line-clamp-1 text-[13px] text-caption">{repo.description}</p>
136-						{/if}
137-						<div class="mt-1.5 flex items-center gap-3 text-[11px] text-ghost">
138-							{#if repo.starCount > 0}
139-								<span>★ {repo.starCount}</span>
140-							{/if}
141-							{#if repo.openIssueCount > 0}
142-								<span>{repo.openIssueCount} issues</span>
140+		{:else}
141+			<div class="divide-y divide-line/40">
142+				{#each otherRepos() as repo (repo.did + '/' + repo.name)}
143+					<div class="flex items-start justify-between gap-4 py-3">
144+						<div class="min-w-0 flex-1">
145+							<div class="flex items-center gap-2">
146+								<a href="/{repo.did}/{repo.name}" class="font-mono text-[13px] font-medium text-ink hover:text-focus-bright transition-colors">
147+									{getHandle(repo.did)}/{repo.name}
148+								</a>
149+								{#if repo.protocol}
150+									<span class="text-[11px] text-ghost">{repo.protocol}</span>
151+								{:else}
152+									<span class="text-[11px] text-ghost">git</span>
153+								{/if}
154+							</div>
155+							{#if repo.description}
156+								<p class="mt-0.5 line-clamp-1 text-[12px] text-caption">{repo.description}</p>
143157 							{/if}
144-							<a href={tangledUrl(repo)} target="_blank" rel="noopener" class="hover:text-caption transition-colors">
145-								View on Tangled ↗
146-							</a>
158+							<div class="mt-1 flex items-center gap-3 text-[11px] text-ghost">
159+								{#if repo.starCount > 0}
160+									<span>★ {repo.starCount}</span>
161+								{/if}
162+								<a href={tangledUrl(repo)} target="_blank" rel="noopener" class="hover:text-caption transition-colors">
163+									View on Tangled ↗
164+								</a>
165+							</div>
147166 						</div>
148-					</div>
149167 
150-					<button
151-						class="shrink-0 rounded-md border border-focus/40 bg-focus/5 px-3 py-1.5 text-[12px] font-medium text-focus-bright transition-all hover:bg-focus/10 hover:border-focus"
152-					>
153-						Import
154-					</button>
155-				</div>
156-			{/each}
157-		</div>
158-	{/if}
168+						<button class="shrink-0 rounded-md border border-line px-3 py-1.5 text-[12px] font-medium text-caption transition-all hover:border-line-bright hover:text-ink">
169+							Fork to Cospan
170+						</button>
171+					</div>
172+				{/each}
173+			</div>
174+		{/if}
175+	</div>
159176 </section>
cospan · schematic version control on atproto built on AT Protocol