diff options
Diffstat (limited to 'packages/taler-wallet-webextension')
14 files changed, 143 insertions, 235 deletions
diff --git a/packages/taler-wallet-webextension/.storybook/preview.js b/packages/taler-wallet-webextension/.storybook/preview.js index b770d7b63..5156b556a 100644 --- a/packages/taler-wallet-webextension/.storybook/preview.js +++ b/packages/taler-wallet-webextension/.storybook/preview.js @@ -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> diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index 9aaeb0d18..6a010f63a 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -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> ); } diff --git a/packages/taler-wallet-webextension/src/components/JustInDevMode.tsx b/packages/taler-wallet-webextension/src/components/JustInDevMode.tsx new file mode 100644 index 000000000..d447f87eb --- /dev/null +++ b/packages/taler-wallet-webextension/src/components/JustInDevMode.tsx @@ -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>; +} diff --git a/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx b/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx index 70d53640d..977ac557d 100644 --- a/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx +++ b/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx @@ -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> ); } diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx index 5dd7318b7..a5ed64a83 100644 --- a/packages/taler-wallet-webextension/src/components/styled/index.tsx +++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx @@ -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")`; diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx index a5f24470e..f5e721033 100644 --- a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx +++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx @@ -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> ); diff --git a/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx b/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx deleted file mode 100644 index 5009684c5..000000000 --- a/packages/taler-wallet-webextension/src/popup/Popup.stories.tsx +++ /dev/null @@ -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", -}); diff --git a/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx b/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx deleted file mode 100644 index 069157475..000000000 --- a/packages/taler-wallet-webextension/src/popup/Settings.stories.tsx +++ /dev/null @@ -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, -}); diff --git a/packages/taler-wallet-webextension/src/popup/Settings.tsx b/packages/taler-wallet-webextension/src/popup/Settings.tsx deleted file mode 100644 index a7cdf9cc0..000000000 --- a/packages/taler-wallet-webextension/src/popup/Settings.tsx +++ /dev/null @@ -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> - ); -} diff --git a/packages/taler-wallet-webextension/src/popup/index.stories.tsx b/packages/taler-wallet-webextension/src/popup/index.stories.tsx index 3abb80021..341b06b41 100644 --- a/packages/taler-wallet-webextension/src/popup/index.stories.tsx +++ b/packages/taler-wallet-webextension/src/popup/index.stories.tsx @@ -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]; diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx index e1d1b9017..8b97b09e9 100644 --- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx @@ -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 { ProviderAddPage } from "./wallet/ProviderAddPage"; -import { ProviderDetailPage } from "./wallet/ProviderDetailPage"; -import { SettingsPage } from "./popup/Settings"; import { TalerActionFound } from "./popup/TalerActionFound"; +import { BackupPage } from "./wallet/BackupPage"; import { ExchangeAddPage } from "./wallet/ExchangeAddPage"; -import { IoCProviderForRuntime } from "./context/iocContext"; import { Pending } from "./wallet/PendingPage"; -import { Match } from "preact-router/match"; +import { ProviderAddPage } from "./wallet/ProviderAddPage"; +import { ProviderDetailPage } from "./wallet/ProviderDetailPage"; 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 }) { diff --git a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx index 629b93fc5..7023ad0f3 100644 --- a/packages/taler-wallet-webextension/src/walletEntryPoint.tsx +++ b/packages/taler-wallet-webextension/src/walletEntryPoint.tsx @@ -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> ); }} diff --git a/packages/taler-wallet-webextension/src/wxBackend.ts b/packages/taler-wallet-webextension/src/wxBackend.ts index a242e8a08..52187936b 100644 --- a/packages/taler-wallet-webextension/src/wxBackend.ts +++ b/packages/taler-wallet-webextension/src/wxBackend.ts @@ -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 }; diff --git a/packages/taler-wallet-webextension/static/img/settings_black_24dp.svg b/packages/taler-wallet-webextension/static/img/settings_black_24dp.svg new file mode 100644 index 000000000..f53024e88 --- /dev/null +++ b/packages/taler-wallet-webextension/static/img/settings_black_24dp.svg @@ -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>
\ No newline at end of file |