mirror of
https://github.com/nextcloud/spreed.git
synced 2025-12-17 21:12:20 +01:00
fix: RTL support in call view
Signed-off-by: Dorra Jaouad <dorra.jaoued7@gmail.com> Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
This commit is contained in:
parent
9815309a80
commit
d19a764143
11 changed files with 77 additions and 59 deletions
|
|
@ -806,7 +806,7 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
@import '../../assets/variables';
|
||||
/* stylelint-disable csstools/use-logical */
|
||||
|
||||
#call-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
|
@ -867,7 +867,7 @@ export default {
|
|||
|
||||
.local-video {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
bottom: 0;
|
||||
width: 300px;
|
||||
height: 250px;
|
||||
|
|
|
|||
|
|
@ -12,10 +12,10 @@
|
|||
:aria-label="stripeButtonTitle"
|
||||
@click="handleClickStripeCollapse">
|
||||
<template #icon>
|
||||
<ChevronDown v-if="stripeOpen"
|
||||
<IconChevronDown v-if="stripeOpen"
|
||||
fill-color="#ffffff"
|
||||
:size="20" />
|
||||
<ChevronUp v-else
|
||||
<IconChevronUp v-else
|
||||
fill-color="#ffffff"
|
||||
:size="20" />
|
||||
</template>
|
||||
|
|
@ -29,7 +29,8 @@
|
|||
:aria-label="t('spreed', 'Previous page of videos')"
|
||||
@click="handleClickPrevious">
|
||||
<template #icon>
|
||||
<ChevronLeft fill-color="#ffffff"
|
||||
<IconChevronLeft class="bidirectional-icon"
|
||||
fill-color="#ffffff"
|
||||
:size="20" />
|
||||
</template>
|
||||
</NcButton>
|
||||
|
|
@ -90,7 +91,8 @@
|
|||
:aria-label="t('spreed', 'Next page of videos')"
|
||||
@click="handleClickNext">
|
||||
<template #icon>
|
||||
<ChevronRight fill-color="#ffffff"
|
||||
<IconChevronRight class="bidirectional-icon"
|
||||
fill-color="#ffffff"
|
||||
:size="20" />
|
||||
</template>
|
||||
</NcButton>
|
||||
|
|
@ -111,7 +113,10 @@
|
|||
aria-label="Toggle screenshot mode"
|
||||
@click="screenshotMode = !screenshotMode">
|
||||
<template #icon>
|
||||
<ChevronLeft v-if="!screenshotMode" fill-color="#00FF41" :size="20" />
|
||||
<IconChevronLeft v-if="!screenshotMode"
|
||||
class="bidirectional-icon"
|
||||
fill-color="#00FF41"
|
||||
:size="20" />
|
||||
</template>
|
||||
</NcButton>
|
||||
<div v-if="!screenshotMode" class="dev-mode__data">
|
||||
|
|
@ -143,10 +148,10 @@
|
|||
import debounce from 'debounce'
|
||||
import { inject, ref } from 'vue'
|
||||
|
||||
import ChevronDown from 'vue-material-design-icons/ChevronDown.vue'
|
||||
import ChevronLeft from 'vue-material-design-icons/ChevronLeft.vue'
|
||||
import ChevronRight from 'vue-material-design-icons/ChevronRight.vue'
|
||||
import ChevronUp from 'vue-material-design-icons/ChevronUp.vue'
|
||||
import IconChevronDown from 'vue-material-design-icons/ChevronDown.vue'
|
||||
import IconChevronLeft from 'vue-material-design-icons/ChevronLeft.vue'
|
||||
import IconChevronRight from 'vue-material-design-icons/ChevronRight.vue'
|
||||
import IconChevronUp from 'vue-material-design-icons/ChevronUp.vue'
|
||||
|
||||
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
|
||||
import { loadState } from '@nextcloud/initial-state'
|
||||
|
|
@ -179,10 +184,10 @@ export default {
|
|||
NcButton,
|
||||
TransitionWrapper,
|
||||
VideoBottomBar,
|
||||
ChevronRight,
|
||||
ChevronLeft,
|
||||
ChevronUp,
|
||||
ChevronDown,
|
||||
IconChevronDown,
|
||||
IconChevronLeft,
|
||||
IconChevronRight,
|
||||
IconChevronUp,
|
||||
},
|
||||
|
||||
props: {
|
||||
|
|
@ -958,7 +963,6 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* stylelint-disable csstools/use-logical */
|
||||
.grid-main-wrapper {
|
||||
--navigation-position: calc(var(--default-grid-baseline) * 2);
|
||||
position: relative;
|
||||
|
|
@ -978,7 +982,7 @@ export default {
|
|||
display: flex;
|
||||
position: relative;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
}
|
||||
|
||||
.grid {
|
||||
|
|
@ -1028,6 +1032,7 @@ export default {
|
|||
|
||||
.dev-mode__title {
|
||||
position: absolute;
|
||||
/* stylelint-disable-next-line csstools/use-logical */
|
||||
left: var(--default-clickable-area);
|
||||
color: #00FF41;
|
||||
z-index: 100;
|
||||
|
|
@ -1040,14 +1045,17 @@ export default {
|
|||
|
||||
.dev-mode__toggle {
|
||||
position: fixed !important;
|
||||
/* stylelint-disable-next-line csstools/use-logical */
|
||||
left: 20px;
|
||||
top: calc(2 * var(--header-height));
|
||||
}
|
||||
|
||||
.dev-mode__data {
|
||||
direction: ltr;
|
||||
font-family: monospace;
|
||||
position: fixed;
|
||||
color: #00FF41;
|
||||
/* stylelint-disable-next-line csstools/use-logical */
|
||||
left: 20px;
|
||||
top: calc(2 * var(--header-height) + 40px);
|
||||
padding: 5px;
|
||||
|
|
@ -1082,11 +1090,11 @@ export default {
|
|||
top: calc(50% - var(--default-clickable-area) / 2);
|
||||
|
||||
&__previous {
|
||||
left: calc(var(--default-grid-baseline) * 2);
|
||||
inset-inline-start: calc(var(--default-grid-baseline) * 2);
|
||||
}
|
||||
|
||||
&__next {
|
||||
right: calc(var(--default-grid-baseline) * 2);
|
||||
inset-inline-end: calc(var(--default-grid-baseline) * 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1095,11 +1103,11 @@ export default {
|
|||
top: calc(var(--navigation-position) + var(--grid-gap));
|
||||
|
||||
&__previous {
|
||||
left: var(--navigation-position);
|
||||
inset-inline-start: var(--navigation-position);
|
||||
}
|
||||
|
||||
&__next {
|
||||
right: calc(var(--navigation-position) + var(--grid-gap));
|
||||
inset-inline-end: calc(var(--navigation-position) + var(--grid-gap));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1107,7 +1115,7 @@ export default {
|
|||
.stripe--collapse {
|
||||
position: absolute !important;
|
||||
top: calc(-1 * (var(--default-clickable-area) + var(--navigation-position) / 2));
|
||||
right: calc(var(--navigation-position) / 2) ;
|
||||
inset-inline-end: calc(var(--navigation-position) / 2) ;
|
||||
}
|
||||
|
||||
.stripe--collapse,
|
||||
|
|
|
|||
|
|
@ -218,6 +218,6 @@ export default {
|
|||
.popover-hint {
|
||||
padding: calc(3 * var(--default-grid-baseline));
|
||||
max-width: 300px;
|
||||
text-align: left;
|
||||
text-align: start;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -360,7 +360,6 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* stylelint-disable csstools/use-logical */
|
||||
.not-connected {
|
||||
video,
|
||||
.avatar-container {
|
||||
|
|
@ -422,7 +421,7 @@ export default {
|
|||
.video-loading {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -451,7 +450,7 @@ export default {
|
|||
height: 100%;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
border-radius: var(--border-radius-element, calc(var(--default-clickable-area) / 2));
|
||||
}
|
||||
|
||||
|
|
@ -508,7 +507,7 @@ export default {
|
|||
.presenter-icon__hide {
|
||||
position: absolute;
|
||||
color: white;
|
||||
left: calc(50% - var(--default-clickable-area) / 2);
|
||||
inset-inline-start: calc(50% - var(--default-clickable-area) / 2);
|
||||
top: calc(100% - var(--default-grid-baseline) - var(--default-clickable-area));
|
||||
opacity: 0.7;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
:resizable="false"
|
||||
:h="presenterOverlaySize"
|
||||
:w="presenterOverlaySize"
|
||||
:x="10"
|
||||
:x="isRTL ? parentWidth - presenterOverlaySize - 10 : 10"
|
||||
:y="10"
|
||||
@dragging="isDragging = true"
|
||||
@dragstop="isDragging = false">
|
||||
|
|
@ -50,11 +50,12 @@
|
|||
|
||||
<script>
|
||||
|
||||
import { ref } from 'vue'
|
||||
import VueDraggableResizable from 'vue-draggable-resizable'
|
||||
|
||||
import AccountBox from 'vue-material-design-icons/AccountBoxOutline.vue'
|
||||
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { t, isRTL } from '@nextcloud/l10n'
|
||||
|
||||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||
|
||||
|
|
@ -106,6 +107,14 @@ export default {
|
|||
|
||||
emits: ['click'],
|
||||
|
||||
setup() {
|
||||
const parentWidth = ref(document.getElementById('videos').getBoundingClientRect().width)
|
||||
return {
|
||||
parentWidth,
|
||||
isRTL,
|
||||
}
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
resizeObserver: null,
|
||||
|
|
@ -150,10 +159,10 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* stylelint-disable csstools/use-logical */
|
||||
.presenter-overlay {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
/* stylelint-disable-next-line csstools/use-logical */
|
||||
left: 0;
|
||||
}
|
||||
|
||||
|
|
@ -181,7 +190,7 @@ export default {
|
|||
position: absolute !important;
|
||||
opacity: .7;
|
||||
bottom: 48px;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
|
||||
#call-container:hover & {
|
||||
background-color: rgba(0, 0, 0, 0.1) !important;
|
||||
|
|
|
|||
|
|
@ -216,11 +216,10 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* stylelint-disable csstools/use-logical */
|
||||
.toaster {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
|
|
@ -231,7 +230,7 @@ export default {
|
|||
.toast {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: var(--horizontal-offset, 0);
|
||||
inset-inline-start: var(--horizontal-offset, 0);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
|
|
|
|||
|
|
@ -204,7 +204,6 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* stylelint-disable csstools/use-logical */
|
||||
.screenContainer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
|
@ -215,7 +214,7 @@ export default {
|
|||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
&--fit {
|
||||
object-fit: contain;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,10 +40,9 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* stylelint-disable csstools/use-logical */
|
||||
.video-background {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
top: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
|
|
@ -55,7 +54,7 @@ export default {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -628,7 +628,6 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* stylelint-disable csstools/use-logical */
|
||||
.not-connected {
|
||||
video,
|
||||
.avatar-container {
|
||||
|
|
@ -693,7 +692,7 @@ export default {
|
|||
& > .dev-mode-video--presenter {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
object-fit: cover;
|
||||
|
|
@ -704,7 +703,7 @@ export default {
|
|||
.video-loading {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
@ -742,7 +741,7 @@ export default {
|
|||
height: 100%;
|
||||
width: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
inset-inline-start: 0;
|
||||
border-radius: var(--border-radius-element, calc(var(--default-clickable-area) / 2));
|
||||
}
|
||||
|
||||
|
|
@ -765,7 +764,7 @@ export default {
|
|||
.presenter-icon__hide {
|
||||
position: absolute;
|
||||
color: white;
|
||||
left: calc(50% - var(--default-clickable-area) / 2);
|
||||
inset-inline-start: calc(50% - var(--default-clickable-area) / 2);
|
||||
top: calc(100% - var(--default-grid-baseline) - var(--default-clickable-area));
|
||||
opacity: 0.7;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
|
|
|
|||
|
|
@ -8,10 +8,7 @@
|
|||
<Portal>
|
||||
<!-- Add .app-talk to use Talk icon classes outside of #content-vue -->
|
||||
<div class="viewer-overlay app-talk"
|
||||
:style="{
|
||||
right: position.right + 'px',
|
||||
bottom: position.bottom + 'px'
|
||||
}">
|
||||
:style="computedStyle">
|
||||
<div class="viewer-overlay__collapse"
|
||||
:class="{ collapsed: isCollapsed }">
|
||||
<NcButton type="secondary"
|
||||
|
|
@ -105,7 +102,7 @@ import ArrowExpand from 'vue-material-design-icons/ArrowExpand.vue'
|
|||
import ChevronDown from 'vue-material-design-icons/ChevronDown.vue'
|
||||
import ChevronUp from 'vue-material-design-icons/ChevronUp.vue'
|
||||
|
||||
import { t } from '@nextcloud/l10n'
|
||||
import { t, isRTL } from '@nextcloud/l10n'
|
||||
|
||||
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
|
||||
|
||||
|
|
@ -194,6 +191,7 @@ export default {
|
|||
observer: null,
|
||||
position: {
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
},
|
||||
}
|
||||
|
|
@ -211,6 +209,13 @@ export default {
|
|||
showLocalScreen() {
|
||||
return this.hasLocalScreen && this.screens[0] === localCallParticipantModel.attributes.peerId
|
||||
},
|
||||
|
||||
computedStyle() {
|
||||
return {
|
||||
[isRTL() ? 'left' : 'right']: this.position[isRTL() ? 'left' : 'right'] + 'px',
|
||||
bottom: this.position.bottom + 'px'
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
mounted() {
|
||||
|
|
@ -233,8 +238,12 @@ export default {
|
|||
},
|
||||
|
||||
updatePosition() {
|
||||
const { right, bottom } = this.$refs.ghost.getBoundingClientRect()
|
||||
this.position.right = window.innerWidth - right
|
||||
const { left, right, bottom } = this.$refs.ghost.getBoundingClientRect()
|
||||
if (isRTL()) {
|
||||
this.position.left = left
|
||||
} else {
|
||||
this.position.right = window.innerWidth - right
|
||||
}
|
||||
this.position.bottom = window.innerHeight - bottom
|
||||
},
|
||||
},
|
||||
|
|
@ -242,12 +251,10 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
/* stylelint-disable csstools/use-logical */
|
||||
.viewer-overlay-ghost {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
left: 0;
|
||||
inset-inline: 0 8px;
|
||||
}
|
||||
|
||||
.viewer-overlay {
|
||||
|
|
@ -270,7 +277,7 @@ export default {
|
|||
.viewer-overlay__collapse {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 8px;
|
||||
inset-inline-end: 8px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
|
|
@ -286,7 +293,7 @@ export default {
|
|||
.video-overlay__top-bar {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 8px;
|
||||
inset-inline-start: 8px;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
|
|
@ -309,13 +316,13 @@ export default {
|
|||
max-height: calc(var(--max-width) * var(--aspect-ratio));
|
||||
/* Note: because of transition it always has position absolute on animation */
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
inset-inline-end: 0;
|
||||
}
|
||||
|
||||
.viewer-overlay__local-video {
|
||||
position: absolute;
|
||||
bottom: 8px;
|
||||
right: 8px;
|
||||
inset-inline-end: 8px;
|
||||
width: 25%;
|
||||
height: 25%;
|
||||
overflow: hidden;
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ stylelintConfig.plugins.push('stylelint-use-logical')
|
|||
stylelintConfig.rules['csstools/use-logical'] = [
|
||||
'always',
|
||||
{
|
||||
severity: 'warning',
|
||||
// Only lint LTR-RTL properties for now
|
||||
except: [
|
||||
// Position properties
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue