From 5698323a118a60ddf0fa865ad4d687d4eb726a0c Mon Sep 17 00:00:00 2001 From: Jack Works Date: Tue, 7 Dec 2021 13:32:53 +0800 Subject: [PATCH 01/28] feat: add metadata reader API --- packages/plugin-infra/src/types.ts | 90 ++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index 3a63e94375b8..a65cfdd429c2 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -48,6 +48,7 @@ export declare namespace Plugin { Dashboard?: Loader /** Load the Worker part of the plugin. */ Worker?: Loader + ContextFree?: Loader } } /** @@ -203,6 +204,8 @@ export namespace Plugin.SNSAdaptor { ToolbarEntry?: ToolbarEntry /** This UI will be rendered as an entry in the wallet status dialog */ ApplicationEntry?: ApplicationEntry + /** Plugin DO NOT need to define this. This will be auto set by the plugin host. */ + __contextFree__?: ContextFree.DefinitionDeferred } //#region Composition entry /** @@ -317,6 +320,8 @@ export namespace Plugin.Dashboard { Web3UI?: Web3Plugin.UI.UI /** This is the context of the currently chosen network. */ Web3State?: Web3Plugin.ObjectCapabilities.Capabilities + /** Plugin DO NOT need to define this. This will be auto set by the plugin host. */ + __contextFree__?: ContextFree.DefinitionDeferred } } @@ -427,6 +432,90 @@ export namespace Plugin.Worker { } } +/** This part defines the plugin part that does not context aware. */ +export namespace Plugin.ContextFree { + export interface DefinitionDeferred { + /** + * Render metadata in many different environments. + * + * 1. Environment + * + * The render component MUST NOT assume they are running in a specific environment (e.g. SNS Adaptor). + * Plugin messages and RPC MAY NOT working. + * + * It MUST NOT assume the environment using the `context` props. + * ALL actions MUST BE DONE with the given props. + * + * Here is some example of *possible* environments. + * - inside SNS Adaptor, given "composition" context, running in the CompositionDialog. + * - inside SNS Adaptor, given "post" context, running in the DecryptedPost. + * - inside Dashboard, given "post" context, running in the PostHistory as the previewer. + * - inside Popups, given "post" context, running in the PostInspector (Isolated mode). + * - on mask.io, given "post" context, allowing preview the message without extension installed. + * + * 2. Contexts + * + * The render component might be used in many different contexts. + * + * - "composition" context, the render should be editable, but not interactive (e.g. allow vote). + * - "post" context, the render should be readonly, but interactive. + * + * 3. Actions + * + * The render component MUST BE a ForwardRefExotic React Component + * that support operations defined in `Plugin.ContextFree.MetadataRender.RenderActions` + */ + metadataRender: MetadataRender.StaticRender | MetadataRender.DynamicRender + } + + export namespace MetadataRender { + export type MetadataReader = (meta: TypedMessage['meta']) => Result + //#region Static render + // new Map([ [reader, react component] ]) + export type StaticRender = ReadonlyMap, StaticRenderComponent> + export type StaticRenderComponent = React.ForwardRefExoticComponent> + export type StaticRenderProps = Context & React.RefAttributes> & { metadata: T } + //#endregion + //#region DynamicRender + export type DynamicRender = React.ForwardRefExoticComponent + export type DynamicRenderProps = Context & + React.RefAttributes> & { metadata: TypedMessage['meta'] } + //#endregion + export type RenderActions = { + /** + * This action make the render into the edit state. + * It should report the result via onEditComplete() props. + * + * If this action does not exist, it will be rendered as non-editable. + */ + edit?(): void + /** + * This action make the render quit the edit state. + * If save is true, the render MUST report the new result via onEditComplete. + * + * If this action does not exist, the render should handle the save/cancel by themself. + */ + quitEdit?(save: boolean): void + } + export type Context = CompositionContext | DecryptedPostContext + /** This metadata render is called in a composition preview context. */ + export interface CompositionContext { + context: 'composition' + /** + * When edit() is called, this component should go into to editable state. + * If the edit completes, the new metadata will be used to replace the old one. + */ + onEditComplete(metaKey: string, replaceMeta: T): void + } + /** + * This metadat render is called in the decrypted post. + */ + export interface DecryptedPostContext { + context: 'post' + } + } +} + // Helper types export namespace Plugin { /** @@ -480,6 +569,7 @@ export enum CurrentSNSNetwork { Facebook = 1, Twitter = 2, Instagram = 3, + Minds = 4, } export interface Pagination { From 427032d3fcc2869cadb9c2aa7ce0dc6244e56b7e Mon Sep 17 00:00:00 2001 From: Jack Works Date: Wed, 18 Aug 2021 23:02:36 +0800 Subject: [PATCH 02/28] chore: add example --- packages/plugin-infra/src/types.ts | 4 ++-- packages/plugins/example/package.json | 3 ++- .../plugins/example/src/ContextFree/index.tsx | 18 ++++++++++++++++++ pnpm-lock.yaml | 2 ++ 4 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 packages/plugins/example/src/ContextFree/index.tsx diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index a65cfdd429c2..37b1c6f6d905 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -473,11 +473,11 @@ export namespace Plugin.ContextFree { //#region Static render // new Map([ [reader, react component] ]) export type StaticRender = ReadonlyMap, StaticRenderComponent> - export type StaticRenderComponent = React.ForwardRefExoticComponent> + export type StaticRenderComponent = Omit>, 'propTypes'> export type StaticRenderProps = Context & React.RefAttributes> & { metadata: T } //#endregion //#region DynamicRender - export type DynamicRender = React.ForwardRefExoticComponent + export type DynamicRender = Omit, 'propTypes'> export type DynamicRenderProps = Context & React.RefAttributes> & { metadata: TypedMessage['meta'] } //#endregion diff --git a/packages/plugins/example/package.json b/packages/plugins/example/package.json index 735809cc9a6e..a7ad9c01e469 100644 --- a/packages/plugins/example/package.json +++ b/packages/plugins/example/package.json @@ -4,6 +4,7 @@ "main": "./dist/index.js", "types": "./dist/index.d.ts", "dependencies": { - "@masknet/plugin-infra": "workspace:*" + "@masknet/plugin-infra": "workspace:*", + "ts-results": "^3.3.0" } } diff --git a/packages/plugins/example/src/ContextFree/index.tsx b/packages/plugins/example/src/ContextFree/index.tsx new file mode 100644 index 000000000000..1f248d189932 --- /dev/null +++ b/packages/plugins/example/src/ContextFree/index.tsx @@ -0,0 +1,18 @@ +import type { Plugin } from '@masknet/plugin-infra' +import { forwardRef, useImperativeHandle } from 'react' +import { Ok, Err } from 'ts-results' + +const metadataReader: Plugin.ContextFree.MetadataRender.MetadataReader = (meta) => { + const raw = meta?.get('io.mask.example/v1') + if (raw) return Ok(raw) + return Err.EMPTY +} +const render: Plugin.ContextFree.MetadataRender.StaticRenderComponent = forwardRef((props, ref) => { + useImperativeHandle(ref, () => ({}), []) + return <>Metadata render for key "io.mask.example/v1" {JSON.stringify(props.metadata)} +}) + +const contextFree: Plugin.ContextFree.DefinitionDeferred = { + metadataRender: new Map([[metadataReader, render]]), +} +export default contextFree diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f57c070647d7..bf7153113686 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -637,8 +637,10 @@ importers: packages/plugins/example: specifiers: '@masknet/plugin-infra': workspace:* + ts-results: ^3.3.0 dependencies: '@masknet/plugin-infra': link:../../plugin-infra + ts-results: 3.3.0 packages/polyfills: specifiers: From 3a734d56859340acd8bfad4de2e719089ed8daf0 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Sun, 26 Sep 2021 14:41:47 +0800 Subject: [PATCH 03/28] fix: typo --- packages/plugin-infra/src/types.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index 37b1c6f6d905..d65903ff3dda 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -493,7 +493,7 @@ export namespace Plugin.ContextFree { * This action make the render quit the edit state. * If save is true, the render MUST report the new result via onEditComplete. * - * If this action does not exist, the render should handle the save/cancel by themself. + * If this action does not exist, the render should handle the save/cancel by themselves. */ quitEdit?(save: boolean): void } @@ -508,7 +508,7 @@ export namespace Plugin.ContextFree { onEditComplete(metaKey: string, replaceMeta: T): void } /** - * This metadat render is called in the decrypted post. + * This metadata render is called in the decrypted post. */ export interface DecryptedPostContext { context: 'post' From 7679efc0fb60455c23b39f710d6078c45a380f6d Mon Sep 17 00:00:00 2001 From: Jack Works Date: Tue, 7 Dec 2021 13:51:58 +0800 Subject: [PATCH 04/28] chore: add contribution field --- packages/plugin-infra/src/types.ts | 21 +++++++++++++++---- .../plugins/example/src/ContextFree/index.tsx | 6 +++--- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index d65903ff3dda..1d0f12e04514 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -48,7 +48,8 @@ export declare namespace Plugin { Dashboard?: Loader /** Load the Worker part of the plugin. */ Worker?: Loader - ContextFree?: Loader + /** Load the General UI of the plugin. */ + GeneralUI?: Loader } } /** @@ -109,6 +110,12 @@ export namespace Plugin.Shared { declareWeb3Providers?: Web3Plugin.ProviderDescriptor[] /** Introduce application category information. */ declareApplicationCategories?: Web3Plugin.ApplicationCategoryDescriptor[] + /** + * Declare what this plugin provides. + * + * Declare this field properly so Mask Network can suggest your plugin when needed. + */ + contribution?: Contribution } /** * This part is shared between Dashboard, SNSAdaptor and Worker part @@ -178,6 +185,12 @@ export namespace Plugin.Shared { export type I18NKey = string export type I18NValue = string export type I18NResource = Record> + export interface Contribution { + /** This plugin can recognize and react to the following metadata keys. */ + metadataKeys?: ReadonlySet + /** This plugin can recognize and enhance the post that matches the following matchers. */ + postContent?: ReadonlySet + } } /** This part runs in the SNSAdaptor */ @@ -205,7 +218,7 @@ export namespace Plugin.SNSAdaptor { /** This UI will be rendered as an entry in the wallet status dialog */ ApplicationEntry?: ApplicationEntry /** Plugin DO NOT need to define this. This will be auto set by the plugin host. */ - __contextFree__?: ContextFree.DefinitionDeferred + __general_ui__?: GeneralUI.DefinitionDeferred } //#region Composition entry /** @@ -321,7 +334,7 @@ export namespace Plugin.Dashboard { /** This is the context of the currently chosen network. */ Web3State?: Web3Plugin.ObjectCapabilities.Capabilities /** Plugin DO NOT need to define this. This will be auto set by the plugin host. */ - __contextFree__?: ContextFree.DefinitionDeferred + __general_ui__?: GeneralUI.DefinitionDeferred } } @@ -433,7 +446,7 @@ export namespace Plugin.Worker { } /** This part defines the plugin part that does not context aware. */ -export namespace Plugin.ContextFree { +export namespace Plugin.GeneralUI { export interface DefinitionDeferred { /** * Render metadata in many different environments. diff --git a/packages/plugins/example/src/ContextFree/index.tsx b/packages/plugins/example/src/ContextFree/index.tsx index 1f248d189932..9f1a12119734 100644 --- a/packages/plugins/example/src/ContextFree/index.tsx +++ b/packages/plugins/example/src/ContextFree/index.tsx @@ -2,17 +2,17 @@ import type { Plugin } from '@masknet/plugin-infra' import { forwardRef, useImperativeHandle } from 'react' import { Ok, Err } from 'ts-results' -const metadataReader: Plugin.ContextFree.MetadataRender.MetadataReader = (meta) => { +const metadataReader: Plugin.GeneralUI.MetadataRender.MetadataReader = (meta) => { const raw = meta?.get('io.mask.example/v1') if (raw) return Ok(raw) return Err.EMPTY } -const render: Plugin.ContextFree.MetadataRender.StaticRenderComponent = forwardRef((props, ref) => { +const render: Plugin.GeneralUI.MetadataRender.StaticRenderComponent = forwardRef((props, ref) => { useImperativeHandle(ref, () => ({}), []) return <>Metadata render for key "io.mask.example/v1" {JSON.stringify(props.metadata)} }) -const contextFree: Plugin.ContextFree.DefinitionDeferred = { +const contextFree: Plugin.GeneralUI.DefinitionDeferred = { metadataRender: new Map([[metadataReader, render]]), } export default contextFree From 6f1bbbd3b32a712e5899a975af760f3e8bf04ca0 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Tue, 7 Dec 2021 14:07:55 +0800 Subject: [PATCH 05/28] chore: declare contributions for all plugin --- packages/mask/src/plugins/Collectible/base.ts | 6 ++++++ packages/mask/src/plugins/FileService/base.ts | 5 ++++- packages/mask/src/plugins/FindTruman/base.ts | 5 +++++ packages/mask/src/plugins/Furucombo/base.tsx | 3 +++ packages/mask/src/plugins/Gitcoin/base.ts | 1 + packages/mask/src/plugins/GoodGhosting/base.ts | 3 +++ packages/mask/src/plugins/ITO/base.ts | 3 ++- packages/mask/src/plugins/MaskBox/base.ts | 3 +++ packages/mask/src/plugins/Polls/base.ts | 3 ++- packages/mask/src/plugins/Polls/constants.ts | 4 ---- packages/mask/src/plugins/Polls/messages.ts | 6 +++--- packages/mask/src/plugins/PoolTogether/base.tsx | 3 ++- packages/mask/src/plugins/RedPacket/base.ts | 5 ++++- packages/mask/src/plugins/Snapshot/base.ts | 3 +++ packages/mask/src/plugins/UnlockProtocol/base.ts | 5 ++++- packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx | 7 +------ packages/mask/src/plugins/dHEDGE/base.tsx | 5 ++++- packages/mask/src/plugins/dHEDGE/constants.ts | 6 ++++++ 18 files changed, 56 insertions(+), 20 deletions(-) diff --git a/packages/mask/src/plugins/Collectible/base.ts b/packages/mask/src/plugins/Collectible/base.ts index 6ee46ee1b738..318d40596cd8 100644 --- a/packages/mask/src/plugins/Collectible/base.ts +++ b/packages/mask/src/plugins/Collectible/base.ts @@ -12,4 +12,10 @@ export const base: Plugin.Shared.Definition = { networks: { type: 'opt-out', networks: {} }, target: 'stable', }, + contribution: { + postContent: new Set([ + /opensea.io\/\/assets\/(0x[\dA-Fa-f]{40})\/(\d+)/, + /rarible.com\/\/token\/(0x[\dA-Fa-f]{40}):(\d+)/, + ]), + }, } diff --git a/packages/mask/src/plugins/FileService/base.ts b/packages/mask/src/plugins/FileService/base.ts index 8ae5ec60f326..f8cd0534d538 100644 --- a/packages/mask/src/plugins/FileService/base.ts +++ b/packages/mask/src/plugins/FileService/base.ts @@ -1,5 +1,5 @@ import type { Plugin } from '@masknet/plugin-infra' -import { FileServicePluginID } from './constants' +import { FileServicePluginID, META_KEY_1, META_KEY_2 } from './constants' export const base: Plugin.Shared.Definition = { ID: FileServicePluginID, @@ -12,4 +12,7 @@ export const base: Plugin.Shared.Definition = { networks: { type: 'opt-out', networks: {} }, target: 'stable', }, + contribution: { + metadataKeys: new Set([META_KEY_1, META_KEY_2]), + }, } diff --git a/packages/mask/src/plugins/FindTruman/base.ts b/packages/mask/src/plugins/FindTruman/base.ts index ab6da4427748..e18c8bc2cd13 100644 --- a/packages/mask/src/plugins/FindTruman/base.ts +++ b/packages/mask/src/plugins/FindTruman/base.ts @@ -14,4 +14,9 @@ export const base: Plugin.Shared.Definition = { networks: { type: 'opt-out', networks: {} }, target: 'stable', }, + contribution: { + postContent: new Set([ + /https:\/\/findtruman.io\/#\/(findtruman\/stories\/[\dA-Za-z]+(\/|\/(puzzles|polls|puzzle_result|poll_result)\/[\dA-Za-z]+\/?)?|encryption\?payload=.+)/, + ]), + }, } diff --git a/packages/mask/src/plugins/Furucombo/base.tsx b/packages/mask/src/plugins/Furucombo/base.tsx index 6371b0623a7d..f6043e6ee753 100644 --- a/packages/mask/src/plugins/Furucombo/base.tsx +++ b/packages/mask/src/plugins/Furucombo/base.tsx @@ -15,4 +15,7 @@ export const base: Plugin.Shared.Definition = { networks: { type: 'opt-out', networks: {} }, target: 'stable', }, + contribution: { + postContent: new Set([/https:\/\/furucombo.app\/invest\/(pool|farm)\/(137|1)\/(0x\w+)/]), + }, } diff --git a/packages/mask/src/plugins/Gitcoin/base.ts b/packages/mask/src/plugins/Gitcoin/base.ts index bcfcb5ea43db..351f388d12bd 100644 --- a/packages/mask/src/plugins/Gitcoin/base.ts +++ b/packages/mask/src/plugins/Gitcoin/base.ts @@ -18,4 +18,5 @@ export const base: Plugin.Shared.Definition = { }, }, }, + contribution: { postContent: new Set([/https:\/\/gitcoin.co\/grants\/\d+/]) }, } diff --git a/packages/mask/src/plugins/GoodGhosting/base.ts b/packages/mask/src/plugins/GoodGhosting/base.ts index 07d100412494..097f3dc73f56 100644 --- a/packages/mask/src/plugins/GoodGhosting/base.ts +++ b/packages/mask/src/plugins/GoodGhosting/base.ts @@ -12,4 +12,7 @@ export const base: Plugin.Shared.Definition = { networks: { type: 'opt-out', networks: {} }, target: 'stable', }, + contribution: { + postContent: new Set([/https:\/\/goodghosting.com/]), + }, } diff --git a/packages/mask/src/plugins/ITO/base.ts b/packages/mask/src/plugins/ITO/base.ts index 9f5031e9d21b..819600954a46 100644 --- a/packages/mask/src/plugins/ITO/base.ts +++ b/packages/mask/src/plugins/ITO/base.ts @@ -1,6 +1,6 @@ import { NetworkPluginID, Plugin } from '@masknet/plugin-infra' import { ChainId } from '@masknet/web3-shared-evm' -import { ITO_PluginID } from './constants' +import { ITO_MetaKey_1, ITO_MetaKey_2, ITO_PluginID } from './constants' export const base: Plugin.Shared.Definition = { ID: ITO_PluginID, @@ -27,4 +27,5 @@ export const base: Plugin.Shared.Definition = { }, }, }, + contribution: { metadataKeys: new Set([ITO_MetaKey_1, ITO_MetaKey_2]) }, } diff --git a/packages/mask/src/plugins/MaskBox/base.ts b/packages/mask/src/plugins/MaskBox/base.ts index 8e48afc090d6..7f70087a198f 100644 --- a/packages/mask/src/plugins/MaskBox/base.ts +++ b/packages/mask/src/plugins/MaskBox/base.ts @@ -15,4 +15,7 @@ export const base: Plugin.Shared.Definition = { }, experimentalMark: true, i18n: languages, + contribution: { + postContent: new Set(['https://box-beta.mask.io', 'https://box.mask.io']), + }, } diff --git a/packages/mask/src/plugins/Polls/base.ts b/packages/mask/src/plugins/Polls/base.ts index b3fca3c7e1b7..75b781cde8d3 100644 --- a/packages/mask/src/plugins/Polls/base.ts +++ b/packages/mask/src/plugins/Polls/base.ts @@ -1,5 +1,5 @@ import type { Plugin } from '@masknet/plugin-infra' -import { PLUGIN_ID, PLUGIN_ICON, PLUGIN_NAME, PLUGIN_DESCRIPTION } from './constants' +import { PLUGIN_ID, PLUGIN_ICON, PLUGIN_NAME, PLUGIN_DESCRIPTION, POLL_META_KEY_1 } from './constants' export const base: Plugin.Shared.Definition = { ID: PLUGIN_ID, @@ -13,4 +13,5 @@ export const base: Plugin.Shared.Definition = { target: 'insider', }, experimentalMark: true, + contribution: { metadataKeys: new Set([POLL_META_KEY_1]) }, } diff --git a/packages/mask/src/plugins/Polls/constants.ts b/packages/mask/src/plugins/Polls/constants.ts index aa4fe5b5b417..04f6c53e58e2 100644 --- a/packages/mask/src/plugins/Polls/constants.ts +++ b/packages/mask/src/plugins/Polls/constants.ts @@ -1,9 +1,5 @@ -export const pluginName = 'Poll' -export const identifier = 'com.maskbook.poll' export const POLL_META_KEY_1 = 'com.maskbook.poll:1' export const PollGunServer = 'com.maskbook.plugin.polls' - -export const PLUGIN_META_KEY = 'com.maskbook.poll:1' export const PLUGIN_ID = 'com.maskbook.poll' export const PLUGIN_NAME = 'Poll' export const PLUGIN_ICON = '🗳️' diff --git a/packages/mask/src/plugins/Polls/messages.ts b/packages/mask/src/plugins/Polls/messages.ts index 428188f732a5..df7a81e69a19 100644 --- a/packages/mask/src/plugins/Polls/messages.ts +++ b/packages/mask/src/plugins/Polls/messages.ts @@ -1,12 +1,12 @@ -import { identifier } from './constants' +import { PLUGIN_ID } from './constants' import { createPluginMessage, createPluginRPC } from '@masknet/plugin-infra' import { OnDemandWorker } from '../../web-workers/OnDemandWorker' import { AsyncCall, _AsyncVersionOf } from 'async-call-rpc' import { WorkerChannel } from 'async-call-rpc/utils/web/worker' -const PollMessage = createPluginMessage(identifier) +const PollMessage = createPluginMessage(PLUGIN_ID) export const PluginPollRPC: _AsyncVersionOf = createPluginRPC( - identifier, + PLUGIN_ID, () => { const PollWorker = new OnDemandWorker(new URL('./Services.ts', import.meta.url), { name: 'Plugin/Poll' }) return AsyncCall({}, { channel: new WorkerChannel(PollWorker), thenable: false }) diff --git a/packages/mask/src/plugins/PoolTogether/base.tsx b/packages/mask/src/plugins/PoolTogether/base.tsx index 9c46710e72c4..874152ecbd37 100644 --- a/packages/mask/src/plugins/PoolTogether/base.tsx +++ b/packages/mask/src/plugins/PoolTogether/base.tsx @@ -1,5 +1,5 @@ import type { Plugin } from '@masknet/plugin-infra' -import { POOLTOGETHER_PLUGIN_ID } from './constants' +import { POOLTOGETHER_PLUGIN_ID, URL_PATTERN } from './constants' import { PoolTogetherIcon } from '../../resources/PoolTogetherIcon' export const base: Plugin.Shared.Definition = { @@ -13,4 +13,5 @@ export const base: Plugin.Shared.Definition = { networks: { type: 'opt-out', networks: {} }, target: 'stable', }, + contribution: { postContent: new Set([URL_PATTERN]) }, } diff --git a/packages/mask/src/plugins/RedPacket/base.ts b/packages/mask/src/plugins/RedPacket/base.ts index acf60d384b3c..2baf19d0a04f 100644 --- a/packages/mask/src/plugins/RedPacket/base.ts +++ b/packages/mask/src/plugins/RedPacket/base.ts @@ -1,6 +1,6 @@ import { NetworkPluginID, Plugin } from '@masknet/plugin-infra' import { ChainId } from '@masknet/web3-shared-evm' -import { RedPacketPluginID } from './constants' +import { RedPacketMetaKey, RedPacketNftMetaKey, RedPacketPluginID } from './constants' export const base: Plugin.Shared.Definition = { ID: RedPacketPluginID, @@ -21,4 +21,7 @@ export const base: Plugin.Shared.Definition = { }, }, }, + contribution: { + metadataKeys: new Set([RedPacketMetaKey, RedPacketNftMetaKey]), + }, } diff --git a/packages/mask/src/plugins/Snapshot/base.ts b/packages/mask/src/plugins/Snapshot/base.ts index 483e9f2b6adb..db6dc7546454 100644 --- a/packages/mask/src/plugins/Snapshot/base.ts +++ b/packages/mask/src/plugins/Snapshot/base.ts @@ -14,4 +14,7 @@ export const base: Plugin.Shared.Definition = { networks: { type: 'opt-out', networks: {} }, target: 'stable', }, + contribution: { + postContent: new Set([/https:\/\/(?:www.)?snapshot.(org|page)\/#\/(.*?)\/proposal\/[\dA-Za-z]+/]), + }, } diff --git a/packages/mask/src/plugins/UnlockProtocol/base.ts b/packages/mask/src/plugins/UnlockProtocol/base.ts index 9fe57f779d9b..47001914e48f 100644 --- a/packages/mask/src/plugins/UnlockProtocol/base.ts +++ b/packages/mask/src/plugins/UnlockProtocol/base.ts @@ -1,6 +1,6 @@ import { NetworkPluginID, Plugin } from '@masknet/plugin-infra' import { ChainId } from '@masknet/web3-shared-evm' -import { pluginDescription, pluginIcon, pluginName, pluginId } from './constants' +import { pluginDescription, pluginIcon, pluginName, pluginId, pluginMetaKey } from './constants' export const base: Plugin.Shared.Definition = { ID: pluginId, @@ -18,4 +18,7 @@ export const base: Plugin.Shared.Definition = { }, }, }, + contribution: { + metadataKeys: new Set([pluginMetaKey]), + }, } diff --git a/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx b/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx index e53d0e2fcf71..88a6a8afd641 100644 --- a/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/dHEDGE/SNSAdaptor/index.tsx @@ -6,12 +6,7 @@ import { base } from '../base' import MaskPluginWrapper from '../../MaskPluginWrapper' import { PoolView } from '../UI/PoolView' import { InvestDialog } from '../UI/InvestDialog' -import { escapeRegExp } from 'lodash-unified' -import { BASE_URL, STAGING_URL } from '../constants' - -function createMatchLink() { - return new RegExp(`(${escapeRegExp(BASE_URL)}|${escapeRegExp(STAGING_URL)})/pool/(\\w+)`) -} +import { createMatchLink } from '../constants' function getPoolFromLink(link: string) { const matchLink = createMatchLink() diff --git a/packages/mask/src/plugins/dHEDGE/base.tsx b/packages/mask/src/plugins/dHEDGE/base.tsx index 1a2c7971fa6b..04c341b8eb50 100644 --- a/packages/mask/src/plugins/dHEDGE/base.tsx +++ b/packages/mask/src/plugins/dHEDGE/base.tsx @@ -1,5 +1,5 @@ import type { Plugin } from '@masknet/plugin-infra' -import { DHEDGE_PLUGIN_ID } from './constants' +import { createMatchLink, DHEDGE_PLUGIN_ID } from './constants' import { DHEDGEIcon } from '../../resources/DHEDGEIcon' export const base: Plugin.Shared.Definition = { @@ -13,4 +13,7 @@ export const base: Plugin.Shared.Definition = { networks: { type: 'opt-out', networks: {} }, target: 'stable', }, + contribution: { + postContent: new Set([createMatchLink()]), + }, } diff --git a/packages/mask/src/plugins/dHEDGE/constants.ts b/packages/mask/src/plugins/dHEDGE/constants.ts index 253a3c6a401c..97dfb0f01059 100644 --- a/packages/mask/src/plugins/dHEDGE/constants.ts +++ b/packages/mask/src/plugins/dHEDGE/constants.ts @@ -1,3 +1,5 @@ +import { escapeRegExp } from 'lodash-unified' + export const DHEDGE_PLUGIN_ID = 'org.dhedge' export const POOL_DESCRIPTION_LIMIT = 210 export const BLOCKIES_OPTIONS = { @@ -9,3 +11,7 @@ export const BLOCKIES_OPTIONS = { export const API_URL = 'https://api-v2.dhedge.org/graphql' export const BASE_URL = 'https://app.dhedge.org' export const STAGING_URL = 'https://dh-pre-prod.web.app' + +export function createMatchLink() { + return new RegExp(`(${escapeRegExp(BASE_URL)}|${escapeRegExp(STAGING_URL)})/pool/(\\w+)`) +} From 4328fe0357f739f757bdb1e514d5cdb502ad4652 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Tue, 7 Dec 2021 15:31:28 +0800 Subject: [PATCH 06/28] feat: plugin contribute hint when disabled. close #4918 --- packages/dashboard/src/pages/Labs/index.tsx | 11 +++- .../DecryptedPost/DecryptedPostSuccess.tsx | 22 ++++++- .../DisabledPluginSuggestion.tsx | 63 +++++++++++++++++++ .../InjectedComponents/PostInspector.tsx | 2 + .../TypedMessageRenderer.tsx | 2 +- .../background-script/SettingsService.ts | 5 +- packages/mask/src/plugin-infra/host.ts | 26 ++------ packages/plugin-infra/src/types.ts | 3 +- 8 files changed, 108 insertions(+), 26 deletions(-) create mode 100644 packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx diff --git a/packages/dashboard/src/pages/Labs/index.tsx b/packages/dashboard/src/pages/Labs/index.tsx index a8bd4f2b8935..9f8562c02633 100644 --- a/packages/dashboard/src/pages/Labs/index.tsx +++ b/packages/dashboard/src/pages/Labs/index.tsx @@ -20,7 +20,7 @@ import { import { useDashboardI18N } from '../../locales' import MarketTrendSettingDialog from './components/MarketTrendSettingDialog' import { useAccount } from '@masknet/web3-shared-evm' -import { PluginMessages } from '../../API' +import { Messages, PluginMessages } from '../../API' import { useRemoteControlledDialog } from '@masknet/shared' import { Services } from '../../API' import { PLUGIN_IDS, TUTORIAL_URLS_EN } from './constants' @@ -71,6 +71,15 @@ export default function Plugins() { [PLUGIN_IDS.POOL_TOGETHER]: true, }) + useEffect( + () => Messages.events.pluginEnabled.on((id) => setPluginStatus({ ...pluginStatus, [id]: true })), + [pluginStatus], + ) + useEffect( + () => Messages.events.pluginDisabled.on((id) => setPluginStatus({ ...pluginStatus, [id]: false })), + [pluginStatus], + ) + const plugins = [ { id: PLUGIN_IDS.RED_PACKET, diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx index c6e3cdecb4ae..728eef0a2b61 100644 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx +++ b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx @@ -5,12 +5,30 @@ import { useShareMenu } from '../SelectPeopleDialog' import { makeStyles, useStylesExtends } from '@masknet/theme' import { Link } from '@mui/material' import type { Profile } from '../../../database' -import type { TypedMessage } from '../../../protocols/typed-message' +import { extractTextFromTypedMessage, TypedMessage } from '../../../protocols/typed-message' import type { ProfileIdentifier } from '../../../database/type' import { wrapAuthorDifferentMessage } from './authorDifferentMessage' import { createInjectHooksRenderer, useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra' +import type { MetadataRendererProps } from '../TypedMessageRenderer' +import { + useDisabledPluginSuggestionFromMeta, + useDisabledPluginSuggestionFromPost, + PossiblePluginSuggestionUI, +} from '../DisabledPluginSuggestion' const PluginRenderer = createInjectHooksRenderer(useActivatedPluginsSNSAdaptor, (x) => x.DecryptedInspector) +function PluginRendererWithSuggestion(props: MetadataRendererProps) { + const a = useDisabledPluginSuggestionFromMeta(props.metadata || new Map()) + const b = useDisabledPluginSuggestionFromPost(extractTextFromTypedMessage(props.message)) + + const suggest = Array.from(new Set(a.concat(b))) + return ( + <> + + + + ) +} export interface DecryptPostSuccessProps extends withClasses { data: { content: TypedMessage } requestAppendRecipients?(to: Profile[]): Promise @@ -56,7 +74,7 @@ export const DecryptPostSuccess = memo(function DecryptPostSuccess(props: Decryp <> {shareMenu.ShareMenu} x.ID)) + const disabledPlugins = [...registeredPlugins].filter((x) => !activated.has(x.ID)) + return disabledPlugins +} + +export function useDisabledPluginSuggestionFromPost(postContext: Result) { + const disabled = useDisabledPlugins().filter((x) => x.contribution?.postContent) + + if (postContext.err) return [] + const matches = disabled.filter((x) => { + for (const pattern of x.contribution!.postContent!) { + if (postContext.val.match(pattern)) return true + } + return false + }) + return matches +} + +export function useDisabledPluginSuggestionFromMeta(meta: ReadonlyMap) { + const disabled = useDisabledPlugins().filter((x) => x.contribution?.metadataKeys) + const keys = [...meta.keys()] + + const matches = disabled.filter((x) => { + const contributes = x.contribution!.metadataKeys! + return keys.some((key) => contributes.has(key)) + }) + return matches +} + +export function PossiblePluginSuggestionPostInspector() { + const message = extractTextFromTypedMessage(usePostInfoDetails.postMessage()) + const matches = useDisabledPluginSuggestionFromPost(message) + return +} +export function PossiblePluginSuggestionUI(props: { plugins: Plugin.DeferredDefinition[] }) { + const { plugins } = props + if (!plugins.length) return null + return ( + <> +

Plugin suggestion:

+
    + {plugins.map((x) => ( +
  • + {x.ID} + +
  • + ))} +
+ + ) +} diff --git a/packages/mask/src/components/InjectedComponents/PostInspector.tsx b/packages/mask/src/components/InjectedComponents/PostInspector.tsx index 37cd87348afb..e7237b57bcec 100644 --- a/packages/mask/src/components/InjectedComponents/PostInspector.tsx +++ b/packages/mask/src/components/InjectedComponents/PostInspector.tsx @@ -14,6 +14,7 @@ import { usePostInfoDetails } from '../DataSource/usePostInfo' import type { PayloadAlpha40_Or_Alpha39, PayloadAlpha38 } from '../../utils/type-transform/Payload' import { decodePublicKeyUI } from '../../social-network/utils/text-payload-ui' import { createInjectHooksRenderer, useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra' +import { PossiblePluginSuggestionPostInspector } from './DisabledPluginSuggestion' const PluginHooksRenderer = createInjectHooksRenderer(useActivatedPluginsSNSAdaptor, (plugin) => plugin.PostInspector) @@ -116,6 +117,7 @@ export function PostInspector(props: PostInspectorProps) { ) : null} {props.slotPosition !== 'after' && slot} {x} + {debugInfo} {props.slotPosition !== 'before' && slot} diff --git a/packages/mask/src/components/InjectedComponents/TypedMessageRenderer.tsx b/packages/mask/src/components/InjectedComponents/TypedMessageRenderer.tsx index fbd1c5a7f869..f25b70554998 100644 --- a/packages/mask/src/components/InjectedComponents/TypedMessageRenderer.tsx +++ b/packages/mask/src/components/InjectedComponents/TypedMessageRenderer.tsx @@ -22,7 +22,7 @@ import { deconstructPayload } from '../../utils/type-transform/Payload' import { PayloadReplacer } from './PayloadReplacer' import { useI18N } from '../../utils' -interface MetadataRendererProps { +export interface MetadataRendererProps { metadata: TypedMessage['meta'] message: TypedMessage } diff --git a/packages/mask/src/extension/background-script/SettingsService.ts b/packages/mask/src/extension/background-script/SettingsService.ts index 547989275570..704f0e170aca 100644 --- a/packages/mask/src/extension/background-script/SettingsService.ts +++ b/packages/mask/src/extension/background-script/SettingsService.ts @@ -35,7 +35,7 @@ import { currentMaskWalletNetworkSettings, currentBalancesSettings, } from '../../plugins/Wallet/settings' -import { Flags } from '../../../shared' +import { Flags, MaskMessages } from '../../../shared' import { indexedDB_KVStorageBackend, inMemory_KVStorageBackend } from '../../../background/database/kv-storage' function create(settings: InternalSettings) { @@ -127,6 +127,9 @@ export async function getPluginEnabled(id: string) { } export async function setPluginEnabled(id: string, enabled: boolean) { currentPluginEnabledStatus['plugin:' + id].value = enabled + + if (enabled) MaskMessages.events.pluginEnabled.sendToAll(id) + else MaskMessages.events.pluginDisabled.sendToAll(id) } export async function openTab(url: string) { diff --git a/packages/mask/src/plugin-infra/host.ts b/packages/mask/src/plugin-infra/host.ts index 4c3c261a462f..db15279e453a 100644 --- a/packages/mask/src/plugin-infra/host.ts +++ b/packages/mask/src/plugin-infra/host.ts @@ -3,38 +3,24 @@ import './register' import type { Plugin } from '@masknet/plugin-infra' import { Emitter } from '@servie/events' -import { currentPluginEnabledStatus } from '../settings/settings' -import { isEnvironment, Environment } from '@dimensiondev/holoflows-kit' // Do not export from '../utils/' to prevent initialization failure import { MaskMessages } from '../utils/messages' import i18nNextInstance from '../../shared-ui/locales_legacy' import { createI18NBundle } from '@masknet/shared' +import Services from '../extension/service' export function createPluginHost( signal: AbortSignal | undefined, createContext: (plugin: string, signal: AbortSignal) => Context, ): Plugin.__Host.Host { - const listening = new Set() const enabled: Plugin.__Host.EnabledStatusReporter = { - isEnabled: (id) => { - const status = currentPluginEnabledStatus['plugin:' + id] - if (!listening.has(id)) { - listening.add(id) - const undo = status.addListener((newVal) => enabled.events.emit(newVal ? 'enabled' : 'disabled', id)) - signal?.addEventListener('abort', undo) - - // TODO: move it elsewhere. - if (isEnvironment(Environment.ManifestBackground)) { - status.addListener((newVal) => { - if (newVal) MaskMessages.events.pluginEnabled.sendToAll(id) - else MaskMessages.events.pluginDisabled.sendToAll(id) - }) - } - } - return status.value - }, + isEnabled: Services.Settings.getPluginEnabled, events: new Emitter(), } + const a = MaskMessages.events.pluginDisabled.on((x) => enabled.events.emit('disabled', x)) + const b = MaskMessages.events.pluginEnabled.on((x) => enabled.events.emit('enabled', x)) + signal?.addEventListener('abort', () => [a(), b()]) + return { signal, enabled, diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index 1d0f12e04514..1e991b687586 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -49,7 +49,8 @@ export declare namespace Plugin { /** Load the Worker part of the plugin. */ Worker?: Loader /** Load the General UI of the plugin. */ - GeneralUI?: Loader + // TODO: not supported yet. + // GeneralUI?: Loader } } /** From 105a050ba273a343d97534a98f60d2ed1fdf4a11 Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Wed, 8 Dec 2021 18:10:29 +0800 Subject: [PATCH 07/28] feat: update PossiblePluginSuggestionUI --- .../dashboard/src/pages/Labs/constants.ts | 2 +- packages/mask/shared-ui/locales/en-US.json | 1 + .../DisabledPluginSuggestion.tsx | 21 ++++++++------- .../mask/src/plugins/MaskPluginWrapper.tsx | 26 ++++++++++++++----- 4 files changed, 32 insertions(+), 18 deletions(-) diff --git a/packages/dashboard/src/pages/Labs/constants.ts b/packages/dashboard/src/pages/Labs/constants.ts index 84da37b752ee..eeb74c44b119 100644 --- a/packages/dashboard/src/pages/Labs/constants.ts +++ b/packages/dashboard/src/pages/Labs/constants.ts @@ -1,7 +1,7 @@ export const PLUGIN_IDS = { FILE_SERVICE: 'com.maskbook.fileservice', GITCOIN: 'co.gitcoin', - DHEDGE: 'co.dhedge', + DHEDGE: 'org.dhedge', RED_PACKET: 'com.maskbook.red_packet', TRANSAK: 'com.maskbook.transak', COLLECTIBLES: 'com.maskbook.collectibles', diff --git a/packages/mask/shared-ui/locales/en-US.json b/packages/mask/shared-ui/locales/en-US.json index dbf54f31dcc0..c5fc2f174f8f 100644 --- a/packages/mask/shared-ui/locales/en-US.json +++ b/packages/mask/shared-ui/locales/en-US.json @@ -181,6 +181,7 @@ "wallet_search_no_result": "No results.", "wallet_confirm_with_password": "Confirm with password", "wallet_airdrop_nft_unclaimed_title": "NFT Airdrop Unclaimed:", + "plugin_not_enabled": "{{plugin}} (Not Enabled)", "plugin_external_unknown_plugin": "New unknown Mask plugins found. Do you want to load them?", "plugin_external_loader_search_holder": "Search for an external plugin", "plugin_external_loader_search_button": "Search for plugin", diff --git a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx index ac946b61c2f9..cf5d9cf8a393 100644 --- a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx +++ b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx @@ -6,8 +6,10 @@ import { Plugin, } from '@masknet/plugin-infra' import { extractTextFromTypedMessage } from '@masknet/shared-base' -import { Button } from '@mui/material' +import { Switch } from '@mui/material' import Services from '../../extension/service' +import MaskPluginWrapper from '../../plugins/MaskPluginWrapper' +import { useI18N } from '../../utils' function useDisabledPlugins() { const activated = new Set(useActivatedPluginsSNSAdaptor().map((x) => x.ID)) @@ -45,19 +47,18 @@ export function PossiblePluginSuggestionPostInspector() { return } export function PossiblePluginSuggestionUI(props: { plugins: Plugin.DeferredDefinition[] }) { + const { t } = useI18N() const { plugins } = props if (!plugins.length) return null return ( <> -

Plugin suggestion:

-
    - {plugins.map((x) => ( -
  • - {x.ID} - -
  • - ))} -
+ {plugins.map((x) => ( + Services.Settings.setPluginEnabled(x.ID, true)} />} + /> + ))} ) } diff --git a/packages/mask/src/plugins/MaskPluginWrapper.tsx b/packages/mask/src/plugins/MaskPluginWrapper.tsx index 24795da818b0..a93fe50df891 100644 --- a/packages/mask/src/plugins/MaskPluginWrapper.tsx +++ b/packages/mask/src/plugins/MaskPluginWrapper.tsx @@ -2,12 +2,13 @@ import { Typography, SnackbarContent } from '@mui/material' import { makeStyles } from '@masknet/theme' import { activatedSocialNetworkUI } from '../social-network' import { MaskIcon } from '../resources/MaskIcon' -import { Suspense } from 'react' +import { Suspense, ReactNode } from 'react' import { isTwitter } from '../social-network-adaptor/twitter.com/base' interface PluginWrapperProps extends React.PropsWithChildren<{}> { pluginName: string width?: number + action?: ReactNode } const useStyles = makeStyles()((theme) => { @@ -31,33 +32,44 @@ const useStyles = makeStyles()((theme) => { display: 'flex', alignItems: 'center', padding: theme.spacing(1, 2), - borderBottom: `1px solid ${theme.palette.divider}`, }, title: { display: 'flex', flexDirection: 'column', paddingLeft: theme.spacing(1), }, + action: { + flex: 1, + display: 'flex', + alignItems: 'center', + justifyContent: 'flex-end', + }, body: { - margin: theme.spacing(2), + borderTop: `1px solid ${theme.palette.divider}`, + padding: theme.spacing(2), }, } }) export default function MaskPluginWrapper(props: PluginWrapperProps) { const { classes } = useStyles() - const { pluginName, children } = props + const { pluginName, children, action } = props const inner = (
ev.stopPropagation()}>
- Mask Plugin - {pluginName} + + Mask Plugin + + + {pluginName} +
+
{action}
-
{children}
+ {children ?
{children}
: null}
) return } children={inner} /> From df5a17373a2f1e02069d481a77e56818fb9c222b Mon Sep 17 00:00:00 2001 From: Jack Works Date: Thu, 9 Dec 2021 15:58:00 +0800 Subject: [PATCH 08/28] chore: add links to match list --- .../DecryptedPost/DecryptedPostSuccess.tsx | 2 +- .../InjectedComponents/DisabledPluginSuggestion.tsx | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx index 728eef0a2b61..91a9f23238ea 100644 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx +++ b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx @@ -19,7 +19,7 @@ import { const PluginRenderer = createInjectHooksRenderer(useActivatedPluginsSNSAdaptor, (x) => x.DecryptedInspector) function PluginRendererWithSuggestion(props: MetadataRendererProps) { const a = useDisabledPluginSuggestionFromMeta(props.metadata || new Map()) - const b = useDisabledPluginSuggestionFromPost(extractTextFromTypedMessage(props.message)) + const b = useDisabledPluginSuggestionFromPost(extractTextFromTypedMessage(props.message), []) const suggest = Array.from(new Set(a.concat(b))) return ( diff --git a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx index cf5d9cf8a393..10c1b26c058b 100644 --- a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx +++ b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx @@ -17,13 +17,14 @@ function useDisabledPlugins() { return disabledPlugins } -export function useDisabledPluginSuggestionFromPost(postContext: Result) { +export function useDisabledPluginSuggestionFromPost(postContent: Result, metaLinks: string[]) { const disabled = useDisabledPlugins().filter((x) => x.contribution?.postContent) - if (postContext.err) return [] + const { ok, val } = postContent const matches = disabled.filter((x) => { for (const pattern of x.contribution!.postContent!) { - if (postContext.val.match(pattern)) return true + if (ok && val.match(pattern)) return true + if (metaLinks.some((link) => link.match(pattern))) return true } return false }) @@ -43,7 +44,8 @@ export function useDisabledPluginSuggestionFromMeta(meta: ReadonlyMap } export function PossiblePluginSuggestionUI(props: { plugins: Plugin.DeferredDefinition[] }) { From 8e9d3937733117ec12267aa92e88a54d3bd4da6b Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Thu, 9 Dec 2021 16:48:51 +0800 Subject: [PATCH 09/28] fix: collectible url match --- packages/mask/src/plugins/Collectible/base.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/mask/src/plugins/Collectible/base.ts b/packages/mask/src/plugins/Collectible/base.ts index 318d40596cd8..f1f4802a1176 100644 --- a/packages/mask/src/plugins/Collectible/base.ts +++ b/packages/mask/src/plugins/Collectible/base.ts @@ -14,8 +14,8 @@ export const base: Plugin.Shared.Definition = { }, contribution: { postContent: new Set([ - /opensea.io\/\/assets\/(0x[\dA-Fa-f]{40})\/(\d+)/, - /rarible.com\/\/token\/(0x[\dA-Fa-f]{40}):(\d+)/, + /opensea.io\/assets\/(0x[\dA-Fa-f]{40})\/(\d+)/, + /rarible.com\/token\/(0x[\dA-Fa-f]{40}):(\d+)/, ]), }, } From 9cb89ac5f2e2f1f755f3cb415264958c3666711b Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Mon, 13 Dec 2021 13:37:43 +0800 Subject: [PATCH 10/28] feat: show persona status in timeline --- packages/mask/shared-ui/locales/en-US.json | 2 + .../DecryptedPost/DecryptPostFailed.tsx | 54 +++++++++++++++++-- 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/packages/mask/shared-ui/locales/en-US.json b/packages/mask/shared-ui/locales/en-US.json index c5fc2f174f8f..cef36c0ab745 100644 --- a/packages/mask/shared-ui/locales/en-US.json +++ b/packages/mask/shared-ui/locales/en-US.json @@ -96,6 +96,8 @@ "user_guide_tip_2": "Click here to have a quick start.", "create_persona": "Create persona", "connect_persona": "Connect persona", + "please_create_persona": "Please create persona", + "please_connect_persona": "Please connect persona", "mask_network": "Mask Network", "import": "Import", "no_search_result": "No result", diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx index 0140bc494c30..9a34df44f21a 100644 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx +++ b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx @@ -1,11 +1,32 @@ import { memo } from 'react' import { useI18N } from '../../../utils' import { AdditionalContent, AdditionalContentProps } from '../AdditionalPostContent' -import { NotSetupYetPrompt } from '../../shared/NotSetupYetPrompt' import type { BannerProps } from '../../Welcomes/Banner' import { DecryptFailedReason } from '../../../utils/constants' import type { ProfileIdentifier } from '../../../database/type' import { wrapAuthorDifferentMessage } from './authorDifferentMessage' +import MaskPluginWrapper from '../../../plugins/MaskPluginWrapper' +import { useMyPersonas } from '../../DataSource/useMyPersonas' +import { Button } from '@mui/material' +import { Services } from '../../../extension/service' +import stringify from 'json-stable-stringify' +import { DashboardRoutes } from '@masknet/shared' +import { currentSetupGuideStatus } from '../../../settings/settings' +import { activatedSocialNetworkUI } from '../../../social-network' +import { SetupGuideStep } from '../SetupGuide' +import { makeStyles, MaskColorVar } from '@masknet/theme' + +const useStyles = makeStyles()(() => { + return { + button: { + color: MaskColorVar.twitterButtonText, + '&,&:hover': { + background: MaskColorVar.twitterButton, + }, + }, + } +}) + export interface DecryptPostFailedProps { error: Error AdditionalContentProps?: Partial @@ -16,10 +37,35 @@ export interface DecryptPostFailedProps { postedBy?: ProfileIdentifier } export const DecryptPostFailed = memo(function DecryptPostFailed(props: DecryptPostFailedProps) { - const { AdditionalContentProps, NotSetupYetPromptProps, author, postedBy, error } = props + const { AdditionalContentProps, author, postedBy, error } = props const { t } = useI18N() - if (error?.message === DecryptFailedReason.MyCryptoKeyNotFound) - return + const { classes } = useStyles() + const personas = useMyPersonas() + const onClick = async () => { + if (!personas.length) { + Services.Welcome.openOptionsPage(DashboardRoutes.Setup) + } else { + const currentPersona = await Services.Settings.getCurrentPersonaIdentifier() + currentSetupGuideStatus[activatedSocialNetworkUI.networkIdentifier].value = stringify({ + status: SetupGuideStep.FindUsername, + persona: currentPersona?.toText(), + }) + } + } + if (error?.message === DecryptFailedReason.MyCryptoKeyNotFound) { + const name = personas.length ? t('please_connect_persona') : t('please_create_persona') + const button = personas.length ? t('connect_persona') : t('create_persona') + return ( + + {button} + + } + /> + ) + } return ( Date: Wed, 15 Dec 2021 14:37:23 +0800 Subject: [PATCH 11/28] style: plugin wrapper ui --- .../InjectedComponents/DisabledPluginSuggestion.tsx | 7 ++++++- packages/mask/src/plugins/MaskPluginWrapper.tsx | 8 ++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx index 10c1b26c058b..ec671a2acc92 100644 --- a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx +++ b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx @@ -58,7 +58,12 @@ export function PossiblePluginSuggestionUI(props: { plugins: Plugin.DeferredDefi Services.Settings.setPluginEnabled(x.ID, true)} />} + action={ + Services.Settings.setPluginEnabled(x.ID, true)} + /> + } /> ))} diff --git a/packages/mask/src/plugins/MaskPluginWrapper.tsx b/packages/mask/src/plugins/MaskPluginWrapper.tsx index a93fe50df891..0fb93f26f5c1 100644 --- a/packages/mask/src/plugins/MaskPluginWrapper.tsx +++ b/packages/mask/src/plugins/MaskPluginWrapper.tsx @@ -27,16 +27,16 @@ const useStyles = makeStyles()((theme) => { : null), }, header: { - backgroundColor: theme.palette.background.paper, + backgroundColor: 'transparent', color: theme.palette.text.primary, display: 'flex', alignItems: 'center', - padding: theme.spacing(1, 2), + padding: theme.spacing(2), }, title: { display: 'flex', flexDirection: 'column', - paddingLeft: theme.spacing(1), + paddingLeft: theme.spacing(1.5), }, action: { flex: 1, @@ -58,7 +58,7 @@ export default function MaskPluginWrapper(props: PluginWrapperProps) { const inner = (
ev.stopPropagation()}>
- +
Mask Plugin From 85b509d723995d31e9ab068c646fad9ff1de1be7 Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Wed, 15 Dec 2021 14:58:45 +0800 Subject: [PATCH 12/28] feat: hide switch for swap and transack --- .../src/pages/Labs/components/PluginItem.tsx | 18 ++++++++++++++++-- packages/dashboard/src/pages/Labs/index.tsx | 6 +++--- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/packages/dashboard/src/pages/Labs/components/PluginItem.tsx b/packages/dashboard/src/pages/Labs/components/PluginItem.tsx index acd79bfde7c9..8aaa4d60b63e 100644 --- a/packages/dashboard/src/pages/Labs/components/PluginItem.tsx +++ b/packages/dashboard/src/pages/Labs/components/PluginItem.tsx @@ -58,6 +58,7 @@ export interface PluginItemProps { desc: string icon?: ReactNode enabled?: boolean + hideSwitch?: boolean onSwitch: (id: string, checked: boolean) => void onTwitter?: (id: string) => void onFacebook?: (id: string) => void @@ -72,7 +73,20 @@ export function PluginItemPlaceholder() { } export default function PluginItem(props: PluginItemProps) { - const { id, title, desc, icon, enabled, onSwitch, onTwitter, onFacebook, onExplore, onSetting, onTutorial } = props + const { + id, + title, + desc, + icon, + enabled, + hideSwitch, + onSwitch, + onTwitter, + onFacebook, + onExplore, + onSetting, + onTutorial, + } = props const { classes } = useStyles() return ( @@ -98,7 +112,7 @@ export default function PluginItem(props: PluginItemProps) { {onExplore ? onExplore(id)} /> : null} ) : null} - {id ? ( + {!hideSwitch ? ( , enabled: pluginStatus[PLUGIN_IDS.SWAP], setting: true, + hideSwitch: true, }, { id: PLUGIN_IDS.TRANSAK, @@ -124,6 +124,7 @@ export default function Plugins() { desc: t.labs_transak_desc(), icon: , enabled: pluginStatus[PLUGIN_IDS.TRANSAK], + hideSwitch: true, }, { id: PLUGIN_IDS.COLLECTIBLES, @@ -190,8 +191,6 @@ export default function Plugins() { }, ] - const language = useLanguage() - const account = useAccount() const { setDialog: setBuyDialog } = useRemoteControlledDialog(PluginMessages.Transak.buyTokenDialogUpdated) const openTransakDialog = useCallback( @@ -266,6 +265,7 @@ export default function Plugins() { onSwitch={onSwitch} onTutorial={onTutorial} onSetting={p.setting ? onSetting : undefined} + hideSwitch={p.hideSwitch} /> ))} From dc85eddceeee966f8db851edc2b2e244d1377351 Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Wed, 15 Dec 2021 16:30:02 +0800 Subject: [PATCH 13/28] fix: enabled initial val --- packages/dashboard/src/pages/Labs/components/PluginItem.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashboard/src/pages/Labs/components/PluginItem.tsx b/packages/dashboard/src/pages/Labs/components/PluginItem.tsx index 8aaa4d60b63e..1585a54e15ca 100644 --- a/packages/dashboard/src/pages/Labs/components/PluginItem.tsx +++ b/packages/dashboard/src/pages/Labs/components/PluginItem.tsx @@ -78,7 +78,7 @@ export default function PluginItem(props: PluginItemProps) { title, desc, icon, - enabled, + enabled = false, hideSwitch, onSwitch, onTwitter, From 118f4cf48883a4d3b88e33a30dcd5df9e5cea59d Mon Sep 17 00:00:00 2001 From: Jack Works Date: Wed, 15 Dec 2021 16:57:32 +0800 Subject: [PATCH 14/28] feat: support minimal mode in plugin infra --- .../src/initialization/PluginHost.ts | 13 ++++- packages/dashboard/src/pages/Labs/index.tsx | 13 ++--- .../CompositionDialog/BadgeRenderer.tsx | 2 +- .../CompositionDialog/PluginEntryRender.tsx | 2 +- .../DecryptedPost/DecryptedPostSuccess.tsx | 5 +- .../DisabledPluginSuggestion.tsx | 7 ++- .../InjectedComponents/PageInspector.tsx | 5 +- .../InjectedComponents/PostInspector.tsx | 5 +- .../InjectedComponents/PostReplacer.tsx | 2 +- .../InjectedComponents/SearchResultBox.tsx | 5 +- .../background-script/SettingsService.ts | 7 +-- packages/mask/src/plugin-infra/host.ts | 19 +++++-- .../SNSAdaptor/trending/TrendingViewDeck.tsx | 2 +- packages/mask/src/utils/native-rpc/Web.ts | 4 +- .../src/hooks/useActivatedPlugin.ts | 4 +- .../src/hooks/useActivatedPluginWeb3State.ts | 2 +- .../src/hooks/useActivatedPluginWeb3UI.ts | 2 +- .../src/hooks/useAllPluginsWeb3State.ts | 2 +- packages/plugin-infra/src/manager/manage.ts | 42 ++++++++++---- .../plugin-infra/src/manager/sns-adaptor.ts | 55 +++++++++++++++---- packages/plugin-infra/src/types.ts | 44 ++++++++++----- packages/plugins/Wallet/src/base.ts | 1 - packages/shared-base/src/Messages/Mask.ts | 3 +- 23 files changed, 171 insertions(+), 75 deletions(-) diff --git a/packages/dashboard/src/initialization/PluginHost.ts b/packages/dashboard/src/initialization/PluginHost.ts index b3f0bdd3d8dd..d3a57c2072e9 100644 --- a/packages/dashboard/src/initialization/PluginHost.ts +++ b/packages/dashboard/src/initialization/PluginHost.ts @@ -9,9 +9,15 @@ import { InMemoryStorages, PersistentStorages } from '../utils/kv-storage' const PluginHost: Plugin.__Host.Host = { enabled: { + // Due to MASK-391, we don't have a user configurable "disabled" plugin. + // All plugins are always loaded but it might be displayed in the invisible mode. + isEnabled: () => true, + events: new Emitter(), + }, + minimalMode: { events: new Emitter(), isEnabled: (id) => { - return Services.Settings.getPluginEnabled(id) + return Services.Settings.getPluginMinimalModeEnabled(id) }, }, addI18NResource(plugin, resource) { @@ -27,7 +33,8 @@ const PluginHost: Plugin.__Host.Host = { }, } setTimeout(() => { - Messages.events.pluginEnabled.on((id) => PluginHost.enabled.events.emit('enabled', id)) - Messages.events.pluginDisabled.on((id) => PluginHost.enabled.events.emit('disabled', id)) + Messages.events.pluginMinimalModeChanged.on(([id, status]) => { + PluginHost.minimalMode.events.emit(status ? 'enabled' : 'disabled', id) + }) startPluginDashboard(PluginHost) }) diff --git a/packages/dashboard/src/pages/Labs/index.tsx b/packages/dashboard/src/pages/Labs/index.tsx index 7053311efe8a..2b3b3dd0a440 100644 --- a/packages/dashboard/src/pages/Labs/index.tsx +++ b/packages/dashboard/src/pages/Labs/index.tsx @@ -72,11 +72,10 @@ export default function Plugins() { }) useEffect( - () => Messages.events.pluginEnabled.on((id) => setPluginStatus({ ...pluginStatus, [id]: true })), - [pluginStatus], - ) - useEffect( - () => Messages.events.pluginDisabled.on((id) => setPluginStatus({ ...pluginStatus, [id]: false })), + () => + Messages.events.pluginMinimalModeChanged.on(([id, newValue]) => + setPluginStatus({ ...pluginStatus, [id]: newValue }), + ), [pluginStatus], ) @@ -207,7 +206,7 @@ export default function Plugins() { const { openDialog: openSwapDialog } = useRemoteControlledDialog(PluginMessages.Swap.swapDialogUpdated) async function onSwitch(id: string, checked: boolean) { - await Services.Settings.setPluginEnabled(id, checked) + await Services.Settings.setPluginMinimalModeEnabled(id, checked) setPluginStatus({ ...pluginStatus, [id]: checked }) } @@ -233,7 +232,7 @@ export default function Plugins() { useEffect(() => { Object.values(PLUGIN_IDS).forEach(async (id) => { - const enabled = await Services.Settings.getPluginEnabled(id) + const enabled = await Services.Settings.getPluginMinimalModeEnabled(id) setPluginStatus((status) => ({ ...status, [id]: enabled })) }) }, []) diff --git a/packages/mask/src/components/CompositionDialog/BadgeRenderer.tsx b/packages/mask/src/components/CompositionDialog/BadgeRenderer.tsx index e50a17d16e27..860bb80f3345 100644 --- a/packages/mask/src/components/CompositionDialog/BadgeRenderer.tsx +++ b/packages/mask/src/components/CompositionDialog/BadgeRenderer.tsx @@ -11,7 +11,7 @@ export interface BadgeRendererProps { } export function BadgeRenderer({ meta, onDeleteMeta, readonly }: BadgeRendererProps) { - const plugins = useActivatedPluginsSNSAdaptor() + const plugins = useActivatedPluginsSNSAdaptor('any') const i18n = usePluginI18NField() const { t } = useI18N() if (!meta) return null diff --git a/packages/mask/src/components/CompositionDialog/PluginEntryRender.tsx b/packages/mask/src/components/CompositionDialog/PluginEntryRender.tsx index ea2f7bf2cbb2..4ec9176689ec 100644 --- a/packages/mask/src/components/CompositionDialog/PluginEntryRender.tsx +++ b/packages/mask/src/components/CompositionDialog/PluginEntryRender.tsx @@ -29,7 +29,7 @@ export const PluginEntryRender = memo( const chainId = useChainId() const pluginID = usePluginIDContext() const operatingSupportedChainMapping = useActivatedPluginSNSAdaptor_Web3Supported(chainId, pluginID) - const result = [...useActivatedPluginsSNSAdaptor()] + const result = [...useActivatedPluginsSNSAdaptor('any')] .sort((plugin) => { // TODO: support priority order if (plugin.ID === RedPacketPluginID || plugin.ID === ITO_PluginID) return -1 diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx index fad7c2eb0a69..09c66ad4e604 100644 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx +++ b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptedPostSuccess.tsx @@ -16,7 +16,10 @@ import { PossiblePluginSuggestionUI, } from '../DisabledPluginSuggestion' -const PluginRenderer = createInjectHooksRenderer(useActivatedPluginsSNSAdaptor, (x) => x.DecryptedInspector) +const PluginRenderer = createInjectHooksRenderer( + useActivatedPluginsSNSAdaptor.visibility.useNotMinimalMode, + (x) => x.DecryptedInspector, +) function PluginRendererWithSuggestion(props: MetadataRendererProps) { const a = useDisabledPluginSuggestionFromMeta(props.metadata || new Map()) const b = useDisabledPluginSuggestionFromPost(extractTextFromTypedMessage(props.message), []) diff --git a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx index ec671a2acc92..782e74d2dfc1 100644 --- a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx +++ b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx @@ -12,8 +12,9 @@ import MaskPluginWrapper from '../../plugins/MaskPluginWrapper' import { useI18N } from '../../utils' function useDisabledPlugins() { - const activated = new Set(useActivatedPluginsSNSAdaptor().map((x) => x.ID)) - const disabledPlugins = [...registeredPlugins].filter((x) => !activated.has(x.ID)) + const activated = new Set(useActivatedPluginsSNSAdaptor('any').map((x) => x.ID)) + const minimalMode = new Set(useActivatedPluginsSNSAdaptor(true).map((x) => x.ID)) + const disabledPlugins = [...registeredPlugins].filter((x) => !activated.has(x.ID) || minimalMode.has(x.ID)) return disabledPlugins } @@ -61,7 +62,7 @@ export function PossiblePluginSuggestionUI(props: { plugins: Plugin.DeferredDefi action={ Services.Settings.setPluginEnabled(x.ID, true)} + onChange={() => Services.Settings.setPluginMinimalModeEnabled(x.ID, true)} /> } /> diff --git a/packages/mask/src/components/InjectedComponents/PageInspector.tsx b/packages/mask/src/components/InjectedComponents/PageInspector.tsx index 6174af5e1bb7..df1da63ed3c3 100644 --- a/packages/mask/src/components/InjectedComponents/PageInspector.tsx +++ b/packages/mask/src/components/InjectedComponents/PageInspector.tsx @@ -5,7 +5,10 @@ import { createInjectHooksRenderer, useActivatedPluginsSNSAdaptor } from '@maskn import { useMatchXS, MaskMessages, useI18N } from '../../utils' import { useAutoPasteFailedDialog } from './AutoPasteFailedDialog' -const PluginRender = createInjectHooksRenderer(useActivatedPluginsSNSAdaptor, (x) => x.GlobalInjection) +const PluginRender = createInjectHooksRenderer( + useActivatedPluginsSNSAdaptor.visibility.useAnyMode, + (x) => x.GlobalInjection, +) export interface PageInspectorProps {} diff --git a/packages/mask/src/components/InjectedComponents/PostInspector.tsx b/packages/mask/src/components/InjectedComponents/PostInspector.tsx index 54e8e51862e9..8a62beeb6bcb 100644 --- a/packages/mask/src/components/InjectedComponents/PostInspector.tsx +++ b/packages/mask/src/components/InjectedComponents/PostInspector.tsx @@ -19,7 +19,10 @@ import { decodePublicKeyUI } from '../../social-network/utils/text-payload-ui' import { createInjectHooksRenderer, useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra' import { PossiblePluginSuggestionPostInspector } from './DisabledPluginSuggestion' -const PluginHooksRenderer = createInjectHooksRenderer(useActivatedPluginsSNSAdaptor, (plugin) => plugin.PostInspector) +const PluginHooksRenderer = createInjectHooksRenderer( + useActivatedPluginsSNSAdaptor.visibility.useNotMinimalMode, + (plugin) => plugin.PostInspector, +) export interface PostInspectorProps { onDecrypted(post: TypedMessageTuple): void diff --git a/packages/mask/src/components/InjectedComponents/PostReplacer.tsx b/packages/mask/src/components/InjectedComponents/PostReplacer.tsx index f7106dbf49e6..4cc045b7461f 100644 --- a/packages/mask/src/components/InjectedComponents/PostReplacer.tsx +++ b/packages/mask/src/components/InjectedComponents/PostReplacer.tsx @@ -29,7 +29,7 @@ export function PostReplacer(props: PostReplacerProps) { const postPayload = usePostInfoDetails.postPayload() const allPostReplacement = useValueRef(allPostReplacementSettings) - const plugins = useActivatedPluginsSNSAdaptor() + const plugins = useActivatedPluginsSNSAdaptor(false) const processedPostMessage = useMemo( () => plugins.reduce((x, plugin) => { diff --git a/packages/mask/src/components/InjectedComponents/SearchResultBox.tsx b/packages/mask/src/components/InjectedComponents/SearchResultBox.tsx index ce9d500c3889..9192957d0021 100644 --- a/packages/mask/src/components/InjectedComponents/SearchResultBox.tsx +++ b/packages/mask/src/components/InjectedComponents/SearchResultBox.tsx @@ -1,6 +1,9 @@ import { createInjectHooksRenderer, useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra' -const PluginRenderer = createInjectHooksRenderer(useActivatedPluginsSNSAdaptor, (x) => x.SearchBoxComponent) +const PluginRenderer = createInjectHooksRenderer( + useActivatedPluginsSNSAdaptor.visibility.useNotMinimalMode, + (x) => x.SearchBoxComponent, +) export interface SearchResultBoxProps {} export function SearchResultBox(props: SearchResultBoxProps) { diff --git a/packages/mask/src/extension/background-script/SettingsService.ts b/packages/mask/src/extension/background-script/SettingsService.ts index e7820960983c..7258127d33f9 100644 --- a/packages/mask/src/extension/background-script/SettingsService.ts +++ b/packages/mask/src/extension/background-script/SettingsService.ts @@ -122,14 +122,13 @@ export async function setCurrentPersonaIdentifier(x: PersonaIdentifier) { await currentPersonaIdentifier.readyPromise currentPersonaIdentifier.value = x.toText() } -export async function getPluginEnabled(id: string) { +export async function getPluginMinimalModeEnabled(id: string) { return currentPluginEnabledStatus['plugin:' + id].value } -export async function setPluginEnabled(id: string, enabled: boolean) { +export async function setPluginMinimalModeEnabled(id: string, enabled: boolean) { currentPluginEnabledStatus['plugin:' + id].value = enabled - if (enabled) MaskMessages.events.pluginEnabled.sendToAll(id) - else MaskMessages.events.pluginDisabled.sendToAll(id) + MaskMessages.events.pluginMinimalModeChanged.sendToAll([id, enabled]) } export async function openTab(url: string) { diff --git a/packages/mask/src/plugin-infra/host.ts b/packages/mask/src/plugin-infra/host.ts index 18a5ca32c891..d4dc1dd8b308 100644 --- a/packages/mask/src/plugin-infra/host.ts +++ b/packages/mask/src/plugin-infra/host.ts @@ -13,17 +13,24 @@ export function createPluginHost( signal: AbortSignal | undefined, createContext: (plugin: string, signal: AbortSignal) => Context, ): Plugin.__Host.Host { - const enabled: Plugin.__Host.EnabledStatusReporter = { - isEnabled: Services.Settings.getPluginEnabled, + const minimalMode: Plugin.__Host.EnabledStatusReporter = { + isEnabled: Services.Settings.getPluginMinimalModeEnabled, events: new Emitter(), } - const a = MaskMessages.events.pluginDisabled.on((x) => enabled.events.emit('disabled', x)) - const b = MaskMessages.events.pluginEnabled.on((x) => enabled.events.emit('enabled', x)) - signal?.addEventListener('abort', () => [a(), b()]) + const removeListener = MaskMessages.events.pluginMinimalModeChanged.on(([id, val]) => + minimalMode.events.emit(val ? 'enabled' : 'disabled', id), + ) + signal?.addEventListener('abort', removeListener) return { signal, - enabled, + // Due to MASK-391, we don't have a user configurable "disabled" plugin. + // All plugins are always loaded but it might be displayed in the summary mode. + enabled: { + events: new Emitter(), + isEnabled: () => true, + }, + minimalMode, addI18NResource(plugin, resource) { createI18NBundle(plugin, resource)(i18nNextInstance) }, diff --git a/packages/mask/src/plugins/Trader/SNSAdaptor/trending/TrendingViewDeck.tsx b/packages/mask/src/plugins/Trader/SNSAdaptor/trending/TrendingViewDeck.tsx index 5176fabf74c9..aba782b53355 100644 --- a/packages/mask/src/plugins/Trader/SNSAdaptor/trending/TrendingViewDeck.tsx +++ b/packages/mask/src/plugins/Trader/SNSAdaptor/trending/TrendingViewDeck.tsx @@ -127,7 +127,7 @@ export function TrendingViewDeck(props: TrendingViewDeckProps) { const classes = useStylesExtends(useStyles(), props) //#region buy - const transakPluginEnabled = useActivatedPluginsSNSAdaptor().find((x) => x.ID === TRANSAK_PLUGIN_ID) + const transakPluginEnabled = useActivatedPluginsSNSAdaptor('any').find((x) => x.ID === TRANSAK_PLUGIN_ID) const account = useAccount() const isAllowanceCoin = useTransakAllowanceCoin(coin) const { setDialog: setBuyDialog } = useRemoteControlledDialog(PluginTransakMessages.buyTokenDialogUpdated) diff --git a/packages/mask/src/utils/native-rpc/Web.ts b/packages/mask/src/utils/native-rpc/Web.ts index 05381cb058c4..7173b4de059a 100644 --- a/packages/mask/src/utils/native-rpc/Web.ts +++ b/packages/mask/src/utils/native-rpc/Web.ts @@ -101,8 +101,8 @@ export const MaskNetworkAPI: MaskNetworkAPIs = { }) return stringify(connectedPersonas) }, - app_isPluginEnabled: ({ pluginID }) => Services.Settings.getPluginEnabled(pluginID), - app_setPluginStatus: ({ pluginID, enabled }) => Services.Settings.setPluginEnabled(pluginID, enabled), + app_isPluginEnabled: ({ pluginID }) => Services.Settings.getPluginMinimalModeEnabled(pluginID), + app_setPluginStatus: ({ pluginID, enabled }) => Services.Settings.setPluginMinimalModeEnabled(pluginID, enabled), setting_getNetworkTraderProvider: ({ network }) => { switch (network) { case NetworkType.Ethereum: diff --git a/packages/plugin-infra/src/hooks/useActivatedPlugin.ts b/packages/plugin-infra/src/hooks/useActivatedPlugin.ts index 057b8d21d13b..a4255c6bee81 100644 --- a/packages/plugin-infra/src/hooks/useActivatedPlugin.ts +++ b/packages/plugin-infra/src/hooks/useActivatedPlugin.ts @@ -1,8 +1,8 @@ import { useActivatedPluginDashboard } from '../manager/dashboard' import { useActivatedPluginSNSAdaptor } from '../manager/sns-adaptor' -export function useActivatedPlugin(pluginID: string) { - const pluginSNSAdaptor = useActivatedPluginSNSAdaptor(pluginID) +export function useActivatedPlugin(pluginID: string, minimalModeEqualsTo: 'any' | boolean) { + const pluginSNSAdaptor = useActivatedPluginSNSAdaptor(pluginID, minimalModeEqualsTo) const pluginDashboard = useActivatedPluginDashboard(pluginID) return pluginSNSAdaptor ?? pluginDashboard ?? null } diff --git a/packages/plugin-infra/src/hooks/useActivatedPluginWeb3State.ts b/packages/plugin-infra/src/hooks/useActivatedPluginWeb3State.ts index 6b265aeb28cc..769c39f1ed9e 100644 --- a/packages/plugin-infra/src/hooks/useActivatedPluginWeb3State.ts +++ b/packages/plugin-infra/src/hooks/useActivatedPluginWeb3State.ts @@ -1,6 +1,6 @@ import { useActivatedPlugin } from './useActivatedPlugin' export function useActivatedPluginWeb3State(pluginID: string) { - const activatedPlugin = useActivatedPlugin(pluginID) + const activatedPlugin = useActivatedPlugin(pluginID, 'any') return activatedPlugin?.Web3State ?? null } diff --git a/packages/plugin-infra/src/hooks/useActivatedPluginWeb3UI.ts b/packages/plugin-infra/src/hooks/useActivatedPluginWeb3UI.ts index bd612859af00..cfbf11f0388c 100644 --- a/packages/plugin-infra/src/hooks/useActivatedPluginWeb3UI.ts +++ b/packages/plugin-infra/src/hooks/useActivatedPluginWeb3UI.ts @@ -1,6 +1,6 @@ import { useActivatedPlugin } from './useActivatedPlugin' export function useActivatedPluginWeb3UI(pluginID: string) { - const activatedPlugin = useActivatedPlugin(pluginID) + const activatedPlugin = useActivatedPlugin(pluginID, 'any') return activatedPlugin?.Web3UI ?? null } diff --git a/packages/plugin-infra/src/hooks/useAllPluginsWeb3State.ts b/packages/plugin-infra/src/hooks/useAllPluginsWeb3State.ts index 81e1a55d6fd1..bd86889f7cef 100644 --- a/packages/plugin-infra/src/hooks/useAllPluginsWeb3State.ts +++ b/packages/plugin-infra/src/hooks/useAllPluginsWeb3State.ts @@ -3,7 +3,7 @@ import { useActivatedPluginsSNSAdaptor } from '../manager/sns-adaptor' import type { Web3Plugin } from '../web3-types' export function useAllPluginsWeb3State() { - const pluginsSNSAdaptor = useActivatedPluginsSNSAdaptor() + const pluginsSNSAdaptor = useActivatedPluginsSNSAdaptor('any') const pluginsDashboard = useActivatedPluginsDashboard() return [...pluginsSNSAdaptor, ...pluginsDashboard].reduce< diff --git a/packages/plugin-infra/src/manager/manage.ts b/packages/plugin-infra/src/manager/manage.ts index b755fca3749d..78ac14bbd1af 100644 --- a/packages/plugin-infra/src/manager/manage.ts +++ b/packages/plugin-infra/src/manager/manage.ts @@ -1,4 +1,5 @@ import { Emitter, ALL_EVENTS } from '@servie/events' +import { noop } from 'lodash-unified' import type { Plugin } from '../types' import { getPluginDefine, registeredPluginIDs, registeredPlugins } from './store' @@ -17,16 +18,18 @@ export function createManager< } const resolved = new Map() const activated = new Map() + const minimalModePluginIDs = new Set() let _host: Plugin.__Host.Host = undefined! const events = new Emitter<{ - activated: [id: string] - stopped: [id: string] + activateChanged: [id: string, enabled: boolean] + minimalModeChanged: [id: string, enabled: boolean] }>() return { configureHostHooks: (host: Plugin.__Host.Host) => (_host = host), activatePlugin, stopPlugin, + isMinimalMode, isActivated, startDaemon, activated: { @@ -37,16 +40,29 @@ export function createManager< }, } as Iterable, }, + minimalMode: { + *[Symbol.iterator]() { + yield* minimalModePluginIDs + }, + }, events, } function startDaemon(host: Plugin.__Host.Host, extraCheck?: (id: string) => boolean) { _host = host - const { enabled, signal, addI18NResource } = _host - const removeListener = enabled.events.on(ALL_EVENTS, checkRequirementAndStartOrStop) + const { enabled, signal, addI18NResource, minimalMode } = _host + const removeListener1 = enabled.events.on(ALL_EVENTS, checkRequirementAndStartOrStop) + const removeListener2 = minimalMode.events.on('enabled', (id) => { + minimalModePluginIDs.add(id) + events.emit('minimalModeChanged', id, true) + }) + const removeListener3 = minimalMode.events.on('disabled', (id) => { + minimalModePluginIDs.delete(id) + events.emit('minimalModeChanged', id, false) + }) signal?.addEventListener('abort', () => [...activated.keys()].forEach(stopPlugin)) - signal?.addEventListener('abort', removeListener) + signal?.addEventListener('abort', () => void [removeListener1(), removeListener2(), removeListener3()]) for (const plugin of registeredPlugins) { plugin.i18n && addI18NResource(plugin.ID, plugin.i18n) @@ -62,9 +78,7 @@ export function createManager< async function meetRequirement(id: string) { const define = getPluginDefine(id) if (!define) return false - if (!define.management?.alwaysOn) { - if (!(await enabled.isEnabled(id))) return false - } + if (!(await enabled.isEnabled(id))) return false if (extraCheck && !extraCheck(id)) return false return true } @@ -82,6 +96,10 @@ export function createManager< const definition = await __getDefinition(id) if (!definition) return + Promise.resolve(_host.minimalMode.isEnabled(id)).then( + (enabled) => (enabled ? minimalModePluginIDs.add(id) : minimalModePluginIDs.delete(id)), + noop, + ) { const icon = definition.icon if (typeof icon === 'string' && (icon.codePointAt(0) || 0) < 256) { @@ -106,7 +124,7 @@ export function createManager< } activated.set(id, activatedPlugin) await definition.init(activatedPlugin.controller.signal, activatedPlugin.context) - events.emit('activated', id) + events.emit('activateChanged', id, true) } function stopPlugin(id: string) { @@ -114,13 +132,17 @@ export function createManager< if (!instance) return instance.controller.abort() activated.delete(id) - events.emit('stopped', id) + events.emit('activateChanged', id, false) } function isActivated(id: string) { return activated.has(id) } + function isMinimalMode(id: string) { + return minimalModePluginIDs.has(id) + } + async function __getDefinition(id: string) { if (resolved.has(id)) return resolved.get(id)! diff --git a/packages/plugin-infra/src/manager/sns-adaptor.ts b/packages/plugin-infra/src/manager/sns-adaptor.ts index 3cd823d35607..2e2e33bfc2d6 100644 --- a/packages/plugin-infra/src/manager/sns-adaptor.ts +++ b/packages/plugin-infra/src/manager/sns-adaptor.ts @@ -1,27 +1,62 @@ -import { ALL_EVENTS } from '@servie/events' import { useSubscription, Subscription } from 'use-subscription' import { createManager } from './manage' import { getPluginDefine } from './store' import type { CurrentSNSNetwork, Plugin } from '../types' import type { NetworkPluginID } from '..' +import { unreachable } from '@dimensiondev/kit' -const { events, activated, startDaemon } = createManager((def) => def.SNSAdaptor) +const { events, activated, startDaemon, minimalMode } = createManager((def) => def.SNSAdaptor) -const subscription: Subscription = { +const activatedSub: Subscription = { getCurrentValue: () => [...activated.plugins], - subscribe: (f) => events.on(ALL_EVENTS, f), + subscribe: (f) => events.on('activateChanged', f), } -export function useActivatedPluginsSNSAdaptor() { - return useSubscription(subscription) +const minimalModeSub: Subscription = { + getCurrentValue: () => [...minimalMode], + subscribe: (f) => events.on('minimalModeChanged', f), +} +export function useActivatedPluginsSNSAdaptor(minimalModeEqualsTo: 'any' | boolean) { + const minimalMode = useSubscription(minimalModeSub) + const result = useSubscription(activatedSub) + if (minimalModeEqualsTo === 'any') return result + else if (minimalModeEqualsTo === true) return result.filter((x) => minimalMode.includes(x.ID)) + else if (minimalModeEqualsTo === false) return result.filter((x) => !minimalMode.includes(x.ID)) + unreachable(minimalModeEqualsTo) +} +useActivatedPluginsSNSAdaptor.visibility = { + useMinimalMode: useActivatedPluginsSNSAdaptor.bind(null, true), + useNotMinimalMode: useActivatedPluginsSNSAdaptor.bind(null, false), + useAnyMode: useActivatedPluginsSNSAdaptor.bind(null, 'any'), +} + +export function useIsMinimalMode(pluginID: string) { + return useSubscription(minimalModeSub).includes(pluginID) } -export function useActivatedPluginSNSAdaptor(pluginID: string) { - const plugins = useActivatedPluginsSNSAdaptor() - return plugins.find((x) => x.ID === pluginID) +/** + * + * @param pluginID Get the plugin ID + * @param visibility Should invisible plugin included? + * @returns + */ +export function useActivatedPluginSNSAdaptor(pluginID: string, minimalModeEqualsTo: 'any' | boolean) { + const plugins = useActivatedPluginsSNSAdaptor(minimalModeEqualsTo) + const minimalMode = useSubscription(minimalModeSub) + const result = plugins.find((x) => x.ID === pluginID) + if (!result) return result + if (minimalModeEqualsTo === 'any') return result + else if (minimalModeEqualsTo === true) { + if (minimalMode.includes(result.ID)) return result + return undefined + } else if (minimalModeEqualsTo === false) { + if (minimalMode.includes(result.ID)) return undefined + return result + } + unreachable(minimalModeEqualsTo) } export function useActivatedPluginSNSAdaptor_Web3Supported(chainId: number, pluginID: string) { - const plugins = useActivatedPluginsSNSAdaptor() + const plugins = useActivatedPluginsSNSAdaptor('any') return plugins.reduce>((acc, cur) => { if (!cur.enableRequirement.web3) { acc[cur.ID] = true diff --git a/packages/plugin-infra/src/types.ts b/packages/plugin-infra/src/types.ts index d513821653ac..f496e072af7e 100644 --- a/packages/plugin-infra/src/types.ts +++ b/packages/plugin-infra/src/types.ts @@ -101,8 +101,6 @@ export namespace Plugin.Shared { * This does not affect if the plugin enable or not. */ experimentalMark?: boolean - /** Configuration of how this plugin is managed by the Mask Network. */ - management?: ManagementProperty /** i18n resources of this plugin */ i18n?: I18NResource /** Introduce networks information. */ @@ -117,6 +115,8 @@ export namespace Plugin.Shared { * Declare this field properly so Mask Network can suggest your plugin when needed. */ contribution?: Contribution + /** Declare ability this plugin supported. */ + ability?: Ability } /** * This part is shared between Dashboard, SNSAdaptor and Worker part @@ -162,18 +162,6 @@ export namespace Plugin.Shared { /** The Web3 Network this plugin supports */ web3?: Web3Plugin.EnableRequirement } - export interface ManagementProperty { - /** This plugin should not displayed in the plugin management page. */ - internal?: boolean - /** - * This plugin should not allow to be "disabled" in the plugin management page. - * - * This property is for the Wallet plugin. It's the core of almost all other plugins. - * - * It should be replaced by "dependency" management in the future (if there are more cases than the Wallet one). - */ - alwaysOn?: boolean - } export interface SupportedNetworksDeclare { /** * opt-in means the listed networks is supported. @@ -192,6 +180,19 @@ export namespace Plugin.Shared { /** This plugin can recognize and enhance the post that matches the following matchers. */ postContent?: ReadonlySet } + export interface Ability { + /** + * Declare that this plugin supports minimal mode. + * In this mode, the automated minimal mode is not applied to this plugin. + * + * The plugin MUST follow the design guide to behave like it is in the automated minimal mode, e.g.: + * + * - Do not display full UI in PostInspector + * - Do not display full UI in DecryptedPostInspector + */ + // TODO: implement this flag when there is use case. + // UX_NEED_APPROVAL_manualMinimalMode?: boolean + } } /** This part runs in the SNSAdaptor */ @@ -604,7 +605,22 @@ export interface Pageable { // --------------------------------------------------- export namespace Plugin.__Host { export interface Host { + /** + * Control if the plugin is enabled or not. + * + * Note: This API currently is not in use. + * + * The "enabled/disabled" UI in the dashboard actually reflects to the "minimalMode" below. + */ enabled: EnabledStatusReporter + /** + * Control if the plugin is in the minimal mode. + * + * If it is in the minimal mode, it will be omitted in some cases. + * + * Plugin can use + */ + minimalMode: EnabledStatusReporter addI18NResource(pluginID: string, resources: Plugin.Shared.I18NResource): void createContext(id: string, signal: AbortSignal): Context signal?: AbortSignal diff --git a/packages/plugins/Wallet/src/base.ts b/packages/plugins/Wallet/src/base.ts index ce8f635f3b68..e3cdb14032e9 100644 --- a/packages/plugins/Wallet/src/base.ts +++ b/packages/plugins/Wallet/src/base.ts @@ -13,6 +13,5 @@ export const base: Plugin.Shared.Definition = { networks: { type: 'opt-out', networks: {} }, target: 'stable', }, - management: { alwaysOn: true }, i18n: languages, } diff --git a/packages/shared-base/src/Messages/Mask.ts b/packages/shared-base/src/Messages/Mask.ts index 894426d3a25a..497d82ae2f26 100644 --- a/packages/shared-base/src/Messages/Mask.ts +++ b/packages/shared-base/src/Messages/Mask.ts @@ -68,8 +68,7 @@ export interface MaskEvents extends MaskSettingsEvents, MaskMobileOnlyEvents, Ma restoreSuccess: void profilesChanged: UpdateEvent[] relationsChanged: RelationChangedEvent[] - pluginEnabled: string - pluginDisabled: string + pluginMinimalModeChanged: [id: string, newStatus: boolean] requestExtensionPermission: RequestExtensionPermissionEvent signRequestApproved: PersonaSignApprovedEvent From 7f45e757fbf3cabe97d8a1d7538851e8f2a4d32c Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Thu, 16 Dec 2021 17:25:47 +0800 Subject: [PATCH 15/28] feat: check persona connect status in plugin wrapper --- .../DataSource/usePersonaConnectStatus.ts | 39 +++++++++++++++ .../DecryptedPost/DecryptPostFailed.tsx | 47 +----------------- .../DisabledPluginSuggestion.tsx | 1 + .../InjectedComponents/ToolboxUnstyled.tsx | 48 +++++-------------- .../mask/src/plugins/MaskPluginWrapper.tsx | 45 ++++++++++++++--- 5 files changed, 92 insertions(+), 88 deletions(-) create mode 100644 packages/mask/src/components/DataSource/usePersonaConnectStatus.ts diff --git a/packages/mask/src/components/DataSource/usePersonaConnectStatus.ts b/packages/mask/src/components/DataSource/usePersonaConnectStatus.ts new file mode 100644 index 000000000000..63149f039159 --- /dev/null +++ b/packages/mask/src/components/DataSource/usePersonaConnectStatus.ts @@ -0,0 +1,39 @@ +import { DashboardRoutes, ProfileIdentifier } from '@masknet/shared-base' +import stringify from 'json-stable-stringify' +import { useMemo } from 'react' +import Services from '../../extension/service' +import { currentSetupGuideStatus } from '../../settings/settings' +import { activatedSocialNetworkUI } from '../../social-network' +import { SetupGuideStep } from '../InjectedComponents/SetupGuide' +import { useLastRecognizedIdentity } from './useActivatedUI' +import { useMyPersonas } from './useMyPersonas' + +export function usePersonaConnectStatus() { + const personas = useMyPersonas() + const lastRecognized = useLastRecognizedIdentity() + + const createPersona = () => { + Services.Welcome.openOptionsPage(DashboardRoutes.Setup) + } + + const connectPersona = async () => { + const currentPersonaIdentifier = await Services.Settings.getCurrentPersonaIdentifier() + currentSetupGuideStatus[activatedSocialNetworkUI.networkIdentifier].value = stringify({ + status: SetupGuideStep.FindUsername, + persona: currentPersonaIdentifier?.toText(), + }) + } + + return useMemo(() => { + const id = new ProfileIdentifier(activatedSocialNetworkUI.networkIdentifier, lastRecognized.identifier.userId) + let connected = false + personas.forEach((p) => { + p.identifier + if (p.linkedProfiles.get(id)) { + connected = true + } + }) + const action = !personas.length ? createPersona : !connected ? connectPersona : null + return { connected, action, hasPersona: !!personas.length } + }, [personas, lastRecognized, activatedSocialNetworkUI]) +} diff --git a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx index fbf88738dc36..0c59454c81f9 100644 --- a/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx +++ b/packages/mask/src/components/InjectedComponents/DecryptedPost/DecryptPostFailed.tsx @@ -6,26 +6,6 @@ import { DecryptFailedReason } from '../../../utils/constants' import type { ProfileIdentifier } from '@masknet/shared-base' import { wrapAuthorDifferentMessage } from './authorDifferentMessage' import MaskPluginWrapper from '../../../plugins/MaskPluginWrapper' -import { useMyPersonas } from '../../DataSource/useMyPersonas' -import { Button } from '@mui/material' -import { Services } from '../../../extension/service' -import stringify from 'json-stable-stringify' -import { DashboardRoutes } from '@masknet/shared-base' -import { currentSetupGuideStatus } from '../../../settings/settings' -import { activatedSocialNetworkUI } from '../../../social-network' -import { SetupGuideStep } from '../SetupGuide' -import { makeStyles, MaskColorVar } from '@masknet/theme' - -const useStyles = makeStyles()(() => { - return { - button: { - color: MaskColorVar.twitterButtonText, - '&,&:hover': { - background: MaskColorVar.twitterButton, - }, - }, - } -}) export interface DecryptPostFailedProps { error: Error @@ -39,32 +19,9 @@ export interface DecryptPostFailedProps { export const DecryptPostFailed = memo(function DecryptPostFailed(props: DecryptPostFailedProps) { const { AdditionalContentProps, author, postedBy, error } = props const { t } = useI18N() - const { classes } = useStyles() - const personas = useMyPersonas() - const onClick = async () => { - if (!personas.length) { - Services.Welcome.openOptionsPage(DashboardRoutes.Setup) - } else { - const currentPersona = await Services.Settings.getCurrentPersonaIdentifier() - currentSetupGuideStatus[activatedSocialNetworkUI.networkIdentifier].value = stringify({ - status: SetupGuideStep.FindUsername, - persona: currentPersona?.toText(), - }) - } - } + if (error?.message === DecryptFailedReason.MyCryptoKeyNotFound) { - const name = personas.length ? t('please_connect_persona') : t('please_create_persona') - const button = personas.length ? t('connect_persona') : t('create_persona') - return ( - - {button} - - } - /> - ) + return } return ( x.ID)) const minimalMode = new Set(useActivatedPluginsSNSAdaptor(true).map((x) => x.ID)) + console.log(minimalMode) const disabledPlugins = [...registeredPlugins].filter((x) => !activated.has(x.ID) || minimalMode.has(x.ID)) return disabledPlugins } diff --git a/packages/mask/src/components/InjectedComponents/ToolboxUnstyled.tsx b/packages/mask/src/components/InjectedComponents/ToolboxUnstyled.tsx index 38d2e0645632..399897911df2 100644 --- a/packages/mask/src/components/InjectedComponents/ToolboxUnstyled.tsx +++ b/packages/mask/src/components/InjectedComponents/ToolboxUnstyled.tsx @@ -24,7 +24,6 @@ import { } from '@masknet/plugin-infra' import { useCallback, useMemo } from 'react' import { useRemoteControlledDialog, WalletIcon } from '@masknet/shared' -import { ProfileIdentifier, DashboardRoutes } from '@masknet/shared-base' import { WalletMessages } from '../../plugins/Wallet/messages' import { hasNativeAPI, nativeAPI, useI18N } from '../../utils' import { useRecentTransactions } from '../../plugins/Wallet/hooks/useRecentTransactions' @@ -32,13 +31,7 @@ import GuideStep from '../GuideStep' import { MaskFilledIcon } from '../../resources/MaskIcon' import { makeStyles } from '@masknet/theme' import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord' -import { useMyPersonas } from '../DataSource/useMyPersonas' -import { useLastRecognizedIdentity } from '../DataSource/useActivatedUI' -import { activatedSocialNetworkUI } from '../../social-network' -import { Services } from '../../extension/service' -import { currentSetupGuideStatus } from '../../settings/settings' -import { SetupGuideStep } from './SetupGuide' -import stringify from 'json-stable-stringify' +import { usePersonaConnectStatus } from '../DataSource/usePersonaConnectStatus' const useStyles = makeStyles()((theme) => ({ font: { @@ -102,37 +95,18 @@ export function ToolboxHintUnstyled(props: ToolboxHintProps) { const networkDescriptor = useNetworkDescriptor() const providerDescriptor = useProviderDescriptor() - - const personas = useMyPersonas() - const lastRecognized = useLastRecognizedIdentity() - - const personaConnected = useMemo(() => { - const id = new ProfileIdentifier(activatedSocialNetworkUI.networkIdentifier, lastRecognized.identifier.userId) - let connected = false - personas.forEach((p) => { - if (p.linkedProfiles.get(id)) { - connected = true - } - }) - return connected - }, [personas, lastRecognized, activatedSocialNetworkUI]) + const personaConnectStatus = usePersonaConnectStatus() const title = useMemo(() => { - return !personas.length ? t('create_persona') : !personaConnected ? t('connect_persona') : walletTitle - }, [personas, personaConnected, walletTitle, t]) - - const onClick = async () => { - if (!personas.length) { - Services.Welcome.openOptionsPage(DashboardRoutes.Setup) - } else if (!personaConnected) { - const currentPersona = await Services.Settings.getCurrentPersonaIdentifier() - currentSetupGuideStatus[activatedSocialNetworkUI.networkIdentifier].value = stringify({ - status: SetupGuideStep.FindUsername, - persona: currentPersona?.toText(), - }) - } else { - openWallet() - } + return !personaConnectStatus.hasPersona + ? t('create_persona') + : !personaConnectStatus.connected + ? t('connect_persona') + : walletTitle + }, [personaConnectStatus, walletTitle, t]) + + const onClick = () => { + personaConnectStatus.action ? personaConnectStatus.action() : openWallet() } return ( diff --git a/packages/mask/src/plugins/MaskPluginWrapper.tsx b/packages/mask/src/plugins/MaskPluginWrapper.tsx index 0fb93f26f5c1..b38a18571521 100644 --- a/packages/mask/src/plugins/MaskPluginWrapper.tsx +++ b/packages/mask/src/plugins/MaskPluginWrapper.tsx @@ -1,9 +1,11 @@ -import { Typography, SnackbarContent } from '@mui/material' -import { makeStyles } from '@masknet/theme' +import { Typography, SnackbarContent, Button } from '@mui/material' +import { makeStyles, MaskColorVar } from '@masknet/theme' import { activatedSocialNetworkUI } from '../social-network' import { MaskIcon } from '../resources/MaskIcon' -import { Suspense, ReactNode } from 'react' +import { Suspense, ReactNode, useMemo } from 'react' import { isTwitter } from '../social-network-adaptor/twitter.com/base' +import { usePersonaConnectStatus } from '../components/DataSource/usePersonaConnectStatus' +import { useI18N } from '../utils' interface PluginWrapperProps extends React.PropsWithChildren<{}> { pluginName: string @@ -48,12 +50,43 @@ const useStyles = makeStyles()((theme) => { borderTop: `1px solid ${theme.palette.divider}`, padding: theme.spacing(2), }, + button: { + color: MaskColorVar.twitterButtonText, + '&,&:hover': { + background: MaskColorVar.twitterButton, + }, + }, } }) export default function MaskPluginWrapper(props: PluginWrapperProps) { const { classes } = useStyles() const { pluginName, children, action } = props + const personaConnectStatus = usePersonaConnectStatus() + const { t } = useI18N() + + const renderChildren = useMemo(() => { + return personaConnectStatus.connected && children + }, [personaConnectStatus, children]) + + const name = useMemo(() => { + return !personaConnectStatus.hasPersona + ? t('please_create_persona') + : !personaConnectStatus.connected + ? t('please_connect_persona') + : pluginName + }, [personaConnectStatus, pluginName]) + + const actionButton = useMemo(() => { + if (!personaConnectStatus.action) return null + + const button = personaConnectStatus.hasPersona ? t('connect_persona') : t('create_persona') + return ( + + ) + }, [personaConnectStatus]) const inner = (
ev.stopPropagation()}> @@ -64,12 +97,12 @@ export default function MaskPluginWrapper(props: PluginWrapperProps) { Mask Plugin - {pluginName} + {name}
-
{action}
+
{actionButton || action}
- {children ?
{children}
: null} + {renderChildren ?
{children}
: null}
) return } children={inner} /> From bf35378134d1b5bf9d44ce5e4747caba7bf0311a Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Thu, 16 Dec 2021 17:26:35 +0800 Subject: [PATCH 16/28] fix: typo --- .../components/InjectedComponents/DisabledPluginSuggestion.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx index 0e59e5f21cb8..782e74d2dfc1 100644 --- a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx +++ b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx @@ -14,7 +14,6 @@ import { useI18N } from '../../utils' function useDisabledPlugins() { const activated = new Set(useActivatedPluginsSNSAdaptor('any').map((x) => x.ID)) const minimalMode = new Set(useActivatedPluginsSNSAdaptor(true).map((x) => x.ID)) - console.log(minimalMode) const disabledPlugins = [...registeredPlugins].filter((x) => !activated.has(x.ID) || minimalMode.has(x.ID)) return disabledPlugins } From 668375a91e1acca1d3392228eb70453530402232 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Thu, 16 Dec 2021 17:40:44 +0800 Subject: [PATCH 17/28] fix: inversed options --- .../mask/src/extension/background-script/SettingsService.ts | 6 +++--- packages/mask/src/settings/settings.ts | 6 +++++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/mask/src/extension/background-script/SettingsService.ts b/packages/mask/src/extension/background-script/SettingsService.ts index 7258127d33f9..6f7fd8e0ddac 100644 --- a/packages/mask/src/extension/background-script/SettingsService.ts +++ b/packages/mask/src/extension/background-script/SettingsService.ts @@ -5,7 +5,7 @@ import { appearanceSettings, currentPersonaIdentifier, languageSettings, - currentPluginEnabledStatus, + currentPluginMinimalModeNOTEnabled, pluginIDSettings, } from '../../settings/settings' import { @@ -123,10 +123,10 @@ export async function setCurrentPersonaIdentifier(x: PersonaIdentifier) { currentPersonaIdentifier.value = x.toText() } export async function getPluginMinimalModeEnabled(id: string) { - return currentPluginEnabledStatus['plugin:' + id].value + return !currentPluginMinimalModeNOTEnabled['plugin:' + id].value } export async function setPluginMinimalModeEnabled(id: string, enabled: boolean) { - currentPluginEnabledStatus['plugin:' + id].value = enabled + currentPluginMinimalModeNOTEnabled['plugin:' + id].value = !enabled MaskMessages.events.pluginMinimalModeChanged.sendToAll([id, enabled]) } diff --git a/packages/mask/src/settings/settings.ts b/packages/mask/src/settings/settings.ts index cc0501082e52..b26a0119b832 100644 --- a/packages/mask/src/settings/settings.ts +++ b/packages/mask/src/settings/settings.ts @@ -73,7 +73,11 @@ export const userGuideStatus: NetworkSettings = createNetworkSettings('u * use `useActivatedPluginsSNSAdaptor().find((x) => x.ID === PLUGIN_ID)` or * `useActivatedPluginsDashboard().find((x) => x.ID === PLUGIN_ID)` instead */ -export const currentPluginEnabledStatus: NetworkSettings = createNetworkSettings('pluginsEnabled', true) +// This was "currentPluginEnabled" before, but we used it to represent minimal mode now to make the settings be able to migrate. +export const currentPluginMinimalModeNOTEnabled: NetworkSettings = createNetworkSettings( + 'pluginsEnabled', + true, +) //#endregion export const launchPageSettings = createGlobalSettings('launchPage', LaunchPage.dashboard, { From 56402b1ebce391204c71b8554e3c05b2cb686c41 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Thu, 16 Dec 2021 17:42:12 +0800 Subject: [PATCH 18/28] fix: inversed options --- packages/dashboard/src/pages/Labs/index.tsx | 2 +- packages/mask/src/utils/native-rpc/Web.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/dashboard/src/pages/Labs/index.tsx b/packages/dashboard/src/pages/Labs/index.tsx index fc05d3a4f966..17818a94b26c 100644 --- a/packages/dashboard/src/pages/Labs/index.tsx +++ b/packages/dashboard/src/pages/Labs/index.tsx @@ -223,7 +223,7 @@ export default function Plugins() { useEffect(() => { Object.values(PLUGIN_IDS).forEach(async (id) => { - const enabled = await Services.Settings.getPluginMinimalModeEnabled(id) + const enabled = !(await Services.Settings.getPluginMinimalModeEnabled(id)) setPluginStatus((status) => ({ ...status, [id]: enabled })) }) }, []) diff --git a/packages/mask/src/utils/native-rpc/Web.ts b/packages/mask/src/utils/native-rpc/Web.ts index 7173b4de059a..891286a0ffcb 100644 --- a/packages/mask/src/utils/native-rpc/Web.ts +++ b/packages/mask/src/utils/native-rpc/Web.ts @@ -101,8 +101,8 @@ export const MaskNetworkAPI: MaskNetworkAPIs = { }) return stringify(connectedPersonas) }, - app_isPluginEnabled: ({ pluginID }) => Services.Settings.getPluginMinimalModeEnabled(pluginID), - app_setPluginStatus: ({ pluginID, enabled }) => Services.Settings.setPluginMinimalModeEnabled(pluginID, enabled), + app_isPluginEnabled: ({ pluginID }) => Services.Settings.getPluginMinimalModeEnabled(pluginID).then((x) => !x), + app_setPluginStatus: ({ pluginID, enabled }) => Services.Settings.setPluginMinimalModeEnabled(pluginID, !enabled), setting_getNetworkTraderProvider: ({ network }) => { switch (network) { case NetworkType.Ethereum: From db8907802056c5530d7840472e9bb2c08b284f62 Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Thu, 16 Dec 2021 17:57:04 +0800 Subject: [PATCH 19/28] fix: minimal mode switch --- packages/dashboard/src/pages/Labs/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/dashboard/src/pages/Labs/index.tsx b/packages/dashboard/src/pages/Labs/index.tsx index 17818a94b26c..444b88f606d5 100644 --- a/packages/dashboard/src/pages/Labs/index.tsx +++ b/packages/dashboard/src/pages/Labs/index.tsx @@ -197,7 +197,7 @@ export default function Plugins() { const { openDialog: openSwapDialog } = useRemoteControlledDialog(PluginMessages.Swap.swapDialogUpdated) async function onSwitch(id: string, checked: boolean) { - await Services.Settings.setPluginMinimalModeEnabled(id, checked) + await Services.Settings.setPluginMinimalModeEnabled(id, !checked) setPluginStatus({ ...pluginStatus, [id]: checked }) } From fd420c02bddd1bffe71eeae4e9e0d29c5ceae6ba Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Thu, 16 Dec 2021 18:02:03 +0800 Subject: [PATCH 20/28] fix: minimal mode switch --- .../components/InjectedComponents/DisabledPluginSuggestion.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx index 782e74d2dfc1..73f6ce03c126 100644 --- a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx +++ b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx @@ -62,7 +62,7 @@ export function PossiblePluginSuggestionUI(props: { plugins: Plugin.DeferredDefi action={ Services.Settings.setPluginMinimalModeEnabled(x.ID, true)} + onChange={() => Services.Settings.setPluginMinimalModeEnabled(x.ID, false)} /> } /> From 7fef05b0cfc9223e545d1bd5e4ddd1dcad31b802 Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Tue, 21 Dec 2021 19:12:04 +0800 Subject: [PATCH 21/28] feat: add minimal mode check for pets plugin --- packages/mask/src/plugins/Pets/SNSAdaptor/animate.tsx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/mask/src/plugins/Pets/SNSAdaptor/animate.tsx b/packages/mask/src/plugins/Pets/SNSAdaptor/animate.tsx index 295f78502587..777087a322f1 100644 --- a/packages/mask/src/plugins/Pets/SNSAdaptor/animate.tsx +++ b/packages/mask/src/plugins/Pets/SNSAdaptor/animate.tsx @@ -5,6 +5,9 @@ import Drag from './drag' import AnimatedMessage from './animatedMsg' import Tip from './tooltip' import { useCurrentVisitingIdentity } from '../../../components/DataSource/useActivatedUI' +import { PetsPluginID } from '../constants' +import { currentPluginMinimalModeNOTEnabled } from '../../../settings/settings' +import { useValueRef } from '@masknet/shared' const useStyles = makeStyles()(() => ({ root: { @@ -36,13 +39,14 @@ const AnimatePic = () => { const [show, setShow] = useState(false) const [infoShow, setInfoShow] = useState(false) + const enabled = useValueRef(currentPluginMinimalModeNOTEnabled['plugin:' + PetsPluginID]) const identity = useCurrentVisitingIdentity() useEffect(() => { const userId = identity.identifier.userId const maskId = 'realMaskNetwork' - setShow(userId === maskId) - }, [identity]) + setShow(enabled && userId === maskId) + }, [identity, enabled]) const handleClose = () => setShow(false) const handleMouseEnter = () => setInfoShow(true) From 0d5ef383a6b62879129afccd77dab1090982d395 Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Tue, 21 Dec 2021 19:55:09 +0800 Subject: [PATCH 22/28] feat: add publisher info for ITO & Lucky Drop --- .../mask/src/plugins/ITO/SNSAdaptor/index.tsx | 2 +- .../mask/src/plugins/MaskPluginWrapper.tsx | 31 +++++++++++++++---- .../plugins/RedPacket/SNSAdaptor/index.tsx | 2 +- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx b/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx index d0bb551acca5..9fcbbd6d364b 100644 --- a/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/ITO/SNSAdaptor/index.tsx @@ -35,7 +35,7 @@ const sns: Plugin.SNSAdaptor.Definition = { const payload = ITO_MetadataReader(props.message.meta) if (!payload.ok) return null return ( - + diff --git a/packages/mask/src/plugins/MaskPluginWrapper.tsx b/packages/mask/src/plugins/MaskPluginWrapper.tsx index b38a18571521..aa7ccf9da567 100644 --- a/packages/mask/src/plugins/MaskPluginWrapper.tsx +++ b/packages/mask/src/plugins/MaskPluginWrapper.tsx @@ -1,4 +1,4 @@ -import { Typography, SnackbarContent, Button } from '@mui/material' +import { Typography, SnackbarContent, Button, Link } from '@mui/material' import { makeStyles, MaskColorVar } from '@masknet/theme' import { activatedSocialNetworkUI } from '../social-network' import { MaskIcon } from '../resources/MaskIcon' @@ -6,11 +6,14 @@ import { Suspense, ReactNode, useMemo } from 'react' import { isTwitter } from '../social-network-adaptor/twitter.com/base' import { usePersonaConnectStatus } from '../components/DataSource/usePersonaConnectStatus' import { useI18N } from '../utils' +import { Box } from '@mui/system' +import type { Plugin } from '@masknet/plugin-infra' interface PluginWrapperProps extends React.PropsWithChildren<{}> { pluginName: string width?: number action?: ReactNode + publisher?: Plugin.Shared.Publisher } const useStyles = makeStyles()((theme) => { @@ -61,7 +64,7 @@ const useStyles = makeStyles()((theme) => { export default function MaskPluginWrapper(props: PluginWrapperProps) { const { classes } = useStyles() - const { pluginName, children, action } = props + const { pluginName, children, action, publisher } = props const personaConnectStatus = usePersonaConnectStatus() const { t } = useI18N() @@ -88,19 +91,35 @@ export default function MaskPluginWrapper(props: PluginWrapperProps) { ) }, [personaConnectStatus]) + const publisherInfo = useMemo(() => { + if (!publisher) return null + return ( + + + Provided by + + + + {publisher.name.fallback} + + + + ) + }, [publisher]) + const inner = (
ev.stopPropagation()}>
- +
- + Mask Plugin - + {name}
-
{actionButton || action}
+
{actionButton || action || publisherInfo}
{renderChildren ?
{children}
: null}
diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx index 38de5fba3e6c..6e2c3b9da82b 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx @@ -28,7 +28,7 @@ const sns: Plugin.SNSAdaptor.Definition = { DecryptedInspector(props) { if (RedPacketMetadataReader(props.message.meta).ok) return ( - + {renderWithRedPacketMetadata(props.message.meta, (r) => ( ))} From 68d9ba5870b1eccbae3e670c97be73be55e0f971 Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Wed, 22 Dec 2021 15:32:53 +0800 Subject: [PATCH 23/28] feat: add publisher info for NFT Lucky Drop & MaskBox --- packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx | 2 +- packages/mask/src/plugins/MaskPluginWrapper.tsx | 8 ++++---- packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx b/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx index 318dcc2b990c..2be5497bfe2c 100644 --- a/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/MaskBox/SNSAdaptor/index.tsx @@ -39,7 +39,7 @@ function Renderer(props: React.PropsWithChildren<{ url: string }>) { if (!chainId || !boxId) return null return ( - + }> diff --git a/packages/mask/src/plugins/MaskPluginWrapper.tsx b/packages/mask/src/plugins/MaskPluginWrapper.tsx index aa7ccf9da567..1b5ef25daae2 100644 --- a/packages/mask/src/plugins/MaskPluginWrapper.tsx +++ b/packages/mask/src/plugins/MaskPluginWrapper.tsx @@ -95,11 +95,11 @@ export default function MaskPluginWrapper(props: PluginWrapperProps) { if (!publisher) return null return ( - + Provided by - + {publisher.name.fallback} @@ -112,10 +112,10 @@ export default function MaskPluginWrapper(props: PluginWrapperProps) {
- + Mask Plugin - + {name}
diff --git a/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx b/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx index 6e2c3b9da82b..6af008f503b1 100644 --- a/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx +++ b/packages/mask/src/plugins/RedPacket/SNSAdaptor/index.tsx @@ -37,7 +37,7 @@ const sns: Plugin.SNSAdaptor.Definition = { if (RedPacketNftMetadataReader(props.message.meta).ok) return ( - + {renderWithRedPacketNftMetadata(props.message.meta, (r) => ( ))} From f45f503f5b45f9c4cbf823a955415faa6fccfaef Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Fri, 24 Dec 2021 14:28:42 +0800 Subject: [PATCH 24/28] chore: reply review --- .../DataSource/usePersonaConnectStatus.ts | 24 +++++++++---------- .../src/plugins/Pets/SNSAdaptor/animate.tsx | 9 ++++--- 2 files changed, 16 insertions(+), 17 deletions(-) diff --git a/packages/mask/src/components/DataSource/usePersonaConnectStatus.ts b/packages/mask/src/components/DataSource/usePersonaConnectStatus.ts index 63149f039159..82f9f49f67b9 100644 --- a/packages/mask/src/components/DataSource/usePersonaConnectStatus.ts +++ b/packages/mask/src/components/DataSource/usePersonaConnectStatus.ts @@ -8,22 +8,22 @@ import { SetupGuideStep } from '../InjectedComponents/SetupGuide' import { useLastRecognizedIdentity } from './useActivatedUI' import { useMyPersonas } from './useMyPersonas' +const createPersona = () => { + Services.Welcome.openOptionsPage(DashboardRoutes.Setup) +} + +const connectPersona = async () => { + const currentPersonaIdentifier = await Services.Settings.getCurrentPersonaIdentifier() + currentSetupGuideStatus[activatedSocialNetworkUI.networkIdentifier].value = stringify({ + status: SetupGuideStep.FindUsername, + persona: currentPersonaIdentifier?.toText(), + }) +} + export function usePersonaConnectStatus() { const personas = useMyPersonas() const lastRecognized = useLastRecognizedIdentity() - const createPersona = () => { - Services.Welcome.openOptionsPage(DashboardRoutes.Setup) - } - - const connectPersona = async () => { - const currentPersonaIdentifier = await Services.Settings.getCurrentPersonaIdentifier() - currentSetupGuideStatus[activatedSocialNetworkUI.networkIdentifier].value = stringify({ - status: SetupGuideStep.FindUsername, - persona: currentPersonaIdentifier?.toText(), - }) - } - return useMemo(() => { const id = new ProfileIdentifier(activatedSocialNetworkUI.networkIdentifier, lastRecognized.identifier.userId) let connected = false diff --git a/packages/mask/src/plugins/Pets/SNSAdaptor/animate.tsx b/packages/mask/src/plugins/Pets/SNSAdaptor/animate.tsx index 777087a322f1..22abc0b7888a 100644 --- a/packages/mask/src/plugins/Pets/SNSAdaptor/animate.tsx +++ b/packages/mask/src/plugins/Pets/SNSAdaptor/animate.tsx @@ -6,8 +6,7 @@ import AnimatedMessage from './animatedMsg' import Tip from './tooltip' import { useCurrentVisitingIdentity } from '../../../components/DataSource/useActivatedUI' import { PetsPluginID } from '../constants' -import { currentPluginMinimalModeNOTEnabled } from '../../../settings/settings' -import { useValueRef } from '@masknet/shared' +import { useIsMinimalMode } from '@masknet/plugin-infra' const useStyles = makeStyles()(() => ({ root: { @@ -39,14 +38,14 @@ const AnimatePic = () => { const [show, setShow] = useState(false) const [infoShow, setInfoShow] = useState(false) - const enabled = useValueRef(currentPluginMinimalModeNOTEnabled['plugin:' + PetsPluginID]) + const disabled = useIsMinimalMode(PetsPluginID) const identity = useCurrentVisitingIdentity() useEffect(() => { const userId = identity.identifier.userId const maskId = 'realMaskNetwork' - setShow(enabled && userId === maskId) - }, [identity, enabled]) + setShow(!disabled && userId === maskId) + }, [identity, disabled]) const handleClose = () => setShow(false) const handleMouseEnter = () => setInfoShow(true) From aa5c1ad8876575357b187da334c9721a24023b30 Mon Sep 17 00:00:00 2001 From: Jack Works Date: Wed, 29 Dec 2021 14:24:16 +0800 Subject: [PATCH 25/28] fix: boundary --- packages/mask/src/web3/UI/EthereumChainBoundary.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mask/src/web3/UI/EthereumChainBoundary.tsx b/packages/mask/src/web3/UI/EthereumChainBoundary.tsx index 32f0f38d865d..869a9afadbc9 100644 --- a/packages/mask/src/web3/UI/EthereumChainBoundary.tsx +++ b/packages/mask/src/web3/UI/EthereumChainBoundary.tsx @@ -44,7 +44,7 @@ export function EthereumChainBoundary(props: EthereumChainBoundaryProps) { const { t } = useI18N() const pluginID = usePluginIDContext() - const plugin = useActivatedPlugin(pluginID) + const plugin = useActivatedPlugin(pluginID, 'any') const account = useAccount() const chainId = useChainId() From 0c2e61357f17da1ceecac6892a8b458604f7e6af Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Wed, 29 Dec 2021 15:43:25 +0800 Subject: [PATCH 26/28] feat: show plugin name --- packages/mask/src/plugins/MaskPluginWrapper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mask/src/plugins/MaskPluginWrapper.tsx b/packages/mask/src/plugins/MaskPluginWrapper.tsx index 1b5ef25daae2..254bcffc1bd4 100644 --- a/packages/mask/src/plugins/MaskPluginWrapper.tsx +++ b/packages/mask/src/plugins/MaskPluginWrapper.tsx @@ -113,7 +113,7 @@ export default function MaskPluginWrapper(props: PluginWrapperProps) {
- Mask Plugin + Mask Plugin {!personaConnectStatus.connected && pluginName ? `(${pluginName})` : ''} {name} From 7e0b7280096b36e5151d8953b9ccd437a5563164 Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Fri, 31 Dec 2021 14:42:40 +0800 Subject: [PATCH 27/28] refactor: reply review --- .../mask/src/plugins/MaskPluginWrapper.tsx | 20 +++++++------------ 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/packages/mask/src/plugins/MaskPluginWrapper.tsx b/packages/mask/src/plugins/MaskPluginWrapper.tsx index 254bcffc1bd4..98b7c47a73d0 100644 --- a/packages/mask/src/plugins/MaskPluginWrapper.tsx +++ b/packages/mask/src/plugins/MaskPluginWrapper.tsx @@ -68,17 +68,11 @@ export default function MaskPluginWrapper(props: PluginWrapperProps) { const personaConnectStatus = usePersonaConnectStatus() const { t } = useI18N() - const renderChildren = useMemo(() => { - return personaConnectStatus.connected && children - }, [personaConnectStatus, children]) - - const name = useMemo(() => { - return !personaConnectStatus.hasPersona - ? t('please_create_persona') - : !personaConnectStatus.connected - ? t('please_connect_persona') - : pluginName - }, [personaConnectStatus, pluginName]) + const name = !personaConnectStatus.hasPersona + ? t('please_create_persona') + : !personaConnectStatus.connected + ? t('please_connect_persona') + : pluginName const actionButton = useMemo(() => { if (!personaConnectStatus.action) return null @@ -89,7 +83,7 @@ export default function MaskPluginWrapper(props: PluginWrapperProps) { {button} ) - }, [personaConnectStatus]) + }, [personaConnectStatus, t]) const publisherInfo = useMemo(() => { if (!publisher) return null @@ -121,7 +115,7 @@ export default function MaskPluginWrapper(props: PluginWrapperProps) {
{actionButton || action || publisherInfo}
- {renderChildren ?
{children}
: null} + {personaConnectStatus.connected && children ?
{children}
: null}
) return } children={inner} /> From d8f092f9813f145bfc5ef85ad0203fc42a6d541d Mon Sep 17 00:00:00 2001 From: Hom Yan Date: Fri, 31 Dec 2021 15:17:15 +0800 Subject: [PATCH 28/28] fix: merge --- .../InjectedComponents/DisabledPluginSuggestion.tsx | 4 ++-- .../mask/src/components/InjectedComponents/ProfileSlider.tsx | 2 +- .../src/components/InjectedComponents/ProfileTabContent.tsx | 4 ++-- packages/mask/src/plugins/Polls/base.ts | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx index 73f6ce03c126..782b76887c99 100644 --- a/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx +++ b/packages/mask/src/components/InjectedComponents/DisabledPluginSuggestion.tsx @@ -44,8 +44,8 @@ export function useDisabledPluginSuggestionFromMeta(meta: ReadonlyMap } diff --git a/packages/mask/src/components/InjectedComponents/ProfileSlider.tsx b/packages/mask/src/components/InjectedComponents/ProfileSlider.tsx index 82988c29e0d4..5d0529635dfd 100644 --- a/packages/mask/src/components/InjectedComponents/ProfileSlider.tsx +++ b/packages/mask/src/components/InjectedComponents/ProfileSlider.tsx @@ -1,6 +1,6 @@ import { createInjectHooksRenderer, useActivatedPluginsSNSAdaptor } from '@masknet/plugin-infra' -const PluginRenderer = createInjectHooksRenderer(useActivatedPluginsSNSAdaptor, (x) => { +const PluginRenderer = createInjectHooksRenderer(useActivatedPluginsSNSAdaptor.visibility.useAnyMode, (x) => { return () => { return
Profile Slider
} diff --git a/packages/mask/src/components/InjectedComponents/ProfileTabContent.tsx b/packages/mask/src/components/InjectedComponents/ProfileTabContent.tsx index e41aa86b1f5b..1fef1f56d258 100644 --- a/packages/mask/src/components/InjectedComponents/ProfileTabContent.tsx +++ b/packages/mask/src/components/InjectedComponents/ProfileTabContent.tsx @@ -11,7 +11,7 @@ import { MaskMessages, useI18N } from '../../utils' import { useCurrentVisitingIdentity } from '../DataSource/useActivatedUI' function getTabContent(tabId: string) { - return createInjectHooksRenderer(useActivatedPluginsSNSAdaptor, (x) => { + return createInjectHooksRenderer(useActivatedPluginsSNSAdaptor.visibility.useAnyMode, (x) => { const tab = x.ProfileTabs?.find((x) => x.ID === tabId) if (!tab) return return tab.UI?.TabContent @@ -48,7 +48,7 @@ export function ProfileTabContent(props: ProfileTabContentProps) { const identity = useCurrentVisitingIdentity() const { value: addressNames, loading: loadingAddressNames } = useAddressNames(identity) - const tabs = useActivatedPluginsSNSAdaptor() + const tabs = useActivatedPluginsSNSAdaptor('any') .flatMap((x) => x.ProfileTabs?.map((y) => ({ ...y, pluginID: x.ID })) ?? []) .filter((z) => z.Utils?.shouldDisplay?.(identity, addressNames) ?? true) .sort((a, z) => { diff --git a/packages/mask/src/plugins/Polls/base.ts b/packages/mask/src/plugins/Polls/base.ts index 75b781cde8d3..4d2d194e3510 100644 --- a/packages/mask/src/plugins/Polls/base.ts +++ b/packages/mask/src/plugins/Polls/base.ts @@ -1,5 +1,5 @@ import type { Plugin } from '@masknet/plugin-infra' -import { PLUGIN_ID, PLUGIN_ICON, PLUGIN_NAME, PLUGIN_DESCRIPTION, POLL_META_KEY_1 } from './constants' +import { PLUGIN_ID, PLUGIN_ICON, PLUGIN_NAME, PLUGIN_DESCRIPTION, PLUGIN_META_KEY } from './constants' export const base: Plugin.Shared.Definition = { ID: PLUGIN_ID, @@ -13,5 +13,5 @@ export const base: Plugin.Shared.Definition = { target: 'insider', }, experimentalMark: true, - contribution: { metadataKeys: new Set([POLL_META_KEY_1]) }, + contribution: { metadataKeys: new Set([PLUGIN_META_KEY]) }, }