feat: more feature flags
This commit is contained in:
parent
1a507679f3
commit
281785952d
@ -9,6 +9,9 @@
|
|||||||
"httpCache": "",
|
"httpCache": "",
|
||||||
"animalNamePlaceholders": false,
|
"animalNamePlaceholders": false,
|
||||||
"features": {
|
"features": {
|
||||||
"subscriptions": true
|
"analytics": true,
|
||||||
|
"subscriptions": true,
|
||||||
|
"deck": true,
|
||||||
|
"zapPool": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
4
packages/app/custom.d.ts
vendored
4
packages/app/custom.d.ts
vendored
@ -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;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -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>
|
||||||
</>
|
</>
|
||||||
|
@ -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";
|
||||||
|
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
)}
|
)}
|
||||||
|
@ -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" />
|
||||||
|
@ -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} />
|
||||||
|
@ -168,4 +168,4 @@ class ZapPool extends ExternalStore<Array<ZapPoolRecipient>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ZapPoolController = new ZapPool();
|
export const ZapPoolController = CONFIG.features.zapPool ? new ZapPool() : undefined;
|
||||||
|
@ -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(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user