feat: add workspace switcher to lock screen (#969)

This commit is contained in:
Aman Harwara
2022-04-13 22:20:56 +05:30
committed by GitHub
parent 8e467f9e6d
commit 9ba7b875a8
15 changed files with 163 additions and 13 deletions

View File

@@ -14,6 +14,9 @@ import { useCallback, useEffect, useState } from 'preact/hooks'
import { Button } from '@/Components/Button/Button'
import { Icon } from '@/Components/Icon'
import { ChallengeModalPrompt } from './ChallengePrompt'
import { LockscreenWorkspaceSwitcher } from './LockscreenWorkspaceSwitcher'
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { AppState } from '@/UIModels/AppState'
type InputValue = {
prompt: ChallengePrompt
@@ -25,6 +28,8 @@ export type ChallengeModalValues = Record<ChallengePrompt['id'], InputValue>
type Props = {
application: WebApplication
appState: AppState
mainApplicationGroup: ApplicationGroup
challenge: Challenge
onDismiss: (challenge: Challenge) => Promise<void>
}
@@ -48,7 +53,13 @@ const validateValues = (
return undefined
}
export const ChallengeModal: FunctionComponent<Props> = ({ application, challenge, onDismiss }) => {
export const ChallengeModal: FunctionComponent<Props> = ({
application,
appState,
mainApplicationGroup,
challenge,
onDismiss,
}) => {
const [values, setValues] = useState<ChallengeModalValues>(() => {
const values = {} as ChallengeModalValues
for (const prompt of challenge.prompts) {
@@ -68,6 +79,7 @@ export const ChallengeModal: FunctionComponent<Props> = ({ application, challeng
ChallengeReason.ApplicationUnlock,
ChallengeReason.Migration,
].includes(challenge.reason)
const shouldShowWorkspaceSwitcher = challenge.reason === ChallengeReason.ApplicationUnlock
const submit = async () => {
const validatedValues = validateValues(values, challenge.prompts)
@@ -252,6 +264,12 @@ export const ChallengeModal: FunctionComponent<Props> = ({ application, challeng
Forgot passcode?
</Button>
)}
{shouldShowWorkspaceSwitcher && (
<LockscreenWorkspaceSwitcher
mainApplicationGroup={mainApplicationGroup}
appState={appState}
/>
)}
</DialogContent>
</DialogOverlay>
)

View File

@@ -0,0 +1,78 @@
import { ApplicationGroup } from '@/UIModels/ApplicationGroup'
import { AppState } from '@/UIModels/AppState'
import { calculateSubmenuStyle, SubmenuStyle } from '@/Utils/CalculateSubmenuStyle'
import { FunctionComponent } from 'preact'
import { useEffect, useRef, useState } from 'preact/hooks'
import { WorkspaceSwitcherMenu } from '@/Components/AccountMenu/WorkspaceSwitcher/WorkspaceSwitcherMenu'
import { Button } from '@/Components/Button/Button'
import { Icon } from '@/Components/Icon'
import { useCloseOnClickOutside } from '@/Hooks/useCloseOnClickOutside'
type Props = {
mainApplicationGroup: ApplicationGroup
appState: AppState
}
export const LockscreenWorkspaceSwitcher: FunctionComponent<Props> = ({
mainApplicationGroup,
appState,
}) => {
const buttonRef = useRef<HTMLButtonElement>(null)
const menuRef = useRef<HTMLDivElement>(null)
const containerRef = useRef<HTMLDivElement>(null)
const [isOpen, setIsOpen] = useState(false)
const [menuStyle, setMenuStyle] = useState<SubmenuStyle>()
useCloseOnClickOutside(containerRef, () => setIsOpen(false))
const toggleMenu = () => {
if (!isOpen) {
const menuPosition = calculateSubmenuStyle(buttonRef.current)
if (menuPosition) {
setMenuStyle(menuPosition)
}
}
setIsOpen(!isOpen)
}
useEffect(() => {
if (isOpen) {
const timeToWaitBeforeCheckingMenuCollision = 0
setTimeout(() => {
const newMenuPosition = calculateSubmenuStyle(buttonRef.current, menuRef.current)
if (newMenuPosition) {
setMenuStyle(newMenuPosition)
}
}, timeToWaitBeforeCheckingMenuCollision)
}
}, [isOpen])
return (
<div ref={containerRef}>
<Button
ref={buttonRef}
onClick={toggleMenu}
className="flex items-center justify-center min-w-76 mt-2"
>
<Icon type="user-switch" className="color-neutral mr-2" />
Switch workspace
</Button>
{isOpen && (
<div
ref={menuRef}
className="sn-dropdown max-h-120 min-w-68 py-2 fixed overflow-y-auto"
style={menuStyle}
>
<WorkspaceSwitcherMenu
mainApplicationGroup={mainApplicationGroup}
appState={appState}
isOpen={isOpen}
hideWorkspaceOptions={true}
/>
</div>
)}
</div>
)
}