Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for merging all networks in the layer selector #1688

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changelog/1686.trivial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Support for more granular configuration for hiding layers
1 change: 1 addition & 0 deletions .changelog/1866.trivial.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add support for merging all networks in the layer selector
56 changes: 31 additions & 25 deletions src/app/components/LayerPicker/LayerDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ import { Link as RouterLink } from 'react-router-dom'
import { docs } from '../../utils/externalLinks'
import { TextList, TextListItem } from '../TextList'
import { getLayerLabels, getNetworkIcons } from '../../utils/content'
import { getNameForScope } from '../../../types/searchScope'
import { getNameForScope, SearchScope } from '../../../types/searchScope'
import { useConsensusFreshness, useRuntimeFreshness } from '../OfflineBanner/hook'
import { LayerStatus } from '../LayerStatus'
import { useScreenSize } from '../../hooks/useScreensize'
import { mergeNetworksInLayerSelector } from '../../utils/route-utils'

type LayerDetailsContent = {
description: string
Expand Down Expand Up @@ -115,32 +116,32 @@ export const StyledButton = styled(Button)(({ theme }) => ({

type LayerDetailsProps = {
handleConfirm: () => void
network: Network
selectedLayer: Layer
selectedNetwork: Network
selectedScope: SearchScope
isOutOfDate: boolean | undefined
}

// Prevent modal height from changing height when switching between layers
const contentMinHeight = '270px'

export const LayerDetails: FC<LayerDetailsProps> = (props: LayerDetailsProps) =>
props.selectedLayer === Layer.consensus ? <ConsensusDetails {...props} /> : <RuntimeDetails {...props} />
props.selectedScope.layer === Layer.consensus ? (
<ConsensusDetails {...props} />
) : (
<RuntimeDetails {...props} />
)

const ConsensusDetails: FC<LayerDetailsProps & { selectedNetwork: Network }> = props => {
const ConsensusDetails: FC<LayerDetailsProps> = props => {
const { t } = useTranslation()
const { handleConfirm, network, selectedLayer, selectedNetwork } = props
const isOutOfDate = useConsensusFreshness(network).outOfDate
const isLocal = selectedNetwork === 'localnet'
const { handleConfirm, selectedScope } = props
const isOutOfDate = useConsensusFreshness(selectedScope.network).outOfDate
const isLocal = selectedScope.network === 'localnet'

return (
<LayerDetailsSection
docsUrl={isLocal ? undefined : docs.consensus}
handleConfirm={handleConfirm}
isOutOfDate={isOutOfDate}
selectedLayer={selectedLayer}
selectedNetwork={selectedNetwork}
network={network}
selectedScope={selectedScope}
>
<Typography sx={{ fontSize: '14px', color: COLORS.brandExtraDark, pb: 4 }}>
{t('layerPicker.consensus')}
Expand All @@ -151,19 +152,25 @@ const ConsensusDetails: FC<LayerDetailsProps & { selectedNetwork: Network }> = p

const RuntimeDetails: FC<LayerDetailsProps> = props => {
const { t } = useTranslation()
const { handleConfirm, network, selectedLayer, selectedNetwork } = props
const isOutOfDate = useRuntimeFreshness({ network, layer: selectedLayer }).outOfDate
const details = getDetails(t)[network]?.[selectedLayer]
const { handleConfirm, selectedScope } = props
const isOutOfDate = useRuntimeFreshness(selectedScope).outOfDate
const details = getDetails(t)[selectedScope.network]?.[selectedScope.layer]
const networkNames = getNetworkNames(t)

return (
<LayerDetailsSection
docsUrl={details?.docs}
handleConfirm={handleConfirm}
isOutOfDate={isOutOfDate}
selectedLayer={selectedLayer}
selectedNetwork={selectedNetwork}
network={network}
selectedScope={selectedScope}
>
{mergeNetworksInLayerSelector && (
<Typography sx={{ fontSize: '14px', color: COLORS.brandExtraDark, pb: 4 }}>
{t('layerPicker.hostedOn', {
network: networkNames[selectedScope.network],
})}
</Typography>
)}
{details?.description && (
<Typography sx={{ fontSize: '14px', color: COLORS.brandExtraDark, pb: 4 }}>
{details.description}
Expand Down Expand Up @@ -216,13 +223,12 @@ export const LayerDetailsSection: FC<LayerDetailsSectionProps> = ({
docsUrl,
handleConfirm,
isOutOfDate,
network,
selectedLayer,
selectedScope,
}) => {
const { t } = useTranslation()
const theme = useTheme()
const { isTablet } = useScreenSize()
const labels = getNetworkNames(t)
const networkNames = getNetworkNames(t)
const layerLabels = getLayerLabels(t)
const icons = getNetworkIcons()

Expand All @@ -238,7 +244,7 @@ export const LayerDetailsSection: FC<LayerDetailsSectionProps> = ({
borderStyle: 'solid',
}}
>
{icons[network]}
{icons[selectedScope.network]}
</Circle>
</Box>
<Box>
Expand All @@ -250,7 +256,7 @@ export const LayerDetailsSection: FC<LayerDetailsSectionProps> = ({
}}
>
<StyledButton variant="text" onClick={handleConfirm}>
{getNameForScope(t, { network, layer: selectedLayer })}
{getNameForScope(t, selectedScope)}
</StyledButton>
<LayerStatus isOutOfDate={isOutOfDate} withTooltip />
</Box>
Expand All @@ -270,8 +276,8 @@ export const LayerDetailsSection: FC<LayerDetailsSectionProps> = ({
}}
>
{t('layerPicker.readMore', {
layer: layerLabels[selectedLayer],
network: labels[network],
layer: layerLabels[selectedScope.layer],
network: networkNames[selectedScope.network],
})}
<OpenInNewIcon sx={{ fontSize: '16px' }} />
</Link>
Expand Down
112 changes: 59 additions & 53 deletions src/app/components/LayerPicker/LayerMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,16 @@ import Tooltip from '@mui/material/Tooltip'
import { COLORS } from '../../../styles/theme/colors'
import { Layer } from '../../../oasis-nexus/api'
import { getLayerLabels } from '../../utils/content'
import { isLayerHidden, RouteUtils } from '../../utils/route-utils'
import { isScopeHidden, mergeNetworksInLayerSelector, RouteUtils } from '../../utils/route-utils'
import { Network } from '../../../types/network'
import { orderByLayer } from '../../../types/layers'
import { useScreenSize } from '../../hooks/useScreensize'
import { useScopeParam } from '../../hooks/useScopeParam'
import { SearchScope } from '../../../types/searchScope'

type BaseLayerMenuItemProps = {
divider: boolean
layer: Layer
targetScope: SearchScope
}

const LayerMenuItemCaption: FC<PropsWithChildren> = ({ children }) => (
Expand All @@ -29,7 +30,7 @@ const LayerMenuItemCaption: FC<PropsWithChildren> = ({ children }) => (
</Typography>
)

export const DisabledLayerMenuItem: FC<BaseLayerMenuItemProps> = ({ divider, layer }) => {
export const DisabledLayerMenuItem: FC<BaseLayerMenuItemProps> = ({ divider, targetScope }) => {
const { isTablet } = useScreenSize()
const { t } = useTranslation()
const labels = getLayerLabels(t)
Expand All @@ -40,7 +41,7 @@ export const DisabledLayerMenuItem: FC<BaseLayerMenuItemProps> = ({ divider, lay
<div>
<MenuItem disabled divider={divider}>
<ListItemText>
{labels[layer]}
{labels[targetScope.layer]}
{isTablet && <LayerMenuItemCaption>{t('layerPicker.comingSoonLabel')}</LayerMenuItemCaption>}
</ListItemText>
</MenuItem>
Expand All @@ -51,74 +52,81 @@ export const DisabledLayerMenuItem: FC<BaseLayerMenuItemProps> = ({ divider, lay

type LayerMenuItemProps = LayerMenuProps &
BaseLayerMenuItemProps & {
hoveredLayer?: Layer
setHoveredLayer: (layer?: Layer) => void
hoveredScope?: SearchScope
setHoveredScope: (scope?: SearchScope) => void
}

export const LayerMenuItem: FC<LayerMenuItemProps> = ({
activeLayer,
divider,
layer,
network,
selectedLayer,
selectedNetwork,
setHoveredLayer,
setSelectedLayer,
targetScope,
selectedScope,
setHoveredScope,
setSelectedScope,
}) => {
const { t } = useTranslation()
const labels = getLayerLabels(t)
const activeLayerSelection = layer === selectedLayer
const activeScope = useScopeParam()!
const isSelected =
targetScope.network === selectedScope?.network && targetScope.layer === selectedScope?.layer
const isActive = targetScope.network === activeScope.network && targetScope.layer === activeScope.layer

return (
<MenuItem
divider={divider}
onMouseEnter={() => {
setHoveredLayer(layer)
setHoveredScope(targetScope)
}}
onMouseLeave={() => {
setHoveredLayer()
setHoveredScope()
}}
onClick={() => {
setSelectedLayer(layer)
setSelectedScope(targetScope)
}}
selected={activeLayerSelection}
tabIndex={activeLayerSelection ? 0 : -1}
selected={isSelected}
tabIndex={isSelected ? 0 : -1}
>
<ListItemText>
{labels[layer]}
{selectedNetwork === network && activeLayer === layer && (
<LayerMenuItemCaption>{t('layerPicker.selected')}</LayerMenuItemCaption>
)}
{labels[targetScope.layer]}
{isActive && <LayerMenuItemCaption>{t('layerPicker.active')}</LayerMenuItemCaption>}
</ListItemText>
{layer === selectedLayer && <KeyboardArrowRightIcon />}
{isSelected && <KeyboardArrowRightIcon />}
</MenuItem>
)
}
type LayerMenuProps = {
activeLayer: Layer
network: Network
selectedLayer?: Layer
selectedNetwork: Network
setSelectedLayer: (layer: Layer) => void
selectedNetwork?: Network
selectedScope?: SearchScope
setSelectedScope: (scope: SearchScope) => void
}

export const LayerMenu: FC<LayerMenuProps> = ({
activeLayer,
network,
selectedLayer,
selectedNetwork,
setSelectedLayer,
}) => {
const currentScope = useScopeParam()
const [hoveredLayer, setHoveredLayer] = useState<undefined | Layer>()
const options = Object.values(Layer)
type LayerMenuOption = {
scope: SearchScope
enabled: boolean
}

const getOptionsForNetwork = (network: Network, activeScope?: SearchScope | undefined): LayerMenuOption[] =>
Object.values(Layer)
.sort(orderByLayer)
// Don't show hidden layers, unless we are already viewing them.
.filter(layer => !isLayerHidden(layer) || layer === currentScope?.layer)
.filter(
layer =>
!isScopeHidden({ network, layer }) ||
(layer === activeScope?.layer && network === activeScope?.network),
)
.map(layer => ({
layer,
enabled: RouteUtils.getAllLayersForNetwork(selectedNetwork || network).enabled.includes(layer),
scope: {
network,
layer,
},
enabled: RouteUtils.getAllLayersForNetwork(network).enabled.includes(layer),
}))
.sort(orderByLayer)

export const LayerMenu: FC<LayerMenuProps> = ({ selectedNetwork, selectedScope, setSelectedScope }) => {
const activeScope = useScopeParam()!
const [hoveredScope, setHoveredScope] = useState<undefined | SearchScope>()
const options = mergeNetworksInLayerSelector
? RouteUtils.getVisibleScopes(activeScope).map(scope => ({ scope, enabled: true }))
: getOptionsForNetwork(selectedNetwork ?? activeScope.network)

return (
<MenuList>
Expand All @@ -128,23 +136,21 @@ export const LayerMenu: FC<LayerMenuProps> = ({
return (
<DisabledLayerMenuItem
divider={index !== options.length - 1}
key={option.layer}
layer={option.layer}
key={option.scope.network + option.scope.layer}
targetScope={option.scope}
/>
)
} else {
return (
<LayerMenuItem
activeLayer={activeLayer}
divider={index !== options.length - 1}
hoveredLayer={hoveredLayer}
key={option.layer}
layer={option.layer}
network={network}
selectedLayer={selectedLayer}
hoveredScope={hoveredScope}
key={option.scope.network + option.scope.layer}
targetScope={option.scope}
selectedScope={selectedScope}
selectedNetwork={selectedNetwork}
setHoveredLayer={setHoveredLayer}
setSelectedLayer={setSelectedLayer}
setHoveredScope={setHoveredScope}
setSelectedScope={setSelectedScope}
/>
)
}
Expand Down
11 changes: 6 additions & 5 deletions src/app/components/LayerPicker/NetworkMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export const NetworkMenuItem: FC<NetworkMenuItemProps> = ({
const { t } = useTranslation()
const labels = getNetworkNames(t)
const icons = getNetworkIcons()
const activeNetworkSelection = network === selectedNetwork
const isSelected = network === selectedNetwork
const isActive = network === activeNetwork

return (
<MenuItem
Expand All @@ -40,21 +41,21 @@ export const NetworkMenuItem: FC<NetworkMenuItemProps> = ({
onMouseLeave={() => {
setHoveredNetwork(undefined)
}}
selected={activeNetworkSelection}
tabIndex={activeNetworkSelection ? 0 : -1}
selected={isSelected}
tabIndex={isSelected ? 0 : -1}
onClick={() => {
setSelectedNetwork(network)
}}
>
<ListItemIcon>{icons[network]}</ListItemIcon>
<ListItemText>
{labels[network]}
{activeNetwork === network && (
{isActive && (
<Typography
component="span"
sx={{ fontSize: '10px', fontStyle: 'italic', color: COLORS.grayMedium, ml: 2 }}
>
{t('layerPicker.selected')}
{t('layerPicker.active')}
</Typography>
)}
</ListItemText>
Expand Down
Loading
Loading