@live-change/video-call-frontend 0.8.40 → 0.8.41

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,235 @@
1
+ {
2
+ "version": "6.0",
3
+ "nxVersion": "18.0.6",
4
+ "deps": {
5
+ "@codemirror/language": "6.10.1",
6
+ "@dotenvx/dotenvx": "0.27.0",
7
+ "@fortawesome/fontawesome-free": "^6.5.2",
8
+ "@live-change/access-control-frontend": "^0.8.40",
9
+ "@live-change/access-control-service": "^0.8.40",
10
+ "@live-change/backup-service": "^0.8.40",
11
+ "@live-change/blog-frontend": "^0.8.40",
12
+ "@live-change/blog-service": "^0.8.40",
13
+ "@live-change/cli": "^0.8.40",
14
+ "@live-change/content-frontend": "^0.8.40",
15
+ "@live-change/content-service": "^0.8.40",
16
+ "@live-change/dao": "^0.8.40",
17
+ "@live-change/dao-vue3": "^0.8.40",
18
+ "@live-change/dao-websocket": "^0.8.40",
19
+ "@live-change/db-client": "^0.8.40",
20
+ "@live-change/email-service": "^0.8.40",
21
+ "@live-change/framework": "^0.8.40",
22
+ "@live-change/frontend-auto-form": "^0.8.40",
23
+ "@live-change/frontend-base": "^0.8.40",
24
+ "@live-change/geoip-service": "^0.8.40",
25
+ "@live-change/image-frontend": "^0.8.40",
26
+ "@live-change/locale-settings-service": "^0.8.40",
27
+ "@live-change/password-authentication-service": "^0.8.40",
28
+ "@live-change/peer-connection-service": "^0.8.40",
29
+ "@live-change/prosemirror-service": "^0.8.40",
30
+ "@live-change/secret-code-service": "^0.8.40",
31
+ "@live-change/secret-link-service": "^0.8.40",
32
+ "@live-change/session-service": "^0.8.40",
33
+ "@live-change/task-service": "^0.8.40",
34
+ "@live-change/upload-frontend": "^0.8.40",
35
+ "@live-change/url-frontend": "^0.8.40",
36
+ "@live-change/url-service": "^0.8.40",
37
+ "@live-change/user-frontend": "^0.8.40",
38
+ "@live-change/user-identification-service": "^0.8.40",
39
+ "@live-change/user-service": "^0.8.40",
40
+ "@live-change/vote-service": "^0.8.40",
41
+ "@live-change/vue3-components": "^0.8.40",
42
+ "@live-change/vue3-ssr": "^0.8.40",
43
+ "@vueuse/core": "^10.11.0",
44
+ "boxicons": "^2.1.4",
45
+ "codeceptjs-assert": "^0.0.5",
46
+ "compression": "^1.7.4",
47
+ "cross-env": "^7.0.3",
48
+ "feather-icons": "^4.29.2",
49
+ "get-port-sync": "1.0.1",
50
+ "pica": "^9.0.1",
51
+ "pretty-bytes": "^6.1.1",
52
+ "primeflex": "^3.3.1",
53
+ "primeicons": "^7.0.0",
54
+ "primevue": "^3.52.0",
55
+ "rollup-plugin-node-builtins": "^2.1.2",
56
+ "rollup-plugin-visualizer": "5.12.0",
57
+ "serialize-javascript": "^6.0.2",
58
+ "serve-static": "^1.15.0",
59
+ "v-shared-element": "3.1.1",
60
+ "vue": "^3.4.29",
61
+ "vue-i18n": "^9.10.1",
62
+ "vue-router": "^4.3.3",
63
+ "vue3-scroll-border": "0.1.6",
64
+ "@live-change/codeceptjs-helper": "^0.8.40",
65
+ "codeceptjs": "^3.5.12",
66
+ "generate-password": "1.7.1",
67
+ "playwright": "^1.41.2",
68
+ "random-profile-generator": "^2.3.0",
69
+ "txtgen": "^3.0.6",
70
+ "webdriverio": "^8.31.1"
71
+ },
72
+ "pathMappings": {},
73
+ "nxJsonPlugins": [],
74
+ "fileMap": {
75
+ "projectFileMap": {},
76
+ "nonProjectFiles": [
77
+ {
78
+ "file": ".gitignore",
79
+ "hash": "16528976885761916170"
80
+ },
81
+ {
82
+ "file": "LICENSE",
83
+ "hash": "10221119794387200971"
84
+ },
85
+ {
86
+ "file": "front/index.html",
87
+ "hash": "3170363056965810468"
88
+ },
89
+ {
90
+ "file": "front/locales/en.js",
91
+ "hash": "10652573724821059037"
92
+ },
93
+ {
94
+ "file": "front/locales/en.json",
95
+ "hash": "7756539891184290419"
96
+ },
97
+ {
98
+ "file": "front/public/favicon.ico",
99
+ "hash": "11176796980188620760"
100
+ },
101
+ {
102
+ "file": "front/public/images/cameraAccess/en.png",
103
+ "hash": "3450745769251948963"
104
+ },
105
+ {
106
+ "file": "front/public/images/empty-photo.svg",
107
+ "hash": "9393138513813369674"
108
+ },
109
+ {
110
+ "file": "front/public/images/empty-user-photo.svg",
111
+ "hash": "17548039285248668212"
112
+ },
113
+ {
114
+ "file": "front/public/images/logo.svg",
115
+ "hash": "5934164668360941413"
116
+ },
117
+ {
118
+ "file": "front/public/images/logo128.png",
119
+ "hash": "4924117807669085214"
120
+ },
121
+ {
122
+ "file": "front/public/video-test/1280x1024.png",
123
+ "hash": "11823584133987003265"
124
+ },
125
+ {
126
+ "file": "front/public/video-test/1280x720.png",
127
+ "hash": "15574426061858183013"
128
+ },
129
+ {
130
+ "file": "front/public/video-test/1280x800.png",
131
+ "hash": "14511549547541683392"
132
+ },
133
+ {
134
+ "file": "front/public/video-test/1280x854.png",
135
+ "hash": "4797987282838464847"
136
+ },
137
+ {
138
+ "file": "front/public/video-test/1280x960.png",
139
+ "hash": "10549452614105172851"
140
+ },
141
+ {
142
+ "file": "front/public/video-test/2048x1080.png",
143
+ "hash": "6151660943780039499"
144
+ },
145
+ {
146
+ "file": "front/src/App.vue",
147
+ "hash": "6472353844158551308"
148
+ },
149
+ {
150
+ "file": "front/src/config.js",
151
+ "hash": "4208481022464725661"
152
+ },
153
+ {
154
+ "file": "front/src/entry-client.js",
155
+ "hash": "1218837904372604167"
156
+ },
157
+ {
158
+ "file": "front/src/entry-server.js",
159
+ "hash": "406370987563099630"
160
+ },
161
+ {
162
+ "file": "front/src/pages/video-wall-test.vue",
163
+ "hash": "8927921712980148693"
164
+ },
165
+ {
166
+ "file": "front/src/room/PeerVideo.vue",
167
+ "hash": "7826013413791984776"
168
+ },
169
+ {
170
+ "file": "front/src/room/Room.vue",
171
+ "hash": "9885330386595086779"
172
+ },
173
+ {
174
+ "file": "front/src/room/VideoWall.vue",
175
+ "hash": "12009121673115555256"
176
+ },
177
+ {
178
+ "file": "front/src/room/allocateSpace.js",
179
+ "hash": "14807348244755613396"
180
+ },
181
+ {
182
+ "file": "front/src/room/videoWallTestData.js",
183
+ "hash": "1081642442820842935"
184
+ },
185
+ {
186
+ "file": "front/src/router.js",
187
+ "hash": "14015810002038028326"
188
+ },
189
+ {
190
+ "file": "front/tsconfig.json",
191
+ "hash": "6166366661637344199"
192
+ },
193
+ {
194
+ "file": "front/tsconfig.node.json",
195
+ "hash": "4208030242441905014"
196
+ },
197
+ {
198
+ "file": "front/vite.config.ts",
199
+ "hash": "17481691610523253886"
200
+ },
201
+ {
202
+ "file": "index.js",
203
+ "hash": "2260432220446614367"
204
+ },
205
+ {
206
+ "file": "package.json",
207
+ "hash": "9403071523936589822"
208
+ },
209
+ {
210
+ "file": "server/app.config.js",
211
+ "hash": "1191433411552651640"
212
+ },
213
+ {
214
+ "file": "server/init.js",
215
+ "hash": "11195994814182901453"
216
+ },
217
+ {
218
+ "file": "server/page.documentType.js",
219
+ "hash": "4319267302010918354"
220
+ },
221
+ {
222
+ "file": "server/security.config.js",
223
+ "hash": "6483730663450187822"
224
+ },
225
+ {
226
+ "file": "server/services.list.js",
227
+ "hash": "1630808974015366632"
228
+ },
229
+ {
230
+ "file": "server/start.js",
231
+ "hash": "12152681523604331573"
232
+ }
233
+ ]
234
+ }
235
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "nodes": {},
3
+ "externalNodes": {},
4
+ "dependencies": {},
5
+ "version": "6.0"
6
+ }
@@ -0,0 +1,31 @@
1
+ <route>
2
+ {
3
+ meta: {
4
+ raw: true
5
+ }
6
+ }
7
+ </route>
8
+
9
+ <template>
10
+
11
+ <!-- <pre>{{ testData }}</pre>-->
12
+ <VideoWall
13
+ :mainVideos="testData.mainVideos"
14
+ :topVideos="testData.topVideos"
15
+ :otherVideos="testData.otherVideos"
16
+ :myVideos="testData.myVideos"
17
+ class="absolute surface-900 w-full h-full"
18
+ />
19
+
20
+ </template>
21
+
22
+ <script setup>
23
+ import testData from "../room/videoWallTestData.js"
24
+ import VideoWall from '../room/VideoWall.vue'
25
+
26
+
27
+ </script>
28
+
29
+ <style scoped>
30
+
31
+ </style>
@@ -1,29 +1,77 @@
1
1
  <template>
2
- <div @click="ev => $emit('click', ev)">
3
- <div v-if="peerState.videoMuted || !stream">
4
- <UserIdentification :ownerType="ownerType" :owner="owner" />
2
+ <div @click="ev => $emit('click', ev)"
3
+ class="absolute surface-900 text-gray-200 border-1 border-white-alpha-30 peer-video">
5
4
 
5
+ <div v-if="image && (!stream || peerState.videoMuted)"
6
+ class="absolute w-full h-full bg-no-repeat bg-center" :style="{
7
+ 'background-image': 'url(' + image + ')',
8
+ 'background-size': '90%'
9
+ }">
6
10
  </div>
7
11
 
8
- <div>
12
+ <div v-if="(peerState?.videoMuted || !stream) && !image"
13
+ class="absolute w-full h-full flex flex-column align-items-center justify-content-center identification">
14
+ <UserIdentification :ownerType="ownerType" :owner="owner" />
15
+ </div>
16
+
17
+ <div v-if="stream">
9
18
  <video autoplay playsinline
10
19
  :src-object.prop.camel="stream"
11
20
  :volume.prop.camel="volume"
21
+ :muted="audioMuted"
12
22
  :ref="videoElement"
13
- @resize="handleVideoResize">
23
+ @resize="handleVideoResize"
24
+ class="w-full h-full"
25
+ :style="mirror ? 'transform: scaleX(-1)' : ''">
14
26
  </video>
15
27
  </div>
16
28
 
17
- <VolumeIndicator v-if="video.srcObject" :stream="stream"></VolumeIndicator>
29
+ <VolumeIndicator v-if="stream" :stream="stream"
30
+ class="absolute" :style="{ right: 'calc(1% + 0.3rem)', top: 'calc(1% + 0.3rem) ' }" />
18
31
 
19
32
  <div v-if="peerState">
20
33
  <i v-if="peerState.videoMuted" class='bx bx-camera-off' />
21
34
  <i v-if="peerState.audioState" class='bx bx-microphone-off' />
22
35
  </div>
23
36
 
37
+ <pre>{{ image }}</pre>
38
+ <!-- <h3>{{ id }}</h3>-->
39
+
24
40
  </div>
25
41
  </template>
26
42
 
43
+ <style lang="scss">
44
+ .peer-video {
45
+ .identification {
46
+ & > span > span, a {
47
+ display: flex !important;
48
+ flex-direction: column !important;
49
+ position: absolute;
50
+ width: 100%;
51
+ left: 0;
52
+ top: 0;
53
+ height: 100%;
54
+ align-items: center;
55
+ justify-content: center;
56
+ height: 100%;
57
+ width: 100%;
58
+ img, i {
59
+ max-height: 70px !important;
60
+ width: auto !important;
61
+ height: 50% !important;
62
+ aspect-ratio: 1/1;
63
+ border: 1px solid red;
64
+ }
65
+ span {
66
+ color: rgba(255,255,255,0.8);
67
+ margin-top: 0.4em;
68
+ font-size: 1.1em
69
+ }
70
+ }
71
+ }
72
+ }
73
+ </style>
74
+
27
75
  <script setup>
28
76
 
29
77
  import { VolumeIndicator } from "@live-change/peer-connection-frontend"
@@ -32,9 +80,17 @@
32
80
  import { defineProps, defineEmits, toRefs, ref, computed } from 'vue'
33
81
 
34
82
  const props = defineProps({
83
+ id: {
84
+ type: String,
85
+ required: true
86
+ },
35
87
  stream: {
36
88
  type: Object,
37
- required: true
89
+ default: null,
90
+ },
91
+ image: {
92
+ type: String,
93
+ required: false
38
94
  },
39
95
  ownerType: {
40
96
  type: String,
@@ -50,10 +106,18 @@
50
106
  },
51
107
  volume: {
52
108
  type: Number,
53
- defaultValue: 1
54
- }
109
+ default: 1
110
+ },
111
+ audioMuted: {
112
+ type: Boolean,
113
+ default: false
114
+ },
115
+ mirror: {
116
+ type: Boolean,
117
+ default: false
118
+ },
55
119
  })
56
- const { stream, ownerType, owner, peerState } = toRefs(props)
120
+ const { id, stream, image, ownerType, owner, peerState, audioMuted, mirror } = toRefs(props)
57
121
 
58
122
  const emit = defineEmits(['resize'])
59
123
 
@@ -1,30 +1,43 @@
1
1
  <template>
2
- <LimitedAccess v-slot="{ authorized }" objectType="videoCall_Room" :object="room" :requiredRoles="requiredRoles">
3
- <div v-if="state === 'welcome'"
4
- class="surface-card shadow-1 border-round p-3 flex flex-row flex-wrap align-items-center">
5
- <div class="w-30rem m-1" style="max-width: 80vw">
6
- <DeviceSelect v-model="selectedDevices" />
2
+ <LimitedAccess objectType="videoCall_Room" :object="room"
3
+ :requiredRoles="requiredRoles"
4
+ hidden
5
+ class="absolute w-full h-full">
6
+ <template #default>
7
+ <div class="absolute w-full h-full flex flex-row align-items-center justify-content-center">
8
+ <div class="surface-card shadow-1 border-round p-3 flex flex-row flex-wrap align-items-center"
9
+ :class="{ hidden: state !== 'welcome' }">
10
+ <div class="w-30rem m-1" style="max-width: 80vw">
11
+ <DeviceSelect v-model="selectedDevices" />
12
+ </div>
13
+ <div class="m-3 text-center">
14
+ <h3>Select your media devices, and join.</h3>
15
+ <Button @click="join" icon="pi pi-check" label="Join" />
16
+ </div>
17
+ </div>
7
18
  </div>
8
- <div class="m-3 text-center">
9
- <h3>Select your media devices, and join.</h3>
10
- <Button @click="join" icon="pi pi-check" label="Join" />
11
- </div>
12
- </div>
13
- <template v-else>
14
- <p>JOINED</p>
19
+ <template v-if="state === 'joined'">
20
+ <VideoWall
21
+ :main-videos="mainVideos ?? []"
22
+ :my-videos="myVideos ?? []"
23
+ class="w-full h-full top-0 absolute surface-900"
24
+ />
25
+ </template>
26
+ <!-- <p>selected devices: {{ selectedDevices }}</p>
27
+ <p>local media streams: {{ localMediaStreams }}</p>
28
+ <p>local tracks: {{ localTracks }}</p>-->
29
+ <!-- <div class="bg-black-alpha-50 shadow-1 border-round mt-3 p-3 absolute text-white-alpha-90">
30
+ <pre>{{ JSON.stringify(peer?.summary, null, " ") }}</pre>
31
+ </div>-->
15
32
  </template>
16
- <!-- <p>selected devices: {{ selectedDevices }}</p>
17
- <p>local media streams: {{ localMediaStreams }}</p>
18
- <p>local tracks: {{ localTracks }}</p>-->
19
- <div class="surface-card shadow-1 border-round mt-3 p-3">
20
- <pre>{{ JSON.stringify(peer?.summary, null, " ") }}</pre>
21
- </div>
33
+
22
34
  </LimitedAccess>
23
35
  </template>
24
36
 
25
37
  <script setup>
26
38
  import { LimitedAccess } from "@live-change/access-control-frontend"
27
39
  import { DeviceSelect } from '@live-change/peer-connection-frontend'
40
+ import VideoWall from './VideoWall.vue'
28
41
 
29
42
  import {
30
43
  ref, unref, computed, watch, watchEffect, toRefs,
@@ -100,6 +113,36 @@
100
113
  await initPeer()
101
114
  })
102
115
 
116
+ const myVideos = computed(() => {
117
+ //return []
118
+ if(!localMediaStreams.value?.length) return []
119
+ return localMediaStreams.value.map(stream => ({
120
+ id: stream.id,
121
+ stream,
122
+ mirror: true,
123
+ audioMuted: true
124
+ }))
125
+ })
126
+
127
+ const mainVideos = computed(() => {
128
+ if(!peer.value) return []
129
+ let output = []
130
+ for(const connection of unref(peer.value.connections)) {
131
+ const peerId = connection.to
132
+ const otherPeer = peer.value.otherPeers.find(peer => peer.id === peerId)
133
+ for(const remoteTrack of unref(connection.remoteTracks)) {
134
+ if(output.find(remoteStream => remoteStream.stream === remoteTrack.stream)) continue
135
+ output.push({
136
+ id: remoteTrack.stream.id,
137
+ from: connection.to,
138
+ stream: remoteTrack.stream,
139
+ peerState: otherPeer,
140
+ })
141
+ }
142
+ }
143
+ return output
144
+ })
145
+
103
146
 
104
147
  </script>
105
148
 
@@ -1,13 +1,28 @@
1
1
  <template>
2
- <div :ref="wall">
3
- <pre style="display: none">{{ JSON.stringify(videoSizes, null, " ") }}</pre>
2
+ <div ref="wall">
3
+ <!-- <pre style="display: none">{{ JSON.stringify(videoSizes, null, " ") }}</pre>-->
4
4
  <!--<pre style="display: none">{{ JSON.stringify(allVisibleVideos, null, " ") }}</pre>
5
5
  <pre style="display: none">{{ JSON.stringify(allVideos, null, " ") }}</pre>-->
6
- <VideoDisplayVideo v-for="tile in videoTiles" :style="videoStyles[tile.id]"
7
- :key="tile.id" :video="tile.video" :volume="volume"
8
- @videoResize="ev => handleVideoResize(tile, ev)"
9
- @click="ev => handleVideoClick(tile, ev)">
10
- </VideoDisplayVideo>
6
+ <!-- <div class="surface-card p-3">
7
+ <pre>videoStyles = {{ videoStyles }}</pre>
8
+ <pre>wall = {{ wall }} {{ wallSize }}</pre>
9
+ <pre>mainVideos = {{ mainVideos }}</pre>
10
+ <pre>topVideos = {{ topVideos }}</pre>
11
+ <pre>bottomVideos = {{ bottomVideos }}</pre>
12
+ <pre>myVideos = {{ myVideos }}</pre>
13
+ </div>-->
14
+ <PeerVideo v-for="tile in videoTiles"
15
+ :key="tile.id" :stream="tile.video?.stream"
16
+ :volume="volume" :audio-muted="tile.video?.audioMuted"
17
+ :id="tile.id" :image="tile.video?.image"
18
+ :mirror="tile.video?.mirror"
19
+ :peer-state="tile.video?.peerState"
20
+ :ownerType="tile.ownerType ?? 'unknown'"
21
+ :owner="tile.owner ?? 'unknown'"
22
+ @resize="ev => handleVideoResize(tile, ev)"
23
+ @click="ev => handleVideoClick(tile, ev)"
24
+ :style="videoStyles[tile.id]">
25
+ </PeerVideo>
11
26
  </div>
12
27
  </template>
13
28
 
@@ -27,7 +42,7 @@
27
42
  type: Array,
28
43
  default: () => [] // testData.otherVideos
29
44
  },
30
- otherVideos: {
45
+ bottomVideos: {
31
46
  type: Array,
32
47
  default: () => [] // testData.otherVideos
33
48
  },
@@ -37,22 +52,22 @@
37
52
  },
38
53
  topBarHeight: {
39
54
  type: Number,
40
- default: 80
55
+ default: 100
41
56
  },
42
57
  bottomBarHeight: {
43
58
  type: Number,
44
- default: 80
59
+ default: 120
45
60
  },
46
61
  volume: {
47
62
  type: Number,
48
63
  defaultValue: 1
49
64
  }
50
65
  })
51
- const { mainVideos, topVideos, otherVideos, myVideos, topBarHeight, bottomBarHeight, volume } = toRefs(props)
66
+ const { mainVideos, topVideos, bottomVideos, myVideos, topBarHeight, bottomBarHeight, volume } = toRefs(props)
52
67
 
53
68
  const emit = defineEmits(['videoClick'])
54
69
 
55
- const allVideos = computed(() => [].concat(mainVideos.value, topVideos.value, otherVideos.value, myVideos.value))
70
+ const allVideos = computed(() => [].concat(mainVideos.value, topVideos.value, bottomVideos.value, myVideos.value))
56
71
 
57
72
  const wall = ref(null)
58
73
  const wallSize = useElementSize(wall)
@@ -64,45 +79,63 @@
64
79
  watch(allVideos, videos => {
65
80
  for(const video of videos) {
66
81
  const index = videoTiles.value.findIndex(v => v.id === video.id)
82
+ const tile = {
83
+ id: video.id,
84
+ video,
85
+ size: { ...(video.size ?? defaultVideoSize) }
86
+ }
67
87
  if(index === -1) {
68
- videoTiles.value.push({ id: video.id, video, size: { ...defaultVideoSize } })
88
+ videoTiles.value.push(tile)
69
89
  } else {
70
- videoTiles.value.splice(index, 1, { id: video.id, video, size: { ...defaultVideoSize } })
90
+ videoTiles.value.splice(index, 1, tile)
91
+ }
92
+ }
93
+ for(let i = videoTiles.value.length - 1; i >= 0; i--) {
94
+ const tile = videoTiles.value[i]
95
+ const index = videos.findIndex(v => v.id === tile.id)
96
+ if(index === -1) {
97
+ videoTiles.value.splice(i, 1)
98
+ i--;
71
99
  }
72
100
  }
73
101
  }, { immediate: true })
74
102
 
75
103
  function handleVideoResize(tile, { width, height }) {
104
+ console.log("handel video resize", arguments)
76
105
  tile.size = { width, height }
77
106
  }
78
107
 
79
- function handleClick(tile, event) {
108
+ function handleVideoClick(tile, event) {
80
109
  emit('videoClick', { event, ...tile })
81
110
  }
82
111
 
83
112
  import allocateSpace from './allocateSpace.js'
84
113
 
85
114
  const videoStyles = computed(() => {
115
+ console.log('recomputeVideoStyles', JSON.stringify(mainVideos.value))
86
116
  if(typeof window == 'undefined') return {}
87
- if(!wallSize?.width || !wallSize?.height) return {}
88
- const areaSize = wallSize.value
117
+ const areaSize = {
118
+ width: wallSize.width.value,
119
+ height: wallSize.height.value
120
+ }
121
+ if(!areaSize?.width || !areaSize?.height) return {}
89
122
 
90
123
  let styles = {}
91
- const bottomBarVisible = otherVideos.value.length > 0 || myVideos.value.length > 0
124
+ const bottomBarVisible = bottomVideos.value.length > 0 || myVideos.value.length > 0
92
125
  const bottomHeight = bottomBarVisible ? bottomBarHeight.value : 0
93
126
 
94
127
  let right = 0
95
128
  for(const video of myVideos.value) {
96
- const size = videoTiles.value.find(v => v.id === video.id)?.size
129
+ const size = videoTiles.value.find(v => v.id === video.id)?.size ?? video.size
97
130
  if(!size || !size.width || !size.height) {
98
- styles[myVideo.id] = { display: 'none' }
131
+ styles[video.id] = { display: 'none' }
99
132
  continue
100
133
  }
101
134
  const { width, height } = size
102
135
  const ratio = width/height
103
- const newWidth = bottomBarHeight * ratio
104
- console.log('NW', newWidth, ratio)
105
- styles[myVideo.id] = {
136
+ const newWidth = bottomHeight * ratio
137
+ console.log('NW', newWidth, ratio, bottomHeight)
138
+ styles[video.id] = {
106
139
  width: newWidth + 'px',
107
140
  height: bottomHeight + 'px',
108
141
  bottom: '0',
@@ -112,22 +145,22 @@
112
145
  }
113
146
 
114
147
  const topBarVisible = topVideos.value.length > 0
115
- const topHeight = topBarVisible ? topBarHeight : 0
148
+ const topHeight = topBarVisible ? topBarHeight.value : 0
116
149
 
117
150
  /// Allocate space for bottom videos
118
151
  allocateSpace(0, areaSize.height - bottomHeight,
119
152
  areaSize.width - right, bottomHeight,
120
- otherVideos, styles)
153
+ bottomVideos.value, videoTiles.value, styles)
121
154
 
122
155
  /// Allocate space for top videos
123
156
  allocateSpace(0, 0,
124
157
  areaSize.width, topHeight,
125
- topVideos, styles)
158
+ topVideos.value, videoTiles.value, styles)
126
159
 
127
160
  /// Allocate space for main videos
128
161
  allocateSpace(0, topHeight,
129
162
  areaSize.width, areaSize.height - bottomHeight - topHeight,
130
- mainVideos, styles)
163
+ mainVideos.value, videoTiles.value, styles)
131
164
 
132
165
  return styles
133
166
 
@@ -1,11 +1,12 @@
1
- function allocateSpace(left, top, width, height, tiles, styles) {
1
+ function allocateSpace(left, top, width, height, tiles, sizes, styles) {
2
2
  console.log("ALLOCATE SPACE FOR TILES", tiles)
3
3
  if(!width || !height) return
4
4
  let visibleTiles = []
5
5
  let allRatioSum = 0
6
6
  for(let tile of tiles) {
7
- const size = tile.size
7
+ const size = (sizes.find(s => s.id === tile.id) ?? tile).size
8
8
  if(!size || !size.width || !size.height) {
9
+ console.error("INVALID TILE SIZE", tile.size, "FOR TILE", tile)
9
10
  styles[tile.id] = { display: 'none' }
10
11
  continue
11
12
  }
@@ -0,0 +1,29 @@
1
+ let lastVideoId = 0
2
+ function testVideos(idPrefix, sizes) {
3
+ return sizes.map(size => {
4
+ const id = idPrefix + (++lastVideoId)
5
+ const [width, height] = size.split('x').map(Number)
6
+ return {
7
+ id,
8
+ size: { width, height },
9
+ image: `/video-test/${size}.png`,
10
+ }
11
+ })
12
+ }
13
+
14
+ export default {
15
+ mainVideos: testVideos('mainVideo-', [
16
+ '1280x960',
17
+ '2048x1080',
18
+ '1280x720',
19
+ '1280x720'
20
+ ]),
21
+ topVideos: testVideos('topVideo-', [
22
+ '1280x960',
23
+ '1280x720',
24
+ '2048x1080',
25
+ ]),
26
+ myVideos: testVideos('myVideo-', [
27
+ '2048x1080'
28
+ ])
29
+ }
@@ -29,6 +29,9 @@ export async function sitemap(route, api) {
29
29
 
30
30
  import { client as useClient } from '@live-change/vue3-ssr'
31
31
 
32
+ import pagesRoutes from '~pages'
33
+ console.log("PAGES ROUTES", pagesRoutes)
34
+
32
35
  export function createRouter(app, config) {
33
36
  const client = useClient(app._context)
34
37
 
@@ -41,8 +44,9 @@ export function createRouter(app, config) {
41
44
  ...peerConnectionRoutes({ ...config, prefix: '/peer-connection/' }),
42
45
  ...dbAdminRoutes({ prefix: '/_db', route: r => ({ ...r, meta: { ...r.meta, raw: true }}) }),
43
46
  ...videoCallRoutes(config),
47
+ ...pagesRoutes,
44
48
  {
45
- name: 'video-call:test-room', path: '/', meta: { },
49
+ name: 'video-call:test-room', path: '/', meta: { raw: true },
46
50
  component: () => import("./room/Room.vue"),
47
51
  props: {
48
52
  room: '[test-room]'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@live-change/video-call-frontend",
3
- "version": "0.8.40",
3
+ "version": "0.8.41",
4
4
  "scripts": {
5
5
  "memDev": "node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess",
6
6
  "localDevInit": "rm tmp.db; node server/start.js localDev --enableSessions --initScript ./init.js",
@@ -35,41 +35,41 @@
35
35
  "@codemirror/language": "6.10.1",
36
36
  "@dotenvx/dotenvx": "0.27.0",
37
37
  "@fortawesome/fontawesome-free": "^6.5.2",
38
- "@live-change/access-control-frontend": "^0.8.40",
39
- "@live-change/access-control-service": "^0.8.40",
40
- "@live-change/backup-service": "^0.8.40",
41
- "@live-change/blog-frontend": "^0.8.40",
42
- "@live-change/blog-service": "^0.8.40",
43
- "@live-change/cli": "^0.8.40",
44
- "@live-change/content-frontend": "^0.8.40",
45
- "@live-change/content-service": "^0.8.40",
46
- "@live-change/dao": "^0.8.40",
47
- "@live-change/dao-vue3": "^0.8.40",
48
- "@live-change/dao-websocket": "^0.8.40",
49
- "@live-change/db-client": "^0.8.40",
50
- "@live-change/email-service": "^0.8.40",
51
- "@live-change/framework": "^0.8.40",
52
- "@live-change/frontend-auto-form": "^0.8.40",
53
- "@live-change/frontend-base": "^0.8.40",
54
- "@live-change/geoip-service": "^0.8.40",
55
- "@live-change/image-frontend": "^0.8.40",
56
- "@live-change/locale-settings-service": "^0.8.40",
57
- "@live-change/password-authentication-service": "^0.8.40",
58
- "@live-change/peer-connection-service": "^0.8.40",
59
- "@live-change/prosemirror-service": "^0.8.40",
60
- "@live-change/secret-code-service": "^0.8.40",
61
- "@live-change/secret-link-service": "^0.8.40",
62
- "@live-change/session-service": "^0.8.40",
63
- "@live-change/task-service": "^0.8.40",
64
- "@live-change/upload-frontend": "^0.8.40",
65
- "@live-change/url-frontend": "^0.8.40",
66
- "@live-change/url-service": "^0.8.40",
67
- "@live-change/user-frontend": "^0.8.40",
68
- "@live-change/user-identification-service": "^0.8.40",
69
- "@live-change/user-service": "^0.8.40",
70
- "@live-change/vote-service": "^0.8.40",
71
- "@live-change/vue3-components": "^0.8.40",
72
- "@live-change/vue3-ssr": "^0.8.40",
38
+ "@live-change/access-control-frontend": "^0.8.41",
39
+ "@live-change/access-control-service": "^0.8.41",
40
+ "@live-change/backup-service": "^0.8.41",
41
+ "@live-change/blog-frontend": "^0.8.41",
42
+ "@live-change/blog-service": "^0.8.41",
43
+ "@live-change/cli": "^0.8.41",
44
+ "@live-change/content-frontend": "^0.8.41",
45
+ "@live-change/content-service": "^0.8.41",
46
+ "@live-change/dao": "^0.8.41",
47
+ "@live-change/dao-vue3": "^0.8.41",
48
+ "@live-change/dao-websocket": "^0.8.41",
49
+ "@live-change/db-client": "^0.8.41",
50
+ "@live-change/email-service": "^0.8.41",
51
+ "@live-change/framework": "^0.8.41",
52
+ "@live-change/frontend-auto-form": "^0.8.41",
53
+ "@live-change/frontend-base": "^0.8.41",
54
+ "@live-change/geoip-service": "^0.8.41",
55
+ "@live-change/image-frontend": "^0.8.41",
56
+ "@live-change/locale-settings-service": "^0.8.41",
57
+ "@live-change/password-authentication-service": "^0.8.41",
58
+ "@live-change/peer-connection-service": "^0.8.41",
59
+ "@live-change/prosemirror-service": "^0.8.41",
60
+ "@live-change/secret-code-service": "^0.8.41",
61
+ "@live-change/secret-link-service": "^0.8.41",
62
+ "@live-change/session-service": "^0.8.41",
63
+ "@live-change/task-service": "^0.8.41",
64
+ "@live-change/upload-frontend": "^0.8.41",
65
+ "@live-change/url-frontend": "^0.8.41",
66
+ "@live-change/url-service": "^0.8.41",
67
+ "@live-change/user-frontend": "^0.8.41",
68
+ "@live-change/user-identification-service": "^0.8.41",
69
+ "@live-change/user-service": "^0.8.41",
70
+ "@live-change/vote-service": "^0.8.41",
71
+ "@live-change/vue3-components": "^0.8.41",
72
+ "@live-change/vue3-ssr": "^0.8.41",
73
73
  "@vueuse/core": "^10.11.0",
74
74
  "boxicons": "^2.1.4",
75
75
  "codeceptjs-assert": "^0.0.5",
@@ -93,7 +93,7 @@
93
93
  "vue3-scroll-border": "0.1.6"
94
94
  },
95
95
  "devDependencies": {
96
- "@live-change/codeceptjs-helper": "^0.8.40",
96
+ "@live-change/codeceptjs-helper": "^0.8.41",
97
97
  "codeceptjs": "^3.5.12",
98
98
  "generate-password": "1.7.1",
99
99
  "playwright": "^1.41.2",
@@ -104,5 +104,5 @@
104
104
  "author": "Michał Łaszczewski <michal@laszczewski.pl>",
105
105
  "license": "ISC",
106
106
  "description": "",
107
- "gitHead": "5a12ec795f6fa16f30203aef3ad1534660fa5146"
107
+ "gitHead": "e4f888357087065749a7cdb331a4eefa089b9aef"
108
108
  }
@@ -1,48 +0,0 @@
1
- export default {
2
- mainVideos: [
3
- {
4
- id: '1',
5
- type: 'image',
6
- src: '/video-test/1280x960.png',
7
- },
8
- {
9
- id: '2',
10
- type: 'image',
11
- src: '/video-test/2048x1080.png',
12
- },
13
- {
14
- id: '3',
15
- type: 'image',
16
- src: '/video-test/1280x720.png',
17
- },
18
- {
19
- id: '3b',
20
- type: 'image',
21
- src: '/video-test/1280x720.png',
22
- }
23
- ],
24
- otherVideos: [
25
- {
26
- id: '4',
27
- type: 'image',
28
- src: '/video-test/1280x960.png',
29
- },
30
- {
31
- id: '5',
32
- type: 'image',
33
- src: '/video-test/1280x720.png',
34
- },
35
- {
36
- id: '6',
37
- type: 'image',
38
- src: '/video-test/2048x1080.png',
39
- }
40
- ],
41
- myVideos: [
42
- {
43
- id: 'me',
44
- type: 'image',
45
- src: '/video-test/2048x1080.png',
46
- }
47
- ],
48
- }