Skip to content

Commit

Permalink
feat(calls): add dragbar resize (#4427)
Browse files Browse the repository at this point in the history
* feat(calls): add dragbar resize

* fix(media): padding and drabbar size

Co-authored-by: Jason Woodland <me@jasonwoodland.com>
  • Loading branch information
josephmcg and jasonwoodland committed Aug 24, 2022
1 parent f7d228e commit 1d7bc26
Show file tree
Hide file tree
Showing 12 changed files with 68 additions and 249 deletions.
7 changes: 2 additions & 5 deletions components/interactables/DragBar/DragBar.less
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@dragbar-thickness: 6px;
@dragbar-thickness: 12px;

.drag-bar {
display: flex;
Expand Down Expand Up @@ -36,10 +36,7 @@

&:active::after {
position: fixed;
top: -100vh;
left: -100vw;
right: -100vw;
bottom: -100vh;
inset: -100vh -100vw;
content: '';
}

Expand Down
2 changes: 1 addition & 1 deletion components/views/chat/conversation/Conversation.less
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
.conversation {
display: flex;
flex-direction: column-reverse;
flex-grow: 1;
flex: 1;
overflow-y: auto;
justify-content: space-between;

Expand Down
18 changes: 7 additions & 11 deletions components/views/media/Media.html
Original file line number Diff line number Diff line change
@@ -1,35 +1,31 @@
<div class="mediastream" data-cy="mediastream" ref="mediastream">
<div class="mediastream" data-cy="mediastream" :style="`height:${height}`">
<MediaHeading />
<div class="media" ref="media">
<div class="media">
<MediaUser
id="local_video"
id="local"
:user="localParticipant"
isLocal
data-cy="local-video"
@dblclick="handleDoubleClick('local_video')"
/>

<MediaUser
v-for="participant in remoteParticipants"
:id="`remote_video_${ participant.did }`"
:user="participant"
data-cy="remote-video"
@dblclick="handleDoubleClick('remote_video')"
/>

<div
<!-- <div
v-if="ui.fullscreen && users.length > fullscreenMaxViewableUsers || !ui.fullscreen && users.length > maxViewableUsers"
class="more-user"
:class="{full: ui.fullscreen, 'full-mobile': fullscreenMaxViewableUsers === 6}"
>
...
</div>
</div> -->
</div>
<MediaActionsVolume
:volume="audio.volume"
:volume="volume"
isPopup
@volumeControlValueChange="volumeControlValueChange"
/>
<MediaActionsSettings />
<MediaActions />
<InteractablesDragBar side="bottom" showHandle @resize="(val)=> height=val" />
</div>
81 changes: 24 additions & 57 deletions components/views/media/Media.less
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
.mediastream {
display: flex;
max-height: 25.5rem;
background-color: @midground;
padding: 0.75rem;
flex-direction: column;
position: relative;
border-radius: @corner-rounding;
min-height: 100px;

.media {
position: relative;
Expand All @@ -18,7 +17,7 @@
gap: 8px;
padding: 8px;

#local_video {
#local {
order: -1;
}

Expand All @@ -31,32 +30,6 @@
height: 100% !important;
&:extend(.third-layer);
}
.video-stream-container {
height: 100%;
width: 100%;
background: @semitransparent-light-gradient;
border: 1px solid @foreground;
border-radius: @corner-rounding;
position: relative;
.video-stream {
width: 100%;
height: 100%;
border-radius: @corner-rounding;
}
.indicators {
display: flex;
flex-flow: row nowrap;
justify-content: flex-end;
position: absolute;
left: 0;
right: 0;
bottom: 0;
padding: 1rem;
.indicator {
margin-left: @light-spacing;
}
}
}
}
}
}
Expand All @@ -70,38 +43,32 @@
.media {
justify-content: center;
flex-direction: row;
.user {
.video-stream-container {
width: 100%;
height: 100%;
}
}
}
}
}

.more-user {
min-width: 16rem;
height: 9rem;
&:extend(.round-corners);
display: flex;
align-self: flex-end;
justify-content: center;
align-items: center;
order: 11;
font-size: 30px;
line-height: 28px;
margin: @xlight-spacing;
padding: @light-spacing;
position: relative;
&.full {
line-height: 13px;
text-align: center;
}
&.full-mobile {
min-width: 12rem !important;
}
}
// .more-user {
// min-width: 16rem;
// height: 9rem;
// &:extend(.round-corners);
// display: flex;
// align-self: flex-end;
// justify-content: center;
// align-items: center;
// order: 11;
// font-size: 30px;
// line-height: 28px;
// margin: @xlight-spacing;
// padding: @light-spacing;
// position: relative;
// &.full {
// line-height: 13px;
// text-align: center;
// }
// &.full-mobile {
// min-width: 12rem !important;
// }
// }

@media only screen and (max-width: @mobile-breakpoint) {
.mediastream {
Expand Down
163 changes: 11 additions & 152 deletions components/views/media/Media.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { mapState } from 'vuex'
import { User } from '~/libraries/Iridium/friends/types'
import iridium from '~/libraries/Iridium/IridiumManager'
import { useWebRTC } from '~/libraries/Iridium/webrtc/hooks'
import { RootState } from '~/types/store/store'
export default Vue.extend({
props: {
Expand Down Expand Up @@ -35,146 +36,16 @@ export default Vue.extend({
}
},
computed: {
...mapState(['ui', 'accounts', 'groups', 'audio']),
},
watch: {
'ui.fullscreen'(value) {
const media: HTMLElement = this.$refs.media as HTMLElement
if (!value) {
const blocks = media.querySelectorAll('.user, .more-user')
if (!media) return
for (let j = 0; j < blocks.length; j++) {
const block = blocks[j] as HTMLElement
/* set media user width to 16rem if 1:1 call on mobile, otherwise set smaller */
block.style.width =
this.$device.isMobile && blocks.length > 2 ? '160px' : '16rem'
block.style.height =
this.$device.isMobile && blocks.length > 2 ? '90px' : '9rem'
}
media.style.paddingTop = ''
media.style.paddingBottom = ''
} else {
// TODO: Listen to scroll event instead.. - AP-396
this.$nextTick(() => {
const isFit = function (
viewportWidth: number,
viewportHeight: number,
blockWidth: number,
blockHeight: number,
blockCount: number,
) {
const cols = Math.floor(viewportWidth / blockWidth)
const rows = Math.ceil(blockCount / cols)
return {
fit: blockHeight * rows < viewportHeight,
matrix: { cols, rows },
}
}
if (!media) return
const blocks = media.querySelectorAll('.user, .more-user')
if (
blocks.length === 0 ||
!document.querySelectorAll('.fullscreen-media')
)
return
const viewportWidth = media.clientWidth
const viewportHeight = media.clientHeight
const blockCount = blocks.length
const blockStyle = window.getComputedStyle(blocks[0])
const blockMargin = Math.floor(
parseInt(blockStyle.margin.replace('px', '')),
)
const marginPerBlock = blockMargin * 2
// Variables created that will either be declared if the user is in 'mobile fullscreen calls'
// Else, they are left undefined and use different logic for 'desktop fullscreen calls'
let mobileMaxBlockContentWidth
let mobileAspectRatio
if (this.$device.isMobile === true) {
if (blockCount === 1) {
mobileMaxBlockContentWidth = viewportWidth - marginPerBlock * 1.5
mobileAspectRatio = 3 / 4
} else if (blockCount === 2) {
mobileMaxBlockContentWidth = viewportWidth - marginPerBlock * 1.5
mobileAspectRatio = 1 / 2
} else if (blockCount <= 4) {
mobileMaxBlockContentWidth =
viewportWidth / 2 - marginPerBlock * 1.5
mobileAspectRatio = 4 / 3
} else {
mobileMaxBlockContentWidth =
viewportWidth / 2 - marginPerBlock * 1.5
mobileAspectRatio = 3 / 4
}
}
// logic for 'desktop fullscreen calls' where we set the max block content size so that a block cannot be larger than half viewportWidth
const maxBlockContentWidth =
typeof mobileMaxBlockContentWidth === 'undefined'
? viewportWidth / 2 - marginPerBlock * 1.5
: mobileMaxBlockContentWidth
const aspectRatio =
typeof mobileAspectRatio === 'undefined'
? 9 / 16
: mobileAspectRatio
let finalWidth = 160
let finalHeight = 90
let finalMatrix = { cols: 1, rows: 1 }
// if max block of a content is reach, stop the loop
let maxBlockContentWidthReached = false
for (let i = 2; i <= 100 && !maxBlockContentWidthReached; i++) {
maxBlockContentWidthReached =
Math.floor((viewportWidth * i) / 100) > maxBlockContentWidth
const blockContentWidth = maxBlockContentWidthReached
? maxBlockContentWidth
: Math.floor((viewportWidth * i) / 100)
const blockContentHeight = Math.floor(
blockContentWidth * aspectRatio,
)
const blockWidth = blockContentWidth + marginPerBlock
const blockHeight = blockContentHeight + marginPerBlock
const { fit, matrix } = isFit(
viewportWidth,
viewportHeight,
blockWidth,
blockHeight,
blockCount,
)
if (!fit) {
break
}
finalWidth = blockContentWidth
finalHeight = blockContentHeight
finalMatrix = matrix
}
for (let i = 0; i < blockCount; i++) {
const block = blocks[i] as HTMLElement
block.style.width = finalWidth + 'px'
block.style.height = finalHeight + 'px'
}
const height = finalHeight * finalMatrix.rows
if (height <= viewportHeight) {
const padding = Math.floor((viewportHeight - height) / 2)
media.style.paddingTop = padding + 'px'
media.style.paddingBottom = padding + 'px'
}
})
}
},
'audio.volume': {
handler(volume) {
// Bind stream audio element volume to slider volume
const audioStreamElements = document.getElementsByClassName(
'remote-audio-stream',
) as HTMLCollectionOf<HTMLAudioElement>
for (const audioStreamElement of audioStreamElements) {
audioStreamElement.volume = volume / 100
}
...mapState({
callHeight: (state) => (state as RootState).ui.callHeight,
volume: (state) => (state as RootState).audio.volume,
}),
height: {
get(): string {
return this.callHeight
},
set(value) {
this.$store.commit('ui/setCallHeight', value)
},
},
},
Expand All @@ -189,18 +60,6 @@ export default Vue.extend({
this.$Sounds.changeLevels(volume / 100)
this.$store.commit('audio/setVolume', volume)
},
handleDoubleClick(id: string) {
if (!this.ui.fullscreen) {
this.$store.commit('ui/fullscreen', true)
}
const media: HTMLElement = this.$refs.media as HTMLElement
const element = media.querySelector(`#${id}`)
if (element?.classList.contains('full-video')) {
element?.classList.remove('full-video')
} else {
element?.classList.add('full-video')
}
},
},
})
</script>
Expand Down
Loading

0 comments on commit 1d7bc26

Please sign in to comment.