diff --git a/ui/component/blockList/index.js b/ui/component/blockList/index.js new file mode 100644 index 000000000..e9f61035d --- /dev/null +++ b/ui/component/blockList/index.js @@ -0,0 +1,2 @@ +import BlockList from './view'; +export default BlockList; diff --git a/ui/component/blockList/view.jsx b/ui/component/blockList/view.jsx new file mode 100644 index 000000000..a4182a300 --- /dev/null +++ b/ui/component/blockList/view.jsx @@ -0,0 +1,83 @@ +// @flow +import React from 'react'; +import classnames from 'classnames'; +import Button from 'component/button'; +import ClaimList from 'component/claimList'; +import Yrbl from 'component/yrbl'; + +type Props = { + uris: Array, + help: string, + titleEmptyList: string, + subtitleEmptyList: string, + getActionButtons?: (url: string) => React$Node, + className: ?string, +}; + +export default function BlockList(props: Props) { + const { uris: list, help, titleEmptyList, subtitleEmptyList, getActionButtons, className } = props; + + // Keep a local list to allow for undoing actions in this component + const [localList, setLocalList] = React.useState(undefined); + const stringifiedList = JSON.stringify(list); + const hasLocalList = localList && localList.length > 0; + const justBlocked = list && localList && localList.length < list.length; + + // ************************************************************************** + // ************************************************************************** + + function getRenderActions() { + if (getActionButtons) { + return (claim) =>
{getActionButtons(claim.permanent_url)}
; + } + return undefined; + } + + // ************************************************************************** + // ************************************************************************** + + React.useEffect(() => { + const list = stringifiedList && JSON.parse(stringifiedList); + if (!hasLocalList) { + setLocalList(list && list.length > 0 ? list : []); + } + }, [stringifiedList, hasLocalList]); + + React.useEffect(() => { + if (justBlocked && stringifiedList) { + setLocalList(JSON.parse(stringifiedList)); + } + }, [stringifiedList, justBlocked, setLocalList]); + + // ************************************************************************** + // ************************************************************************** + + if (localList === undefined) { + return null; + } + + if (!hasLocalList) { + return ( +
+ +
+ } + /> + + ); + } + + return ( + <> +
{help}
+
+ +
+ + ); +} diff --git a/ui/page/listBlocked/view.jsx b/ui/page/listBlocked/view.jsx index 8036a8f1f..bee5ce11a 100644 --- a/ui/page/listBlocked/view.jsx +++ b/ui/page/listBlocked/view.jsx @@ -5,7 +5,7 @@ import React from 'react'; import classnames from 'classnames'; import moment from 'moment'; import humanizeDuration from 'humanize-duration'; -import ClaimList from 'component/claimList'; +import BlockList from 'component/blockList'; import ClaimPreview from 'component/claimPreview'; import Page from 'component/page'; import Spinner from 'component/spinner'; @@ -13,7 +13,6 @@ import Button from 'component/button'; import usePersistedState from 'effects/use-persisted-state'; import ChannelBlockButton from 'component/channelBlockButton'; import ChannelMuteButton from 'component/channelMuteButton'; -import Yrbl from 'component/yrbl'; const VIEW = { BLOCKED: 'blocked', @@ -47,7 +46,7 @@ function ListBlocked(props: Props) { personalTimeoutMap, adminTimeoutMap, moderatorTimeoutMap, - moderatorBlockListDelegatorsMap, + moderatorBlockListDelegatorsMap: delegatorsMap, fetchingModerationBlockList, fetchModBlockedList, fetchModAmIList, @@ -56,55 +55,36 @@ function ListBlocked(props: Props) { } = props; const [viewMode, setViewMode] = usePersistedState('blocked-muted:display', VIEW.BLOCKED); - // Keep a local list to allow for undoing actions in this component - const [localPersonalList, setLocalPersonalList] = React.useState(undefined); - const [localAdminList, setLocalAdminList] = React.useState(undefined); - const [localModeratorList, setLocalModeratorList] = React.useState(undefined); - const [localModeratorListDelegatorsMap, setLocalModeratorListDelegatorsMap] = React.useState(undefined); - const [localMutedList, setLocalMutedList] = React.useState(undefined); + const [localDelegatorsMap, setLocalDelegatorsMap] = React.useState(undefined); - const hasLocalMuteList = localMutedList && localMutedList.length > 0; - const hasLocalPersonalList = localPersonalList && localPersonalList.length > 0; - - const stringifiedMutedList = JSON.stringify(mutedUris); - const stringifiedPersonalList = JSON.stringify(personalBlockList); - const stringifiedAdminList = JSON.stringify(adminBlockList); - const stringifiedModeratorList = JSON.stringify(moderatorBlockList); - const stringifiedModeratorListDelegatorsMap = JSON.stringify(moderatorBlockListDelegatorsMap); - - const stringifiedLocalAdminList = JSON.stringify(localAdminList); - const stringifiedLocalModeratorList = JSON.stringify(localModeratorList); - const stringifiedLocalModeratorListDelegatorsMap = JSON.stringify(localModeratorListDelegatorsMap); - - const justMuted = localMutedList && mutedUris && localMutedList.length < mutedUris.length; - const justPersonalBlocked = - localPersonalList && personalBlockList && localPersonalList.length < personalBlockList.length; + const stringifiedDelegatorsMap = JSON.stringify(delegatorsMap); + const stringifiedLocalDelegatorsMap = JSON.stringify(localDelegatorsMap); const isAdmin = myChannelClaims && myChannelClaims.some((c) => delegatorsById[c.claim_id] && delegatorsById[c.claim_id].global); + const isModerator = myChannelClaims && myChannelClaims.some( (c) => delegatorsById[c.claim_id] && Object.keys(delegatorsById[c.claim_id].delegators).length > 0 ); - const listForView = getLocalList(viewMode); - const showUris = listForView && listForView.length > 0; + // ************************************************************************** - function getLocalList(view) { + function getList(view) { switch (view) { case VIEW.BLOCKED: - return localPersonalList; + return personalBlockList; case VIEW.ADMIN: - return localAdminList; + return adminBlockList; case VIEW.MODERATOR: - return localModeratorList; + return moderatorBlockList; case VIEW.MUTED: - return localMutedList; + return mutedUris; } } - function getButtons(view, uri) { + function getActionButtons(uri) { const getDurationStr = (durationNs) => { const NANO_TO_MS = 1000000; return humanizeDuration(durationNs / NANO_TO_MS, { round: true }); @@ -127,7 +107,7 @@ function ListBlocked(props: Props) { ); }; - switch (view) { + switch (viewMode) { case VIEW.BLOCKED: return ( <> @@ -146,7 +126,7 @@ function ListBlocked(props: Props) { ); case VIEW.MODERATOR: - const delegatorUrisForBlockedUri = localModeratorListDelegatorsMap && localModeratorListDelegatorsMap[uri]; + const delegatorUrisForBlockedUri = localDelegatorsMap && localDelegatorsMap[uri]; if (!delegatorUrisForBlockedUri) return null; return ( <> @@ -218,52 +198,43 @@ function ListBlocked(props: Props) { return source && (!local || local.length < source.length); } - React.useEffect(() => { - const jsonMutedChannels = stringifiedMutedList && JSON.parse(stringifiedMutedList); - if (!hasLocalMuteList && jsonMutedChannels && jsonMutedChannels.length > 0) { - setLocalMutedList(jsonMutedChannels); - } - }, [stringifiedMutedList, hasLocalMuteList]); + function getViewElem(view, label, icon) { + return ( +