Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue 3050] Extension - Add popup remind backup account #3098

Merged
merged 2 commits into from
May 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/extension-base/src/constants/storage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ export const LANGUAGE = 'current-language';

export const CURRENCY = 'current-currency';

export const REMIND_EXPORT_ACCOUNT = 'remind_export_account';

export const LATEST_SESSION = 'general.latest-session';
30 changes: 29 additions & 1 deletion packages/extension-base/src/koni/background/handlers/State.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { withErrorLog } from '@subwallet/extension-base/background/handlers/help
import { isSubscriptionRunning, unsubscribe } from '@subwallet/extension-base/background/handlers/subscriptions';
import { AccountRefMap, AddTokenRequestExternal, AmountData, APIItemState, ApiMap, AuthRequestV2, BasicTxErrorType, ChainStakingMetadata, ChainType, ConfirmationsQueue, CrowdloanItem, CrowdloanJson, CurrencyType, CurrentAccountInfo, EvmProviderErrorType, EvmSendTransactionParams, EvmSendTransactionRequest, EvmSignatureRequest, ExternalRequestPromise, ExternalRequestPromiseStatus, ExtrinsicType, MantaAuthorizationContext, MantaPayConfig, MantaPaySyncState, NftCollection, NftItem, NftJson, NominatorMetadata, RequestAccountExportPrivateKey, RequestCheckPublicAndSecretKey, RequestConfirmationComplete, RequestCrowdloanContributions, RequestSettingsType, ResponseAccountExportPrivateKey, ResponseCheckPublicAndSecretKey, ServiceInfo, SingleModeJson, StakingItem, StakingJson, StakingRewardItem, StakingRewardJson, StakingType, UiSettings } from '@subwallet/extension-base/background/KoniTypes';
import { AccountJson, RequestAuthorizeTab, RequestRpcSend, RequestRpcSubscribe, RequestRpcUnsubscribe, RequestSign, ResponseRpcListProviders, ResponseSigning } from '@subwallet/extension-base/background/types';
import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH, MANTA_PAY_BALANCE_INTERVAL } from '@subwallet/extension-base/constants';
import { ALL_ACCOUNT_KEY, ALL_GENESIS_HASH, MANTA_PAY_BALANCE_INTERVAL, REMIND_EXPORT_ACCOUNT } from '@subwallet/extension-base/constants';
import { BalanceService } from '@subwallet/extension-base/services/balance-service';
import { ServiceStatus } from '@subwallet/extension-base/services/base/types';
import BuyService from '@subwallet/extension-base/services/buy-service';
Expand All @@ -27,6 +27,7 @@ import MintCampaignService from '@subwallet/extension-base/services/mint-campaig
import NotificationService from '@subwallet/extension-base/services/notification-service/NotificationService';
import { PriceService } from '@subwallet/extension-base/services/price-service';
import RequestService from '@subwallet/extension-base/services/request-service';
import { openPopup } from '@subwallet/extension-base/services/request-service/handler/PopupHandler';
import { AuthUrls, MetaRequest, SignRequest } from '@subwallet/extension-base/services/request-service/types';
import SettingService from '@subwallet/extension-base/services/setting-service/SettingService';
import DatabaseService from '@subwallet/extension-base/services/storage-service/DatabaseService';
Expand All @@ -36,6 +37,7 @@ import { SwapService } from '@subwallet/extension-base/services/swap-service';
import TransactionService from '@subwallet/extension-base/services/transaction-service';
import { TransactionEventResponse } from '@subwallet/extension-base/services/transaction-service/types';
import WalletConnectService from '@subwallet/extension-base/services/wallet-connect-service';
import { SWStorage } from '@subwallet/extension-base/storage';
import AccountRefStore from '@subwallet/extension-base/stores/AccountRef';
import { BalanceItem, BalanceMap, EvmFeeInfo } from '@subwallet/extension-base/types';
import { isAccountAll, stripUrl, TARGET_ENV, wait } from '@subwallet/extension-base/utils';
Expand Down Expand Up @@ -1640,6 +1642,32 @@ export default class KoniState {
return await this.requestService.completeConfirmation(request);
}

private onHandleRemindExportAccount () {
const remindStatus = SWStorage.instance.getItem(REMIND_EXPORT_ACCOUNT);

if (!remindStatus || !remindStatus.includes('done')) {
const handleRemind = (account: CurrentAccountInfo) => {
if (account.address !== '') {
// Open remind tab
const url = `${chrome.runtime.getURL('index.html')}#/remind-export-account`;

openPopup(url);
subscription.unsubscribe();
} else {
setTimeout(() => {
subscription.unsubscribe();
}, 3000);
}
};

const subscription = this.keyringService.currentAccountSubject.subscribe(handleRemind);
}
}

public onCheckToRemindUser () {
this.onHandleRemindExportAccount();
}

public onInstall () {
// const singleModes = Object.values(_PREDEFINED_SINGLE_MODES);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@ const NORMAL_WINDOW_OPTS: chrome.windows.CreateData = {
url: NOTIFICATION_URL
};

export function openPopup (url: string) {
chrome.windows.getCurrent(
(win) => {
const popupOptions = { ...POPUP_WINDOW_OPTS, url };

if (win) {
popupOptions.left = (win.left || 0) + (win.width || 0) - (popupOptions.width || 0) - 20;
popupOptions.top = (win.top || 0) + 110;
}

chrome.windows.create(popupOptions).catch(console.error);
}
);
}

export default class PopupHandler {
readonly #requestService: RequestService;
#notification: BrowserConfirmationType = DEFAULT_NOTIFICATION_TYPE;
Expand Down
130 changes: 130 additions & 0 deletions packages/extension-koni-ui/src/Popup/RemindExportAccount.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// Copyright 2019-2022 @subwallet/extension-koni-ui authors & contributors
// SPDX-License-Identifier: Apache-2.0

import { Layout } from '@subwallet/extension-koni-ui/components';
import { USER_GUIDE_URL } from '@subwallet/extension-koni-ui/constants';
import { Theme, ThemeProps } from '@subwallet/extension-koni-ui/types';
import { Icon, PageIcon } from '@subwallet/react-ui';
import CN from 'classnames';
import { ArrowCircleRight, Export, X, XCircle } from 'phosphor-react';
import React, { useCallback, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import styled, { useTheme } from 'styled-components';
import { useLocalStorage } from 'usehooks-ts';

type Props = ThemeProps;

const SUB_DOMAIN_USER_GUIDE = 'account-management/export-and-backup-accounts#export-all-accounts';
const keyStorage = 'remind_export_account';

const Component: React.FC<Props> = (props: Props) => {
const { className } = props;
const { token } = useTheme() as Theme;
const [, setStorage] = useLocalStorage(keyStorage, 'init');
const learnMore = useCallback(() => {
window.open(`${USER_GUIDE_URL}/${SUB_DOMAIN_USER_GUIDE}`);
setStorage('done');
setTimeout(() => {
window.close();
}, 300);
}, [setStorage]);

const dismiss = useCallback(() => {
setStorage('done');
window.close();
}, [setStorage]);

useEffect(() => {
const handleCloseTabs = () => {
window.localStorage.setItem(keyStorage, 'done');
window.removeEventListener('beforeunload', handleCloseTabs);
};

window.addEventListener('beforeunload', handleCloseTabs);
}, []);

const { t } = useTranslation();

return (
<Layout.WithSubHeaderOnly
leftFooterButton={{
children: t('Dismiss'),
onClick: dismiss,
schema: 'secondary',
icon: <Icon
phosphorIcon={XCircle}
weight={'fill'}
/>
}}
rightFooterButton={{
children: t('Learn more'),
onClick: learnMore,
icon: <Icon
phosphorIcon={ArrowCircleRight}
weight={'fill'}
/>
}}
showBackButton={false}
subHeaderLeft={(
<Icon
phosphorIcon={X}
size='md'
/>
)}
title={t('Pay attention')}
>
<div className={CN(className)}>
<div className='page-icon'>
<PageIcon
color={token.colorWarning}
iconProps={{
weight: 'fill',
phosphorIcon: Export
}}
/>
</div>
<div className='title'>
{t('Back up your accounts!')}
</div>
<div className='description'>
{t('If you lose your seed phrases/private keys/JSON backup files/QR backup codes, your accounts can\'t be recovered and your assets are lost. Learn how to back up your accounts to secure your assets now.')}
</div>
</div>
</Layout.WithSubHeaderOnly>
);
};

const RemindExportAccount = styled(Component)<Props>(({ theme: { token } }: Props) => {
return {
textAlign: 'center',

'.page-icon': {
display: 'flex',
justifyContent: 'center',
marginTop: token.controlHeightLG,
marginBottom: token.margin,
'--page-icon-color': token.colorSecondary
},

'.title': {
marginTop: token.margin,
marginBottom: token.margin,
fontWeight: token.fontWeightStrong,
fontSize: token.fontSizeHeading3,
lineHeight: token.lineHeightHeading3,
color: token.colorTextBase
},

'.description': {
padding: `0 ${token.controlHeightLG - token.padding}px`,
marginTop: token.margin,
marginBottom: token.margin * 2,
fontSize: token.fontSizeHeading5,
lineHeight: token.lineHeightHeading5,
color: token.colorTextDescription,
textAlign: 'center'
}
};
});

export default RemindExportAccount;
3 changes: 2 additions & 1 deletion packages/extension-koni-ui/src/Popup/Root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ const welcomeUrl = '/welcome';
const tokenUrl = '/home/tokens';
const loginUrl = '/keyring/login';
const phishingUrl = '/phishing-page-detected';
const remindExportAccountUrl = '/remind-export-account';
const createPasswordUrl = '/keyring/create-password';
const migratePasswordUrl = '/keyring/migrate-password';
const accountNewSeedPhrase = '/accounts/new-seed-phrase';
Expand Down Expand Up @@ -167,7 +168,7 @@ function DefaultRoute ({ children }: { children: React.ReactNode }): React.React
// Do nothing
} else if (needMigrate && hasMasterPassword && !needUnlock) {
redirectTarget = migratePasswordUrl;
} else if (hasMasterPassword && needUnlock) {
} else if (hasMasterPassword && needUnlock && pathName !== remindExportAccountUrl) {
redirectTarget = loginUrl;
} else if (hasMasterPassword && pathName === createPasswordUrl) {
redirectTarget = DEFAULT_ROUTER_PATH;
Expand Down
2 changes: 2 additions & 0 deletions packages/extension-koni-ui/src/Popup/router.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export class LazyLoader {
const PhishingDetected = new LazyLoader('PhishingDetected', () => import('@subwallet/extension-koni-ui/Popup/PhishingDetected'));
const Welcome = new LazyLoader('Welcome', () => import('@subwallet/extension-koni-ui/Popup/Welcome'));
const CreateDone = new LazyLoader('CreateDone', () => import('@subwallet/extension-koni-ui/Popup/CreateDone'));
const RemindExportAccount = new LazyLoader('RemindExportAccount', () => import('@subwallet/extension-koni-ui/Popup/RemindExportAccount'));
const BuyTokens = new LazyLoader('BuyTokens', () => import('@subwallet/extension-koni-ui/Popup/BuyTokens'));
// const Staking = new LazyLoader('Staking', () => import('@subwallet/extension-koni-ui/Popup/Home/Staking'));

Expand Down Expand Up @@ -149,6 +150,7 @@ export const router = createHashRouter([
Welcome.generateRouterObject('/welcome'),
BuyTokens.generateRouterObject('/buy-tokens'),
CreateDone.generateRouterObject('/create-done'),
RemindExportAccount.generateRouterObject('/remind-export-account'),
{
...Home.generateRouterObject('/home'),
children: [
Expand Down
1 change: 0 additions & 1 deletion packages/extension-koni-ui/src/constants/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const EXTENSION_VERSION = chrome.runtime.getManifest().version;
export const WIKI_URL = 'https://docs.subwallet.app/';
export const PRIVACY_AND_POLICY_URL = 'https://docs.subwallet.app/privacy-and-security/privacy-policy';
export const TERMS_OF_SERVICE_URL = 'https://docs.subwallet.app/privacy-and-security/terms-of-service';

export const USER_GUIDE_URL = 'https://docs.subwallet.app/main/extension-user-guide';
export const WEBSITE_URL = 'https://subwallet.app/';
export const TELEGRAM_URL = 'https://t.me/subwallet';
Expand Down
6 changes: 6 additions & 0 deletions packages/extension-koni/src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ function handleExtensionIdling () { // handle extension being idle since the ini
}, IDLE_TIME);
}

function handleRemindUserToExportAccount () {
koniState.onCheckToRemindUser();
}

handleRemindUserToExportAccount();

// listen to all messages and handle appropriately
chrome.runtime.onConnect.addListener((port): void => {
// shouldn't happen, however... only listen to what we know about
Expand Down
Loading