diff --git a/src/App/Header.svelte b/src/App/Header.svelte index c9bf5e7ae..ecceeccdd 100644 --- a/src/App/Header.svelte +++ b/src/App/Header.svelte @@ -11,6 +11,7 @@ import NodeInfo from "@app/App/Header/NodeInfo.svelte"; import Popover from "@app/components/Popover.svelte"; import ConnectInstructions from "@app/components/ConnectInstructions.svelte"; + import { experimental } from "@app/lib/appearance"; const buttonTitle: Record = { stopped: "radicle-httpd is stopped", @@ -60,24 +61,26 @@
- {#if $httpdStore.state === "stopped"} - - -
- -
-
- {:else} - - + {#if $experimental} + {#if $httpdStore.state === "stopped"} + + +
+ +
+
+ {:else} + + + {/if} {/if}
diff --git a/src/App/Settings.svelte b/src/App/Settings.svelte index b14ed5467..7e96e6260 100644 --- a/src/App/Settings.svelte +++ b/src/App/Settings.svelte @@ -2,7 +2,9 @@ import { codeFont, codeFonts, + experimental, storeCodeFont, + storeExperimental, storeTheme, theme, } from "@app/lib/appearance"; @@ -14,7 +16,7 @@
- {#if $httpdStore.state === "running"} -
Authenticate with your local node to make changes.
- + {#if $experimental} + {#if $httpdStore.state === "running"} +
+ Authenticate with your local node to make changes. +
+ + {:else} +
Connect & Authenticate
+
+ Connect to your local node to browse projects on your local machine, + create issues, and participate in discussions. +
+ + +
+
New to Radicle?
+
+ Visit to download Radicle + and get started. +
+ {/if} {:else} -
Connect & Authenticate
+
Browse your local projects
- Connect to your local node to browse projects on your local machine, - create issues, and participate in discussions. + To browse projects on your local node, run the following command.
- +
New to Radicle?
- Run the following command and follow the instructions to install Radicle + Visit to download Radicle and get started.
- {/if}
diff --git a/src/components/Reactions.svelte b/src/components/Reactions.svelte index 79b73be14..d0d5f68af 100644 --- a/src/components/Reactions.svelte +++ b/src/components/Reactions.svelte @@ -25,16 +25,23 @@
{#each reactions as { emoji, authors }} - { - if (handleReaction) { - await handleReaction(authors, emoji); - } - }}> -
+ {#if handleReaction} + { + if (handleReaction) { + await handleReaction(authors, emoji); + } + }}> +
+ {emoji} + {authors.length} +
+
+ {:else} +
{emoji} {authors.length}
- + {/if} {/each}
diff --git a/src/lib/appearance.ts b/src/lib/appearance.ts index 7856377e3..fe1a17dd2 100644 --- a/src/lib/appearance.ts +++ b/src/lib/appearance.ts @@ -48,3 +48,25 @@ export function storeCodeFont(newCodeFont: CodeFont): void { codeFont.set(newCodeFont); window.localStorage.setItem("codefont", newCodeFont); } + +export const experimental = writable( + loadExperimentalSetting(), +); + +function loadExperimentalSetting(): true | undefined { + const storedExperimental = window.localStorage.getItem("experimental"); + + if (storedExperimental === null) { + return undefined; + } else { + return storedExperimental === "true" ? true : undefined; + } +} + +export function storeExperimental(newSetting: true | undefined): void { + experimental.set(newSetting); + window.localStorage.setItem( + "experimental", + newSetting === true ? "true" : "undefined", + ); +} diff --git a/src/lib/httpd.ts b/src/lib/httpd.ts index e036ecdb1..bb4c6f76e 100644 --- a/src/lib/httpd.ts +++ b/src/lib/httpd.ts @@ -6,6 +6,7 @@ import { withTimeout, Mutex, E_CANCELED, E_TIMEOUT } from "async-mutex"; import { HttpdClient } from "@httpd-client"; import { config } from "@app/lib/config"; import { deduplicateStore } from "@app/lib/deduplicateStore"; +import { experimental } from "./appearance"; export interface Session { id: string; @@ -128,6 +129,15 @@ async function checkState() { try { const node = await api.getNode(); + // Return quickly and avoid additional fetches + // if experimental settings aren't updated + if (!get(experimental)) { + update({ + state: "running", + node, + }); + } + if (httpdState && httpdState.state !== "stopped") { httpdState.node = node; } diff --git a/src/lib/roles.ts b/src/lib/roles.ts index bf2097bf5..6c3b97c3c 100644 --- a/src/lib/roles.ts +++ b/src/lib/roles.ts @@ -1,4 +1,6 @@ import { parseNodeId } from "@app/lib/utils"; +import { get } from "svelte/store"; +import { experimental } from "./appearance"; export function isDelegate( publicKey: string | undefined, @@ -27,10 +29,13 @@ function matchAuthor( // All restricted actions are a combination of either: // - the user is a delegate // - the user is an author of the comment, issue, patch, etc. +// +// If the experimental setting isn't turned on, we return undefined early. export function isDelegateOrAuthor( publicKey: string | undefined, delegates: string[], author: string, ) { + if (get(experimental) === undefined) return undefined; return isDelegate(publicKey, delegates) || matchAuthor(publicKey, author); } diff --git a/src/views/home/Index.svelte b/src/views/home/Index.svelte index c6867ab9c..94c3d99d5 100644 --- a/src/views/home/Index.svelte +++ b/src/views/home/Index.svelte @@ -6,8 +6,9 @@ import { literal, union } from "zod"; import { api, httpdStore } from "@app/lib/httpd"; - import { deduplicateStore } from "@app/lib/deduplicateStore"; import { baseUrlToString } from "@app/lib/utils"; + import { deduplicateStore } from "@app/lib/deduplicateStore"; + import { experimental } from "@app/lib/appearance"; import { handleError } from "@app/views/home/error"; import { isDelegate } from "@app/lib/roles"; import { preferredSeeds } from "@app/lib/seeds"; @@ -127,54 +128,65 @@
-
- - - - - - -
- {#if !nodeId} -
- -
- {:else if localProjects instanceof Error} - - {:else if !localProjects?.length} -
No local projects
-
- Seed or check out a project to work with it on your local node. -
- {:else} -
Nothing to see here
-
- No local projects matched your filter settings. -
+ {#if $experimental} +
+ + + + + + +
+ {#if !nodeId} +
+ +
+ {:else if localProjects instanceof Error} + + {:else if !localProjects?.length} +
No local projects
+
+ Seed or check out a project to work with it on your local + node. +
+ {:else} +
Nothing to see here
+
+ No local projects matched your filter settings. +
+ {/if} +
+
+
+ {#if filteredLocalProjects && !(filteredLocalProjects instanceof Error)} + {#each filteredLocalProjects as projectInfo} + + {/each} {/if}
- -
- {#if filteredLocalProjects && !(filteredLocalProjects instanceof Error)} - {#each filteredLocalProjects as projectInfo} - - {/each} - {/if} -
-
-
+ +
+ {/if} import * as modal from "@app/lib/modal"; + import { experimental } from "@app/lib/appearance"; import { httpdStore, api } from "@app/lib/httpd"; import Button from "@app/components/Button.svelte"; + import Command from "@app/components/Command.svelte"; import ErrorModal from "@app/modals/ErrorModal.svelte"; import IconSmall from "@app/components/IconSmall.svelte"; import Popover from "@app/components/Popover.svelte"; @@ -70,63 +72,80 @@ .counter { font-weight: var(--font-weight-regular); border-radius: var(--border-radius-tiny); - background-color: var(--color-fill-secondary-counter); + background-color: var(--color-fill-ghost-hover); border: 1px solid var(--color-border-secondary-counter); - color: var(--color-foreground-match-background); + color: var(--color-foreground-contrast); padding: 0 0.25rem; } .seeding { background-color: var(--color-fill-counter-emphasized); color: var(--color-foreground-emphasized); } + .not-seeding { + background-color: var(--color-fill-secondary-counter); + color: var(--color-foreground-match-background); + } .disabled { - background-color: var(--color-fill-ghost-hover); + background-color: var(--color-fill-float-hover); color: var(--color-foreground-disabled); } -
-
Stop seeding
-
- Are you sure you want to stop seeding this project? If you don't seed a - project it won't appear in the local projects section anymore and any - changes you make to it won't propagate to the network. -
- +
+ {#if $experimental && canEditSeeding && seeding} +
Stop seeding
+
+ Are you sure you want to stop seeding this project? If you don't seed a + project it won't appear in the local projects section anymore and any + changes you make to it won't propagate to the network. +
+ + {:else} + + Use the Radicle CLI to {seeding ? "stop" : "start"} seeding this project. + + + {/if}
diff --git a/src/views/projects/Issue.svelte b/src/views/projects/Issue.svelte index ef6176d2d..aa321485c 100644 --- a/src/views/projects/Issue.svelte +++ b/src/views/projects/Issue.svelte @@ -17,6 +17,7 @@ import * as role from "@app/lib/roles"; import * as router from "@app/lib/router"; import * as utils from "@app/lib/utils"; + import { experimental } from "@app/lib/appearance"; import { HttpdClient } from "@httpd-client"; import { closeFocused } from "@app/components/Popover.svelte"; import { httpdStore } from "@app/lib/httpd"; @@ -537,7 +538,7 @@ {/if}
- {#if issueState !== "read"} + {#if $experimental && issueState !== "read"} newTitle.length > 0} disallowEmptyBody @@ -578,7 +579,7 @@ No description {/if}
- {#if session} + {#if $experimental && session} { @@ -635,14 +636,20 @@ session?.publicKey, project.delegates, )} - editComment={session && partial(editComment, session.id)} - createReply={session && partial(createReply, session.id)} - reactOnComment={session && partial(reactOnComment, session)} /> + editComment={$experimental && + session && + partial(editComment, session.id)} + createReply={$experimental && + session && + partial(createReply, session.id)} + reactOnComment={$experimental && + session && + partial(reactOnComment, session)} />
{/each}
{/if} - {#if session} + {#if $experimental && session} {#if threads.length === 0}
{/if} import type { BaseUrl, Issue, IssueState, Project } from "@httpd-client"; + import capitalize from "lodash/capitalize"; import { HttpdClient } from "@httpd-client"; import { ISSUES_PER_PAGE } from "./router"; - import { closeFocused } from "@app/components/Popover.svelte"; - import { httpdStore } from "@app/lib/httpd"; import { baseUrlToString, isLocal } from "@app/lib/utils"; - import capitalize from "lodash/capitalize"; + import { closeFocused } from "@app/components/Popover.svelte"; + import { experimental } from "@app/lib/appearance"; + import { httpdStore } from "@app/lib/httpd"; import Button from "@app/components/Button.svelte"; import DropdownList from "@app/components/DropdownList.svelte"; @@ -146,7 +147,7 @@
- {#if $httpdStore.state === "authenticated" && isLocal(baseUrl.hostname)} + {#if $experimental && $httpdStore.state === "authenticated" && isLocal(baseUrl.hostname)}
- {#if session && patchState !== "read" && lastEdit} + {#if $experimental && session && patchState !== "read" && lastEdit} patch.title.length > 0} enableAttachments @@ -802,7 +803,7 @@ {:else} No description available {/if} - {#if session || (firstRevision.revisionReactions && firstRevision.revisionReactions.length > 0)} + {#if ($experimental && session) || (firstRevision.revisionReactions && firstRevision.revisionReactions.length > 0)}
{#if session} {#if index === patch.revisions.length - 1} - {#if session && view.name === "activity"} + {#if $experimental && session && view.name === "activity"}
- {#if $httpdStore.state === "authenticated" && isLocal(baseUrl.hostname)} + {#if $experimental && $httpdStore.state === "authenticated" && isLocal(baseUrl.hostname)}