From bfd1fd021825df1db1a551928df175dcb437cb77 Mon Sep 17 00:00:00 2001 From: guanbinrui Date: Tue, 1 Sep 2020 15:19:52 +0800 Subject: [PATCH] chore: check available before displaying TrendingView --- .../InjectedComponents/PostDummy.tsx | 6 ---- src/plugins/Trader/README.md | 31 ++++++++++++++++ src/plugins/Trader/UI/TrendingPopper.tsx | 1 - src/plugins/Trader/apis/index.ts | 36 ++++++++++++++++++- src/plugins/Trader/constants.ts | 2 ++ src/plugins/Trader/define.tsx | 12 +++++-- .../messages/TypedMessageCashTrending.tsx | 16 +++++---- 7 files changed, 88 insertions(+), 16 deletions(-) create mode 100644 src/plugins/Trader/README.md create mode 100644 src/plugins/Trader/constants.ts diff --git a/src/components/InjectedComponents/PostDummy.tsx b/src/components/InjectedComponents/PostDummy.tsx index 5820e90d160..1effd5217c1 100644 --- a/src/components/InjectedComponents/PostDummy.tsx +++ b/src/components/InjectedComponents/PostDummy.tsx @@ -29,12 +29,6 @@ export function PostDummy(props: PostDummyProps) { // render dummy for posts which encrypted by maskbook (wholePostVisibilitySettings === WholePostVisibility.encryptedOnly && postPayload.ok) - console.log(`DEBUG: postDummyVisible`) - console.log({ - postDummyVisible, - wholePostVisibilitySettings, - }) - // zip original post useEffect(() => { if (postDummyVisible) props.zip?.() diff --git a/src/plugins/Trader/README.md b/src/plugins/Trader/README.md new file mode 100644 index 00000000000..9dfe199519a --- /dev/null +++ b/src/plugins/Trader/README.md @@ -0,0 +1,31 @@ +# Plugin: Trader + +## Feature Set + +- [x] View trending info of a cryptocurrency with cash tag. ++ [ ] \[TODO\] View trending info of a stock with cash tag ++ [ ] \[TODO\] Do trading between different cryptocurrencies + +## Files + +- `./apis/` - data vendor APIs +- `./hooks/` - customized hooks +- `./messages/` - customized typed messags +- `./UI/` - UI related stuff +- `./services.ts` - A plugin specific message center +- `./settings.ts` - Some plugin specific settings +- `./types.ts` - Some plugin specific TypeScript typings +- `./constants.ts` - Some plugin specific constants +- `./define.ts` - The definition of the plugin + +## Related discussion + +- + +## Pull requests + +- + +## Prototype + +- \ No newline at end of file diff --git a/src/plugins/Trader/UI/TrendingPopper.tsx b/src/plugins/Trader/UI/TrendingPopper.tsx index cf3d8e37d2d..eedffcfccb7 100644 --- a/src/plugins/Trader/UI/TrendingPopper.tsx +++ b/src/plugins/Trader/UI/TrendingPopper.tsx @@ -2,7 +2,6 @@ import React, { useState, useEffect, useRef, useMemo } from 'react' import type PopperJs from 'popper.js' import { Popper, ClickAwayListener, PopperProps } from '@material-ui/core' import { MessageCenter, ObserveCashTagEvent } from '../messages' -import { useInterval } from 'react-use' export interface TrendingPopperProps { children?: (name: string, reposition?: () => void) => React.ReactNode diff --git a/src/plugins/Trader/apis/index.ts b/src/plugins/Trader/apis/index.ts index 8247e6e1a4a..86b747a498a 100644 --- a/src/plugins/Trader/apis/index.ts +++ b/src/plugins/Trader/apis/index.ts @@ -1,7 +1,8 @@ -import { Platform, Currency, Coin, Trending, Market, Stat } from '../types' +import { Platform, Currency, Coin, Trending, Stat } from '../types' import * as coinGeckoAPI from './coingecko' import * as coinMarketCapAPI from './coinmarketcap' import { Days } from '../UI/PriceChartDaysControl' +import { getEnumAsArray } from '../../../utils/enum' export async function getCurrenies(platform: Platform): Promise { if (platform === Platform.COIN_GECKO) { @@ -46,6 +47,39 @@ export async function getCoins(platform: Platform): Promise { })) } +//#region check a specific coin is available on specific platform +const availabilityCache = new Map< + Platform, + { + supported: Set + lastUpdated: Date + } +>() + +export async function checkAvailabilityAtPlatform(platform: Platform, keyword: string) { + if ( + // cache never built before + !availabilityCache.has(platform) || + // cache expired in 24h + new Date().getTime() - (availabilityCache.get(platform)?.lastUpdated.getTime() ?? 0) > + 24 /* hours */ * 60 /* minutes */ * 60 /* seconds */ * 1000 /* milliseconds */ + ) { + const coins = await getCoins(platform) + availabilityCache.set(platform, { + supported: new Set(coins.map((x) => x.symbol.toLowerCase())), + lastUpdated: new Date(), + }) + } + return availabilityCache.get(platform)?.supported.has(keyword.toLowerCase()) ?? false +} + +export async function checkAvailability(keyword: string) { + return (await Promise.all(getEnumAsArray(Platform).map((x) => checkAvailabilityAtPlatform(x.value, keyword)))).some( + Boolean, + ) +} +//#endregion + export async function getCoinInfo(id: string, platform: Platform, currency: Currency): Promise { if (platform === Platform.COIN_GECKO) { const info = await coinGeckoAPI.getCoinInfo(id) diff --git a/src/plugins/Trader/constants.ts b/src/plugins/Trader/constants.ts new file mode 100644 index 00000000000..c71de33a4aa --- /dev/null +++ b/src/plugins/Trader/constants.ts @@ -0,0 +1,2 @@ +export const PLUGIN_IDENTIFIER = 'co.maskbook.trader' +export const PLUGIN_METADATA_KEY = 'com.maskbook.trader:1' diff --git a/src/plugins/Trader/define.tsx b/src/plugins/Trader/define.tsx index 02d3b31df9a..142c9714fa1 100644 --- a/src/plugins/Trader/define.tsx +++ b/src/plugins/Trader/define.tsx @@ -9,13 +9,17 @@ import { import { makeTypedMessageCashTrending } from './messages/TypedMessageCashTrending' import { TrendingPopper } from './UI/TrendingPopper' import { TrendingView } from './UI/TrendingView' +import Services from '../../extension/service' +import { Platform } from './types' +import { getEnumAsArray } from '../../utils/enum' +import { PLUGIN_IDENTIFIER, PLUGIN_METADATA_KEY } from './constants' const isCashTagMessage = (m: TypedMessage): m is TypedMessageAnchor => isTypedMessgaeAnchor(m) && m.category === 'cash' export const TraderPluginDefine: PluginConfig = { pluginName: 'Trader', - identifier: 'co.maskbook.trader', - postDialogMetadataBadge: new Map([['com.maskbook.trader:1', (meta) => 'no metadata']]), + identifier: PLUGIN_IDENTIFIER, + postDialogMetadataBadge: new Map([[PLUGIN_METADATA_KEY, (meta) => 'no metadata']]), postMessageProcessor(message: TypedMessageCompound) { return { ...message, @@ -23,6 +27,10 @@ export const TraderPluginDefine: PluginConfig = { } }, pageInspector() { + // build availability cache in the background page + getEnumAsArray(Platform).forEach((p) => + Services.Plugin.invokePlugin('maskbook.trader', 'checkAvailability', 'BTC'), + ) return ( {(name: string, reposition?: () => void) => } diff --git a/src/plugins/Trader/messages/TypedMessageCashTrending.tsx b/src/plugins/Trader/messages/TypedMessageCashTrending.tsx index ff813ce7bec..2faef19a735 100644 --- a/src/plugins/Trader/messages/TypedMessageCashTrending.tsx +++ b/src/plugins/Trader/messages/TypedMessageCashTrending.tsx @@ -3,6 +3,7 @@ import { TypedMessageAnchor, registerTypedMessageRenderer } from '../../../proto import { Link, Typography } from '@material-ui/core' import type { TypedMessageRendererProps } from '../../../components/InjectedComponents/TypedMessageRenderer' import { MessageCenter } from '../messages' +import Services from '../../../extension/service' export interface TypedMessageCashTrending extends Omit { readonly type: 'anchor/cash_trending' @@ -24,13 +25,16 @@ registerTypedMessageRenderer('anchor/cash_trending', { }) function DefaultTypedMessageCashTrendingRenderer(props: TypedMessageRendererProps) { - const onHoverCashTag = (ev: React.MouseEvent) => { - MessageCenter.emit('cashTagObserved', { - name: props.message.name, - element: ev.currentTarget, - }) + const onHoverCashTag = async (ev: React.MouseEvent) => { + // should cache before async operations + const element = ev.currentTarget + if (await Services.Plugin.invokePlugin('maskbook.trader', 'checkAvailability', props.message.name)) { + MessageCenter.emit('cashTagObserved', { + name: props.message.name, + element, + }) + } } - return (