Bumps w/ eslint (#338)

* Bumps w/ eslint

* Additional

* Additional

* Additional

* Additional

* Additional

* Linting done, tsc fixes remain

* Final round
This commit is contained in:
Jaco Greeff
2020-05-24 12:17:53 +02:00
committed by GitHub
parent f313d13a44
commit 837fb52a3a
86 changed files with 970 additions and 758 deletions
+5 -5
View File
@@ -6,11 +6,11 @@
import chrome from 'sinon-chrome';
class MessagingFake {
private listeners: any = [];
private listeners: ((...params: unknown[]) => unknown)[] = [];
get onMessage (): any {
return {
addListener: (cb: any): any => this.listeners.push(cb)
addListener: (cb: (...params: unknown[]) => unknown) => this.listeners.push(cb)
};
}
@@ -20,8 +20,8 @@ class MessagingFake {
};
}
postMessage (data: any): void {
this.listeners.forEach((cb: any) => cb.call(this, data));
postMessage (data: unknown): void {
this.listeners.forEach((cb) => cb.call(this, data));
}
}
@@ -29,7 +29,7 @@ const messagingFake = new MessagingFake();
chrome.runtime.connect.returns(messagingFake);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
// eslint-disable-next-line @typescript-eslint/no-explicit-any,@typescript-eslint/no-unsafe-member-access
(window as any).chrome = chrome;
export default chrome;
+6 -6
View File
@@ -7,9 +7,9 @@
"packages/*"
],
"resolutions": {
"@polkadot/api": "^1.14.1",
"@polkadot/api": "^1.15.1",
"@polkadot/keyring": "^2.10.1",
"@polkadot/types": "^1.14.1",
"@polkadot/types": "^1.15.1",
"@polkadot/util": "^2.10.1",
"@polkadot/util-crypto": "^2.10.1",
"babel-core": "^7.0.0-bridge.0"
@@ -30,12 +30,12 @@
},
"devDependencies": {
"@babel/core": "^7.9.6",
"@polkadot/dev": "^0.53.5",
"@polkadot/typegen": "^1.14.1",
"@types/jest": "^25.2.2",
"@polkadot/dev": "^0.54.1",
"@polkadot/typegen": "^1.15.1",
"@types/jest": "^25.2.3",
"copy-webpack-plugin": "^5.1.1",
"sinon-chrome": "^3.0.1",
"stylelint": "^13.3.3",
"stylelint": "^13.5.0",
"stylelint-config-recommended": "^3.0.0",
"stylelint-config-styled-components": "^0.1.1"
}
+2 -2
View File
@@ -6,9 +6,9 @@
"license": "Apache-2",
"dependencies": {
"@babel/runtime": "^7.9.6",
"@polkadot/api": "^1.14.1",
"@polkadot/api": "^1.15.1",
"@polkadot/extension-inject": "0.26.0-beta.2",
"@polkadot/keyring": "^2.10.1",
"@polkadot/ui-keyring": "^0.53.1"
"@polkadot/ui-keyring": "^0.54.0-beta.1"
}
}
@@ -13,12 +13,15 @@ import chrome from '@polkadot/extension-inject/chrome';
import { MetadataStore } from '../../stores';
interface AuthRequest {
interface Resolver <T> {
reject: (error: Error) => void;
resolve: (result: T) => void;
}
interface AuthRequest extends Resolver<boolean> {
id: string;
idStr: string;
request: RequestAuthorizeTab;
resolve: (result: boolean) => void;
reject: (error: Error) => void;
url: string;
}
@@ -30,11 +33,9 @@ type AuthUrls = Record<string, {
url: string;
}>;
interface MetaRequest {
interface MetaRequest extends Resolver<boolean> {
id: string;
request: MetadataDef;
resolve: (result: boolean) => void;
reject: (error: Error) => void;
url: string;
}
@@ -47,12 +48,10 @@ type Providers = Record<string, {
start: () => ProviderInterface;
}>
interface SignRequest {
interface SignRequest extends Resolver<ResponseSigning> {
account: AccountJson;
id: string;
request: RequestSign;
resolve: (result: ResponseSigning) => void;
reject: (error: Error) => void;
url: string;
}
@@ -81,7 +80,7 @@ export default class State {
readonly #metaStore = new MetadataStore();
// Map of providers currently injected in tabs
readonly #injectedProviders: Map<chrome.runtime.Port, ProviderInterface> = new Map();
readonly #injectedProviders = new Map<chrome.runtime.Port, ProviderInterface>();
readonly #metaRequests: Record<string, MetaRequest> = {};
@@ -155,8 +154,8 @@ export default class State {
});
}
private authComplete = (id: string, fn: Function): (result: boolean | Error) => void => {
return (result: boolean | Error): void => {
private authComplete = (id: string, resolve: (result: boolean) => void, reject: (error: Error) => void): Resolver<boolean> => {
const complete = (result: boolean | Error) => {
const isAllowed = result === true;
const { idStr, request: { origin }, url } = this.#authRequests[id];
@@ -170,26 +169,53 @@ export default class State {
delete this.#authRequests[id];
this.updateIconAuth(true);
};
fn(result);
return {
reject: (error: Error): void => {
complete(error);
reject(error);
},
resolve: (result: boolean): void => {
complete(result);
resolve(result);
}
};
}
private metaComplete = (id: string, fn: Function): (result: boolean | Error) => void => {
return (result: boolean | Error): void => {
private metaComplete = (id: string, resolve: (result: boolean) => void, reject: (error: Error) => void): Resolver<boolean> => {
const complete = (): void => {
delete this.#metaRequests[id];
this.updateIconMeta(true);
};
fn(result);
return {
reject: (error: Error): void => {
complete();
reject(error);
},
resolve: (result: boolean): void => {
complete();
resolve(result);
}
};
}
private signComplete = (id: string, fn: Function): (result: ResponseSigning | Error) => void => {
return (result: ResponseSigning | Error): void => {
private signComplete = (id: string, resolve: (result: ResponseSigning) => void, reject: (error: Error) => void): Resolver<ResponseSigning> => {
const complete = (): void => {
delete this.#signRequests[id];
this.updateIconSign(true);
};
fn(result);
return {
reject: (error: Error): void => {
complete();
reject(error);
},
resolve: (result: ResponseSigning): void => {
complete();
resolve(result);
}
};
}
@@ -248,11 +274,10 @@ export default class State {
const id = getId();
this.#authRequests[id] = {
...this.authComplete(id, resolve, reject),
id,
idStr,
reject: this.authComplete(id, reject),
request,
resolve: this.authComplete(id, resolve),
url
};
@@ -275,10 +300,9 @@ export default class State {
const id = getId();
this.#metaRequests[id] = {
...this.metaComplete(id, resolve, reject),
id,
reject: this.metaComplete(id, reject),
request,
resolve: this.metaComplete(id, resolve),
url
};
@@ -313,7 +337,7 @@ export default class State {
assert(provider, 'Cannot call pub(rpc.subscribe) before provider is set');
return provider.send(request.method, request.params);
return provider.send(request.method, request.params) as Promise<JsonRpcResponse>;
}
// Start a provider, return its meta
@@ -378,11 +402,10 @@ export default class State {
return new Promise((resolve, reject): void => {
this.#signRequests[id] = {
...this.signComplete(id, resolve, reject),
account,
id,
reject: this.signComplete(id, reject),
request,
resolve: this.signComplete(id, resolve),
url
};
@@ -108,7 +108,7 @@ export default class Tabs {
port.onDisconnect.addListener((): void => {
unsubscribe(id);
this.rpcUnsubscribe({ ...request, subscriptionId }, port);
this.rpcUnsubscribe({ ...request, subscriptionId }, port).catch(console.error);
});
return true;
@@ -39,7 +39,7 @@ export default function handler<TMessageType extends MessageTypes> ({ id, messag
port.postMessage({ id, response });
})
.catch((error): void => {
.catch((error: Error): void => {
console.log(`[err] ${source}:: ${error.message}`);
// only send message back to port if it's still connected
@@ -12,8 +12,7 @@ const subscriptions: Subscriptions = {};
export function createSubscription<TMessageType extends MessageTypesWithSubscriptions> (id: string, port: chrome.runtime.Port): (data: SubscriptionMessageTypes[TMessageType]) => void {
subscriptions[id] = port;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return (subscription: any): void => {
return (subscription: unknown): void => {
if (subscriptions[id]) {
port.postMessage({ id, subscription });
}
@@ -199,8 +199,7 @@ export type RequestAccountSubscribe = null;
export interface RequestRpcSend {
method: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
params: any[];
params: unknown[];
}
export interface RequestRpcSubscribe extends RequestRpcSend {
+1 -2
View File
@@ -17,8 +17,7 @@ export default class Accounts implements InjectedAccounts {
return sendRequest('pub(accounts.list)');
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public subscribe (cb: (accounts: InjectedAccount[]) => any): Unsubcall {
public subscribe (cb: (accounts: InjectedAccount[]) => unknown): Unsubcall {
sendRequest('pub(accounts.subscribe)', null, cb)
.catch((error: Error) => console.error(error));
@@ -12,8 +12,7 @@ import { ProviderList, ProviderMeta, InjectedProvider } from '@polkadot/extensio
const l = logger('PostMessageProvider');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type CallbackHandler = (error?: null | Error, value?: any) => void;
type CallbackHandler = (error?: null | Error, value?: unknown) => void;
// Same as https://github.com/polkadot-js/api/blob/57ca9a9c3204339e1e1f693fcacc33039868dc27/packages/rpc-provider/src/ws/Provider.ts#L17
interface SubscriptionHandler {
@@ -100,24 +99,20 @@ export default class PostMessageProvider implements InjectedProvider {
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public send (method: string, params: any[], subscription?: SubscriptionHandler): Promise<any> {
public async send (method: string, params: unknown[], subscription?: SubscriptionHandler): Promise<any> {
if (subscription) {
const { callback, type } = subscription;
return sendRequest(
'pub(rpc.subscribe)',
{ method, params, type },
(res) => {
subscription.callback(null, res);
}
).then((id): number => {
this.#subscriptions[`${type}::${id}`] = callback;
return id;
const id = await sendRequest('pub(rpc.subscribe)', { method, params, type }, (res): void => {
subscription.callback(null, res);
});
} else {
return sendRequest('pub(rpc.send)', { method, params });
this.#subscriptions[`${type}::${id}`] = callback;
return id;
}
return sendRequest('pub(rpc.send)', { method, params });
}
/**
@@ -130,6 +125,7 @@ export default class PostMessageProvider implements InjectedProvider {
const meta = await sendRequest('pub(rpc.startProvider)', key);
// eslint-disable-next-line @typescript-eslint/no-floating-promises
sendRequest('pub(rpc.subscribeConnected)', null, (connected) => {
this.#isConnected = connected;
@@ -145,11 +141,8 @@ export default class PostMessageProvider implements InjectedProvider {
return meta;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public async subscribe (type: string, method: string, params: any[], callback: AnyFunction): Promise<number> {
const id = await this.send(method, params, { callback, type });
return id as number;
public subscribe (type: string, method: string, params: unknown[], callback: AnyFunction): Promise<number> {
return this.send(method, params, { callback, type }) as Promise<number>;
}
/**
@@ -170,8 +163,6 @@ export default class PostMessageProvider implements InjectedProvider {
delete this.#subscriptions[subscription];
const result = await this.send(method, [id]);
return result as boolean;
return this.send(method, [id]) as Promise<boolean>;
}
}
+4 -5
View File
@@ -15,7 +15,7 @@ import Injected from './Injected';
export interface Handler {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
resolve: (data: any) => void;
resolve: (data?: any) => void;
reject: (error: Error) => void;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
subscriber?: (data: any) => void;
@@ -32,8 +32,7 @@ export function sendMessage<TMessageType extends MessageTypesWithNullRequest>(me
export function sendMessage<TMessageType extends MessageTypesWithNoSubscriptions>(message: TMessageType, request: RequestTypes[TMessageType]): Promise<ResponseTypes[TMessageType]>;
export function sendMessage<TMessageType extends MessageTypesWithSubscriptions>(message: TMessageType, request: RequestTypes[TMessageType], subscriber: (data: SubscriptionMessageTypes[TMessageType]) => void): Promise<ResponseTypes[TMessageType]>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function sendMessage<TMessageType extends MessageTypes> (message: TMessageType, request?: RequestTypes[TMessageType], subscriber?: (data: any) => void): Promise<ResponseTypes[TMessageType]> {
export function sendMessage<TMessageType extends MessageTypes> (message: TMessageType, request?: RequestTypes[TMessageType], subscriber?: (data: unknown) => void): Promise<ResponseTypes[TMessageType]> {
return new Promise((resolve, reject): void => {
const id = `${Date.now()}.${++idCounter}`;
@@ -57,8 +56,7 @@ export async function enable (origin: string): Promise<Injected> {
return new Injected(sendMessage);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function handleResponse<TMessageType extends MessageTypes> (data: TransportResponseMessage<TMessageType> & { subscription?: any }): void {
export function handleResponse<TMessageType extends MessageTypes> (data: TransportResponseMessage<TMessageType> & { subscription?: string }): void {
const handler = handlers[data.id];
if (!handler) {
@@ -72,6 +70,7 @@ export function handleResponse<TMessageType extends MessageTypes> (data: Transpo
}
if (data.subscription) {
// eslint-disable-next-line @typescript-eslint/ban-types
(handler.subscriber as Function)(data.subscription);
} else if (data.error) {
handler.reject(new Error(data.error));
@@ -6,7 +6,7 @@ import { KeyringStore, KeyringJson } from '@polkadot/ui-keyring/types';
import BaseStore from './Base';
export default class AccountsStore extends BaseStore implements KeyringStore {
export default class AccountsStore extends BaseStore<KeyringJson> implements KeyringStore {
constructor () {
super(null);
}
@@ -15,22 +15,22 @@ export default class AccountsStore extends BaseStore implements KeyringStore {
super.all(cb);
}
public get (key: string, cb: (value: KeyringJson) => void): void {
super.get(key, cb);
public get (key: string, update: (value: KeyringJson) => void): void {
super.get(key, update);
}
public remove (key: string, cb?: () => void): void {
super.remove(key, cb);
public remove (key: string, update?: () => void): void {
super.remove(key, update);
}
public set (key: string, value: KeyringJson, cb?: () => void): void {
public set (key: string, value: KeyringJson, update?: () => void): void {
// shortcut, don't save testing accounts in extension storage
if (key.startsWith('account:') && value.meta && value.meta.isTesting) {
cb && cb();
update && update();
return;
}
super.set(key, value, cb);
super.set(key, value, update);
}
}
+10 -15
View File
@@ -4,8 +4,7 @@
import chrome from '@polkadot/extension-inject/chrome';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type StoreValue = Record<string, any>;
type StoreValue = Record<string, unknown>;
const lastError = (type: string): void => {
const error = chrome.runtime.lastError;
@@ -15,15 +14,14 @@ const lastError = (type: string): void => {
}
};
export default abstract class BaseStore {
export default abstract class BaseStore <T> {
#prefix: string;
constructor (prefix: string | null) {
this.#prefix = prefix ? `${prefix}:` : '';
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public all (cb: (key: string, value: any) => void): void {
public all (update: (key: string, value: T) => void): void {
chrome.storage.local.get(null, (result: StoreValue): void => {
lastError('all');
@@ -31,41 +29,38 @@ export default abstract class BaseStore {
.entries(result)
.filter(([key]) => key.startsWith(this.#prefix))
.forEach(([key, value]): void => {
cb(key.replace(this.#prefix, ''), value);
update(key.replace(this.#prefix, ''), value as T);
});
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public get (_key: string, cb: (value: any) => void): void {
public get (_key: string, update: (value: T) => void): void {
const key = `${this.#prefix}${_key}`;
chrome.storage.local.get([key], (result: StoreValue): void => {
lastError('get');
cb(result[key]);
update(result[key] as T);
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public remove (_key: string, cb?: () => void): void {
public remove (_key: string, update?: () => void): void {
const key = `${this.#prefix}${_key}`;
chrome.storage.local.remove(key, (): void => {
lastError('remove');
cb && cb();
update && update();
});
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
public set (_key: string, value: any, cb?: () => void): void {
public set (_key: string, value: T, update?: () => void): void {
const key = `${this.#prefix}${_key}`;
chrome.storage.local.set({ [key]: value }, (): void => {
lastError('set');
cb && cb();
update && update();
});
}
}
@@ -6,7 +6,7 @@ import { MetadataDef } from '@polkadot/extension-inject/types';
import BaseStore from './Base';
export default class MetadataStore extends BaseStore {
export default class MetadataStore extends BaseStore<MetadataDef> {
constructor () {
super('metadata');
}
@@ -15,15 +15,15 @@ export default class MetadataStore extends BaseStore {
super.all(cb);
}
public get (key: string, cb: (value: MetadataDef) => void): void {
super.get(key, cb);
public get (key: string, update: (value: MetadataDef) => void): void {
super.get(key, update);
}
public remove (key: string, cb?: () => void): void {
super.remove(key, cb);
public remove (key: string, update?: () => void): void {
super.remove(key, update);
}
public set (key: string, value: MetadataDef, cb?: () => void): void {
super.set(key, value, cb);
public set (key: string, value: MetadataDef, update?: () => void): void {
super.set(key, value, update);
}
}
+13
View File
@@ -0,0 +1,13 @@
// Copyright 2019-2020 @polkadot/extension authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
export interface Message extends MessageEvent {
data: {
error?: string;
id: string;
origin: string;
response?: string;
subscription?: string;
}
}
+1 -2
View File
@@ -19,8 +19,7 @@ function metadataExpand (definition: MetadataDef): Chain {
const { chain, genesisHash, icon, metaCalls, specVersion, ss58Format, tokenDecimals, tokenSymbol, types } = definition;
const registry = new TypeRegistry();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
registry.register(types as any);
registry.register(types);
const isUnknown = genesisHash === '0x';
const metadata = metaCalls
+13 -11
View File
@@ -58,9 +58,8 @@ export function web3Enable (originName: string): Promise<InjectedExtension[]> {
.map(([info, ext]): InjectedExtension => {
// if we don't have an accounts subscriber, add a single-shot version
if (ext && !ext.accounts.subscribe) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
ext.accounts.subscribe = (cb: (accounts: InjectedAccount[]) => any): Unsubcall => {
ext.accounts.get().then(cb).catch((error: Error) => console.error(error));
ext.accounts.subscribe = (cb: (accounts: InjectedAccount[]) => void | Promise<void>): Unsubcall => {
ext.accounts.get().then(cb).catch(console.error);
return (): void => {
// no ubsubscribe needed, this is a single-shot
@@ -119,25 +118,28 @@ export async function web3Accounts (): Promise<InjectedAccountWithMeta[]> {
return accounts;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export async function web3AccountsSubscribe (cb: (accounts: InjectedAccountWithMeta[]) => any): Promise<Unsubcall> {
export async function web3AccountsSubscribe (cb: (accounts: InjectedAccountWithMeta[]) => void | Promise<void>): Promise<Unsubcall> {
if (!web3EnablePromise) {
return throwError('web3AccountsSubscribe');
}
const accounts: Record<string, InjectedAccount[]> = {};
const triggerUpdate = (): void => {
cb(Object.entries(accounts).reduce((result, [source, list]): InjectedAccountWithMeta[] => {
result.push(...mapAccounts(source, list));
const triggerUpdate = (): void | Promise<void> => cb(
Object
.entries(accounts)
.reduce((result: InjectedAccountWithMeta[], [source, list]): InjectedAccountWithMeta[] => {
result.push(...mapAccounts(source, list));
return result;
}, [] as InjectedAccountWithMeta[]));
};
return result;
}, [])
);
const unsubs = (await web3EnablePromise).map(({ accounts: { subscribe }, name: source }): Unsubcall =>
subscribe((result): void => {
accounts[source] = result;
// eslint-disable-next-line @typescript-eslint/no-floating-promises
triggerUpdate();
})
);
+1 -1
View File
@@ -8,7 +8,7 @@
"@babel/runtime": "^7.9.6"
},
"devDependencies": {
"@types/chrome": "^0.0.112",
"@types/chrome": "^0.0.114",
"@types/firefox-webext-browser": "^70.0.1"
},
"peerDependencies": {
+2 -3
View File
@@ -27,8 +27,7 @@ export interface InjectedAccountWithMeta {
export interface InjectedAccounts {
get: () => Promise<InjectedAccount[]>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
subscribe: (cb: (accounts: InjectedAccount[]) => any) => Unsubcall;
subscribe: (cb: (accounts: InjectedAccount[]) => void | Promise<void>) => Unsubcall;
}
export interface InjectedExtensionInfo {
@@ -56,7 +55,7 @@ export interface MetadataDef {
ss58Format: number;
tokenDecimals: number;
tokenSymbol: string;
types: Record<string, object | string>;
types: Record<string, Record<string, string> | string>;
metaCalls?: string;
}
+3 -3
View File
@@ -9,8 +9,8 @@
"@polkadot/extension-base": "0.26.0-beta.2",
"@polkadot/extension-inject": "0.26.0-beta.2",
"@polkadot/keyring": "^2.10.1",
"@polkadot/react-identicon": "^0.53.1",
"@polkadot/react-qr": "^0.53.1",
"@polkadot/react-identicon": "^0.54.0-beta.1",
"@polkadot/react-qr": "^0.54.0-beta.1",
"@polkadot/util": "^2.10.1",
"@polkadot/util-crypto": "^2.10.1",
"react": "^16.13.1",
@@ -28,7 +28,7 @@
"@types/react-dom": "^16.9.8",
"@types/react-router": "^5.1.7",
"@types/react-router-dom": "^5.1.5",
"@types/sinon-chrome": "^2.2.8",
"@types/sinon-chrome": "^2.2.9",
"@types/styled-components": "^5.1.0",
"enzyme": "^3.11.0",
"enzyme-adapter-react-16": "^1.15.2",
@@ -18,8 +18,8 @@ configure({ adapter: new Adapter() });
describe('Account component', () => {
let wrapper: ReactWrapper;
const VALID_ADDRESS = 'HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const mountAccountComponent = (additionalAccountProperties: any, theme: Theme = themes.dark): ReactWrapper => mount(
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
const mountAccountComponent = (additionalAccountProperties: Record<string, unknown>, theme: Theme = themes.dark): ReactWrapper => mount(
<MemoryRouter>
<ThemeProvider theme={theme}>
<Account
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { AccountJson } from '@polkadot/extension-base/background/types';
import { ThemeProps } from '../../types';
import React, { useCallback, useContext, useState } from 'react';
import styled from 'styled-components';
@@ -82,7 +83,7 @@ function Account ({ address, className, isExternal, parentName }: Props): React.
const MenuGroup = styled.div`
padding-bottom: 16px;
margin-bottom: 16px;
border-bottom: 1px solid ${({ theme }): string => theme.boxBorderColor};
border-bottom: 1px solid ${({ theme }: ThemeProps): string => theme.boxBorderColor};
`;
const MenuItem = styled(Link)`
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../../types';
import React, { useContext } from 'react';
import styled from 'styled-components';
@@ -10,9 +12,7 @@ import { AddAccount, Header } from '../../partials';
import AccountsTree from './AccountsTree';
import qrIcon from '../../assets/qr.svg';
type Props = {};
export default function Accounts (): React.ReactElement<Props> {
export default function Accounts (): React.ReactElement {
const { hierarchy, master } = useContext(AccountContext);
const mediaAllowed = useContext(MediaContext);
@@ -64,7 +64,7 @@ const QrButton = styled(Button)`
${Svg} {
width: 20px;
height: 20px;
background: ${({ theme }): string => theme.buttonTextColor};
background: ${({ theme }: ThemeProps): string => theme.buttonTextColor};
}
`;
@@ -19,6 +19,7 @@ import Request from './Request';
configure({ adapter: new Adapter() });
describe('Authorize', () => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
const mountAuthorize = (authorizeRequests: AuthorizeRequest[] = []): ReactWrapper => mount(
<AuthorizeReqContext.Provider value={authorizeRequests}>
<ThemeProvider theme={themes.dark}>
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { RequestAuthorizeTab } from '@polkadot/extension-base/background/types';
import { ThemeProps } from '../../types';
import React, { useContext } from 'react';
import styled from 'styled-components';
@@ -72,7 +73,7 @@ const RequestInfo = styled.div`
flex-direction: column;
align-items: center;
margin-bottom: 8px;
background: ${({ theme }): string => theme.highlightedAreaBackground};
background: ${({ theme }: ThemeProps): string => theme.highlightedAreaBackground};
`;
const Info = styled.div`
@@ -99,7 +100,7 @@ const RejectButton = styled(ActionBar)`
export default styled(Request)`
.icon {
background: ${({ theme }): string => theme.buttonBackgroundDanger};
background: ${({ theme }: ThemeProps): string => theme.buttonBackgroundDanger};
color: white;
min-width: 18px;
width: 14px;
@@ -118,7 +119,7 @@ export default styled(Request)`
.tab-name,
.tab-url {
color: ${({ theme }): string => theme.textColor};
color: ${({ theme }: ThemeProps): string => theme.textColor};
display: inline-block;
max-width: 20rem;
overflow: hidden;
@@ -9,7 +9,7 @@ import { AuthorizeReqContext } from '../../components';
import { Header } from '../../partials';
import Request from './Request';
export default function Authorize (): React.ReactElement<{}> {
export default function Authorize (): React.ReactElement {
const requests = useContext(AuthorizeReqContext);
return (
@@ -3,7 +3,8 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import React, { useCallback, useState } from 'react';
import { Address, BackButton, ButtonArea, NextStepButton, VerticalSpace } from '../..//components';
import { Address, BackButton, ButtonArea, NextStepButton, VerticalSpace } from '../../components';
import { Name, Password } from '../../partials';
interface Props {
@@ -25,6 +25,7 @@ describe('Create Account', () => {
address: 'HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5',
seed: 'horse battery staple correct'
};
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
const mountComponent = (): ReactWrapper => mount(
<ActionContext.Provider value={onActionStub}>
<ThemeProvider theme={themes.dark}>
@@ -2,9 +2,12 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../../types';
import React from 'react';
import styled from 'styled-components';
import { ActionText, Title } from '@polkadot/extension-ui/components';
import { ActionText, Title } from '../../components';
interface Props {
step: number;
@@ -36,16 +39,16 @@ const CreateAnAccount = styled(Title).attrs(() => ({
`;
const CurrentStep = styled.span`
font-size: ${({ theme }): string => theme.labelFontSize};
line-height: ${({ theme }): string => theme.labelLineHeight};
color: ${({ theme }): string => theme.primaryColor};
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps): string => theme.labelLineHeight};
color: ${({ theme }: ThemeProps): string => theme.primaryColor};
font-weight: 600;
`;
const TotalSteps = styled.span`
font-size: ${({ theme }): string => theme.labelFontSize};
line-height: ${({ theme }): string => theme.labelLineHeight};
color: ${({ theme }): string => theme.textColor};
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps): string => theme.labelLineHeight};
color: ${({ theme }: ThemeProps): string => theme.textColor};
font-weight: 600;
`;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../../types';
import React, { useCallback, useRef, useState } from 'react';
import styled from 'styled-components';
@@ -54,11 +56,11 @@ const HiddenOptions = styled.div<{ visible: boolean }>`
visibility: ${({ visible }): string => (visible ? 'visible' : 'hidden')};
width: 430px;
z-index: 100;
background: ${({ theme }): string => theme.bodyColor};
background: ${({ theme }: ThemeProps): string => theme.bodyColor};
max-height: ${({ visible }): string => (visible ? '200px' : '0')};
overflow: scroll;
padding: 5px;
border: 1px solid ${({ theme }): string => theme.boxBorderColor};
border: 1px solid ${({ theme }: ThemeProps): string => theme.boxBorderColor};
box-sizing: border-box;
border-radius: 4px;
margin-top: -8px;
@@ -81,10 +83,10 @@ export default styled(AddressDropdown)`
width: 30px;
height: 30px;
background: url(${arrow}) center no-repeat;
background-color: ${({ theme }): string => theme.inputBackground};
background-color: ${({ theme }: ThemeProps): string => theme.inputBackground};
pointer-events: none;
border-radius: 4px;
border: 1px solid ${({ theme }): string => theme.boxBorderColor};
border: 1px solid ${({ theme }: ThemeProps): string => theme.boxBorderColor};
}
${Address} ${Svg} {
@@ -30,6 +30,7 @@ describe('Export component', () => {
beforeEach(() => {
jest.spyOn(messaging, 'exportAccount').mockResolvedValue({ exportedJson: '{ "meta": { "name": "account_name" } }' });
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
wrapper = mount(
<MemoryRouter initialEntries={ [`/account/export/${VALID_ADDRESS}`] }>
<ThemeProvider theme={themes.dark}>
+2 -1
View File
@@ -29,9 +29,10 @@ function Export ({ match: { params: { address } } }: Props): React.ReactElement<
exportAccount(address, pass)
.then(({ exportedJson }) => {
const element = document.createElement('a');
const { meta } = JSON.parse(exportedJson) as { meta: { name: string } };
element.href = `data:text/plain;charset=utf-8,${exportedJson}`;
element.download = `${JSON.parse(exportedJson).meta.name}_exported_account_${Date.now()}.json`;
element.download = `${meta.name}_exported_account_${Date.now()}.json`;
element.click();
onAction('/');
+1 -3
View File
@@ -9,9 +9,7 @@ import { ActionContext, Address, NextStepButton, ButtonArea, VerticalSpace } fro
import { createAccountExternal } from '../messaging';
import { Header, Name } from '../partials';
type Props = {};
export default function ImportQr (): React.ReactElement<Props> {
export default function ImportQr (): React.ReactElement {
const onAction = useContext(ActionContext);
const [account, setAccount] = useState<null | { address: string; genesisHash: string }>(null);
const [name, setName] = useState<string | null>(null);
@@ -10,24 +10,22 @@ import { allOf, isNotShorterThan, Result } from '../validators';
import { createAccountSuri, validateSeed } from '../messaging';
import { Header, Name, Password } from '../partials';
type Props = {};
const validate = async (suri: string): Promise<Result<string>> => {
async function validate (suri: string): Promise<Result<string>> {
try {
await validateSeed(suri);
return Result.ok(suri);
} catch (err) {
return Result.error(err.message);
} catch (error) {
return Result.error((error as Error).message);
}
};
}
const isSeedValid = allOf(
isNotShorterThan(1, 'Seed is empty'),
validate
);
export default function Import (): React.ReactElement<Props> {
export default function Import (): React.ReactElement {
const onAction = useContext(ActionContext);
const [account, setAccount] = useState<null | { address: string; suri: string }>(null);
const [name, setName] = useState<string | null>(null);
@@ -49,8 +47,8 @@ export default function Import (): React.ReactElement<Props> {
// this should always be the case
if (name && password && account) {
createAccountSuri(name, password, account.suri)
.then((): void => onAction('/'))
.catch((error: Error) => console.error(error));
.then(() => onAction('/'))
.catch(console.error);
}
}, [account, name, onAction, password]);
@@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { MetadataDef } from '@polkadot/extension-inject/types';
import { ThemeProps } from '../../types';
import React, { useContext } from 'react';
import styled from 'styled-components';
@@ -10,6 +11,7 @@ import styled from 'styled-components';
import { ActionBar, ActionContext, Button, Link, Table, Warning } from '../../components';
import useMetadata from '../../hooks/useMetadata';
import { approveMetaRequest, rejectMetaRequest } from '../../messaging';
interface Props {
className?: string;
request: MetadataDef;
@@ -78,7 +80,7 @@ const RequestInfo = styled.div`
flex-direction: column;
align-items: center;
margin-bottom: 8px;
background: ${({ theme }): string => theme.highlightedAreaBackground};
background: ${({ theme }: ThemeProps): string => theme.highlightedAreaBackground};
`;
const AcceptButton = styled(Button)`
@@ -99,7 +101,7 @@ const RejectButton = styled(ActionBar)`
export default styled(Request)`
.icon {
background: ${({ theme }): string => theme.buttonBackgroundDanger};
background: ${({ theme }: ThemeProps): string => theme.buttonBackgroundDanger};
color: white;
min-width: 18px;
width: 14px;
@@ -118,7 +120,7 @@ export default styled(Request)`
.tab-name,
.tab-url {
color: ${({ theme }): string => theme.textColor};
color: ${({ theme }: ThemeProps): string => theme.textColor};
display: inline-block;
max-width: 20rem;
overflow: hidden;
@@ -8,7 +8,7 @@ import { Loading, MetadataReqContext } from '../../components';
import { Header } from '../../partials';
import Request from './Request';
export default function Metadata (): React.ReactElement<{}> {
export default function Metadata (): React.ReactElement {
const requests = useContext(MetadataReqContext);
return (
@@ -33,8 +33,7 @@ function decodeMethod (data: string, isDecoded: boolean, chain: Chain | null, sp
try {
if (isDecoded && chain && chain.hasMetadata && specVersion.eqn(chain.specVersion)) {
method = chain.registry.createType('Call', data);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
args = (method.toHuman() as any).args;
args = (method.toHuman() as { args: AnyJson }).args;
}
} catch (error) {
args = null;
@@ -43,6 +43,7 @@ describe.skip('Signing requests', () => {
}
const mountComponent = async (): Promise<void> => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
wrapper = mount(
<ActionContext.Provider value={onActionStub}>
<ThemeProvider theme={themes.dark}>
@@ -2,8 +2,11 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../../types';
import React from 'react';
import styled from 'styled-components';
import { Svg } from '../../components';
import ArrowLeftImage from '../../assets/arrowLeft.svg';
@@ -15,6 +18,10 @@ interface Props {
className?: string;
}
interface ArrowProps extends ThemeProps {
isActive: boolean;
}
function TransactionIndex ({ index, onNextClick, onPreviousClick, totalItems }: Props): React.ReactElement<Props> {
const previousClickActive = index !== 0;
const nextClickActive = index < totalItems - 1;
@@ -48,29 +55,23 @@ const CreationSteps = styled.div`
`;
const CurrentStep = styled.span`
font-size: ${({ theme }): string => theme.labelFontSize};
line-height: ${({ theme }): string => theme.labelLineHeight};
color: ${({ theme }): string => theme.primaryColor};
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps): string => theme.labelLineHeight};
color: ${({ theme }: ThemeProps): string => theme.primaryColor};
font-weight: 600;
margin-left: 10px;
`;
const TotalSteps = styled.span`
font-size: ${({ theme }): string => theme.labelFontSize};
line-height: ${({ theme }): string => theme.labelLineHeight};
color: ${({ theme }): string => theme.textColor};
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps): string => theme.labelLineHeight};
color: ${({ theme }: ThemeProps): string => theme.textColor};
font-weight: 600;
`;
interface ArrowProps {
isActive: boolean;
}
const ArrowLeft = styled(Svg).attrs(() => ({
src: ArrowLeftImage
}))<ArrowProps>`
const ArrowLeft = styled(Svg).attrs(() => ({ src: ArrowLeftImage }))<ArrowProps>`
display: inline-block;
background: ${({ isActive, theme }): string => isActive ? theme.primaryColor : theme.iconNeutralColor};
background: ${({ isActive, theme }: ArrowProps): string => isActive ? theme.primaryColor : theme.iconNeutralColor};
cursor: ${({ isActive }): string => isActive ? 'pointer' : 'default'};
width: 12px;
height: 12px;
@@ -25,7 +25,7 @@ export default function Unlock ({ buttonText = 'Sign the transaction', className
);
const _onClick = useCallback(
(): Promise<void> =>
onSign(password).catch((error): void => setError(error.message)),
onSign(password).catch((error: Error) => setError(error.message)),
[onSign, password]
);
@@ -15,7 +15,7 @@ function isInnerTransaction (signingRequest: SigningRequest): boolean {
return 'blockNumber' in signingRequest.request.payload;
}
export default function Signing (): React.ReactElement<{}> {
export default function Signing (): React.ReactElement {
const requests = useContext(SigningReqContext);
const [requestIndex, setRequestIndex] = useState(0);
const isTransaction = useMemo(
+5 -5
View File
@@ -2,14 +2,14 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps as Props } from '../types';
import React, { useContext } from 'react';
import styled from 'styled-components';
import { ActionContext, Box, Button, ButtonArea, List, VerticalSpace } from '../components';
import { Header } from '../partials';
type Props = {};
export default function Welcome (): React.ReactElement<Props> {
const onAction = useContext(ActionContext);
@@ -41,11 +41,11 @@ export default function Welcome (): React.ReactElement<Props> {
const Note = styled.p`
margin-bottom: 6px;
margin-top: 0;
color: ${({ theme }): string => theme.subTextColor};
color: ${({ theme }: Props): string => theme.subTextColor};
`;
const TextBox = styled(Box)`
margin: 0.75rem 24px;
border: 1px solid ${({ theme }): string => theme.inputBorderColor};
color: ${({ theme }): string => theme.subTextColor};
border: 1px solid ${({ theme }: Props): string => theme.inputBorderColor};
color: ${({ theme }: Props): string => theme.subTextColor};
`;
+3 -3
View File
@@ -44,7 +44,7 @@ async function requestMediaAccess (cameraOn: boolean): Promise<boolean> {
return true;
} catch (error) {
console.error('Permission for video declined', error.message);
console.error('Permission for video declined', (error as Error).message);
}
return false;
@@ -62,7 +62,7 @@ function initAccountContext (accounts: AccountJson[]): AccountsContext {
};
}
export default function Popup (): React.ReactElement<{}> {
export default function Popup (): React.ReactElement {
const [accounts, setAccounts] = useState<null | AccountJson[]>(null);
const [authRequests, setAuthRequests] = useState<null | AuthorizeRequest[]>(null);
const [cameraOn, setCameraOn] = useState(settings.get().camera === 'on');
@@ -93,7 +93,7 @@ export default function Popup (): React.ReactElement<{}> {
}, []);
useEffect((): void => {
requestMediaAccess(cameraOn).then(setMediaAllowed);
requestMediaAccess(cameraOn).then(setMediaAllowed).catch(console.error);
}, [cameraOn]);
const Root = isWelcomeDone
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React, { MouseEventHandler } from 'react';
import Svg from '@polkadot/extension-ui/components/Svg';
import styled from 'styled-components';
@@ -29,14 +31,14 @@ export default styled(ActionText)`
cursor: pointer;
span {
font-size: ${({ theme }): string => theme.labelFontSize};
line-height: ${({ theme }): string => theme.labelLineHeight};
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps): string => theme.labelLineHeight};
text-decoration-line: underline;
color: ${({ theme }): string => theme.labelColor}
color: ${({ theme }: ThemeProps): string => theme.labelColor}
}
${Svg} {
background: ${({ theme }): string => theme.iconNeutralColor};
background: ${({ theme }: ThemeProps): string => theme.iconNeutralColor};
display: inline-block;
position: relative;
top: 2px;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import { AccountJson, AccountWithChildren } from '@polkadot/extension-base/background/types';
import { Chain } from '@polkadot/extension-chains/types';
@@ -168,9 +170,9 @@ const CopyAddress = styled.div`
width: 14px;
height: 14px;
margin-right: 10px;
background: ${({ theme }): string => theme.accountDotsIconColor};
background: ${({ theme }: ThemeProps): string => theme.accountDotsIconColor};
&:hover {
background: ${({ theme }): string => theme.labelColor};
background: ${({ theme }: ThemeProps): string => theme.labelColor};
cursor: pointer;
}
}
@@ -207,7 +209,7 @@ const FullAddress = styled.div`
width: 270px;
overflow: hidden;
text-overflow: ellipsis;
color: ${({ theme }): string => theme.labelColor};
color: ${({ theme }: ThemeProps): string => theme.labelColor};
font-size: 12px;
line-height: 16px;
`;
@@ -234,12 +236,12 @@ const Settings = styled.div`
top: 25%;
bottom: 25%;
width: 1px;
background: ${({ theme }): string => theme.boxBorderColor};
background: ${({ theme }: ThemeProps): string => theme.boxBorderColor};
}
&:hover {
cursor: pointer;
background: ${({ theme }): string => theme.readonlyInputBackground};
background: ${({ theme }: ThemeProps): string => theme.readonlyInputBackground};
}
`;
@@ -248,13 +250,13 @@ Settings.displayName = 'Details';
const ActionsIcon = styled(Svg).attrs(() => ({
src: details
}))`
background: ${({ theme }): string => theme.accountDotsIconColor};
background: ${({ theme }: ThemeProps): string => theme.accountDotsIconColor};
`;
const ActiveActionsIcon = styled(Svg).attrs(() => ({
src: details
}))`
background: ${({ theme }): string => theme.primaryColor};
background: ${({ theme }: ThemeProps): string => theme.primaryColor};
`;
const Banner = styled.div`
@@ -269,7 +271,7 @@ const Banner = styled.div`
const ChainBanner = styled(Banner)`
padding: 0.1rem 0.5rem;
right: 40px;
background: ${({ theme }): string => theme.primaryColor};
background: ${({ theme }: ThemeProps): string => theme.primaryColor};
`;
const ParentName = styled.div`
@@ -277,7 +279,7 @@ const ParentName = styled.div`
font-weight: 600;
font-size: 10px;
line-height: 14px;
color: ${({ theme }): string => theme.labelColor};
color: ${({ theme }: ThemeProps): string => theme.labelColor};
text-overflow: ellipsis;
overflow: hidden;
width: 270px;
@@ -290,7 +292,7 @@ const ArrowLabel = styled(Svg).attrs(() => ({
top: 5px;
width: 9px;
height: 9px;
background: ${({ theme }): string => theme.labelColor};
background: ${({ theme }: ThemeProps): string => theme.labelColor};
`;
const MovableMenu = styled(Menu) <{ isMoved: boolean }>`
@@ -302,8 +304,8 @@ export default styled(Address)`
margin-bottom: 8px;
& > div {
background: ${({ theme }): string => theme.accountBackground};
border: 1px solid ${({ theme }): string => theme.boxBorderColor};
background: ${({ theme }: ThemeProps): string => theme.accountBackground};
border: 1px solid ${({ theme }: ThemeProps): string => theme.boxBorderColor};
box-sizing: border-box;
border-radius: 4px;
}
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
@@ -24,7 +26,7 @@ export default function BackButton ({ onClick }: Props): React.ReactElement<Prop
const SmallButton = styled(Button)`
margin-right: 11px;
width: 42px;
background: ${({ theme }): string => theme.backButtonBackground};
background: ${({ theme }: ThemeProps): string => theme.backButtonBackground};
`;
const ArrowLeft = styled(Svg).attrs(() => ({
@@ -34,5 +36,5 @@ const ArrowLeft = styled(Svg).attrs(() => ({
height: 12px;
display: block;
margin: auto;
background: ${({ theme }): string => theme.backButtonTextColor};
background: ${({ theme }: ThemeProps): string => theme.backButtonTextColor};
`;
+10 -8
View File
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
@@ -21,19 +23,19 @@ function Box ({ banner, children, className }: Props): React.ReactElement<Props>
}
export default styled(Box)`
background: ${({ theme }): string => theme.readonlyInputBackground};
background: ${({ theme }: ThemeProps): string => theme.readonlyInputBackground};
border: none;
border-radius: ${({ theme }): string => theme.borderRadius};
color: ${({ theme }): string => theme.textColor};
font-family: ${({ theme }): string => theme.fontFamily};
font-size: ${({ theme }): string => theme.fontSize};
margin: ${({ theme }): string => theme.boxMargin};
padding: ${({ theme }): string => theme.boxPadding};
border-radius: ${({ theme }: ThemeProps): string => theme.borderRadius};
color: ${({ theme }: ThemeProps): string => theme.textColor};
font-family: ${({ theme }: ThemeProps): string => theme.fontFamily};
font-size: ${({ theme }: ThemeProps): string => theme.fontSize};
margin: ${({ theme }: ThemeProps): string => theme.boxMargin};
padding: ${({ theme }: ThemeProps): string => theme.boxPadding};
position: relative;
.banner {
background: darkorange;
border-radius: 0 ${({ theme }): string => theme.borderRadius} 0 ${({ theme }): string => theme.borderRadius};
border-radius: 0 ${({ theme }: ThemeProps): string => theme.borderRadius} 0 ${({ theme }: ThemeProps): string => theme.borderRadius};
color: white;
font-size: 0.75rem;
padding: 0.25rem 0.5rem;
@@ -2,10 +2,12 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
interface Props {
interface Props extends ThemeProps {
className?: string;
children?: React.ReactNode;
isDanger?: boolean;
@@ -41,17 +43,17 @@ function Button ({ children, className, isDisabled, onClick, to }: Props): React
export default styled(Button)`
display: block;
width: 100%;
height: ${({ isDanger }): string => isDanger ? '40px' : '48px'};
height: ${({ isDanger }: Props): string => isDanger ? '40px' : '48px'};
box-sizing: border-box;
border: none;
border-radius: ${({ theme }): string => theme.borderRadius};
color: ${({ theme }): string => theme.buttonTextColor};
border-radius: ${({ theme }: Props): string => theme.borderRadius};
color: ${({ theme }: Props): string => theme.buttonTextColor};
font-size: 15px;
font-weight: 800;
line-height: 20px;
padding: 0 1rem;
text-align: center;
background: ${({ isDanger, theme }): string => isDanger ? theme.buttonBackgroundDanger : theme.buttonBackground};
background: ${({ isDanger, theme }: Props): string => isDanger ? theme.buttonBackgroundDanger : theme.buttonBackground};
cursor: pointer;
&:disabled {
@@ -60,6 +62,6 @@ export default styled(Button)`
}
&:not(:disabled):hover {
background: ${({ isDanger, theme }): string => isDanger ? theme.buttonBackgroundDangerHover : theme.buttonBackgroundHover};
background: ${({ isDanger, theme }: Props): string => isDanger ? theme.buttonBackgroundDangerHover : theme.buttonBackgroundHover};
}
`;
@@ -2,14 +2,16 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import styled from 'styled-components';
import Button from './Button';
export default styled.div`
display: flex;
flex-direction: row;
background: ${({ theme }): string => theme.highlightedAreaBackground};
border-top: 1px solid ${({ theme }): string => theme.inputBorderColor};
background: ${({ theme }: ThemeProps): string => theme.highlightedAreaBackground};
border-top: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
padding: 12px 24px;
&&& {
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
import Checkmark from '../assets/checkmark.svg';
@@ -30,7 +32,7 @@ function Checkbox ({ checked, className, label, onChange }: Props): React.ReactE
}
export default styled(Checkbox)`
margin: ${({ theme }): string => theme.boxMargin};
margin: ${({ theme }: ThemeProps): string => theme.boxMargin};
label {
display: block;
@@ -39,9 +41,9 @@ export default styled(Checkbox)`
user-select: none;
padding-left: 24px;
padding-top: 1px;
color: ${({ theme }): string => theme.subTextColor};
font-size: ${({ theme }): string => theme.fontSize};
line-height: ${({ theme }): string => theme.lineHeight};
color: ${({ theme }: ThemeProps): string => theme.subTextColor};
font-size: ${({ theme }: ThemeProps): string => theme.fontSize};
line-height: ${({ theme }: ThemeProps): string => theme.lineHeight};
& input {
position: absolute;
@@ -57,10 +59,10 @@ export default styled(Checkbox)`
left: 0;
height: 16px;
width: 16px;
border-radius: ${({ theme }): string => theme.borderRadius};
background-color: ${({ theme }): string => theme.readonlyInputBackground};
border: 1px solid ${({ theme }): string => theme.inputBorderColor};
border: 1px solid ${({ theme }): string => theme.inputBorderColor};
border-radius: ${({ theme }: ThemeProps): string => theme.borderRadius};
background-color: ${({ theme }: ThemeProps): string => theme.readonlyInputBackground};
border: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
border: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
&:after {
content: '';
display: none;
@@ -71,12 +73,12 @@ export default styled(Checkbox)`
top: 2px;
mask: url(${Checkmark});
mask-size: cover;
background: ${({ theme }): string => theme.primaryColor};
background: ${({ theme }: ThemeProps): string => theme.primaryColor};
}
}
&:hover input ~ span {
background-color: ${({ theme }): string => theme.inputBackground};
background-color: ${({ theme }: ThemeProps): string => theme.inputBackground};
}
input:checked ~ span:after {
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
@@ -13,7 +15,7 @@ interface DropdownOption {
value: string;
}
interface Props {
interface Props extends ThemeProps {
className?: string;
defaultValue?: string | null;
isError?: boolean;
@@ -64,16 +66,16 @@ export default styled(Dropdown)`
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
background: ${({ theme }): string => theme.readonlyInputBackground};
border-color: ${({ isError, theme }): string => isError ? theme.errorBorderColor : theme.inputBorderColor};
border-radius: ${({ theme }): string => theme.borderRadius};
background: ${({ theme }: Props): string => theme.readonlyInputBackground};
border-color: ${({ isError, theme }: Props): string => isError ? theme.errorBorderColor : theme.inputBorderColor};
border-radius: ${({ theme }: ThemeProps): string => theme.borderRadius};
border-style: solid;
border-width: 1px;
box-sizing: border-box;
color: ${({ isError, theme }): string => isError ? theme.errorBorderColor : theme.textColor};
color: ${({ isError, theme }: Props): string => isError ? theme.errorBorderColor : theme.textColor};
display: block;
font-family: ${({ theme }): string => theme.fontFamily};
font-size: ${({ theme }): string => theme.fontSize};
font-family: ${({ theme }: Props): string => theme.fontFamily};
font-size: ${({ theme }: Props): string => theme.fontSize};
font-weight: 600;
padding: 0.5rem 0.75rem;
width: 100%;
@@ -11,7 +11,7 @@ interface Props {
onClick?: () => void | Promise<void>;
}
function Icon ({ className, icon, onClick }: Props): React.ReactElement<Props> {
function Icon ({ className = '', icon, onClick }: Props): React.ReactElement<Props> {
return (
<div
className={`${className} icon`}
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
import Icon from '@polkadot/react-identicon';
@@ -35,7 +37,7 @@ export default styled(Identicon)`
.container:before {
box-shadow: none;
background: ${({ theme }): string => theme.identiconBackground};
background: ${({ theme }: ThemeProps): string => theme.identiconBackground};
}
svg {
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
@@ -21,7 +23,7 @@ function Label ({ children, className, label }: Props): React.ReactElement<Props
}
export default styled(Label)`
color: ${({ theme }): string => theme.textColor};
color: ${({ theme }: ThemeProps): string => theme.textColor};
label {
font-size: 10px;
+11 -9
View File
@@ -2,11 +2,13 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
import { Link as RouterLink } from 'react-router-dom';
interface Props {
interface Props extends ThemeProps {
children?: React.ReactNode;
className?: string;
isDanger?: boolean;
@@ -15,8 +17,8 @@ interface Props {
}
function Link ({ children, className, onClick, to }: Props): React.ReactElement<Props> {
return (
to ? (
return to
? (
<RouterLink
className={className}
onClick={onClick}
@@ -24,7 +26,8 @@ function Link ({ children, className, onClick, to }: Props): React.ReactElement<
>
{children}
</RouterLink>
) : (
)
: (
<a
className={className}
href='#'
@@ -32,24 +35,23 @@ function Link ({ children, className, onClick, to }: Props): React.ReactElement<
>
{children}
</a>
)
);
);
}
export default styled(Link)`
display: flex;
align-items: center;
color: ${({ isDanger, theme }): string => isDanger ? theme.textColorDanger : theme.textColor};
color: ${({ isDanger, theme }: Props): string => isDanger ? theme.textColorDanger : theme.textColor};
opacity: 0.9;
text-decoration: none;
vertical-align: middle;
&:hover {
color: ${({ isDanger, theme }): string => isDanger ? theme.textColorDanger : theme.textColor};
color: ${({ isDanger, theme }: Props): string => isDanger ? theme.textColorDanger : theme.textColor};
opacity: 1.0;
}
&:visited {
color: ${({ isDanger, theme }): string => isDanger ? theme.textColorDanger : theme.textColor};
color: ${({ isDanger, theme }: Props): string => isDanger ? theme.textColorDanger : theme.textColor};
}
`;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import styled from 'styled-components';
export default styled.ul`
@@ -17,7 +19,7 @@ export default styled.ul`
li::before {
content: '\\2022';
color: ${({ theme }): string => theme.primaryColor};
color: ${({ theme }: ThemeProps): string => theme.primaryColor};
font-size: 30px;
font-weight: bold;
margin-right: 10px;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
@@ -27,10 +29,10 @@ export default styled(Menu)`
right: 0;
margin-top: 90px;
padding: 16px 0;
background: ${({ theme }): string => theme.popupBackground};
background: ${({ theme }: ThemeProps): string => theme.popupBackground};
border-radius: 4px;
border: 1px solid ${({ theme }): string => theme.boxBorderColor};
border: 1px solid ${({ theme }: ThemeProps): string => theme.boxBorderColor};
box-sizing: border-box;
box-shadow: 0 0 32px ${({ theme }): string => theme.boxShadow};
box-shadow: 0 0 32px ${({ theme }: ThemeProps): string => theme.boxShadow};
z-index: 1;
`;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import styled from 'styled-components';
import React, { MouseEventHandler } from 'react';
import TextAreaWithLabel from './TextAreaWithLabel';
@@ -35,13 +37,13 @@ const MnemonicText = styled(TextAreaWithLabel).attrs(() => ({
label: 'Generated 12-word mnemonic seed:'
}))`
textarea {
font-size: ${({ theme }): string => theme.fontSize};
line-height: ${({ theme }): string => theme.lineHeight};
font-size: ${({ theme }: ThemeProps): string => theme.fontSize};
line-height: ${({ theme }: ThemeProps): string => theme.lineHeight};
height: unset;
letter-spacing: -0.01em;
padding: 14px;
margin-bottom: 10px;
color: ${({ theme }): string => theme.primaryColor};
color: ${({ theme }: ThemeProps): string => theme.primaryColor};
}
`;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
@@ -28,5 +30,5 @@ const ArrowRight = styled(Svg).attrs(() => ({
height: 12px;
margin: 4px 1px 0 0;
transform: rotate(180deg);
background: ${({ theme }): string => theme.buttonTextColor};
background: ${({ theme }: ThemeProps): string => theme.buttonTextColor};
`;
+3 -1
View File
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import styled from 'styled-components';
interface Props {
@@ -12,5 +14,5 @@ export default styled.span<Props>`
display: block;
mask: ${({ src }): string => `url(${src})`};
mask-size: cover;
background: ${({ theme }): string => theme.textColor};
background: ${({ theme }: ThemeProps): string => theme.textColor};
`;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React, { useCallback } from 'react';
import styled from 'styled-components';
@@ -15,7 +17,7 @@ interface Props {
function Switch ({ checked, checkedLabel, className, onChange, uncheckedLabel }: Props): React.ReactElement<Props> {
const _onChange = useCallback(
(event) => onChange(event.target.checked),
(event: React.ChangeEvent<HTMLInputElement>) => onChange(event.target.checked),
[onChange]
);
@@ -41,10 +43,10 @@ const Slider = styled.span`
left: 0;
right: 0;
bottom: 0;
background-color: ${({ theme }): string => theme.readonlyInputBackground};
background-color: ${({ theme }: ThemeProps): string => theme.readonlyInputBackground};
transition: 0.2s;
border-radius: 100px;
border: 1px solid ${({ theme }): string => theme.inputBorderColor};
border: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
&:before {
position: absolute;
@@ -53,7 +55,7 @@ const Slider = styled.span`
width: 16px;
left: 4px;
bottom: 3px;
background-color: ${({ theme }): string => theme.primaryColor};
background-color: ${({ theme }: ThemeProps): string => theme.primaryColor};
transition: 0.4s;
border-radius: 50%;
}
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
@@ -11,9 +13,9 @@ interface Props {
isFull?: boolean;
}
function Table ({ children, className, isFull }: Props): React.ReactElement<Props> {
function Table ({ children, className = '', isFull }: Props): React.ReactElement<Props> {
return (
<table className={`${className} ${isFull && 'isFull'}`}>
<table className={`${className} ${isFull ? 'isFull' : ''}`}>
<tbody>
{children}
</tbody>
@@ -24,8 +26,8 @@ function Table ({ children, className, isFull }: Props): React.ReactElement<Prop
export default React.memo(styled(Table)`
border: 0;
display: block;
font-size: ${({ theme }): string => theme.labelFontSize};
line-height: ${({ theme }): string => theme.labelLineHeight};
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps): string => theme.labelLineHeight};
margin-bottom: 1rem;
&.isFull {
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import styled, { css } from 'styled-components';
interface Props {
@@ -9,25 +11,25 @@ interface Props {
}
const DefaultTextInputColors = css`
background: ${({ theme }): string => theme.inputBackground};
border-color: ${({ theme }): string => theme.inputBorderColor};
color: ${({ theme }): string => theme.textColor};
background: ${({ theme }: ThemeProps): string => theme.inputBackground};
border-color: ${({ theme }: ThemeProps): string => theme.inputBorderColor};
color: ${({ theme }: ThemeProps): string => theme.textColor};
`;
const ErroredTextInputColors = css`
background: ${({ theme }): string => theme.inputBackground};
border-color: ${({ theme }): string => theme.errorBorderColor};
color: ${({ theme }): string => theme.errorColor};
background: ${({ theme }: ThemeProps): string => theme.inputBackground};
border-color: ${({ theme }: ThemeProps): string => theme.errorBorderColor};
color: ${({ theme }: ThemeProps): string => theme.errorColor};
`;
const TextInput = css<Props>`
border-radius: ${({ theme }): string => theme.borderRadius};
border: ${({ theme }): string => `1px solid ${theme.inputBorderColor}`};
border-radius: ${({ theme }: ThemeProps): string => theme.borderRadius};
border: ${({ theme }: ThemeProps): string => `1px solid ${theme.inputBorderColor}`};
outline: none;
box-sizing: border-box;
display: block;
font-family: ${({ theme }): string => theme.fontFamily};
font-size: ${({ theme }): string => theme.fontSize};
font-family: ${({ theme }: ThemeProps): string => theme.fontFamily};
font-size: ${({ theme }: ThemeProps): string => theme.fontSize};
font-weight: 600;
height: 40px;
padding: 0.5rem 0.75rem;
@@ -36,7 +38,7 @@ const TextInput = css<Props>`
${({ withError }): typeof ErroredTextInputColors => (withError ? ErroredTextInputColors : DefaultTextInputColors)};
&:read-only {
background: ${({ theme }): string => theme.readonlyInputBackground};
background: ${({ theme }: ThemeProps): string => theme.readonlyInputBackground};
box-shadow: none;
outline: none;
}
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import styled from 'styled-components';
export default styled.div`
@@ -13,6 +15,6 @@ export default styled.div`
line-height: 14px;
letter-spacing: 0.04em;
text-transform: uppercase;
color: ${({ theme }): string => theme.textColor};
color: ${({ theme }: ThemeProps): string => theme.textColor};
opacity: 0.65;
`;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../../types';
import React from 'react';
import styled from 'styled-components';
@@ -30,6 +32,6 @@ export default styled(Toast)<{visible: boolean}>`
&& {
margin: auto;
border-radius: 25px;
background: ${({ theme }): string => theme.highlightedAreaBackground};
background: ${({ theme }: ThemeProps): string => theme.highlightedAreaBackground};
}
`;
@@ -2,9 +2,11 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import React, { useState, useEffect } from 'react';
import { ThemeProps } from '../types';
import React, { useState, useEffect } from 'react';
import styled from 'styled-components';
import { Result, Validator } from '../validators';
interface BasicProps {
@@ -21,7 +23,7 @@ type Props<T extends BasicProps> = T & {
defaultValue?: string;
}
function ValidatedInput<T extends object> ({ className, component: Input, defaultValue, onValidatedChange, validator, ...props }: Props<T>): React.ReactElement<Props<T>> {
function ValidatedInput<T extends Record<string, unknown>> ({ className, component: Input, defaultValue, onValidatedChange, validator, ...props }: Props<T>): React.ReactElement<Props<T>> {
const [value, setValue] = useState(defaultValue || '');
const [wasMounted, setWasMounted] = useState(false);
const [validationResult, setValidationResult] = useState<Result<string>>(Result.ok(''));
@@ -31,6 +33,7 @@ function ValidatedInput<T extends object> ({ className, component: Input, defaul
setWasMounted(true);
}
// eslint-disable-next-line @typescript-eslint/no-floating-promises
(async (): Promise<void> => {
const result = await validator(value);
@@ -43,7 +46,7 @@ function ValidatedInput<T extends object> ({ className, component: Input, defaul
return (
<div className={className}>
<Input
{...props as T}
{...props as unknown as T}
isError={Result.isError(validationResult)}
onChange={setValue}
value={value}
@@ -56,9 +59,9 @@ function ValidatedInput<T extends object> ({ className, component: Input, defaul
const ErrorMessage = styled.span`
display: block;
margin-top: -10px;
font-size: ${({ theme }): string => theme.labelFontSize};
line-height: ${({ theme }): string => theme.labelLineHeight};
color: ${({ theme }): string => theme.errorColor};
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps): string => theme.labelLineHeight};
color: ${({ theme }: ThemeProps): string => theme.errorColor};
`;
ErrorMessage.displayName = 'ErrorMessage';
+13 -9
View File
@@ -2,9 +2,13 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React, { useState } from 'react';
import styled, { ThemeProvider, createGlobalStyle } from 'styled-components';
import { AvailableThemes, chooseTheme, themes, ThemeSwitchContext, Theme } from '.';
// FIXME We should not import from index when this one is imported there as well
import { AvailableThemes, chooseTheme, themes, ThemeSwitchContext } from '.';
interface Props {
children: React.ReactNode;
@@ -32,9 +36,9 @@ function View ({ children, className }: Props): React.ReactElement<Props> {
);
}
const BodyTheme = createGlobalStyle<{ theme: Theme }>`
const BodyTheme = createGlobalStyle<ThemeProps>`
body {
background-color: ${({ theme }): string => theme.bodyColor};
background-color: ${({ theme }: ThemeProps): string => theme.bodyColor};
}
html {
@@ -50,14 +54,14 @@ const Main = styled.main`
display: flex;
flex-direction: column;
height: 100%;
background: ${({ theme }): string => theme.background};
color: ${({ theme }): string => theme.textColor};
font-size: ${({ theme }): string => theme.fontSize};
line-height: ${({ theme }): string => theme.lineHeight};
border: 1px solid ${({ theme }): string => theme.inputBorderColor};
background: ${({ theme }: ThemeProps): string => theme.background};
color: ${({ theme }: ThemeProps): string => theme.textColor};
font-size: ${({ theme }: ThemeProps): string => theme.fontSize};
line-height: ${({ theme }: ThemeProps): string => theme.lineHeight};
border: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
* {
font-family: ${({ theme }): string => theme.fontFamily};
font-family: ${({ theme }: ThemeProps): string => theme.fontFamily};
}
> * {
@@ -2,45 +2,46 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
import WarningImageSrc from '../assets/warning.svg';
import Svg from '@polkadot/extension-ui/components/Svg';
interface Props {
import warningImageSrc from '../assets/warning.svg';
import Svg from './Svg';
interface Props extends ThemeProps {
children: React.ReactNode;
danger?: boolean;
className?: string;
}
function Warning ({ children, className, danger }: Props): React.ReactElement<Props> {
function Warning ({ children, className }: Props): React.ReactElement<Props> {
return (
<div className={className}>
<div>
<WarningImage
danger={danger}
src={WarningImageSrc}
<Svg
className='warningImage'
src={warningImageSrc}
/>
</div>
<div>
{children}
</div>
<div>{children}</div>
</div>
);
}
const WarningImage = styled(Svg)<Pick<Props, 'danger'>>`
width: 16px;
height: 14px;
margin: 5px 10px 5px 0;
background: ${({ danger, theme }): string => danger ? theme.iconDangerColor : theme.iconWarningColor};
`;
export default styled(Warning)`
export default React.memo(styled(Warning)`
display: flex;
flex-direction: row;
padding-left: ${({ danger }): string => danger ? '18px' : ''};
color: ${({ theme }): string => theme.subTextColor};
color: ${({ theme }: Props): string => theme.subTextColor};
margin-right: 20px;
border-left: ${({ danger, theme }): string => danger ? `0.25rem solid ${theme.buttonBackgroundDanger}` : ''};
`;
border-left: ${({ danger, theme }: Props): string => danger ? `0.25rem solid ${theme.buttonBackgroundDanger}` : ''};
.warningImage {
width: 16px;
height: 14px;
margin: 5px 10px 5px 0;
background: ${({ danger, theme }: Props): string => danger ? theme.iconDangerColor : theme.iconWarningColor};
}
`);
@@ -76,12 +76,14 @@ export function chooseTheme (): AvailableThemes {
const preferredTheme = localStorage.getItem('theme');
if (preferredTheme) {
return preferredTheme === 'dark' ? 'dark' : 'light';
return preferredTheme === 'dark'
? 'dark'
: 'light';
}
const isLightColorSchemePreferred = window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches;
return isLightColorSchemePreferred ? 'light' : 'dark';
return window.matchMedia && window.matchMedia('(prefers-color-scheme: light)').matches
? 'light'
: 'dark';
}
export declare type Theme = typeof darkTheme;
@@ -12,7 +12,7 @@ export default function useMetadata (genesisHash?: string | null): Chain | null
const [chain, setChain] = useState<Chain | null>(null);
useEffect((): void => {
getMetadata(genesisHash).then(setChain);
getMetadata(genesisHash).then(setChain).catch(console.error);
}, [genesisHash]);
return chain;
+1 -1
View File
@@ -17,7 +17,7 @@ describe('messaging sends message to background via extension port for', () => {
const callback = jest.fn();
chrome.runtime.connect().onMessage.addListener(callback);
exportAccount('HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5', 'passw0rd');
exportAccount('HjoBp62cvsWDA3vtNMWxz6c9q13ReEHi9UGHK7JbZweH5g5', 'passw0rd').catch(console.error);
expect(callback).toHaveBeenCalledWith(
expect.objectContaining({
+4 -3
View File
@@ -2,6 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Message } from '@polkadot/extension-base/types';
import { AccountJson, AuthorizeRequest, SigningRequest, RequestTypes, MessageTypes, ResponseTypes, SeedLengths, SubscriptionMessageTypes, MetadataRequest, MessageTypesWithNullRequest, MessageTypesWithNoSubscriptions, MessageTypesWithSubscriptions, ResponseDeriveValidate } from '@polkadot/extension-base/background/types';
import { Chain } from '@polkadot/extension-chains/types';
import { KeypairType } from '@polkadot/util-crypto/types';
@@ -25,7 +26,7 @@ const handlers: Handlers = {};
let idCounter = 0;
// setup a listener for messages, any incoming resolves the promise
port.onMessage.addListener((data): void => {
port.onMessage.addListener((data: Message['data']): void => {
const handler = handlers[data.id];
if (!handler) {
@@ -39,6 +40,7 @@ port.onMessage.addListener((data): void => {
}
if (data.subscription) {
// eslint-disable-next-line @typescript-eslint/ban-types
(handler.subscriber as Function)(data.subscription);
} else if (data.error) {
handler.reject(new Error(data.error));
@@ -50,8 +52,7 @@ port.onMessage.addListener((data): void => {
function sendMessage<TMessageType extends MessageTypesWithNullRequest>(message: TMessageType): Promise<ResponseTypes[TMessageType]>;
function sendMessage<TMessageType extends MessageTypesWithNoSubscriptions>(message: TMessageType, request: RequestTypes[TMessageType]): Promise<ResponseTypes[TMessageType]>;
function sendMessage<TMessageType extends MessageTypesWithSubscriptions>(message: TMessageType, request: RequestTypes[TMessageType], subscriber: (data: SubscriptionMessageTypes[TMessageType]) => void): Promise<ResponseTypes[TMessageType]>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function sendMessage<TMessageType extends MessageTypes> (message: TMessageType, request?: RequestTypes[TMessageType], subscriber?: (data: any) => void): Promise<ResponseTypes[TMessageType]> {
function sendMessage<TMessageType extends MessageTypes> (message: TMessageType, request?: RequestTypes[TMessageType], subscriber?: (data: unknown) => void): Promise<ResponseTypes[TMessageType]> {
return new Promise((resolve, reject): void => {
const id = `${Date.now()}.${++idCounter}`;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React, { useCallback, useContext } from 'react';
import styled from 'styled-components';
@@ -43,7 +45,7 @@ const TipText = styled.p`
font-size: 16px;
line-height: 26px;
margin: 0 30px;
color: ${({ theme }): string => theme.subTextColor};
color: ${({ theme }: ThemeProps): string => theme.subTextColor};
`;
const Image = styled.div`
@@ -52,11 +54,11 @@ const Image = styled.div`
`;
export default styled(AddAccount)`
color: ${({ theme }): string => theme.textColor};
color: ${({ theme }: ThemeProps): string => theme.textColor};
height: 100%;
h3 {
color: ${({ theme }): string => theme.textColor};
color: ${({ theme }: ThemeProps): string => theme.textColor};
margin-top: 0;
font-weight: normal;
font-size: 24px;
@@ -8,10 +8,12 @@
/* eslint-disable react/jsx-sort-props */
/* eslint-disable react/jsx-max-props-per-line */
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
interface Props {
interface Props extends ThemeProps {
className?: string;
onClick: () => void;
}
@@ -73,11 +75,11 @@ export default styled(AddAccountImage)`
}
path {
fill: ${({ theme }): string => theme.textColor};
fill: ${({ theme }: Props): string => theme.textColor};
}
& > g > circle {
stroke: ${({ theme }): string => theme.inputBorderColor};
fill: ${({ theme }): string => theme.addAccountImageBackground};
stroke: ${({ theme }: Props): string => theme.inputBorderColor};
fill: ${({ theme }: Props): string => theme.addAccountImageBackground};
}
`;
+7 -5
View File
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React from 'react';
import styled from 'styled-components';
@@ -28,22 +30,22 @@ const ArrowLeft = styled(Svg).attrs(() => ({ src: ArrowLeftImage }))`
width: 12px;
height: 12px;
margin-right: 13px;
background: ${({ theme }): string => theme.labelColor};
background: ${({ theme }: ThemeProps) => theme.labelColor};
`;
const BackLink = styled(Link)`
width: min-content;
text-decoration: underline;
color: ${({ theme }): string => theme.labelColor};
color: ${({ theme }: ThemeProps) => theme.labelColor};
&:visited {
color: ${({ theme }): string => theme.labelColor};
color: ${({ theme }: ThemeProps) => theme.labelColor};
}
`;
export default styled(Back)`
margin: 0;
line-height: 52px;
border-bottom: 1px solid ${({ theme }): string => theme.inputBorderColor};
font-size: ${({ theme }): string => theme.labelFontSize};
border-bottom: 1px solid ${({ theme }: ThemeProps): string => theme.inputBorderColor};
font-size: ${({ theme }: ThemeProps): string => theme.labelFontSize};
`;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React, { useCallback, useState } from 'react';
import styled from 'styled-components';
@@ -90,7 +92,7 @@ const LockIcon = styled(Svg).attrs(() => ({
}))`
width: 11px;
height: 14px;
background: ${({ theme }): string => theme.iconNeutralColor};
background: ${({ theme }: ThemeProps) => theme.iconNeutralColor};
`;
const UnlockIcon = styled(Svg).attrs(() => ({
@@ -98,7 +100,7 @@ const UnlockIcon = styled(Svg).attrs(() => ({
}))`
width: 11px;
height: 14px;
background: ${({ theme }): string => theme.iconNeutralColor};
background: ${({ theme }: ThemeProps) => theme.iconNeutralColor};
`;
const LockButton = styled(Button)`
@@ -18,6 +18,7 @@ configure({ adapter: new Adapter() });
describe('Header component', () => {
let wrapper: ReactWrapper;
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
const mountHeader = (props: React.ComponentProps<typeof Header> = {}): ReactWrapper => mount(
<MemoryRouter>
<ThemeProvider theme={themes.dark}>
+13 -15
View File
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React, { useCallback, useRef, useState } from 'react';
import styled from 'styled-components';
@@ -62,28 +64,26 @@ function Header ({ children, className, showBackArrow, showSettings, text }: Pro
const BackLink = styled(Link)`
width: min-content;
text-decoration: underline;
color: ${({ theme }): string => theme.labelColor};
color: ${({ theme }: ThemeProps) => theme.labelColor};
min-height: 52px;
&:visited {
color: ${({ theme }): string => theme.labelColor};
color: ${({ theme }: ThemeProps) => theme.labelColor};
}
`;
const ArrowLeft = styled(Svg).attrs(() => ({
src: ArrowLeftImage
}))`
const ArrowLeft = styled(Svg).attrs(() => ({ src: ArrowLeftImage }))`
width: 12px;
height: 12px;
margin-right: 13px;
background: ${({ theme }): string => theme.labelColor};
background: ${({ theme }: ThemeProps) => theme.labelColor};
`;
const Container = styled.div`
display: flex;
justify-content: space-between;
width: 100%;
border-bottom: 1px solid ${({ theme }): string => theme.inputBorderColor};
border-bottom: 1px solid ${({ theme }: ThemeProps) => theme.inputBorderColor};
min-height: 70px;
`;
@@ -91,8 +91,8 @@ const Branding = styled.div`
display: flex;
justify-content: center;
align-items: center;
color: ${({ theme }): string => theme.labelColor};
font-family: ${({ theme }): string => theme.fontFamily};
color: ${({ theme }: ThemeProps) => theme.labelColor};
font-family: ${({ theme }: ThemeProps) => theme.fontFamily};
text-align: center;
margin-left: 24px;
`;
@@ -107,21 +107,19 @@ interface GearProps {
isSelected: boolean;
}
const Gear = styled(Svg).attrs(() => ({
src: gear
}))<GearProps>`
const Gear = styled(Svg).attrs(() => ({ src: gear }))<GearProps>`
height: 18px;
width: 18px;
margin-right: 24px;
align-self: center;
background: ${({ isSelected, theme }): string => isSelected ? theme.primaryColor : theme.iconNeutralColor};
background: ${({ isSelected, theme }: ThemeProps & GearProps): string => isSelected ? theme.primaryColor : theme.iconNeutralColor};
`;
Gear.displayName = 'Gear';
const LogoText = styled.span`
color: ${({ theme }): string => theme.textColor};
font-family: ${({ theme }): string => theme.fontFamily};
color: ${({ theme }: ThemeProps) => theme.textColor};
font-family: ${({ theme }: ThemeProps) => theme.fontFamily};
font-size: 20px;
line-height: 27px;
`;
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { ThemeProps } from '../types';
import React, { useCallback, useContext } from 'react';
import styled from 'styled-components';
@@ -46,15 +48,15 @@ const CreationSteps = styled.div`
`;
const CurrentStep = styled.span`
font-size: ${({ theme }): string => theme.labelFontSize};
line-height: ${({ theme }): string => theme.labelLineHeight};
color: ${({ theme }): string => theme.primaryColor};
font-size: ${({ theme }: ThemeProps) => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps) => theme.labelLineHeight};
color: ${({ theme }: ThemeProps) => theme.primaryColor};
font-weight: 600;
`;
const TotalSteps = styled.span`
font-size: ${({ theme }): string => theme.labelFontSize};
line-height: ${({ theme }): string => theme.labelLineHeight};
color: ${({ theme }): string => theme.textColor};
font-size: ${({ theme }: ThemeProps) => theme.labelFontSize};
line-height: ${({ theme }: ThemeProps) => theme.labelLineHeight};
color: ${({ theme }: ThemeProps) => theme.textColor};
font-weight: 600;
`;
+38 -23
View File
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Theme, ThemeProps } from '../types';
import React, { useCallback, useContext, useState, useEffect } from 'react';
import styled, { ThemeContext } from 'styled-components';
import { setSS58Format } from '@polkadot/util-crypto';
@@ -16,6 +18,11 @@ interface Option {
value: string;
}
interface Props extends ThemeProps {
className?: string;
reference: React.MutableRefObject<null>;
}
const isPopup = window.innerWidth <= 480;
const prefixOptions = settings.availablePrefixes.map(({ text, value }): Option => ({
text: value === -1
@@ -24,10 +31,10 @@ const prefixOptions = settings.availablePrefixes.map(({ text, value }): Option =
value: `${value}`
}));
export default function Settings ({ reference }: { reference: React.MutableRefObject<null> }): React.ReactElement {
function Settings ({ className, reference }: Props): React.ReactElement<Props> {
const [camera, setCamera] = useState(settings.camera === 'on');
const [prefix, setPrefix] = useState(`${settings.prefix}`);
const themeContext = useContext(ThemeContext);
const themeContext = useContext<Theme>(ThemeContext);
const setTheme = useContext(ThemeSwitchContext);
useEffect(() => {
@@ -56,7 +63,10 @@ export default function Settings ({ reference }: { reference: React.MutableRefOb
);
return (
<SettingsMenu reference={reference}>
<Menu
className={className}
reference={reference}
>
<Setting>
<SettingTitle>Theme</SettingTitle>
<Switch
@@ -92,28 +102,22 @@ export default function Settings ({ reference }: { reference: React.MutableRefOb
/>
</Setting>
)}
</SettingsMenu>
</Menu>
);
}
const SettingsMenu = styled(Menu)`
margin-top: 56px;
right: 24px;
user-select: none;
`;
const CheckboxSetting = styled(Checkbox)`
font-size: 15px;
font-weight: 600;
line-height: 20px;
color: ${({ theme }): string => theme.textColor};
color: ${({ theme }: ThemeProps) => theme.textColor};
label {
color: ${({ theme }): string => theme.textColor};
color: ${({ theme }: ThemeProps) => theme.textColor};
}
`;
const DropdownSetting = styled(Dropdown)`
background: ${({ theme }): string => theme.background};
background: ${({ theme }: ThemeProps) => theme.background};
margin-top: 9px;
margin-bottom: 12px;
width : 100%;
@@ -125,27 +129,38 @@ const SettingTitle = styled(Title)`
`;
const Setting = styled.div`
padding: 0 16px;
max-width: 100%;
& + & {
padding-top: 18px;
border-top: 1px solid ${({ theme }): string => theme.inputBorderColor};
}
`;
const OpenInNewWindowButton = styled(ActionText)`
span {
color: ${({ theme }): string => theme.textColor};
color: ${({ theme }: ThemeProps) => theme.textColor};
text-decoration: none;
font-weight: 600;
font-size: ${({ theme }): string => theme.fontSize};
line-height: ${({ theme }): string => theme.lineHeight};
font-size: ${({ theme }: ThemeProps) => theme.fontSize};
line-height: ${({ theme }: ThemeProps) => theme.lineHeight};
}
${Svg} {
width: 20px;
height: 20px;
top: 4px;
background: ${({ theme }): string => theme.textColor};
background: ${({ theme }: ThemeProps) => theme.textColor};
}
`;
export default React.memo(styled(Settings)`
margin-top: 56px;
right: 24px;
user-select: none;
.setting {
padding: 0 16px;
max-width: 100%;
& + & {
padding-top: 18px;
border-top: 1px solid ${({ theme }: Props): string => theme.inputBorderColor};
}
}
`);
+11
View File
@@ -0,0 +1,11 @@
// Copyright 2019-2020 @polkadot/extension-ui authors & contributors
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Theme } from './components/themes';
export { Theme };
export interface ThemeProps {
theme: Theme;
}
+1 -1
View File
@@ -11,7 +11,7 @@
"@polkadot/extension-ui": "0.26.0-beta.2"
},
"devDependencies": {
"@polkadot/dev": "^0.53.5",
"@polkadot/dev": "^0.54.1",
"babel-loader": "^8.1.0",
"extract-loader": "^5.0.1",
"file-loader": "^6.0.0",
+3 -1
View File
@@ -2,6 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Message } from '@polkadot/extension-base/types';
import { PORT_CONTENT } from '@polkadot/extension-base/defaults';
import chrome from '@polkadot/extension-inject/chrome';
@@ -14,7 +16,7 @@ port.onMessage.addListener((data): void => {
});
// all messages from the page, pass them to the extension
window.addEventListener('message', ({ data, source }): void => {
window.addEventListener('message', ({ data, source }: Message): void => {
// only allow messages from our window, by the inject
if (source !== window || data.origin !== 'page') {
return;
+5 -2
View File
@@ -2,18 +2,21 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { Message } from '@polkadot/extension-base/types';
import { enable, handleResponse } from '@polkadot/extension-base/page';
import { injectExtension } from '@polkadot/extension-inject';
// setup a response listener (events created by the loader for extension responses)
window.addEventListener('message', ({ data, source }): void => {
window.addEventListener('message', ({ data, source }: Message): void => {
// only allow messages from our window, by the loader
if (source !== window || data.origin !== 'content') {
return;
}
if (data.id) {
handleResponse(data);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
handleResponse(data as any);
} else {
console.error('Missing id for response.');
}
-1
View File
@@ -61,7 +61,6 @@ function createWebpack ({ alias = {}, context }) {
]
},
node: {
// eslint-disable-next-line @typescript-eslint/camelcase
child_process: 'empty',
dgram: 'empty',
fs: 'empty',
+457 -366
View File
File diff suppressed because it is too large Load Diff