codehost 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/package.json +1 -1
- package/src/shared/repo.ts +6 -2
- package/src/web/discovery.tsx +27 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
# [0.14.0](https://github.com/snomiao/codehost/compare/v0.13.0...v0.14.0) (2026-06-10)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* **web:** always show /tree/<branch> for repo workspaces ([ad34bc2](https://github.com/snomiao/codehost/commit/ad34bc2e2e8acea98ac392b90766488c6f3b4e52))
|
|
7
|
+
|
|
1
8
|
# [0.13.0](https://github.com/snomiao/codehost/compare/v0.12.0...v0.13.0) (2026-06-09)
|
|
2
9
|
|
|
3
10
|
|
package/package.json
CHANGED
package/src/shared/repo.ts
CHANGED
|
@@ -7,6 +7,10 @@ import type { PeerInfo, PeerMeta } from "./signaling";
|
|
|
7
7
|
|
|
8
8
|
export const DEFAULT_LAYOUT = "{owner}/{repo}/tree/{branch}";
|
|
9
9
|
export const GITHUB_HOST = "github.com";
|
|
10
|
+
/** Branch assumed when a repo link/target carries none — what `fillLayout` opens
|
|
11
|
+
* and what the address bar shows, so a bare `/gh/<owner>/<repo>` canonicalizes
|
|
12
|
+
* to `/gh/<owner>/<repo>/tree/<DEFAULT_BRANCH>`. */
|
|
13
|
+
export const DEFAULT_BRANCH = "main";
|
|
10
14
|
|
|
11
15
|
export interface RepoTarget {
|
|
12
16
|
/** Git host, e.g. "github.com" or "gitlab.com". */
|
|
@@ -96,12 +100,12 @@ export function toPosixPath(p: string): string {
|
|
|
96
100
|
return p.replace(/\\/g, "/");
|
|
97
101
|
}
|
|
98
102
|
|
|
99
|
-
/** Fill a layout template from a repo target (default branch ->
|
|
103
|
+
/** Fill a layout template from a repo target (default branch -> DEFAULT_BRANCH). */
|
|
100
104
|
export function fillLayout(layout: string, t: RepoTarget): string {
|
|
101
105
|
return layout
|
|
102
106
|
.replace(/\{owner\}/g, t.owner)
|
|
103
107
|
.replace(/\{repo\}/g, t.name)
|
|
104
|
-
.replace(/\{branch\}/g, t.branch ||
|
|
108
|
+
.replace(/\{branch\}/g, t.branch || DEFAULT_BRANCH);
|
|
105
109
|
}
|
|
106
110
|
|
|
107
111
|
/**
|
package/src/web/discovery.tsx
CHANGED
|
@@ -8,6 +8,7 @@ import { getSignalUrl } from "./config";
|
|
|
8
8
|
import { registerTunnelHost } from "./tunnel-host";
|
|
9
9
|
import { connBroker } from "./conn-broker";
|
|
10
10
|
import {
|
|
11
|
+
DEFAULT_BRANCH,
|
|
11
12
|
type DeepLink,
|
|
12
13
|
type RoomMatch,
|
|
13
14
|
parseDeepLink,
|
|
@@ -356,10 +357,19 @@ export function Discovery() {
|
|
|
356
357
|
sharePathRef.current = window.location.pathname;
|
|
357
358
|
} else {
|
|
358
359
|
const targetPath = shareablePathFor(server, openFolder);
|
|
359
|
-
didPush = !!targetPath && targetPath !== window.location.pathname;
|
|
360
|
-
if (didPush) history.pushState(null, "", targetPath);
|
|
361
|
-
pushedRef.current = didPush;
|
|
362
360
|
sharePathRef.current = targetPath ?? window.location.pathname;
|
|
361
|
+
if (targetPath && targetPath !== window.location.pathname) {
|
|
362
|
+
if (deepLinkRef.current) {
|
|
363
|
+
// Arrived via a deep link — canonicalize the URL in place (e.g. add
|
|
364
|
+
// /tree/<branch>). Same destination, so replace, don't push a
|
|
365
|
+
// back-to-the-list entry.
|
|
366
|
+
history.replaceState(null, "", targetPath);
|
|
367
|
+
} else {
|
|
368
|
+
history.pushState(null, "", targetPath);
|
|
369
|
+
didPush = true;
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
pushedRef.current = didPush;
|
|
363
373
|
}
|
|
364
374
|
|
|
365
375
|
// The broker decides whether this tab owns the connection. `establish` is
|
|
@@ -417,14 +427,20 @@ export function Discovery() {
|
|
|
417
427
|
// token — Share adds that). Keeps an existing deep-link path as-is; otherwise
|
|
418
428
|
// derives /gh|/git|/dev from the server's repo identity or opened folder.
|
|
419
429
|
function shareablePathFor(server: PeerInfo, folder?: string): string | null {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
430
|
+
const dl = deepLinkRef.current;
|
|
431
|
+
// A repo workspace always shows /tree/<branch> (GitHub-style, and it pins the
|
|
432
|
+
// worktree in snomiao's /tree/<branch> layout). Branch source, in order: the
|
|
433
|
+
// deep link's branch, the server's reported branch, else the layout default —
|
|
434
|
+
// matching the worktree fillLayout actually opened.
|
|
435
|
+
if (dl?.type === "repo") {
|
|
436
|
+
const branch = dl.target.branch ?? server.meta?.branch ?? DEFAULT_BRANCH;
|
|
437
|
+
return shareableDeepLink({ repo: repoKey(dl.target), branch });
|
|
438
|
+
}
|
|
439
|
+
if (server.meta?.repo) {
|
|
440
|
+
return shareableDeepLink({ repo: server.meta.repo, branch: server.meta.branch ?? DEFAULT_BRANCH });
|
|
441
|
+
}
|
|
442
|
+
// Folder mount: keep the deep-link path as-is, else derive the host-scoped one.
|
|
443
|
+
return dl ? window.location.pathname : shareableDeepLink({ folder, host: server.meta?.host });
|
|
428
444
|
}
|
|
429
445
|
|
|
430
446
|
async function shareLink() {
|