mirror of
https://seed.radicle.dev/rad:z4V1sjrXqjvFdnCUbxPFqd5p4DtH5.git
synced 2026-11-15 11:20:36 +08:00
Implement more simplifications
Signed-off-by: Alexis Sellier <self@cloudhead.io>
This commit is contained in:
+22
-18
@@ -212,29 +212,33 @@ export class Org {
|
||||
async getPendingProjects(config: Config): Promise<PendingAnchor[]> {
|
||||
if (! config.safe.client) return [];
|
||||
|
||||
const orgAddr = ethers.utils.getAddress(this.address);
|
||||
const response = await config.safe.client.getPendingTransactions(
|
||||
ethers.utils.getAddress(this.owner)
|
||||
);
|
||||
const projects: PendingAnchor[] = [];
|
||||
try {
|
||||
const orgAddr = ethers.utils.getAddress(this.address);
|
||||
const response = await config.safe.client.getPendingTransactions(
|
||||
ethers.utils.getAddress(this.owner)
|
||||
);
|
||||
const projects: PendingAnchor[] = [];
|
||||
|
||||
for (const tx of response.results || []) {
|
||||
if (tx.data && tx.to === orgAddr) {
|
||||
const anchor = parseAnchorTx(tx.data, config);
|
||||
const confirmations = tx.confirmations?.map(t => t.owner) || [];
|
||||
for (const tx of response.results || []) {
|
||||
if (tx.data && tx.to === orgAddr) {
|
||||
const anchor = parseAnchorTx(tx.data, config);
|
||||
const confirmations = tx.confirmations?.map(t => t.owner) || [];
|
||||
|
||||
if (anchor) {
|
||||
projects.push({
|
||||
id: anchor.id,
|
||||
anchor: { stateHash: anchor.stateHash },
|
||||
confirmations,
|
||||
safeTxHash: tx.safeTxHash,
|
||||
confirmed: false,
|
||||
});
|
||||
if (anchor) {
|
||||
projects.push({
|
||||
id: anchor.id,
|
||||
anchor: { stateHash: anchor.stateHash },
|
||||
confirmations,
|
||||
safeTxHash: tx.safeTxHash,
|
||||
confirmed: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return projects;
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
return projects;
|
||||
}
|
||||
|
||||
static async getAnchor(orgAddr: string, urn: string, config: Config): Promise<string | null> {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from "svelte";
|
||||
import { ProjectInfo, Branches, getOid } from "@app/project";
|
||||
import { formatCommit, isOid } from "@app/utils";
|
||||
import { formatCommit } from "@app/utils";
|
||||
import Dropdown from "@app/Dropdown.svelte";
|
||||
|
||||
export let branches: Branches;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
$: browser = $browserStore;
|
||||
$: path = browser.path || "/";
|
||||
$: revision = browser.revision || browser.branches[project.head];
|
||||
$: revision = browser.revision || source.branches[project.head];
|
||||
|
||||
// When the component is loaded the first time, the blob is yet to be loaded.
|
||||
let state: State = { status: Status.Loading, path };
|
||||
@@ -71,7 +71,7 @@
|
||||
mobileFileTree = !mobileFileTree;
|
||||
};
|
||||
|
||||
$: commit = proj.getOid(revision, browser.branches) || project.head;
|
||||
$: commit = proj.getOid(revision, source.branches) || project.head;
|
||||
$: getBlob = loadBlob(path);
|
||||
$: loadingPath = state.status == Status.Loading ? state.path : null;
|
||||
</script>
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
export let commit: string;
|
||||
export let browserStore: Writable<Browser>;
|
||||
export let peerSelector: boolean; // If peerSelector should be showed.
|
||||
export let branches: proj.Branches;
|
||||
|
||||
let { urn, project, peers, seed, anchors } = source;
|
||||
|
||||
@@ -22,12 +21,6 @@
|
||||
$: revision = browser.revision || commit;
|
||||
$: content = browser.content;
|
||||
|
||||
$: if (Object.keys(browser.branches).length > 0) {
|
||||
branches = browser.branches;
|
||||
} else {
|
||||
proj.browse({ branches });
|
||||
}
|
||||
|
||||
let dropdownState: { [key: string]: boolean } = { clone: false, seed: false, branch: false, peer: false };
|
||||
function toggleDropdown(input: string) {
|
||||
Object.keys(dropdownState).map((key: string) => {
|
||||
@@ -164,7 +157,7 @@
|
||||
bind:peersDropdown={dropdownState.peer}
|
||||
on:peerChanged={(event) => updatePeer(event.detail)} />
|
||||
{/if}
|
||||
<BranchSelector {branches} {project} {revision} {toggleDropdown}
|
||||
<BranchSelector branches={source.branches} {project} {revision} {toggleDropdown}
|
||||
bind:branchesDropdown={dropdownState.branch}
|
||||
on:branchChanged={(event) => updateRevision(event.detail)} />
|
||||
<div class="anchor">
|
||||
|
||||
@@ -7,12 +7,16 @@
|
||||
import { browserStore } from '@app/project';
|
||||
|
||||
import Header from '@app/base/projects/Header.svelte';
|
||||
import ProjectContentRoutes from '@app/base/projects/ProjectContentRoutes.svelte';
|
||||
|
||||
import Browser from "./Browser.svelte";
|
||||
import Commit from "./Commit.svelte";
|
||||
import History from "./History.svelte";
|
||||
|
||||
export let peer: string | null = null;
|
||||
export let config: Config;
|
||||
export let source: proj.Source;
|
||||
export let peerSelector = false;
|
||||
export let content: proj.ProjectContent;
|
||||
export let revision: string;
|
||||
|
||||
const project = source.project;
|
||||
|
||||
@@ -43,11 +47,6 @@
|
||||
{ prop: "og:description", content: project.description },
|
||||
{ prop: "og:url", content: window.location.href }
|
||||
]);
|
||||
|
||||
// Necessary for the initial load, but causes double rendering.
|
||||
// Once the content routing is above this component, this can go
|
||||
// away.
|
||||
$: revision = $browserStore.revision;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
@@ -119,9 +118,16 @@
|
||||
<div class="description">{source.project.description}</div>
|
||||
</header>
|
||||
|
||||
{#await proj.getRoot(source.project, revision, peer, source.seed.api) then { tree, branches, commit }}
|
||||
<Header {tree} {branches} {commit} {browserStore} {source} {peerSelector} />
|
||||
<ProjectContentRoutes {tree} {peer} {branches} {browserStore} {source} />
|
||||
{#await proj.getRoot(source.project, revision, source.branches, source.seed.api) then { tree, commit }}
|
||||
<Header {tree} {commit} {browserStore} {source} peerSelector={! source.profile} />
|
||||
|
||||
{#if content == proj.ProjectContent.Tree}
|
||||
<Browser {source} {tree} {browserStore} />
|
||||
{:else if content == proj.ProjectContent.History}
|
||||
<History {source} {commit} />
|
||||
{:else if content == proj.ProjectContent.Commit}
|
||||
<Commit {source} {commit} />
|
||||
{/if}
|
||||
{:catch err}
|
||||
<div class="container center-content">
|
||||
<div class="error error-message text-xsmall">
|
||||
|
||||
@@ -1,65 +1,38 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from "svelte/store";
|
||||
import { Route, Router } from "svelte-routing";
|
||||
import type * as proj from "@app/project";
|
||||
import type { Config } from "@app/config";
|
||||
import { ProjectContent } from "@app/project";
|
||||
import Browser from "./Browser.svelte";
|
||||
import Commit from "./Commit.svelte";
|
||||
import History from "./History.svelte";
|
||||
import RouteContext from "./RouteContext.svelte";
|
||||
|
||||
export let config: Config;
|
||||
export let source: proj.Source;
|
||||
export let tree: proj.Tree;
|
||||
export let browserStore: Writable<proj.Browser>;
|
||||
export let peer: string | null;
|
||||
export let branches: proj.Branches;
|
||||
|
||||
const project = source.project;
|
||||
</script>
|
||||
|
||||
<Router>
|
||||
<!-- The default action is to render Browser with the default branch head -->
|
||||
<Route path="/">
|
||||
<RouteContext {browserStore} {peer} {branches} {project}>
|
||||
<Browser {source} {tree} {browserStore} />
|
||||
</RouteContext>
|
||||
<RouteContext content={ProjectContent.Tree} {peer} {source} {config} />
|
||||
</Route>
|
||||
<Route path="/tree">
|
||||
<RouteContext {browserStore} {peer} {branches} {project}>
|
||||
<Browser {source} {tree} {browserStore} />
|
||||
</RouteContext>
|
||||
<RouteContext content={ProjectContent.Tree} {peer} {source} {config} />
|
||||
</Route>
|
||||
<Route path="/tree/*" let:params>
|
||||
<RouteContext route={params["*"]} {browserStore} {peer} {branches} {project}>
|
||||
<Browser {source} {tree} {browserStore} />
|
||||
</RouteContext>
|
||||
<RouteContext route={params["*"]} content={ProjectContent.Tree} {peer} {source} {config} />
|
||||
</Route>
|
||||
|
||||
<Route path="/history">
|
||||
<RouteContext {browserStore} content={ProjectContent.History} {peer} {branches} {project} let:commit>
|
||||
{#if commit}
|
||||
<History {source} {commit} />
|
||||
{/if}
|
||||
</RouteContext>
|
||||
<RouteContext content={ProjectContent.History} {peer} {source} {config} />
|
||||
</Route>
|
||||
<Route path="/history/*" let:params>
|
||||
<RouteContext route={params["*"]} {browserStore} content={ProjectContent.History} {peer} {branches} {project} let:commit>
|
||||
{#if commit}
|
||||
<History {source} {commit} />
|
||||
{/if}
|
||||
</RouteContext>
|
||||
<RouteContext route={params["*"]} content={ProjectContent.History} {peer} {source} {config} />
|
||||
</Route>
|
||||
|
||||
<Route path="/commits/:commit" let:params>
|
||||
<RouteContext revision={params.commit} {browserStore} {project} content={ProjectContent.Commit} {peer} {branches} let:revision>
|
||||
{#if revision}
|
||||
<Commit {source} commit={revision} />
|
||||
{/if}
|
||||
</RouteContext>
|
||||
<RouteContext revision={params.commit} content={ProjectContent.Commit} {peer} {source} {config} />
|
||||
</Route>
|
||||
<Route path="/commits/*" let:params>
|
||||
<RouteContext route={params["*"]} {browserStore} {project} content={ProjectContent.Commit} {peer} {branches} let:revision>
|
||||
{#if revision}
|
||||
<Commit {source} commit={revision} />
|
||||
{/if}
|
||||
</RouteContext>
|
||||
<RouteContext route={params["*"]} content={ProjectContent.Commit} {peer} {source} {config} />
|
||||
</Route>
|
||||
</Router>
|
||||
|
||||
@@ -1,42 +1,40 @@
|
||||
<script lang="ts">
|
||||
import type { Writable } from 'svelte/store';
|
||||
import type { Config } from "@app/config";
|
||||
import * as proj from '@app/project';
|
||||
|
||||
export let browserStore: Writable<proj.Browser>;
|
||||
import Project from './Project.svelte';
|
||||
|
||||
export let browserStore: Writable<proj.Browser> = proj.browserStore;
|
||||
export let route: string | null = null;
|
||||
export let revision: string | null = null;
|
||||
export let peer: string | null;
|
||||
export let content: proj.ProjectContent = proj.ProjectContent.Tree;
|
||||
export let branches: proj.Branches;
|
||||
export let project: proj.ProjectInfo;
|
||||
export let source: proj.Source;
|
||||
export let config: Config;
|
||||
|
||||
const browse: any = { content, peer, branches, path: "/" };
|
||||
const browse: any = { content, peer, path: "/" };
|
||||
const head = source.branches[source.project.defaultBranch];
|
||||
|
||||
$: if (route) {
|
||||
const result = proj.splitPrefixFromPath(route, $browserStore.branches);
|
||||
const { path, revision } = proj.parseRoute(route, source.branches);
|
||||
|
||||
console.log("RouteParser", route, result);
|
||||
|
||||
if (result) {
|
||||
const [revision, path] = result;
|
||||
|
||||
browse.revision = revision;
|
||||
browse.path = path;
|
||||
}
|
||||
if (path) browse.path = path;
|
||||
if (revision) browse.revision = revision;
|
||||
} else if (revision) {
|
||||
browse.revision = revision;
|
||||
} else {
|
||||
browse.revision = branches[project.defaultBranch];
|
||||
browse.revision = head;
|
||||
}
|
||||
|
||||
$: proj.browse(browse);
|
||||
$: browser = $browserStore;
|
||||
$: commit = browser.revision && proj.getOid(browser.revision, browser.branches);
|
||||
</script>
|
||||
|
||||
<slot
|
||||
revision={browser.revision}
|
||||
<Project
|
||||
peer={browser.peer}
|
||||
path={browser.path || "/"}
|
||||
{commit}
|
||||
></slot>
|
||||
revision={browser.revision || head}
|
||||
content={browser.content}
|
||||
{source}
|
||||
{config}
|
||||
/>
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
import Redirect from "@app/Redirect.svelte";
|
||||
|
||||
export let config: Config;
|
||||
|
||||
</script>
|
||||
|
||||
<!-- With an Seed context -->
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
import { Seed } from '@app/base/seeds/Seed';
|
||||
import NotFound from '@app/NotFound.svelte';
|
||||
|
||||
import Project from './Project.svelte';
|
||||
import ProjectContentRoutes from './ProjectContentRoutes.svelte';
|
||||
|
||||
export let id: string; // Project name or URN.
|
||||
export let seedHost: string | null = null;
|
||||
@@ -15,14 +15,6 @@
|
||||
export let peer: string | null = null;
|
||||
export let config: Config;
|
||||
|
||||
// Show peer selector only if we're browsing via a seed.
|
||||
const peerSelector = Boolean(seedHost);
|
||||
|
||||
// Nb. Once we move the content routing above this component, this should
|
||||
// no longer be necessary, but right now, we have the project header that
|
||||
// is rendered before the routes are parsed, so we have to set this here.
|
||||
proj.browse({ peer });
|
||||
|
||||
const getProject = async (): Promise<proj.Source> => {
|
||||
const profile = profileName ? await Profile.get(profileName, ProfileType.Project, config) : null;
|
||||
const seed = profile ? profile.seed : seedHost ? await Seed.lookup(seedHost, config) : null;
|
||||
@@ -34,18 +26,25 @@
|
||||
throw new Error("Couldn't load project: invalid seed");
|
||||
}
|
||||
|
||||
const info = await proj.getInfo(id, seed.api);
|
||||
const urn = isRadicleId(id) ? id : info.urn;
|
||||
const project = await proj.getInfo(id, seed.api);
|
||||
const urn = isRadicleId(id) ? id : project.urn;
|
||||
const anchors = profile ? await profile.confirmedProjectAnchors(urn, config) : [];
|
||||
|
||||
// Older versions of http-api don't include the URN.
|
||||
if (! info.urn) info.urn = urn;
|
||||
if (! project.urn) project.urn = urn;
|
||||
|
||||
const peers: proj.PeerId[] = info.delegates
|
||||
const peers: proj.PeerId[] = project.delegates
|
||||
? await proj.getRemotes(urn, seed.api)
|
||||
: [];
|
||||
|
||||
return { urn, seed, project: info, peers, profile, anchors };
|
||||
let remote: proj.Remote = {
|
||||
heads: { [project.defaultBranch]: project.head }
|
||||
};
|
||||
|
||||
if (peer) {
|
||||
remote = await proj.getRemote(urn, peer, seed.api);
|
||||
}
|
||||
return { urn, seed, project, peers, branches: remote.heads, profile, anchors };
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -77,7 +76,7 @@
|
||||
<Loading center />
|
||||
</header>
|
||||
{:then source}
|
||||
<Project {source} {peer} {config} {peerSelector} />
|
||||
<ProjectContentRoutes {source} {peer} {config} />
|
||||
{:catch}
|
||||
<NotFound title={id} subtitle="This project was not found." />
|
||||
{/await}
|
||||
|
||||
+24
-31
@@ -33,6 +33,7 @@ export interface Source {
|
||||
urn: string;
|
||||
project: ProjectInfo;
|
||||
peers: PeerId[];
|
||||
branches: Branches;
|
||||
anchors: string[];
|
||||
seed: Seed;
|
||||
profile?: Profile | null;
|
||||
@@ -97,7 +98,6 @@ export interface Remote {
|
||||
|
||||
export interface Browser {
|
||||
content: ProjectContent;
|
||||
branches: Branches;
|
||||
revision: string | null;
|
||||
peer: string | null;
|
||||
path: string | null;
|
||||
@@ -112,21 +112,16 @@ export const browserStore = writable({
|
||||
} as Browser);
|
||||
|
||||
export interface BrowseTo {
|
||||
content?: ProjectContent;
|
||||
revision?: string | null;
|
||||
path?: string | null;
|
||||
peer?: string | null;
|
||||
branches?: Branches;
|
||||
}
|
||||
|
||||
export interface PathOptions {
|
||||
urn: string;
|
||||
content?: ProjectContent;
|
||||
profile?: string | null;
|
||||
seed?: string | null;
|
||||
peer?: string | null;
|
||||
revision?: string | null;
|
||||
path?: string | null;
|
||||
peer?: string | null;
|
||||
}
|
||||
|
||||
export interface PathOptions extends BrowseTo {
|
||||
urn: string;
|
||||
profile?: string | null;
|
||||
seed?: string | null;
|
||||
}
|
||||
|
||||
export function browse(browse: BrowseTo): void {
|
||||
@@ -191,28 +186,20 @@ export async function getRemotes(urn: string, host: api.Host): Promise<PeerId[]>
|
||||
export async function getRoot(
|
||||
project: ProjectInfo,
|
||||
revision: string | null,
|
||||
peer: string | null,
|
||||
heads: Branches,
|
||||
host: api.Host
|
||||
): Promise<{ tree: Tree; branches: Branches; commit: string }> {
|
||||
): Promise<{ tree: Tree; commit: string }> {
|
||||
const urn = project.urn;
|
||||
|
||||
let remote: Remote = {
|
||||
heads: { [project.defaultBranch]: project.head }
|
||||
};
|
||||
|
||||
if (peer) {
|
||||
remote = await getRemote(urn, peer, host);
|
||||
}
|
||||
|
||||
const head = remote.heads[project.defaultBranch];
|
||||
const commit = revision ? getOid(revision, remote.heads) : head;
|
||||
const head = heads[project.defaultBranch];
|
||||
const commit = revision ? getOid(revision, heads) : head;
|
||||
|
||||
if (! commit) {
|
||||
throw new Error(`Revision ${revision} not found`);
|
||||
}
|
||||
const tree = await getTree(urn, commit, "/", host);
|
||||
|
||||
return { tree, branches: remote.heads, commit };
|
||||
return { tree, commit };
|
||||
}
|
||||
|
||||
export async function getTree(
|
||||
@@ -298,16 +285,22 @@ export function getOid(revision: string, branches?: Branches): string | null {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Splits the path consisting of a revision (eg. branch or commit) and file path into a tuple [revision, file-path]
|
||||
export function splitPrefixFromPath(input: string, branches: Branches): [string, string] | null {
|
||||
// Parses the path consisting of a revision (eg. branch or commit) and file path into a tuple [revision, file-path]
|
||||
export function parseRoute(input: string, branches: Branches): { path?: string; revision?: string } {
|
||||
const branch = Object.entries(branches).find(([branchName,]) => input.startsWith(branchName));
|
||||
const commitPath = [input.slice(0, 40), input.slice(41)];
|
||||
const parsed: { path?: string; revision?: string } = {};
|
||||
|
||||
if (branch) {
|
||||
const [rev, path] = [input.slice(0, branch[0].length), input.slice(branch[0].length + 1)];
|
||||
return [rev, path ? path : "/"];
|
||||
|
||||
parsed.revision = rev;
|
||||
parsed.path = path ? path : "/";
|
||||
} else if (isOid(commitPath[0])) {
|
||||
return [commitPath[0], commitPath[1] ? commitPath[1] : "/"];
|
||||
parsed.revision = commitPath[0];
|
||||
parsed.path = commitPath[1] ? commitPath[1] : "/";
|
||||
} else {
|
||||
parsed.path = input;
|
||||
}
|
||||
return null;
|
||||
return parsed;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user