diff options
author | Sebastian <sebasjm@gmail.com> | 2021-06-30 00:24:43 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2021-06-30 00:24:52 -0300 |
commit | 05e89a3cf7bc2e04ecb88be87ab5c14bb66d71e7 (patch) | |
tree | 2bab1f0b836b9b953a91da11e8d696d065e9f2a6 | |
parent | b43c476590508b5b3b10a5c2da34ac30f1fbdf57 (diff) |
developer mode
14 files changed, 292 insertions, 51 deletions
diff --git a/packages/taler-wallet-webextension/.storybook/main.js b/packages/taler-wallet-webextension/.storybook/main.js index 01765e009..38ca14b64 100644 --- a/packages/taler-wallet-webextension/.storybook/main.js +++ b/packages/taler-wallet-webextension/.storybook/main.js @@ -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 ], diff --git a/packages/taler-wallet-webextension/package.json b/packages/taler-wallet-webextension/package.json index 206ce8c1b..1c6795234 100644 --- a/packages/taler-wallet-webextension/package.json +++ b/packages/taler-wallet-webextension/package.json @@ -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": { diff --git a/packages/taler-wallet-webextension/src/components/PermissionsCheckbox.tsx b/packages/taler-wallet-webextension/src/components/Checkbox.tsx index 50f4feb62..6b3dc024e 100644 --- a/packages/taler-wallet-webextension/src/components/PermissionsCheckbox.tsx +++ b/packages/taler-wallet-webextension/src/components/Checkbox.tsx @@ -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> ); } diff --git a/packages/taler-wallet-webextension/src/context/useDevContext.ts b/packages/taler-wallet-webextension/src/context/useDevContext.ts new file mode 100644 index 000000000..ea2ba4ceb --- /dev/null +++ b/packages/taler-wallet-webextension/src/context/useDevContext.ts @@ -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 }); +} diff --git a/packages/taler-wallet-webextension/src/hooks/useLocalStorage.ts b/packages/taler-wallet-webextension/src/hooks/useLocalStorage.ts new file mode 100644 index 000000000..30f681940 --- /dev/null +++ b/packages/taler-wallet-webextension/src/hooks/useLocalStorage.ts @@ -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]; +} diff --git a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx new file mode 100644 index 000000000..4bbca9072 --- /dev/null +++ b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx @@ -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> + ) +}
\ No newline at end of file diff --git a/packages/taler-wallet-webextension/src/popup/Debug.tsx b/packages/taler-wallet-webextension/src/popup/Debug.tsx index 073dac2ca..1f6014e8e 100644 --- a/packages/taler-wallet-webextension/src/popup/Debug.tsx +++ b/packages/taler-wallet-webextension/src/popup/Debug.tsx @@ -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> diff --git a/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx b/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx new file mode 100644 index 000000000..b6d852d52 --- /dev/null +++ b/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx @@ -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, +}); + diff --git a/packages/taler-wallet-webextension/src/popup/Settings.tsx b/packages/taler-wallet-webextension/src/popup/Settings.tsx index 5028b597c..0a57092bb 100644 --- a/packages/taler-wallet-webextension/src/popup/Settings.tsx +++ b/packages/taler-wallet-webextension/src/popup/Settings.tsx @@ -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> - ); -} + ) +}
\ No newline at end of file diff --git a/packages/taler-wallet-webextension/src/popup/popup.tsx b/packages/taler-wallet-webextension/src/popup/popup.tsx index 3692a0537..fab5a834a 100644 --- a/packages/taler-wallet-webextension/src/popup/popup.tsx +++ b/packages/taler-wallet-webextension/src/popup/popup.tsx @@ -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> } diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx index 84501c2d2..c777e01de 100644 --- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx @@ -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> ); } diff --git a/packages/taler-wallet-webextension/src/wallet/Welcome.tsx b/packages/taler-wallet-webextension/src/wallet/Welcome.tsx index 0f9cc8677..c74384596 100644 --- a/packages/taler-wallet-webextension/src/wallet/Welcome.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Welcome.tsx @@ -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 ยป diff --git a/packages/taler-wallet-webextension/static/style/popup.css b/packages/taler-wallet-webextension/static/style/popup.css index cd885556a..1e01030c5 100644 --- a/packages/taler-wallet-webextension/static/style/popup.css +++ b/packages/taler-wallet-webextension/static/style/popup.css @@ -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; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ca93291bc..dc570a2c0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -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: |