settings new design

This commit is contained in:
Sebastian 2022-02-16 15:15:47 -03:00
parent bc1c33e1ce
commit 3e92c24968
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
14 changed files with 144 additions and 236 deletions

View File

@ -15,7 +15,7 @@
*/
import { h, Fragment } from "preact"
import { NavBar } from '../src/NavigationBar'
import { PopupNavBar, WalletNavBar } from '../src/NavigationBar'
import { LogoHeader } from '../src/components/LogoHeader'
import { TranslationProvider } from '../src/context/translation'
import { PopupBox, WalletBox } from '../src/components/styled'
@ -56,7 +56,7 @@ export const decorators = [
const path = /popup(\/.*).*/.exec(kind)[1];
// add a fake header so it looks similar
return <Fragment>
<NavBar path={path} devMode={path === '/dev'} />
<PopupNavBar path={path} devMode={path === '/dev'} />
<PopupBox>
<Story />
</PopupBox>
@ -155,7 +155,7 @@ export const decorators = [
}`}
</style>
<LogoHeader />
<NavBar path={path} devMode={path === '/dev'} />
<WalletNavBar path={path} />
<WalletBox>
<Story />
</WalletBox>

View File

@ -25,8 +25,9 @@
* Imports.
*/
import { i18n } from "@gnu-taler/taler-util";
import { ComponentChildren, h, VNode } from "preact";
import { PopupNavigation } from "./components/styled";
import { VNode, h } from "preact";
import { JustInDevMode } from "./components/JustInDevMode";
import { NavigationHeader, NavigationHeaderHolder } from "./components/styled";
export enum Pages {
welcome = "/welcome",
@ -55,40 +56,56 @@ export enum Pages {
cta_withdraw = "/cta/withdraw",
}
interface TabProps {
target: string;
current?: string;
children?: ComponentChildren;
}
function Tab(props: TabProps): VNode {
let cssClass = "";
if (props.current?.startsWith(props.target)) {
cssClass = "active";
}
export function PopupNavBar({ path = "" }: { path?: string }): VNode {
const innerUrl = chrome.runtime
? new URL(chrome.runtime.getURL("/static/wallet.html#/settings")).href
: "#";
return (
<a href={props.target} class={cssClass}>
{props.children}
</a>
<NavigationHeader>
<a
href="/balance"
class={path.startsWith("/balance") ? "active" : ""}
>{i18n.str`Balance`}</a>
<a
href="/backup"
class={path.startsWith("/backup") ? "active" : ""}
>{i18n.str`Backup`}</a>
<a />
<a href={innerUrl} target="_blank" rel="noreferrer">
<div class="settings-icon" title="Settings" />
</a>
</NavigationHeader>
);
}
export function NavBar({
devMode,
path,
}: {
path: string;
devMode: boolean;
}): VNode {
export function WalletNavBar({ path = "" }: { path?: string }): VNode {
return (
<PopupNavigation devMode={devMode}>
<div>
<Tab target="/balance" current={path}>{i18n.str`Balance`}</Tab>
<Tab target="/pending" current={path}>{i18n.str`Pending`}</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>
</PopupNavigation>
<NavigationHeaderHolder>
<NavigationHeader>
<a
href="/balance"
class={path.startsWith("/balance") ? "active" : ""}
>{i18n.str`Balance`}</a>
<a
href="/backup"
class={path.startsWith("/backup") ? "active" : ""}
>{i18n.str`Backup`}</a>
<JustInDevMode>
<a
href="/dev"
class={path.startsWith("/dev") ? "active" : ""}
>{i18n.str`Dev`}</a>
</JustInDevMode>
<a />
<a
href="/settings"
class={path.startsWith("/settings") ? "active" : ""}
>
<div class="settings-icon" title="Settings" />
</a>
</NavigationHeader>
</NavigationHeaderHolder>
);
}

View File

@ -0,0 +1,12 @@
import { ComponentChildren, Fragment, h, VNode } from "preact";
import { useDevContext } from "../context/devContext";
export function JustInDevMode({
children,
}: {
children: ComponentChildren;
}): VNode {
const { devMode } = useDevContext();
if (!devMode) return <Fragment />;
return <Fragment>{children}</Fragment>;
}

View File

@ -69,18 +69,21 @@ export function MultiActionButton({
))}
</div>
)}
<ButtonPrimary
<ButtonBoxPrimary
onClick={() => doClick(selected)}
style={{
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
marginRight: 0,
maxWidth: 170,
overflowX: "hidden",
textOverflow: "ellipsis",
}}
>
{label(selected)}
</ButtonPrimary>
</ButtonBoxPrimary>
<ButtonBoxPrimary
<ButtonPrimary
onClick={() => setOpened((s) => !s)}
style={{
marginLeft: 0,
@ -89,7 +92,7 @@ export function MultiActionButton({
}}
>
<img style={{ height: 14 }} src={arrowDown} />
</ButtonBoxPrimary>
</ButtonPrimary>
</div>
);
}

View File

@ -391,6 +391,7 @@ export const Button = styled.button<{ upperCased?: boolean }>`
background-color: "#e6e6e6";
text-decoration: none;
border-radius: 2px;
text-transform: uppercase;
:focus {
outline: 0;
@ -507,12 +508,12 @@ export const LinkPrimary = styled(Link)`
export const ButtonPrimary = styled(ButtonVariant)<{ small?: boolean }>`
font-size: ${({ small }) => (small ? "small" : "inherit")};
background-color: rgb(66, 184, 221);
border-color: rgb(66, 184, 221);
background-color: #0042b2;
border-color: #0042b2;
`;
export const ButtonBoxPrimary = styled(ButtonBox)`
color: rgb(66, 184, 221);
border-color: rgb(66, 184, 221);
color: #0042b2;
border-color: #0042b2;
`;
export const ButtonSuccess = styled(ButtonVariant)`
@ -776,31 +777,53 @@ export const WarningBox = styled(ErrorBox)`
border-color: #ffecb5;
`;
export const PopupNavigation = styled.div<{ devMode?: boolean }>`
import settingsIcon from "../../../static/img/settings_black_24dp.svg";
export const NavigationHeaderHolder = styled.div`
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
background-color: #0042b2;
`;
export const NavigationHeader = styled.div`
background-color: #0042b2;
height: 35px;
justify-content: space-around;
display: flex;
& > div {
& {
width: 500px;
}
& > div > a {
& > a {
color: #f8faf7;
display: inline-block;
width: 100px;
width: 100%;
text-align: center;
text-decoration: none;
vertical-align: middle;
line-height: 35px;
}
& > div > a.active {
& > a > div.settings-icon {
mask: url(${settingsIcon}) no-repeat center;
background-color: white;
width: 24px;
height: 24px;
margin-left: auto;
margin-right: 8px;
padding: 4px;
}
& > a.active {
background-color: #f8faf7;
color: #0042b2;
font-weight: bold;
}
& > a.active > div.settings-icon {
background-color: #0042b2;
}
`;
const image = `url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e")`;

View File

@ -17,10 +17,11 @@
import { Amounts, Balance, i18n } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { BalanceTable } from "../components/BalanceTable";
import { JustInDevMode } from "../components/JustInDevMode";
import { Loading } from "../components/Loading";
import { LoadingError } from "../components/LoadingError";
import { MultiActionButton } from "../components/MultiActionButton";
import { ButtonPrimary } from "../components/styled";
import { ButtonBoxPrimary, ButtonPrimary } from "../components/styled";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook";
import { PageLink } from "../renderHtml";
import * as wxApi from "../wxApi";
@ -77,8 +78,10 @@ export function BalanceView({
<Fragment>
<p>
<i18n.Translate>
You have no balance to show. Need some{" "}
<PageLink pageName="/welcome">help</PageLink> getting started?
You have no balance to show.
<a href="https://demo.taler.net/" style={{ display: "block" }}>
Learn how to top up your wallet balance »
</a>
</i18n.Translate>
</p>
<footer style={{ justifyContent: "space-between" }}>
@ -109,6 +112,9 @@ export function BalanceView({
onClick={(c) => goToWalletDeposit(c)}
/>
)}
<JustInDevMode>
<ButtonBoxPrimary onClick={() => null}>enter uri</ButtonBoxPrimary>
</JustInDevMode>
</footer>
</Fragment>
);

View File

@ -1,43 +0,0 @@
/*
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 { createExample } from "../test-utils";
import { NavBar as TestedComponent } from "../NavigationBar";
export default {
title: "popup/header",
// component: TestedComponent,
argTypes: {
onRetry: { action: "onRetry" },
onDelete: { action: "onDelete" },
onBack: { action: "onBack" },
},
};
export const OnBalance = createExample(TestedComponent, {
devMode: false,
path: "/balance",
});
export const OnHistoryWithDevMode = createExample(TestedComponent, {
devMode: true,
path: "/history",
});

View File

@ -1,37 +0,0 @@
/*
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 { createExample } from "../test-utils";
import { SettingsView as TestedComponent } from "./Settings";
export default {
title: "popup/settings",
component: TestedComponent,
argTypes: {
setDeviceName: () => Promise.resolve(),
},
};
export const AllOff = createExample(TestedComponent, {});
export const OneChecked = createExample(TestedComponent, {
permissionsEnabled: true,
});

View File

@ -1,74 +0,0 @@
/*
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 { i18n } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { Checkbox } from "../components/Checkbox";
import { useExtendedPermissions } from "../hooks/useExtendedPermissions";
export function SettingsPage(): VNode {
const [permissionsEnabled, togglePermissions] = useExtendedPermissions();
return (
<SettingsView
permissionsEnabled={permissionsEnabled}
togglePermissions={togglePermissions}
/>
);
}
export interface ViewProps {
permissionsEnabled: boolean;
togglePermissions: () => void;
}
export function SettingsView({
permissionsEnabled,
togglePermissions,
}: ViewProps): VNode {
return (
<Fragment>
<section>
<h2>
<i18n.Translate>Permissions</i18n.Translate>
</h2>
<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}
/>
</section>
<footer style={{ justifyContent: "space-around" }}>
<a
target="_blank"
rel="noopener noreferrer"
style={{ color: "darkgreen", textDecoration: "none" }}
href={
// eslint-disable-next-line no-undef
chrome.runtime
? // eslint-disable-next-line no-undef
chrome.runtime.getURL(`/static/wallet.html#/settings`)
: "#"
}
>
VIEW MORE SETTINGS
</a>
</footer>
</Fragment>
);
}

View File

@ -22,7 +22,6 @@
import * as a1 from "../wallet/AddNewActionView.stories";
import * as a2 from "./Balance.stories";
import * as a3 from "./DeveloperPage.stories";
import * as a5 from "./Popup.stories";
import * as a6 from "./TalerActionFound.stories";
export default [a1, a2, a3, a5, a6];
export default [a1, a2, a3, a6];

View File

@ -22,25 +22,24 @@
import { setupI18n } from "@gnu-taler/taler-util";
import { createHashHistory } from "history";
import { render, h, VNode, Fragment } from "preact";
import { Fragment, h, render, VNode } from "preact";
import Router, { route, Route } from "preact-router";
import { Match } from "preact-router/match";
import { useEffect } from "preact/hooks";
import { PopupBox } from "./components/styled";
import { DevContextProvider } from "./context/devContext";
import { IoCProviderForRuntime } from "./context/iocContext";
import { useTalerActionURL } from "./hooks/useTalerActionURL";
import { strings } from "./i18n/strings";
import { NavBar, Pages } from "./NavigationBar";
import { BackupPage } from "./wallet/BackupPage";
import { Pages, PopupNavBar } from "./NavigationBar";
import { BalancePage } from "./popup/BalancePage";
import { DeveloperPage } from "./popup/DeveloperPage";
import { TalerActionFound } from "./popup/TalerActionFound";
import { BackupPage } from "./wallet/BackupPage";
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
import { Pending } from "./wallet/PendingPage";
import { ProviderAddPage } from "./wallet/ProviderAddPage";
import { ProviderDetailPage } from "./wallet/ProviderDetailPage";
import { SettingsPage } from "./popup/Settings";
import { TalerActionFound } from "./popup/TalerActionFound";
import { ExchangeAddPage } from "./wallet/ExchangeAddPage";
import { IoCProviderForRuntime } from "./context/iocContext";
import { Pending } from "./wallet/PendingPage";
import { Match } from "preact-router/match";
function main(): void {
try {
@ -84,9 +83,7 @@ function Application(): VNode {
{({ devMode }: { devMode: boolean }) => (
<IoCProviderForRuntime>
<Match>
{({ path }: { path: string }) => (
<NavBar devMode={devMode} path={path} />
)}
{({ path }: { path: string }) => <PopupNavBar path={path} />}
</Match>
<CheckTalerActionComponent />
<PopupBox devMode={devMode}>
@ -112,7 +109,6 @@ function Application(): VNode {
)
}
/>
<Route path={Pages.settings} component={SettingsPage} />
<Route
path={Pages.cta}
component={function Action({ action }: { action: string }) {

View File

@ -20,14 +20,19 @@
* @author Florian Dold <dold@taler.net>
*/
import { setupI18n } from "@gnu-taler/taler-util";
import { i18n, setupI18n } from "@gnu-taler/taler-util";
import { createHashHistory } from "history";
import { Fragment, h, render, VNode } from "preact";
import Router, { route, Route } from "preact-router";
import Match from "preact-router/match";
import { useEffect, useState } from "preact/hooks";
import { LogoHeader } from "./components/LogoHeader";
import { SuccessBox, WalletBox } from "./components/styled";
import {
NavigationHeader,
NavigationHeaderHolder,
SuccessBox,
WalletBox,
} from "./components/styled";
import { DevContextProvider } from "./context/devContext";
import { IoCProviderForRuntime } from "./context/iocContext";
import { PayPage } from "./cta/Pay";
@ -35,7 +40,7 @@ import { RefundPage } from "./cta/Refund";
import { TipPage } from "./cta/Tip";
import { WithdrawPage } from "./cta/Withdraw";
import { strings } from "./i18n/strings";
import { NavBar, Pages } from "./NavigationBar";
import { Pages, WalletNavBar } from "./NavigationBar";
import { DeveloperPage } from "./popup/DeveloperPage";
import { BackupPage } from "./wallet/BackupPage";
import { DepositPage } from "./wallet/DepositPage";
@ -94,7 +99,7 @@ function Application(): VNode {
return (
<Fragment>
<LogoHeader />
<NavBar devMode={devMode} path={path} />
<WalletNavBar path={path} />
</Fragment>
);
}}

View File

@ -226,18 +226,18 @@ function makeSyncWalletRedirect(
.join("&");
innerUrl.hash = innerUrl.hash + "?" + hParams;
}
if (isFirefox()) {
// Some platforms don't support the sync redirect (yet), so fall back to
// async redirect after a timeout.
const doit = async (): Promise<void> => {
await waitMs(150);
const tab = await getTab(tabId);
if (tab.url === oldUrl) {
chrome.tabs.update(tabId, { url: innerUrl.href });
}
};
doit();
}
// if (isFirefox()) {
// // Some platforms don't support the sync redirect (yet), so fall back to
// // async redirect after a timeout.
// const doit = async (): Promise<void> => {
// await waitMs(150);
// const tab = await getTab(tabId);
// if (tab.url === oldUrl) {
// chrome.tabs.update(tabId, { url: innerUrl.href });
// }
// };
// doit();
// }
console.log("redirecting to", innerUrl.href);
chrome.tabs.update(tabId, { url: innerUrl.href });
return { redirectUrl: innerUrl.href };

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 24 24" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><g><path d="M0,0h24v24H0V0z" fill="none"/><path d="M19.14,12.94c0.04-0.3,0.06-0.61,0.06-0.94c0-0.32-0.02-0.64-0.07-0.94l2.03-1.58c0.18-0.14,0.23-0.41,0.12-0.61 l-1.92-3.32c-0.12-0.22-0.37-0.29-0.59-0.22l-2.39,0.96c-0.5-0.38-1.03-0.7-1.62-0.94L14.4,2.81c-0.04-0.24-0.24-0.41-0.48-0.41 h-3.84c-0.24,0-0.43,0.17-0.47,0.41L9.25,5.35C8.66,5.59,8.12,5.92,7.63,6.29L5.24,5.33c-0.22-0.08-0.47,0-0.59,0.22L2.74,8.87 C2.62,9.08,2.66,9.34,2.86,9.48l2.03,1.58C4.84,11.36,4.8,11.69,4.8,12s0.02,0.64,0.07,0.94l-2.03,1.58 c-0.18,0.14-0.23,0.41-0.12,0.61l1.92,3.32c0.12,0.22,0.37,0.29,0.59,0.22l2.39-0.96c0.5,0.38,1.03,0.7,1.62,0.94l0.36,2.54 c0.05,0.24,0.24,0.41,0.48,0.41h3.84c0.24,0,0.44-0.17,0.47-0.41l0.36-2.54c0.59-0.24,1.13-0.56,1.62-0.94l2.39,0.96 c0.22,0.08,0.47,0,0.59-0.22l1.92-3.32c0.12-0.22,0.07-0.47-0.12-0.61L19.14,12.94z M12,15.6c-1.98,0-3.6-1.62-3.6-3.6 s1.62-3.6,3.6-3.6s3.6,1.62,3.6,3.6S13.98,15.6,12,15.6z"/></g></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB