developer mode

This commit is contained in:
Sebastian 2021-06-30 00:24:43 -03:00
parent b43c476590
commit 05e89a3cf7
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
14 changed files with 292 additions and 51 deletions

View File

@ -25,6 +25,7 @@ module.exports = {
"../src/**/*.stories.tsx",
],
"addons": [
"storybook-dark-mode",
"@storybook/addon-a11y",
"@storybook/addon-essentials" //docs, control, actions, viewport, toolbar, background
],

View File

@ -54,6 +54,7 @@
"rollup-plugin-ignore": "^1.0.9",
"rollup-plugin-sourcemaps": "^0.6.3",
"rollup-plugin-terser": "^7.0.2",
"storybook-dark-mode": "^1.0.8",
"typescript": "^4.1.3"
},
"jest": {

View File

@ -16,22 +16,29 @@
import { JSX } from "preact/jsx-runtime";
export function PermissionsCheckbox({ enabled, onToggle }: { enabled: boolean; onToggle: () => void; }): JSX.Element {
interface Props {
enabled: boolean;
onToggle: () => void;
label: string;
name: string;
description?: string;
}
export function Checkbox({ name, enabled, onToggle, label, description }: Props): JSX.Element {
return (
<div>
<input
checked={enabled}
onClick={onToggle}
type="checkbox"
id="checkbox-perm"
id={`checkbox-${name}`}
style={{ width: "1.5em", height: "1.5em", verticalAlign: "middle" }} />
<label
htmlFor="checkbox-perm"
htmlFor={`checkbox-${name}`}
style={{ marginLeft: "0.5em", fontWeight: "bold" }}
>
Automatically open wallet based on page content
{label}
</label>
<span
{description && <span
style={{
color: "#383838",
fontSize: "smaller",
@ -39,9 +46,8 @@ export function PermissionsCheckbox({ enabled, onToggle }: { enabled: boolean; o
marginLeft: "2em",
}}
>
(Enabling this option below will make using the wallet faster, but
requires more permissions from your browser.)
</span>
{description}
</span>}
</div>
);
}

View File

@ -0,0 +1,42 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import { createContext, h, VNode } from 'preact'
import { useContext, useState } from 'preact/hooks'
import { useLocalStorage } from '../hooks/useLocalStorage';
interface Type {
devMode: boolean;
toggleDevMode: () => void;
}
const Context = createContext<Type>({
devMode: false,
toggleDevMode: () => null
})
export const useDevContext = (): Type => useContext(Context);
export const DevContextProvider = ({ children }: { children: any }): VNode => {
const [value, setter] = useLocalStorage('devMode')
const devMode = value === "true"
const toggleDevMode = () => setter(v => !v ? "true" : undefined)
return h(Context.Provider, { value: { devMode, toggleDevMode }, children });
}

View File

@ -0,0 +1,44 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import { StateUpdater, useState } from "preact/hooks";
export function useLocalStorage(key: string, initialValue?: string): [string | undefined, StateUpdater<string | undefined>] {
const [storedValue, setStoredValue] = useState<string | undefined>((): string | undefined => {
return typeof window !== "undefined" ? window.localStorage.getItem(key) || initialValue : initialValue;
});
const setValue = (value?: string | ((val?: string) => string | undefined)) => {
setStoredValue(p => {
const toStore = value instanceof Function ? value(p) : value
if (typeof window !== "undefined") {
if (!toStore) {
window.localStorage.removeItem(key)
} else {
window.localStorage.setItem(key, toStore);
}
}
return toStore
})
};
return [storedValue, setValue];
}

View File

@ -0,0 +1,35 @@
/*
This file is part of TALER
(C) 2016 GNUnet e.V.
TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { VNode } from "preact";
import { useDevContext } from "../context/useDevContext";
import { useExtendedPermissions } from "../hooks/useExtendedPermissions";
export function BackupPage(): VNode {
return <BackupView />;
}
export interface ViewProps {
}
export function BackupView({}: ViewProps): VNode {
return (
<div>
Backup page
</div>
)
}

View File

@ -19,7 +19,7 @@ import { Diagnostics } from "../components/Diagnostics";
import * as wxApi from "../wxApi";
export function DebugPage(props: any): JSX.Element {
export function DeveloperPage(props: any): JSX.Element {
return (
<div>
<p>Debug tools:</p>

View File

@ -0,0 +1,54 @@
/*
This file is part of GNU Taler
(C) 2021 Taler Systems S.A.
GNU Taler is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 3, or (at your option) any later version.
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
import {
PaymentStatus,
TransactionCommon, TransactionDeposit, TransactionPayment,
TransactionRefresh, TransactionRefund, TransactionTip, TransactionType,
TransactionWithdrawal,
WithdrawalType
} from '@gnu-taler/taler-util';
import { FunctionalComponent } from 'preact';
import { SettingsView as TestedComponent } from './Settings';
export default {
title: 'popup/settings',
component: TestedComponent,
argTypes: {
onRetry: { action: 'onRetry' },
onDelete: { action: 'onDelete' },
onBack: { action: 'onBack' },
}
};
function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
const r = (args: any) => <Component {...args} />
r.args = props
return r
}
export const AllOff = createExample(TestedComponent, {});
export const OneChecked = createExample(TestedComponent, {
permissionsEnabled: true,
});

View File

@ -15,20 +15,42 @@
*/
import { PermissionsCheckbox } from "../components/PermissionsCheckbox";
import { VNode } from "preact";
import { Checkbox } from "../components/Checkbox";
import { useDevContext } from "../context/useDevContext";
import { useExtendedPermissions } from "../hooks/useExtendedPermissions";
export function SettingsPage() {
export function SettingsPage(): VNode {
const [permissionsEnabled, togglePermissions] = useExtendedPermissions();
const { devMode, toggleDevMode } = useDevContext()
return <SettingsView
permissionsEnabled={permissionsEnabled} togglePermissions={togglePermissions}
developerMode={devMode} toggleDeveloperMode={toggleDevMode}
/>;
}
export interface ViewProps {
permissionsEnabled: boolean;
togglePermissions: () => void;
developerMode: boolean;
toggleDeveloperMode: () => void;
}
export function SettingsView({permissionsEnabled, togglePermissions, developerMode, toggleDeveloperMode}: ViewProps): VNode {
return (
<div>
<h2>Permissions</h2>
<PermissionsCheckbox enabled={permissionsEnabled} onToggle={togglePermissions} />
{/*
<h2>Developer mode</h2>
<DebugCheckbox enabled={permissionsEnabled} onToggle={togglePermissions} />
*/}
<Checkbox label="Automatically open wallet based on page content"
name="perm"
description="(Enabling this option below will make using the wallet faster, but requires more permissions from your browser.)"
enabled={permissionsEnabled} onToggle={togglePermissions}
/>
<h2>Config</h2>
<Checkbox label="Developer mode"
name="devMode"
description="(More options and information useful for debugging)"
enabled={developerMode} onToggle={toggleDeveloperMode}
/>
</div>
);
}
)
}

View File

@ -28,11 +28,14 @@ import {
classifyTalerUri, i18n, TalerUriType
} from "@gnu-taler/taler-util";
import { ComponentChildren, JSX } from "preact";
import Match from "preact-router/match";
import { useDevContext } from "../context/useDevContext";
export enum Pages {
balance = '/balance',
settings = '/settings',
debug = '/debug',
dev = '/dev',
backup = '/backup',
history = '/history',
transaction = '/transaction/:tid',
}
@ -55,14 +58,19 @@ function Tab(props: TabProps): JSX.Element {
);
}
export function WalletNavBar({ current }: { current?: string }) {
return (
<div class="nav" id="header">
<Tab target="/balance" current={current}>{i18n.str`Balance`}</Tab>
<Tab target="/history" current={current}>{i18n.str`History`}</Tab>
<Tab target="/settings" current={current}>{i18n.str`Settings`}</Tab>
<Tab target="/debug" current={current}>{i18n.str`Debug`}</Tab>
</div>
);
export function WalletNavBar() {
const { devMode } = useDevContext()
return <Match>{({ path }: any) => {
console.log("current", path)
return (
<div class="nav" id="header">
<Tab target="/balance" current={path}>{i18n.str`Balance`}</Tab>
<Tab target="/history" current={path}>{i18n.str`History`}</Tab>
<Tab target="/backup" current={path}>{i18n.str`Backup`}</Tab>
<Tab target="/settings" current={path}>{i18n.str`Settings`}</Tab>
{devMode && <Tab target="/dev" current={path}>{i18n.str`Dev`}</Tab>}
</div>
)
}}</Match>
}

View File

@ -20,7 +20,7 @@
* @author Florian Dold <dold@taler.net>
*/
import { render } from "preact";
import { Fragment, render } from "preact";
import { setupI18n } from "@gnu-taler/taler-util";
import { strings } from "./i18n/strings";
import { useEffect } from "preact/hooks";
@ -28,14 +28,16 @@ import {
Pages, WalletNavBar
} from "./popup/popup";
import { HistoryPage } from "./popup/History";
import { DebugPage } from "./popup/Debug";
import { DeveloperPage as DeveloperPage } from "./popup/Debug";
import { SettingsPage } from "./popup/Settings";
import { TransactionPage } from "./popup/Transaction";
import { BalancePage } from "./popup/Balance";
import Match from "preact-router/match";
import Router, { route, Route } from "preact-router";
import Router, { getCurrentUrl, route, Route } from "preact-router";
import { useTalerActionURL } from "./hooks/useTalerActionURL";
import { createHashHistory } from "history";
import { DevContextProvider } from "./context/useDevContext";
import { BackupPage } from "./popup/BackupPage";
function main(): void {
try {
@ -88,17 +90,20 @@ function Application() {
return (
<div>
<Match>{({ path }: any) => <WalletNavBar current={path} />}</Match >
<div style={{ padding: 8, width: 'calc(400px - 16px)', height: 'calc(320px - 34px - 16px)' }}>
<Router history={createHashHistory()}>
<Route path={Pages.balance} component={BalancePage} />
<Route path={Pages.settings} component={SettingsPage} />
<Route path={Pages.debug} component={DebugPage} />
<Route path={Pages.history} component={HistoryPage} />
<Route path={Pages.transaction} component={TransactionPage} />
<Route default component={Redirect} to={Pages.balance} />
</Router>
</div>
<DevContextProvider>
<WalletNavBar />
<div style={{ padding: 8, width: 'calc(400px - 16px)', height: 'calc(320px - 34px - 16px)' }}>
<Router history={createHashHistory()}>
<Route path={Pages.balance} component={BalancePage} />
<Route path={Pages.settings} component={SettingsPage} />
<Route path={Pages.dev} component={DeveloperPage} />
<Route path={Pages.history} component={HistoryPage} />
<Route path={Pages.backup} component={BackupPage} />
<Route path={Pages.transaction} component={TransactionPage} />
<Route default component={Redirect} to={Pages.balance} />
</Router>
</div>
</DevContextProvider>
</div>
);
}

View File

@ -21,7 +21,7 @@
*/
import { JSX } from "preact/jsx-runtime";
import { PermissionsCheckbox } from "../components/PermissionsCheckbox";
import { Checkbox } from "../components/Checkbox";
import { useExtendedPermissions } from "../hooks/useExtendedPermissions";
import { Diagnostics } from "../components/Diagnostics";
@ -32,7 +32,11 @@ export function WelcomePage(): JSX.Element {
<p>Thank you for installing the wallet.</p>
<Diagnostics />
<h2>Permissions</h2>
<PermissionsCheckbox enabled={permissionsEnabled} onToggle={togglePermissions}/>
<Checkbox label="Automatically open wallet based on page content"
name="perm"
description="(Enabling this option below will make using the wallet faster, but requires more permissions from your browser.)"
enabled={permissionsEnabled} onToggle={togglePermissions}
/>
<h2>Next Steps</h2>
<a href="https://demo.taler.net/" style={{ display: "block" }}>
Try the demo »

View File

@ -29,12 +29,16 @@ body {
.nav {
background-color: #033;
padding: 0.5em 0;
/* padding: 0.5em 0; */
}
.nav a {
color: #f8faf7;
padding: 0.7em 1.4em;
padding-top: 0.7em;
display: inline-block;
width: calc(400px / 5);
padding-bottom: 0.7em;
text-align: center;
text-decoration: none;
}
@ -235,12 +239,12 @@ button.accept:disabled {
.errorbox {
border: 2px solid #f5c6cb;
border-radius: .25em;
border-radius: 0.25em;
display: block;
/* margin: 0.5em; */
padding-left: 1em;
padding-right: 1em;
width: '100%';
width: "100%";
color: #721c24;
background: #f8d7da;
}
@ -286,7 +290,7 @@ table.detailsTable.pending {
.overflow::before {
position: absolute;
content: "...";
/* inset-block-end: 0;
/* inset-block-end: 0;
inset-inline-end: 0; */
bottom: 0;
right: 0;
@ -294,7 +298,7 @@ table.detailsTable.pending {
.overflow::after {
content: "";
position: absolute;
/* inset-inline-end: 0; */
/* inset-inline-end: 0; */
right: 0;
width: 1rem;
height: 1rem;

View File

@ -240,6 +240,7 @@ importers:
rollup-plugin-ignore: ^1.0.9
rollup-plugin-sourcemaps: ^0.6.3
rollup-plugin-terser: ^7.0.2
storybook-dark-mode: ^1.0.8
tslib: ^2.1.0
typescript: ^4.1.3
dependencies:
@ -280,6 +281,7 @@ importers:
rollup-plugin-ignore: 1.0.9
rollup-plugin-sourcemaps: 0.6.3_38ff52cc32daa1ae80c428f8a47a4e22
rollup-plugin-terser: 7.0.2_rollup@2.37.1
storybook-dark-mode: 1.0.8
typescript: 4.1.3
packages:
@ -16532,6 +16534,19 @@ packages:
resolution: {integrity: sha512-7t+/wpKLanLzSnQPX8WAcuLCCeuSHoWdQuh9SB3xD0kNOM38DNf+0Oa+wmvxmYueRzkmh6IcdKFtvTa+ecgPDw==}
dev: true
/storybook-dark-mode/1.0.8:
resolution: {integrity: sha512-uY6yTSd1vYE0YwlON50u+iIoNF/fmMj59ww1cpd/naUcmOmCjwawViKFG5YjichwdR/yJ5ybWRUF0tnRQfaSiw==}
peerDependencies:
'@storybook/addons': ^6.0.0
'@storybook/api': ^6.0.0
'@storybook/components': ^6.0.0
'@storybook/core-events': ^6.0.0
'@storybook/theming': ^6.0.0
dependencies:
fast-deep-equal: 3.1.3
memoizerific: 1.11.3
dev: true
/stream-browserify/2.0.2:
resolution: {integrity: sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==}
dependencies: