Bumps w/ eslint (#338)
* Bumps w/ eslint * Additional * Additional * Additional * Additional * Additional * Linting done, tsc fixes remain * Final round
This commit is contained in:
+5
-5
@@ -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
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
})
|
||||
);
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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}>
|
||||
|
||||
@@ -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('/');
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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};
|
||||
`;
|
||||
|
||||
@@ -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};
|
||||
`;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
`;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -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}>
|
||||
|
||||
@@ -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;
|
||||
`;
|
||||
|
||||
@@ -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};
|
||||
}
|
||||
}
|
||||
`);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.');
|
||||
}
|
||||
|
||||
@@ -61,7 +61,6 @@ function createWebpack ({ alias = {}, context }) {
|
||||
]
|
||||
},
|
||||
node: {
|
||||
// eslint-disable-next-line @typescript-eslint/camelcase
|
||||
child_process: 'empty',
|
||||
dgram: 'empty',
|
||||
fs: 'empty',
|
||||
|
||||
Reference in New Issue
Block a user