feat: more feature flags
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Kieran 2023-10-17 10:54:34 +01:00
parent 1a507679f3
commit 281785952d
Signed by: Kieran
GPG Key ID: DE71CEB3925BE941
12 changed files with 119 additions and 87 deletions

View File

@ -9,6 +9,9 @@
"httpCache": "", "httpCache": "",
"animalNamePlaceholders": false, "animalNamePlaceholders": false,
"features": { "features": {
"subscriptions": true "analytics": true,
"subscriptions": true,
"deck": true,
"zapPool": true
} }
} }

View File

@ -9,6 +9,9 @@
"httpCache": "https://api.iris.to", "httpCache": "https://api.iris.to",
"animalNamePlaceholders": true, "animalNamePlaceholders": true,
"features": { "features": {
"subscriptions": false "analytics": true,
"subscriptions": false,
"deck": true,
"zapPool": true
} }
} }

View File

@ -45,7 +45,11 @@ declare const CONFIG: {
appleTouchIconUrl: string; appleTouchIconUrl: string;
httpCache: string; httpCache: string;
animalNamePlaceholders: boolean; animalNamePlaceholders: boolean;
defaultZapPoolFee?: number;
features: { features: {
analytics: boolean;
subscriptions: boolean; subscriptions: boolean;
deck: boolean;
zapPool: boolean;
}; };
}; };

View File

@ -80,7 +80,7 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
return ( return (
<> <>
<button className="circle flex flex-center" onClick={() => attachFile()}> <button className="circle flex f-center" onClick={() => attachFile()}>
{uploading ? <Spinner width={20} /> : <Icon name="attachment" size={20} />} {uploading ? <Spinner width={20} /> : <Icon name="attachment" size={20} />}
</button> </button>
<div className="w-max"> <div className="w-max">
@ -97,7 +97,7 @@ export default function WriteMessage({ chat }: { chat: Chat }) {
/> />
{error && <b className="error">{error}</b>} {error && <b className="error">{error}</b>}
</div> </div>
<button className="circle flex flex-center" onClick={() => sendMessage()}> <button className="circle flex f-center" onClick={() => sendMessage()}>
{sending ? <Spinner width={20} /> : <Icon name="arrow-right" size={20} />} {sending ? <Spinner width={20} /> : <Icon name="arrow-right" size={20} />}
</button> </button>
</> </>

View File

@ -1,11 +1,12 @@
import "./Markdown.css"; import "./Markdown.css";
import { ReactNode, forwardRef, useMemo } from "react"; import { ReactNode, forwardRef, useMemo } from "react";
import { transformText } from "@snort/system";
import { marked, Token } from "marked"; import { marked, Token } from "marked";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import markedFootnote, { Footnotes, Footnote, FootnoteRef } from "marked-footnote"; import markedFootnote, { Footnotes, Footnote, FootnoteRef } from "marked-footnote";
import { ProxyImg } from "Element/ProxyImg"; import { ProxyImg } from "Element/ProxyImg";
import { transformText } from "@snort/system";
import Mention from "Element/Embed/Mention"; import Mention from "Element/Embed/Mention";
import NostrLink from "Element/Embed/NostrLink"; import NostrLink from "Element/Embed/NostrLink";

View File

@ -159,7 +159,9 @@ export default function NoteFooter(props: NoteFooterProps) {
const result = await zapper.send(wallet, targets, amount); const result = await zapper.send(wallet, targets, amount);
const totalSent = result.reduce((acc, v) => (acc += v.sent), 0); const totalSent = result.reduce((acc, v) => (acc += v.sent), 0);
if (totalSent > 0) { if (totalSent > 0) {
ZapPoolController.allocate(totalSent); if (CONFIG.features.zapPool) {
ZapPoolController?.allocate(totalSent);
}
await interactionCache.zap(); await interactionCache.zap();
} }
}); });

View File

@ -78,7 +78,7 @@ export default function Layout() {
onClick={() => { onClick={() => {
LoginStore.removeSession(id); LoginStore.removeSession(id);
}}> }}>
<button type="button" className="circle flex flex-center"> <button type="button" className="circle flex f-center">
<Icon name="close" /> <Icon name="close" />
</button> </button>
</div> </div>

View File

@ -34,6 +34,7 @@ const DataProviders = [
]; ];
function ZapTarget({ target }: { target: ZapPoolRecipient }) { function ZapTarget({ target }: { target: ZapPoolRecipient }) {
if (!ZapPoolController) return;
const login = useLogin(); const login = useLogin();
const profile = useUserProfile(target.pubkey); const profile = useUserProfile(target.pubkey);
const hasAddress = profile?.lud16 || profile?.lud06; const hasAddress = profile?.lud16 || profile?.lud06;
@ -54,7 +55,7 @@ function ZapTarget({ target }: { target: ZapPoolRecipient }) {
max={100} max={100}
value={target.split} value={target.split}
onChange={e => onChange={e =>
ZapPoolController.set({ ZapPoolController?.set({
...target, ...target,
split: e.target.valueAsNumber, split: e.target.valueAsNumber,
}) })
@ -70,11 +71,12 @@ function ZapTarget({ target }: { target: ZapPoolRecipient }) {
} }
export default function ZapPoolPage() { export default function ZapPoolPage() {
if (!ZapPoolController) return;
const login = useLogin(); const login = useLogin();
const { system } = useEventPublisher(); const { system } = useEventPublisher();
const zapPool = useSyncExternalStore( const zapPool = useSyncExternalStore(
c => ZapPoolController.hook(c), c => unwrap(ZapPoolController).hook(c),
() => ZapPoolController.snapshot(), () => unwrap(ZapPoolController).snapshot(),
); );
const { wallet } = useWallet(); const { wallet } = useWallet();
@ -146,7 +148,7 @@ export default function ZapPoolPage() {
</p> </p>
<p> <p>
{wallet && ( {wallet && (
<AsyncButton onClick={() => ZapPoolController.payout(wallet)}> <AsyncButton onClick={() => ZapPoolController?.payout(wallet)}>
<FormattedMessage defaultMessage="Payout Now" /> <FormattedMessage defaultMessage="Payout Now" />
</AsyncButton> </AsyncButton>
)} )}

View File

@ -207,7 +207,7 @@ export default function ProfileSettings(props: ProfileSettingsProps) {
<Avatar pubkey={id} user={user} image={picture} /> <Avatar pubkey={id} user={user} image={picture} />
<AsyncButton <AsyncButton
type="button" type="button"
className="circle flex flex-center" className="circle flex f-center"
onClick={() => setNewAvatar()} onClick={() => setNewAvatar()}
disabled={readonly}> disabled={readonly}>
<Icon name="upload-01" /> <Icon name="upload-01" />

View File

@ -92,11 +92,13 @@ const SettingsIndex = () => {
<FormattedMessage {...messages.Donate} /> <FormattedMessage {...messages.Donate} />
<Icon name="arrowFront" size={16} /> <Icon name="arrowFront" size={16} />
</div> </div>
<div className="settings-row" onClick={() => navigate("/zap-pool")}> {CONFIG.features.zapPool && (
<Icon name="piggy-bank" size={24} /> <div className="settings-row" onClick={() => navigate("/zap-pool")}>
<FormattedMessage defaultMessage="Zap Pool" /> <Icon name="piggy-bank" size={24} />
<Icon name="arrowFront" size={16} /> <FormattedMessage defaultMessage="Zap Pool" />
</div> <Icon name="arrowFront" size={16} />
</div>
)}
<div className="settings-row" onClick={handleLogout}> <div className="settings-row" onClick={handleLogout}>
<Icon name="logout" size={24} /> <Icon name="logout" size={24} />
<FormattedMessage {...messages.LogOut} /> <FormattedMessage {...messages.LogOut} />

View File

@ -168,4 +168,4 @@ class ZapPool extends ExternalStore<Array<ZapPoolRecipient>> {
} }
} }
export const ZapPoolController = new ZapPool(); export const ZapPoolController = CONFIG.features.zapPool ? new ZapPool() : undefined;

View File

@ -7,7 +7,7 @@ import WasmPath from "@snort/system-wasm/pkg/system_wasm_bg.wasm";
import { StrictMode } from "react"; import { StrictMode } from "react";
import * as ReactDOM from "react-dom/client"; import * as ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom"; import { createBrowserRouter, RouteObject, RouterProvider } from "react-router-dom";
import { import {
NostrSystem, NostrSystem,
ProfileLoaderService, ProfileLoaderService,
@ -148,7 +148,7 @@ async function initSite() {
// inject analytics script // inject analytics script
// <script defer data-domain="snort.social" src="http://analytics.v0l.io/js/script.js"></script> // <script defer data-domain="snort.social" src="http://analytics.v0l.io/js/script.js"></script>
if (login.preferences.telemetry ?? true) { if (CONFIG.features.analytics && (login.preferences.telemetry ?? true)) {
const sc = document.createElement("script"); const sc = document.createElement("script");
sc.src = "https://analytics.v0l.io/js/script.js"; sc.src = "https://analytics.v0l.io/js/script.js";
sc.defer = true; sc.defer = true;
@ -159,7 +159,79 @@ async function initSite() {
} }
let didInit = false; let didInit = false;
export const router = createBrowserRouter([ const mainRoutes = [
...RootRoutes,
{
path: "/login",
element: <LoginPage />,
},
{
path: "/help",
element: <HelpPage />,
},
{
path: "/e/:id",
element: <ThreadRoute />,
},
{
path: "/p/:id",
element: <ProfilePage />,
},
{
path: "/notifications",
element: <NotificationsPage />,
},
{
path: "/settings",
element: <SettingsPage />,
children: SettingsRoutes,
},
{
path: "/free-nostr-address",
element: <FreeNostrAddressPage />,
},
{
path: "/nostr-address",
element: <NostrAddressPage />,
},
{
path: "/messages/:id?",
element: <MessagesPage />,
},
{
path: "/donate",
element: <DonatePage />,
},
{
path: "/search/:keyword?",
element: <SearchPage />,
},
{
path: "/list-feed/:id",
element: <ListFeedPage />,
},
...NewUserRoutes,
...WalletRoutes,
] as Array<RouteObject>;
if (CONFIG.features.zapPool) {
mainRoutes.push({
path: "/zap-pool",
element: <ZapPoolPage />,
});
}
if (CONFIG.features.subscriptions) {
mainRoutes.push(...SubscribeRoutes);
}
// add catch all route
mainRoutes.push({
path: "/*",
element: <NostrLinkHandler />,
});
const routes = [
{ {
element: <Layout />, element: <Layout />,
errorElement: <ErrorPage />, errorElement: <ErrorPage />,
@ -170,71 +242,12 @@ export const router = createBrowserRouter([
} }
return null; return null;
}, },
children: [ children: mainRoutes,
...RootRoutes,
{
path: "/login",
element: <LoginPage />,
},
{
path: "/help",
element: <HelpPage />,
},
{
path: "/e/:id",
element: <ThreadRoute />,
},
{
path: "/p/:id",
element: <ProfilePage />,
},
{
path: "/notifications",
element: <NotificationsPage />,
},
{
path: "/settings",
element: <SettingsPage />,
children: SettingsRoutes,
},
{
path: "/free-nostr-address",
element: <FreeNostrAddressPage />,
},
{
path: "/nostr-address",
element: <NostrAddressPage />,
},
{
path: "/messages/:id?",
element: <MessagesPage />,
},
{
path: "/donate",
element: <DonatePage />,
},
{
path: "/search/:keyword?",
element: <SearchPage />,
},
{
path: "/zap-pool",
element: <ZapPoolPage />,
},
{
path: "/list-feed/:id",
element: <ListFeedPage />,
},
...NewUserRoutes,
...WalletRoutes,
...(CONFIG.features.subscriptions ? SubscribeRoutes : []),
{
path: "/*",
element: <NostrLinkHandler />,
},
],
}, },
{ ] as Array<RouteObject>;
if (CONFIG.features.deck) {
routes.push({
path: "/deck", path: "/deck",
element: <SnortDeckLayout />, element: <SnortDeckLayout />,
loader: async () => { loader: async () => {
@ -245,8 +258,10 @@ export const router = createBrowserRouter([
return null; return null;
}, },
children: RootTabRoutes, children: RootTabRoutes,
}, } as RouteObject);
]); }
export const router = createBrowserRouter(routes);
const root = ReactDOM.createRoot(unwrap(document.getElementById("root"))); const root = ReactDOM.createRoot(unwrap(document.getElementById("root")));
root.render( root.render(