mirror of
https://github.com/hcengineering/platform.git
synced 2025-04-15 12:55:59 +00:00
Mobile layout fixes (#7077)
Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
parent
da0da6b452
commit
7710ff8fa1
@ -1053,6 +1053,7 @@ a.no-line {
|
|||||||
.bottom-divider { border-bottom: 1px solid var(--theme-divider-color); }
|
.bottom-divider { border-bottom: 1px solid var(--theme-divider-color); }
|
||||||
.left-divider { border-left: 1px solid var(--theme-divider-color); }
|
.left-divider { border-left: 1px solid var(--theme-divider-color); }
|
||||||
.right-divider { border-right: 1px solid var(--theme-divider-color); }
|
.right-divider { border-right: 1px solid var(--theme-divider-color); }
|
||||||
|
.right-navpanel-border { border-right: 1px solid var(--theme-navpanel-border); }
|
||||||
.bottom-highlight-select { border-bottom: 1px solid var(--highlight-select); }
|
.bottom-highlight-select { border-bottom: 1px solid var(--highlight-select); }
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
|
|
||||||
let sState: SeparatorState
|
let sState: SeparatorState
|
||||||
$: sState = typeof float === 'string' ? SeparatorState.FLOAT : float ? SeparatorState.HIDDEN : SeparatorState.NORMAL
|
$: sState = typeof float === 'string' ? SeparatorState.FLOAT : float ? SeparatorState.HIDDEN : SeparatorState.NORMAL
|
||||||
|
const checkFullWidth = (): boolean =>
|
||||||
|
sState === SeparatorState.FLOAT && $deviceInfo.isMobile && $deviceInfo.isPortrait
|
||||||
|
|
||||||
const direction: 'horizontal' | 'vertical' = 'horizontal'
|
const direction: 'horizontal' | 'vertical' = 'horizontal'
|
||||||
let separators: SeparatedItem[] | null = null
|
let separators: SeparatedItem[] | null = null
|
||||||
@ -67,6 +69,10 @@
|
|||||||
let disabled: boolean = false
|
let disabled: boolean = false
|
||||||
let side: 'start' | 'end' | undefined = undefined
|
let side: 'start' | 'end' | undefined = undefined
|
||||||
|
|
||||||
|
$: fs = $deviceInfo.fontSize
|
||||||
|
const remToPx = (rem: number): number => rem * fs
|
||||||
|
const pxToRem = (px: number): number => px / fs
|
||||||
|
|
||||||
const fetchSeparators = (): void => {
|
const fetchSeparators = (): void => {
|
||||||
const res = getSeparators(name, float)
|
const res = getSeparators(name, float)
|
||||||
if (res !== null && !Array.isArray(res)) panel = res
|
if (res !== null && !Array.isArray(res)) panel = res
|
||||||
@ -90,10 +96,6 @@
|
|||||||
checkSizes()
|
checkSizes()
|
||||||
}
|
}
|
||||||
|
|
||||||
$: fs = $deviceInfo.fontSize
|
|
||||||
const remToPx = (rem: number): number => rem * fs
|
|
||||||
const pxToRem = (px: number): number => px / fs
|
|
||||||
|
|
||||||
const convertSize = (prop: TSeparatedItem): string => (typeof prop === 'number' ? `${prop}px` : '')
|
const convertSize = (prop: TSeparatedItem): string => (typeof prop === 'number' ? `${prop}px` : '')
|
||||||
|
|
||||||
const setSize = (element: HTMLElement, size: TSeparatedItem, next: boolean = false): void => {
|
const setSize = (element: HTMLElement, size: TSeparatedItem, next: boolean = false): void => {
|
||||||
@ -229,6 +231,12 @@
|
|||||||
|
|
||||||
const checkSizes = (): void => {
|
const checkSizes = (): void => {
|
||||||
if (sState === SeparatorState.FLOAT) {
|
if (sState === SeparatorState.FLOAT) {
|
||||||
|
if (checkFullWidth() && panel != null) {
|
||||||
|
const s = pxToRem(window.innerWidth)
|
||||||
|
panel.size = s
|
||||||
|
panel.maxSize = s
|
||||||
|
panel.minSize = s
|
||||||
|
}
|
||||||
if (parentElement != null && panel != null) initSize(parentElement, panel)
|
if (parentElement != null && panel != null) initSize(parentElement, panel)
|
||||||
} else if (sState === SeparatorState.NORMAL) {
|
} else if (sState === SeparatorState.NORMAL) {
|
||||||
if (prevElement != null && prevElSize != null) initSize(prevElement, prevElSize)
|
if (prevElement != null && prevElSize != null) initSize(prevElement, prevElSize)
|
||||||
@ -442,12 +450,13 @@
|
|||||||
}
|
}
|
||||||
} else if (sState === SeparatorState.FLOAT && parentElement != null) {
|
} else if (sState === SeparatorState.FLOAT && parentElement != null) {
|
||||||
parentElement.style.pointerEvents = 'all'
|
parentElement.style.pointerEvents = 'all'
|
||||||
saveSeparator(name, float, panel)
|
if (!checkFullWidth()) saveSeparator(name, float, panel)
|
||||||
}
|
}
|
||||||
document.body.style.cursor = ''
|
document.body.style.cursor = ''
|
||||||
}
|
}
|
||||||
|
|
||||||
function pointerDown (event: PointerEvent): void {
|
function pointerDown (event: PointerEvent): void {
|
||||||
|
if (checkFullWidth()) return
|
||||||
prepareSeparation(event)
|
prepareSeparation(event)
|
||||||
document.addEventListener('pointermove', pointerMove)
|
document.addEventListener('pointermove', pointerMove)
|
||||||
document.addEventListener('pointerup', pointerUp)
|
document.addEventListener('pointerup', pointerUp)
|
||||||
|
@ -148,7 +148,7 @@ export function saveSeparator (
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const panelSeparators: DefSeparators = [
|
export const panelSeparators: DefSeparators = [
|
||||||
{ minSize: 30, size: 'auto', maxSize: 'auto' },
|
{ minSize: 20, size: 'auto', maxSize: 'auto' },
|
||||||
{ minSize: 17, size: 25, maxSize: 35, float: 'aside' }
|
{ minSize: 17, size: 25, maxSize: 35, float: 'aside' }
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -28,7 +28,8 @@
|
|||||||
getCurrentLocation,
|
getCurrentLocation,
|
||||||
showPopup,
|
showPopup,
|
||||||
type AnySvelteComponent,
|
type AnySvelteComponent,
|
||||||
type CompAndProps
|
type CompAndProps,
|
||||||
|
resizeObserver
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import view from '@hcengineering/view'
|
import view from '@hcengineering/view'
|
||||||
import plugin from '../plugin'
|
import plugin from '../plugin'
|
||||||
@ -51,6 +52,7 @@
|
|||||||
import CamSettingPopup from './CamSettingPopup.svelte'
|
import CamSettingPopup from './CamSettingPopup.svelte'
|
||||||
import MicSettingPopup from './MicSettingPopup.svelte'
|
import MicSettingPopup from './MicSettingPopup.svelte'
|
||||||
import RoomAccessPopup from './RoomAccessPopup.svelte'
|
import RoomAccessPopup from './RoomAccessPopup.svelte'
|
||||||
|
import { afterUpdate } from 'svelte'
|
||||||
|
|
||||||
export let room: Room
|
export let room: Room
|
||||||
export let fullScreen: boolean = false
|
export let fullScreen: boolean = false
|
||||||
@ -59,6 +61,11 @@
|
|||||||
const allowShare: boolean = true
|
const allowShare: boolean = true
|
||||||
let allowLeave: boolean = false
|
let allowLeave: boolean = false
|
||||||
let popup: CompAndProps | undefined = undefined
|
let popup: CompAndProps | undefined = undefined
|
||||||
|
let grow: HTMLElement
|
||||||
|
let leftPanel: HTMLElement
|
||||||
|
let leftPanelSize: number = 0
|
||||||
|
let noLabel: boolean = false
|
||||||
|
let combinePanel: boolean = false
|
||||||
|
|
||||||
$: allowCam = $currentRoom?.type === RoomType.Video
|
$: allowCam = $currentRoom?.type === RoomType.Video
|
||||||
$: allowLeave = $myInfo?.room !== ($myOffice?._id ?? plugin.ids.Reception)
|
$: allowLeave = $myInfo?.room !== ($myOffice?._id ?? plugin.ids.Reception)
|
||||||
@ -149,9 +156,22 @@
|
|||||||
|
|
||||||
const camKeys = client.getModel().findAllSync(view.class.Action, { _id: plugin.action.ToggleVideo })?.[0]?.keyBinding
|
const camKeys = client.getModel().findAllSync(view.class.Action, { _id: plugin.action.ToggleVideo })?.[0]?.keyBinding
|
||||||
const micKeys = client.getModel().findAllSync(view.class.Action, { _id: plugin.action.ToggleMic })?.[0]?.keyBinding
|
const micKeys = client.getModel().findAllSync(view.class.Action, { _id: plugin.action.ToggleMic })?.[0]?.keyBinding
|
||||||
|
|
||||||
|
const checkBar = (): void => {
|
||||||
|
if (grow === undefined || leftPanel === undefined) return
|
||||||
|
if (!noLabel && leftPanel.clientWidth > leftPanelSize) leftPanelSize = leftPanel.clientWidth
|
||||||
|
if (grow.clientWidth - 16 < leftPanel.clientWidth && !noLabel && !combinePanel) noLabel = true
|
||||||
|
else if (grow.clientWidth - 16 < leftPanel.clientWidth && noLabel && !combinePanel) combinePanel = true
|
||||||
|
else if (grow.clientWidth * 2 - 32 > leftPanel.clientWidth && noLabel && combinePanel) combinePanel = false
|
||||||
|
else if (grow.clientWidth - 32 >= leftPanelSize && noLabel && !combinePanel) noLabel = false
|
||||||
|
}
|
||||||
|
afterUpdate(() => {
|
||||||
|
checkBar()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="bar w-full flex-center flex-gap-2 flex-no-shrink">
|
<div class="bar w-full flex-center flex-gap-2 flex-no-shrink" class:combinePanel use:resizeObserver={checkBar}>
|
||||||
|
<div bind:this={grow} class="flex-grow" />
|
||||||
{#if room._id !== plugin.ids.Reception}
|
{#if room._id !== plugin.ids.Reception}
|
||||||
<ModernButton
|
<ModernButton
|
||||||
icon={roomAccessIcon[room.access]}
|
icon={roomAccessIcon[room.access]}
|
||||||
@ -205,7 +225,7 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
<div class="bar__left-panel flex-gap-2 flex-center">
|
<div bind:this={leftPanel} class="bar__left-panel flex-gap-2 flex-center">
|
||||||
{#if $isConnected}
|
{#if $isConnected}
|
||||||
<ModernButton
|
<ModernButton
|
||||||
icon={$isFullScreen ? love.icon.ExitFullScreen : love.icon.FullScreen}
|
icon={$isFullScreen ? love.icon.ExitFullScreen : love.icon.FullScreen}
|
||||||
@ -232,7 +252,7 @@
|
|||||||
{#if allowLeave}
|
{#if allowLeave}
|
||||||
<ModernButton
|
<ModernButton
|
||||||
icon={plugin.icon.LeaveRoom}
|
icon={plugin.icon.LeaveRoom}
|
||||||
label={plugin.string.LeaveRoom}
|
label={noLabel ? undefined : plugin.string.LeaveRoom}
|
||||||
tooltip={{ label: plugin.string.LeaveRoom, direction: 'top' }}
|
tooltip={{ label: plugin.string.LeaveRoom, direction: 'top' }}
|
||||||
kind={'negative'}
|
kind={'negative'}
|
||||||
size={'large'}
|
size={'large'}
|
||||||
@ -240,6 +260,7 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="flex-grow" />
|
||||||
{#if popup && fullScreen}
|
{#if popup && fullScreen}
|
||||||
<PopupInstance
|
<PopupInstance
|
||||||
is={popup.is}
|
is={popup.is}
|
||||||
@ -259,6 +280,7 @@
|
|||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.bar {
|
.bar {
|
||||||
|
overflow-x: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
padding: 1rem;
|
padding: 1rem;
|
||||||
border-top: 1px solid var(--theme-divider-color);
|
border-top: 1px solid var(--theme-divider-color);
|
||||||
@ -270,5 +292,9 @@
|
|||||||
right: 1rem;
|
right: 1rem;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.combinePanel .bar__left-panel {
|
||||||
|
position: static;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import { personByIdStore } from '@hcengineering/contact-resources'
|
import { personByIdStore } from '@hcengineering/contact-resources'
|
||||||
import { Room as TypeRoom } from '@hcengineering/love'
|
import { Room as TypeRoom } from '@hcengineering/love'
|
||||||
import { getMetadata } from '@hcengineering/platform'
|
import { getMetadata } from '@hcengineering/platform'
|
||||||
import { Label, Loading, resizeObserver } from '@hcengineering/ui'
|
import { Label, Loading, resizeObserver, deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
||||||
import {
|
import {
|
||||||
LocalParticipant,
|
LocalParticipant,
|
||||||
LocalTrackPublication,
|
LocalTrackPublication,
|
||||||
@ -333,7 +333,7 @@
|
|||||||
$: if (((document.fullscreenElement && !$isFullScreen) || $isFullScreen) && roomEl) toggleFullscreen()
|
$: if (((document.fullscreenElement && !$isFullScreen) || $isFullScreen) && roomEl) toggleFullscreen()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div bind:this={roomEl} class="flex-col-center w-full h-full" class:theme-dark={$isFullScreen}>
|
<div bind:this={roomEl} class="flex-col-center w-full h-full right-navpanel-border" class:theme-dark={$isFullScreen}>
|
||||||
{#if $isConnected && !$isCurrentInstanceConnected}
|
{#if $isConnected && !$isCurrentInstanceConnected}
|
||||||
<div class="flex justify-center error h-full w-full clear-mins">
|
<div class="flex justify-center error h-full w-full clear-mins">
|
||||||
<Label label={love.string.AnotherWindowError} />
|
<Label label={love.string.AnotherWindowError} />
|
||||||
@ -345,7 +345,13 @@
|
|||||||
{:else if loading}
|
{:else if loading}
|
||||||
<Loading />
|
<Loading />
|
||||||
{/if}
|
{/if}
|
||||||
<div class="room-container" class:sharing={$screenSharing} class:many={columns > 3} class:hidden={loading}>
|
<div
|
||||||
|
class="room-container"
|
||||||
|
class:sharing={$screenSharing}
|
||||||
|
class:many={columns > 3}
|
||||||
|
class:hidden={loading}
|
||||||
|
class:mobile={$deviceInfo.isMobile}
|
||||||
|
>
|
||||||
<div class="screenContainer">
|
<div class="screenContainer">
|
||||||
<video class="screen" bind:this={screen}></video>
|
<video class="screen" bind:this={screen}></video>
|
||||||
</div>
|
</div>
|
||||||
@ -452,6 +458,15 @@
|
|||||||
gap: 0.5rem;
|
gap: 0.5rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.mobile {
|
||||||
|
padding: var(--spacing-0_5);
|
||||||
|
|
||||||
|
&:not(.sharing) .videoGrid,
|
||||||
|
&.sharing {
|
||||||
|
gap: var(--spacing-0_5);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.hidden {
|
.hidden {
|
||||||
display: none;
|
display: none;
|
||||||
|
@ -647,6 +647,18 @@
|
|||||||
const checkOnHide = (): void => {
|
const checkOnHide = (): void => {
|
||||||
if ($deviceInfo.navigator.visible && $deviceInfo.docWidth <= 1024) $deviceInfo.navigator.visible = false
|
if ($deviceInfo.navigator.visible && $deviceInfo.docWidth <= 1024) $deviceInfo.navigator.visible = false
|
||||||
}
|
}
|
||||||
|
let oldNavVisible: boolean = $deviceInfo.navigator.visible
|
||||||
|
let oldASideVisible: boolean = $deviceInfo.aside.visible
|
||||||
|
$: if (oldNavVisible !== $deviceInfo.navigator.visible || oldASideVisible !== $deviceInfo.aside.visible) {
|
||||||
|
if ($deviceInfo.isMobile && $deviceInfo.isPortrait && $deviceInfo.navigator.float) {
|
||||||
|
if ($deviceInfo.navigator.visible && $deviceInfo.aside.visible) {
|
||||||
|
if (oldNavVisible) $deviceInfo.navigator.visible = false
|
||||||
|
else $deviceInfo.aside.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
oldNavVisible = $deviceInfo.navigator.visible
|
||||||
|
oldASideVisible = $deviceInfo.aside.visible
|
||||||
|
}
|
||||||
$: $deviceInfo.navigator.direction = $deviceInfo.isMobile && $deviceInfo.isPortrait ? 'horizontal' : 'vertical'
|
$: $deviceInfo.navigator.direction = $deviceInfo.isMobile && $deviceInfo.isPortrait ? 'horizontal' : 'vertical'
|
||||||
let appsMini: boolean
|
let appsMini: boolean
|
||||||
$: appsMini =
|
$: appsMini =
|
||||||
|
@ -57,23 +57,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{:else if !mini}
|
{:else if !mini}
|
||||||
<ScrollerBar bind:scroller padding={'.25rem 0'}>
|
<div class="flex-row-center gap-1 py-1 overflow-x-auto">
|
||||||
{#each $tabsStore as tab (tab._id)}
|
{#each $tabsStore as tab (tab._id)}
|
||||||
<WorkbenchTabPresenter {tab} />
|
<WorkbenchTabPresenter {tab} />
|
||||||
{/each}
|
{/each}
|
||||||
</ScrollerBar>
|
</div>
|
||||||
{:else if selectedTab !== undefined}
|
{:else if selectedTab !== undefined}
|
||||||
<WorkbenchTabPresenter tab={selectedTab} />
|
<WorkbenchTabPresenter tab={selectedTab} />
|
||||||
<ButtonIcon
|
{#if $tabsStore.length > 1}
|
||||||
bind:element
|
<ButtonIcon
|
||||||
icon={IconMoreH}
|
bind:element
|
||||||
iconProps={{ fill: 'var(--theme-dark-color)' }}
|
icon={IconMoreH}
|
||||||
size={'extra-small'}
|
iconProps={{ fill: 'var(--theme-dark-color)' }}
|
||||||
kind={'tertiary'}
|
size={'extra-small'}
|
||||||
hasMenu
|
kind={'tertiary'}
|
||||||
{pressed}
|
hasMenu
|
||||||
on:click={showTabs}
|
{pressed}
|
||||||
/>
|
on:click={showTabs}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#if !popup}
|
{#if !popup}
|
||||||
<ButtonIcon
|
<ButtonIcon
|
||||||
|
Loading…
Reference in New Issue
Block a user