From 870f477475404e5e4813b73744faf062591b1685 Mon Sep 17 00:00:00 2001 From: guanbinrui Date: Mon, 24 Aug 2020 15:37:39 +0800 Subject: [PATCH] chore(ui): add TrendingView --- .../shared-settings/useSettingsUI.tsx | 7 +- .../background-script/PluginService.ts | 2 +- src/plugins/Gitcoin/DonateDialog.tsx | 6 +- src/plugins/Trader/UI/SettingsDialog.tsx | 174 ++++++++++++++++++ src/plugins/Trader/UI/TreadingView.tsx | 0 src/plugins/Trader/UI/TrendingView.tsx | 113 ++++++++++++ src/plugins/Trader/apis/coingecko/index.ts | 4 +- src/plugins/Trader/apis/index.ts | 19 ++ src/plugins/Trader/define.tsx | 13 +- .../Trader/{service.ts => services.ts} | 0 src/plugins/Trader/settings.ts | 4 + src/plugins/Trader/type.ts | 34 ++++ .../twitter.com/utils/theme.ts | 1 + src/utils/enum.ts | 8 + 14 files changed, 376 insertions(+), 9 deletions(-) create mode 100644 src/plugins/Trader/UI/SettingsDialog.tsx delete mode 100644 src/plugins/Trader/UI/TreadingView.tsx create mode 100644 src/plugins/Trader/UI/TrendingView.tsx create mode 100644 src/plugins/Trader/apis/index.ts rename src/plugins/Trader/{service.ts => services.ts} (100%) create mode 100644 src/plugins/Trader/settings.ts create mode 100644 src/plugins/Trader/type.ts create mode 100644 src/utils/enum.ts diff --git a/src/components/shared-settings/useSettingsUI.tsx b/src/components/shared-settings/useSettingsUI.tsx index 7f9969a0b45b..7c7329a62f05 100644 --- a/src/components/shared-settings/useSettingsUI.tsx +++ b/src/components/shared-settings/useSettingsUI.tsx @@ -16,6 +16,7 @@ import { } from '@material-ui/core' import ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos' import { useStylesExtends } from '../custom-ui-helper' +import { getEnumAsArray } from '../../utils/enum' const useStyles = makeStyles((theme) => createStyles({ @@ -153,16 +154,12 @@ export function useSettingsUI(ref: ValueRef) { function useEnumSettings( ...[ref, enumObject, getText, selectProps]: useEnumSettingsParams ): HookedUI { - const enum_ = Object.keys(enumObject) - // Leave only key of enum - .filter((x) => Number.isNaN(parseInt(x))) - .map((key) => ({ key, value: enumObject[key as keyof Q] })) + const enum_ = getEnumAsArray(enumObject) const change = (value: any) => { if (!Number.isNaN(parseInt(value))) { value = parseInt(value) } if (!enum_.some((x) => x.value === value)) { - console.log(value) throw new Error('Invalid state') } ref.value = value diff --git a/src/extension/background-script/PluginService.ts b/src/extension/background-script/PluginService.ts index 9aa0d5fe30bc..27872f60d761 100644 --- a/src/extension/background-script/PluginService.ts +++ b/src/extension/background-script/PluginService.ts @@ -2,7 +2,7 @@ import * as RedPacket from '../../plugins/Wallet/red-packet-fsm' import * as Wallet from '../../plugins/Wallet/wallet' import * as Gitcoin from '../../plugins/Gitcoin/Services' import * as FileService from '../../plugins/FileService/service' -import * as Trader from '../../plugins/Trader/service' +import * as Trader from '../../plugins/Trader/services' import type { ERC20TokenRecord, ManagedWalletRecord, ExoticWalletRecord } from '../../plugins/Wallet/database/types' const Plugins = { diff --git a/src/plugins/Gitcoin/DonateDialog.tsx b/src/plugins/Gitcoin/DonateDialog.tsx index 44d4922f6f94..9d9c113fb7e4 100644 --- a/src/plugins/Gitcoin/DonateDialog.tsx +++ b/src/plugins/Gitcoin/DonateDialog.tsx @@ -35,7 +35,11 @@ import type { ERC20TokenDetails, WalletDetails } from '../../extension/backgroun const useStyles = makeStyles((theme: Theme) => createStyles({ - form: { '& > *': { margin: theme.spacing(1, 0) } }, + form: { + '& > *': { + margin: theme.spacing(1, 0), + }, + }, title: { marginLeft: 6, }, diff --git a/src/plugins/Trader/UI/SettingsDialog.tsx b/src/plugins/Trader/UI/SettingsDialog.tsx new file mode 100644 index 000000000000..ea255c013bb9 --- /dev/null +++ b/src/plugins/Trader/UI/SettingsDialog.tsx @@ -0,0 +1,174 @@ +import React, { useState } from 'react' +import { useI18N } from '../../../utils/i18n-next-ui' +import { + makeStyles, + DialogTitle, + IconButton, + Typography, + DialogContent, + Theme, + DialogProps, + FormControl, + Select, + MenuItem, + InputLabel, + createStyles, + DialogActions, + Button, + Divider, +} from '@material-ui/core' +import ShadowRootDialog from '../../../utils/jss/ShadowRootDialog' +import { DialogDismissIconUI } from '../../../components/InjectedComponents/DialogDismissIcon' +import { Currency, Platform, resolveCurrencyName, resolvePlatformName } from '../type' +import { useStylesExtends } from '../../../components/custom-ui-helper' +import { getActivatedUI } from '../../../social-network/ui' +import { + useTwitterDialog, + useTwitterButton, + useTwitterCloseButton, +} from '../../../social-network-provider/twitter.com/utils/theme' +import { PortalShadowRoot } from '../../../utils/jss/ShadowRootPortal' +import { getEnumAsArray } from '../../../utils/enum' + +const useStyles = makeStyles((theme: Theme) => + createStyles({ + title: { + marginLeft: 6, + }, + form: { + '& > *': { + margin: theme.spacing(1, 0), + }, + }, + menuPaper: { + maxHeight: 300, + }, + }), +) + +interface SettingsDialogUIProps + extends withClasses< + | KeysInferFromUseStyles + | 'root' + | 'dialog' + | 'backdrop' + | 'container' + | 'paper' + | 'header' + | 'content' + | 'actions' + | 'close' + | 'button' + > { + open: boolean + theme?: Theme + currencies: Currency[] + currency: Currency + platform: Platform + onCurrencyChange?: (currency: Currency) => void + onPlatformChange?: (platform: Platform) => void + onClose?: () => void + DialogProps?: Partial +} + +function SettingsDialogUI(props: SettingsDialogUIProps) { + const { t } = useI18N() + const { currency, platform, currencies } = props + const classes = useStylesExtends(useStyles(), props) + return ( +
+ + + + + + + {t('post_dialog__title')} + + + + +
+ + Data Source + + + + Currency + + +
+
+ + + +
+
+ ) +} + +export interface SettingsDialogProps extends SettingsDialogUIProps {} + +export function SettingsDialog(props: SettingsDialogProps) { + const ui = getActivatedUI() + const twitterClasses = { + ...useTwitterDialog(), + ...useTwitterButton(), + ...useTwitterCloseButton(), + } + return ui.internalName === 'twitter' ? ( + + ) : ( + + ) +} diff --git a/src/plugins/Trader/UI/TreadingView.tsx b/src/plugins/Trader/UI/TreadingView.tsx deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/src/plugins/Trader/UI/TrendingView.tsx b/src/plugins/Trader/UI/TrendingView.tsx new file mode 100644 index 000000000000..d943419b8e52 --- /dev/null +++ b/src/plugins/Trader/UI/TrendingView.tsx @@ -0,0 +1,113 @@ +import React, { useState, useEffect } from 'react' +import { makeStyles, Avatar, Typography, Card, CardHeader, IconButton, CardActions } from '@material-ui/core' +import { useAsync } from 'react-use' +import SettingsIcon from '@material-ui/icons/Settings' +import { SettingsDialog } from './SettingsDialog' +import { Platform, Currency, resolvePlatformName, Settings } from '../type' +import { getCurrenies } from '../apis' +import { PortalShadowRoot, portalShadowRoot } from '../../../utils/jss/ShadowRootPortal' +import { setStorage, getStorage } from '../../../utils/browser.storage' +import { getActivatedUI } from '../../../social-network/ui' +import stringify from 'json-stable-stringify' +import { currentTrendingViewSettings, currentTrendingViewPlatformSettings } from '../settings' +import { useValueRef } from '../../../utils/hooks/useValueRef' + +const network = getActivatedUI().networkIdentifier + +const useStyles = makeStyles({ + root: {}, + header: { + display: 'flex', + }, + body: {}, + avatar: {}, + amount: {}, +}) + +export interface TrendingViewProps extends withClasses> { + keyword: string +} + +export function TrendingView(props: TrendingViewProps) { + const classes = useStyles() + const [settingsDialogOpen, setSettingsDialogOpen] = useState(false) + + const [platform, setPlatform] = useState(Platform.COIN_GECKO) + const [currency, setCurrency] = useState(null) + + const networkKey = `${network}-${platform}` + const trendingSettings = useValueRef(currentTrendingViewSettings[networkKey]) + const trendingPlatformSettings = useValueRef(currentTrendingViewPlatformSettings[network]) + + //#region currency & platform + const { value: currencies = [], loading: loadingCurrencies, error } = useAsync(() => getCurrenies(platform), [ + platform, + ]) + + // sync platform + useEffect(() => { + if (String(platform) !== trendingPlatformSettings) { + if (trendingPlatformSettings === String(Platform.COIN_GECKO)) setPlatform(Platform.COIN_GECKO) + if (trendingPlatformSettings === String(Platform.COIN_MARKET_CAP)) setPlatform(Platform.COIN_MARKET_CAP) + } + }, [platform, trendingPlatformSettings]) + + // sync currency + useEffect(() => { + if (!currencies.length) return + try { + const parsed = JSON.parse(trendingSettings || '{}') as Settings + if (parsed.currency && currencies.some((x) => x.id === parsed.currency.id)) setCurrency(parsed.currency) + else setCurrency(currencies[0]) + } catch (e) { + setCurrency(null) + } + }, [trendingSettings, currencies.length]) + //#endregion + + if (loadingCurrencies || !currency) return null + return ( + <> + + + } + action={ + setSettingsDialogOpen(true)}> + + + } + title={{`BTC / ${currency.name}`}} + subheader={ + + {`${currency.name} 12,223`} + (1.2%) + + } + /> + + + Powered by {resolvePlatformName(platform)} + + + + { + currentTrendingViewSettings[networkKey].value = stringify({ + currency, + }) + }} + onPlatformChange={(platform) => { + currentTrendingViewPlatformSettings[network].value = String(platform) + }} + onClose={() => setSettingsDialogOpen(false)} + /> + + ) +} diff --git a/src/plugins/Trader/apis/coingecko/index.ts b/src/plugins/Trader/apis/coingecko/index.ts index 2edff8ade7e4..cf335db12fc7 100644 --- a/src/plugins/Trader/apis/coingecko/index.ts +++ b/src/plugins/Trader/apis/coingecko/index.ts @@ -1,4 +1,6 @@ -const BASE_URL = 'https://coingecko.com/api/documentations/v3' +import type { Currency } from '../../type' + +const BASE_URL = 'https://api.coingecko.com/api/v3' //#region get currency export async function getAllCurrenies() { diff --git a/src/plugins/Trader/apis/index.ts b/src/plugins/Trader/apis/index.ts new file mode 100644 index 000000000000..a68f9cda46dc --- /dev/null +++ b/src/plugins/Trader/apis/index.ts @@ -0,0 +1,19 @@ +import { Platform, Currency } from '../type' +import * as coinGeckoAPI from './coingecko' +import * as coinMarketCapAPI from './coinmarketcap' + +export async function getCurrenies(platform: Platform): Promise { + if (platform === Platform.COIN_GECKO) { + const currencies = await coinGeckoAPI.getAllCurrenies() + return currencies.map((x) => ({ + id: x, + name: x.toUpperCase(), + })) + } + return Object.values(coinMarketCapAPI.getAllCurrenies()).map((x) => ({ + id: String(x.id), + name: x.symbol.toUpperCase(), + symbol: x.token, + description: x.name, + })) +} diff --git a/src/plugins/Trader/define.tsx b/src/plugins/Trader/define.tsx index d02754709825..8c105f82befc 100644 --- a/src/plugins/Trader/define.tsx +++ b/src/plugins/Trader/define.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { Suspense } from 'react' import type { PluginConfig } from '../plugin' import { TypedMessage, @@ -7,6 +7,8 @@ import { TypedMessageCompound, } from '../../protocols/typed-message' import { makeTypedMessageCashTrending } from './messages/TypedMessageCashTrending' +import { TrendingView } from './UI/TrendingView' +import MaskbookPluginWrapper from '../MaskbookPluginWrapper' const isCashTagMessage = (m: TypedMessage): m is TypedMessageAnchor => isTypedMessgaeAnchor(m) && m.category === 'cash' @@ -20,4 +22,13 @@ export const TraderPluginDefine: PluginConfig = { items: message.items.map((m: TypedMessage) => (isCashTagMessage(m) ? makeTypedMessageCashTrending(m) : m)), } }, + postInspector() { + return ( + + + + + + ) + }, } diff --git a/src/plugins/Trader/service.ts b/src/plugins/Trader/services.ts similarity index 100% rename from src/plugins/Trader/service.ts rename to src/plugins/Trader/services.ts diff --git a/src/plugins/Trader/settings.ts b/src/plugins/Trader/settings.ts new file mode 100644 index 000000000000..0442af59263f --- /dev/null +++ b/src/plugins/Trader/settings.ts @@ -0,0 +1,4 @@ +import { createNetworkSettings } from '../../settings/createSettings' + +export const currentTrendingViewSettings = createNetworkSettings('currentTrendingViewSettings') +export const currentTrendingViewPlatformSettings = createNetworkSettings('currentTrendingViewPlatformSettings') diff --git a/src/plugins/Trader/type.ts b/src/plugins/Trader/type.ts new file mode 100644 index 000000000000..276084d2d1d5 --- /dev/null +++ b/src/plugins/Trader/type.ts @@ -0,0 +1,34 @@ +export interface Settings { + currency: Currency +} + +export enum Platform { + COIN_GECKO, + COIN_MARKET_CAP, +} + +export interface Currency { + id: string + name: string + symbol?: string + description?: string +} + +export function resolveCurrencyName(currency: Currency) { + return [ + currency.name, + currency.symbol ? `"${currency.symbol}"` : '', + currency.description ? `(${currency.description})` : '', + ].join(' ') +} + +export function resolvePlatformName(platform: Platform) { + switch (platform) { + case Platform.COIN_GECKO: + return 'Coin Gecko' + case Platform.COIN_MARKET_CAP: + return 'Coin Market Cap' + default: + return '' + } +} diff --git a/src/social-network-provider/twitter.com/utils/theme.ts b/src/social-network-provider/twitter.com/utils/theme.ts index 860730f997dd..afabb2d74e84 100644 --- a/src/social-network-provider/twitter.com/utils/theme.ts +++ b/src/social-network-provider/twitter.com/utils/theme.ts @@ -99,6 +99,7 @@ export const useTwitterDialog = makeStyles((theme: Theme) => { }, }, actions: { + padding: '10px 15px', [`@media (max-width: ${theme.breakpoints.width('sm')}px)`]: { '&': { display: 'flex', diff --git a/src/utils/enum.ts b/src/utils/enum.ts new file mode 100644 index 000000000000..74cc569db601 --- /dev/null +++ b/src/utils/enum.ts @@ -0,0 +1,8 @@ +export function getEnumAsArray(enumObject: T) { + return ( + Object.keys(enumObject) + // Leave only key of enum + .filter((x) => Number.isNaN(parseInt(x))) + .map((key) => ({ key, value: enumObject[key as keyof T] })) + ) +}