Skip to content
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
50 changes: 14 additions & 36 deletions shared/crypto/sub-nav/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,9 @@ import * as Kb from '@/common-adapters'
import * as Common from '@/router-v2/common'
import * as TestIDs from '@/tests/e2e/shared/test-ids'
import NavRow from './nav-row'
import {
useNavigationBuilder,
TabRouter,
createNavigatorFactory,
} from '@react-navigation/core'
import type {TypedNavigator, NavigatorTypeBagBase} from '@react-navigation/native'
import {routeMapToScreenElements} from '@/router-v2/routes'
import {useNavigationBuilder, TabRouter, createNavigatorFactory} from '@react-navigation/core'
import {routeMapToStaticScreens} from '@/router-v2/routes'
import {makeLayout} from '@/router-v2/screen-layout'
import type {RouteDef, GetOptionsParams} from '@/constants/types/router'
import {defineRouteMap} from '@/constants/types/router'
import LeftNav from './left-nav.desktop'

Expand Down Expand Up @@ -86,35 +80,19 @@ function LeftTabNavigator({
)
}

type NavType = NavigatorTypeBagBase & {
ParamList: {
[key in keyof typeof cryptoSubRoutes]: {}
}
}
// The factory's static-config call signature is hidden by our custom-navigator typing, so
// re-surface it with a cast. Screens come from the same route-map converter the root uses.
const createLeftTabNavigator = createNavigatorFactory(LeftTabNavigator) as unknown as (config: {
backBehavior: 'none'
initialRouteName: string
screens: ReturnType<typeof routeMapToStaticScreens>
}) => {getComponent: () => React.ComponentType}

const createLeftTabNavigator = createNavigatorFactory(LeftTabNavigator) as unknown as () => TypedNavigator<NavType>
const TabNavigator = createLeftTabNavigator()
const makeOptions = (rd: RouteDef) => {
return ({route, navigation}: GetOptionsParams) => {
const no = rd.getOptions
const opt = typeof no === 'function' ? no({navigation, route}) : no
return {...opt}
}
}
const cryptoScreens = routeMapToScreenElements(
cryptoSubRoutes,
TabNavigator.Screen,
makeLayout,
makeOptions,
false,
false,
false
)
const DesktopCryptoSubNavigator = () => (
<TabNavigator.Navigator initialRouteName={Crypto.encryptTab} backBehavior="none">
{cryptoScreens}
</TabNavigator.Navigator>
)
const DesktopCryptoSubNavigator = createLeftTabNavigator({
backBehavior: 'none',
initialRouteName: Crypto.encryptTab,
screens: routeMapToStaticScreens(cryptoSubRoutes, makeLayout, false, false, false),
}).getComponent()

const NativeCryptoSubNav = () => {
const {navigate} = C.useNav()
Expand Down
48 changes: 14 additions & 34 deletions shared/router-v2/account-switcher/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,17 @@ import {useConfigState} from '@/stores/config'
import * as Kb from '@/common-adapters'
import * as React from 'react'
import type * as T from '@/constants/types'
import {settingsLogOutTab} from '@/constants/settings'
import {useUsersState} from '@/stores/users'
import {useCurrentUserState} from '@/stores/current-user'
import {navToProfile} from '@/constants/router'

const prepareAccountRows = <T extends {username: string; hasStoredSecret: boolean}>(
accountRows: ReadonlyArray<T>,
myUsername: string
): Array<T> => accountRows.filter(account => account.username !== myUsername)

const AccountSwitcher = () => {
const _fullnames = useUsersState(s => s.infoMap)
const _accountRows = useConfigState(s => s.configuredAccounts)
const you = useCurrentUserState(s => s.username)
const fullname = _fullnames.get(you)?.fullname ?? ''
const waiting = C.Waiting.useAnyWaiting(C.waitingKeyConfigLogin)
const onLoginAsAnotherUser = useConfigState(s => s.dispatch.logoutToLoggedOutFlow)
const navigateUp = C.Router2.navigateUp
const onCancel = () => {
navigateUp()
}

const setUserSwitching = useConfigState(s => s.dispatch.setUserSwitching)
const login = useConfigState(s => s.dispatch.login)
Expand All @@ -33,48 +23,40 @@ const AccountSwitcher = () => {
login(username, '')
}
const onSelectAccountLoggedOut = useConfigState(s => s.dispatch.logoutAndTryToLogInAs)
const navigateAppend = C.Router2.navigateAppend
const onSignOut = () => {
navigateAppend({name: settingsLogOutTab, params: {}})
}

const accountRows = prepareAccountRows(_accountRows, you)
const accountRows = _accountRows.filter(account => account.username !== you)
const props = {
accountRows: accountRows.map(account => ({
account: account,
fullName: (_fullnames.get(account.username) || {fullname: ''}).fullname || '',
})),
fullname,
onCancel,
onLoginAsAnotherUser,
onProfileClick: () => navToProfile(you),
onSelectAccount: (username: string) => {
const rows = accountRows.filter(account => account.username === username)
const loggedIn = (rows.length && rows[0]?.hasStoredSecret) ?? false
return loggedIn ? onSelectAccountLoggedIn(username) : onSelectAccountLoggedOut(username)
},
onSignOut,
username: you,
waiting,
}

return (
<>
<Kb.ScrollView alwaysBounceVertical={false}>
<Kb.Box2 direction="vertical" fullWidth={true} centerChildren={true}>
{isMobile && <MobileHeader {...props} />}
<Kb.Divider style={styles.divider} />
{isMobile ? (
<Kb.ScrollView alwaysBounceVertical={false}>
<Kb.Box2 direction="vertical" fullWidth={true} centerChildren={true}>
{isMobile && <MobileHeader {...props} />}
<Kb.Divider style={styles.divider} />
{isMobile ? (
<AccountsRows {...props} />
) : (
<Kb.ScrollView style={styles.desktopScrollview} className="accountSwitcherScrollView">
<AccountsRows {...props} />
) : (
<Kb.ScrollView style={styles.desktopScrollview} className="accountSwitcherScrollView">
<AccountsRows {...props} />
</Kb.ScrollView>
)}
{props.accountRows.length > 0 && !isMobile && <Kb.Divider style={styles.divider} />}
</Kb.Box2>
</Kb.ScrollView>
</>
</Kb.ScrollView>
)}
{props.accountRows.length > 0 && !isMobile && <Kb.Divider style={styles.divider} />}
</Kb.Box2>
</Kb.ScrollView>
)
}

Expand All @@ -87,10 +69,8 @@ type Props = {
accountRows: Array<AccountRowItem>
fullname: string
onLoginAsAnotherUser: () => void
onCancel: () => void
onProfileClick: () => void
onSelectAccount: (username: string) => void
onSignOut: () => void
username: string
waiting: boolean
}
Expand Down
67 changes: 34 additions & 33 deletions shared/router-v2/common.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type * as React from 'react'
import * as React from 'react'
import * as Kb from '@/common-adapters'
import * as Tabs from '@/constants/tabs'
import * as TestIDs from '@/tests/e2e/shared/test-ids'
import {TabActions, type NavigationContainerRef} from '@react-navigation/core'
import type {ParamListBase} from '@react-navigation/native'
import type {HeaderOptions} from '@react-navigation/elements'
import type {NativeStackHeaderProps} from '@react-navigation/native-stack'
import {HeaderLeftButton} from '@/common-adapters/header-buttons'
import type {NavState} from '@/constants/router'
import {useCurrentUserState} from '@/stores/current-user'
import Header from './header/index'

export const headerDefaultStyle = isMobile
Expand All @@ -26,6 +29,33 @@ export const tabBarStyle = {
export const tabBarBlurEffect = isMobile ? ('systemDefault' as const) : undefined
export const tabBarMinimizeBehavior = undefined

export const tabToTestID = new Map<Tabs.Tab, string>([
[Tabs.peopleTab, TestIDs.NAV_TAB_PEOPLE],
[Tabs.chatTab, TestIDs.NAV_TAB_CHAT],
[Tabs.fsTab, TestIDs.NAV_TAB_FILES],
[Tabs.cryptoTab, TestIDs.NAV_TAB_CRYPTO],
[Tabs.teamsTab, TestIDs.NAV_TAB_TEAMS],
[Tabs.gitTab, TestIDs.NAV_TAB_GIT],
[Tabs.devicesTab, TestIDs.NAV_TAB_DEVICES],
[Tabs.settingsTab, TestIDs.NAV_TAB_SETTINGS],
])

// Remount the navigator when switching between two logged-in users.
// Ignore '' → username (initial login) so in-flight unbox requests aren't interrupted.
export const useUserSwitchNavKey = () => {
const username = useCurrentUserState(s => s.username)
const [navKey, setNavKey] = React.useState('')
const prevUsernameRef = React.useRef(username)
React.useEffect(() => {
const prev = prevUsernameRef.current
prevUsernameRef.current = username
if (prev && username && prev !== username) {
setNavKey(username)
}
}, [username])
return navKey
}

const actionWidth = 64
const DEBUGCOLORS = __DEV__ && (false as boolean)

Expand Down Expand Up @@ -119,43 +149,14 @@ const styles = Kb.Styles.styleSheetCreate(() => ({
type SubnavNavigation = Pick<NavigationContainerRef<ParamListBase>, 'dispatch' | 'emit'>

export const useSubnavTabAction = (navigation: SubnavNavigation, state: NavState) => {
if (!isMobile) {
const routesRef = {current: state?.routes}
const stateKeyRef = {current: state?.key}
const navRef = {current: navigation}

const onSelectTab = (tab: string) => {
const r = routesRef.current?.find((r: {name?: string; key?: string}) => {
return r.name === tab
})

const key = r?.key ?? ''
const event = key
? navRef.current.emit({
canPreventDefault: true,
target: key,
// @ts-expect-error tabPress is valid but not in the emit type
type: 'tabPress',
})
: {defaultPrevented: false}

if (!event.defaultPrevented) {
navRef.current.dispatch({
...TabActions.jumpTo(tab),
target: stateKeyRef.current,
})
}
}
return onSelectTab
}

const onSelectTab = (tab: string) => {
const routes = state && 'routes' in state ? state.routes : undefined
const route = routes?.find((r: {name?: string; key?: string}) => r.name === tab)
const event = route
const key = route?.key
const event = key
? navigation.emit({
canPreventDefault: true,
target: route.key,
target: key,
// @ts-expect-error tabPress is valid but not in the emit type
type: 'tabPress',
})
Expand Down
19 changes: 4 additions & 15 deletions shared/router-v2/header/index.desktop.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import * as React from 'react'
import type * as React from 'react'
import * as Kb from '@/common-adapters'
import * as Platform from '@/constants/platform'
import SyncingFolders from './syncing-folders'
Expand Down Expand Up @@ -29,18 +29,11 @@ type RawOptions = {
headerStyle?: Kb.Styles.CollapsibleStyle
}

type Options = {
headerMode?: string
title?: React.ReactNode
// Same as RawOptions but with the component-constructor variants already rendered to nodes
type Options = Omit<RawOptions, 'headerTitle' | 'headerRightActions' | 'subHeader'> & {
headerTitle?: React.ReactNode
headerLeft?: React.ReactNode | ((props: HeaderBackButtonProps) => React.ReactNode)
headerRight?: React.ReactNode | ((p: {tintColor?: string}) => React.ReactNode)
headerRightActions?: React.ReactNode
subHeader?: React.ReactNode
headerTransparent?: boolean
headerShadowVisible?: boolean
headerBottomStyle?: Kb.Styles.StylesCrossPlatform
headerStyle?: Kb.Styles.CollapsibleStyle
}

// A mobile-like header for desktop
Expand All @@ -52,7 +45,6 @@ type Props = {
back?: boolean
style?: Kb.Styles._StylesCrossPlatform
useNativeFrame: boolean
params?: unknown
isMaximized: boolean
navigation: {
pop: () => void
Expand Down Expand Up @@ -170,8 +162,6 @@ function DesktopHeader(p: Props) {
? Kb.Styles.globalColors.black_10
: Kb.Styles.globalColors.transparent

const popupAnchor = React.createRef<Kb.MeasureRef | null>()

const defaultBackButton = (
<Kb.ClickableBox
className={Kb.Styles.classNames('hover_container', {
Expand Down Expand Up @@ -279,7 +269,6 @@ function DesktopHeader(p: Props) {
fullWidth={true}
style={styles.headerBack}
alignItems="center"
ref={popupAnchor}
>
{/* TODO have headerLeft be the back button */}
{backButton}
Expand Down Expand Up @@ -396,6 +385,7 @@ const styles = Kb.Styles.styleSheetCreate(
type HeaderProps = Omit<Props, 'back' | 'loggedIn' | 'useNativeFrame' | 'isMaximized'> & {
back?: NativeStackHeaderProps['back']
options: RawOptions
params?: unknown
}

function DesktopHeaderWrapper(p: HeaderProps) {
Expand Down Expand Up @@ -446,7 +436,6 @@ function DesktopHeaderWrapper(p: HeaderProps) {
options={options}
back={!!back /* not a bool upstream */}
style={style}
params={params}
navigation={navigation}
/>
)
Expand Down
12 changes: 9 additions & 3 deletions shared/router-v2/header/syncing-folders.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ type Props = {

const SyncingFolders = (props: Props) =>
props.show && props.progress !== 1.0 ? (
<Kb.WithTooltip tooltip={props.tooltip} containerStyle={{alignSelf: 'center'}}>
<Kb.WithTooltip tooltip={props.tooltip} containerStyle={styles.tooltipContainer}>
<Kb.Box2 direction="horizontal" alignItems="center">
<PieSlice degrees={props.progress * 360} animated={true} negative={props.negative} />
<Kb.Text type="BodyTiny" negative={props.negative} style={{marginLeft: 5}}>
<Kb.Text type="BodyTiny" negative={props.negative} style={styles.text}>
Syncing folders...
</Kb.Text>
</Kb.Box2>
Expand All @@ -32,7 +32,7 @@ const SyncFolders = (op: OwnProps) => {
const {negative} = op

if (syncingFoldersProgress.bytesTotal === 0) {
return <SyncingFolders progress={0} show={false} tooltip="" />
return null
}

const progress = syncingFoldersProgress.bytesFetched / syncingFoldersProgress.bytesTotal
Expand All @@ -42,4 +42,10 @@ const SyncFolders = (op: OwnProps) => {
)
return <SyncingFolders negative={negative} show={online} tooltip={tooltip} progress={progress} />
}

const styles = Kb.Styles.styleSheetCreate(() => ({
text: {marginLeft: 5},
tooltipContainer: {alignSelf: 'center'},
}))

export default SyncFolders
21 changes: 0 additions & 21 deletions shared/router-v2/hooks.native.tsx

This file was deleted.

Loading