@live-change/video-call-frontend 0.8.37
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.
- package/LICENSE +21 -0
- package/front/index.html +78 -0
- package/front/locales/en.js +26 -0
- package/front/locales/en.json +7 -0
- package/front/public/favicon.ico +0 -0
- package/front/public/images/empty-photo.svg +38 -0
- package/front/public/images/empty-user-photo.svg +33 -0
- package/front/public/images/logo.svg +34 -0
- package/front/public/images/logo128.png +0 -0
- package/front/public/video-test/1280x1024.png +0 -0
- package/front/public/video-test/1280x720.png +0 -0
- package/front/public/video-test/1280x800.png +0 -0
- package/front/public/video-test/1280x854.png +0 -0
- package/front/public/video-test/1280x960.png +0 -0
- package/front/public/video-test/2048x1080.png +0 -0
- package/front/src/App.vue +59 -0
- package/front/src/config.js +26 -0
- package/front/src/entry-client.js +8 -0
- package/front/src/entry-server.js +8 -0
- package/front/src/room/PeerVideo.vue +75 -0
- package/front/src/room/Room.vue +50 -0
- package/front/src/room/VideoWall.vue +143 -0
- package/front/src/room/allocateSpace.js +133 -0
- package/front/src/room/peerVideoTestData.js +48 -0
- package/front/src/router.js +75 -0
- package/front/tsconfig.json +26 -0
- package/front/tsconfig.node.json +11 -0
- package/front/vite.config.ts +53 -0
- package/index.js +2 -0
- package/package.json +108 -0
- package/server/app.config.js +118 -0
- package/server/init.js +23 -0
- package/server/page.documentType.js +103 -0
- package/server/security.config.js +53 -0
- package/server/services.list.js +50 -0
- package/server/start.js +37 -0
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
function allocateSpace(left, top, width, height, tiles, styles) {
|
|
2
|
+
console.log("ALLOCATE SPACE FOR TILES", tiles)
|
|
3
|
+
if(!width || !height) return
|
|
4
|
+
let visibleTiles = []
|
|
5
|
+
let allRatioSum = 0
|
|
6
|
+
for(let tile of tiles) {
|
|
7
|
+
const size = tile.size
|
|
8
|
+
if(!size || !size.width || !size.height) {
|
|
9
|
+
styles[tile.id] = { display: 'none' }
|
|
10
|
+
continue
|
|
11
|
+
}
|
|
12
|
+
const { width, height } = size
|
|
13
|
+
allRatioSum += width / height
|
|
14
|
+
visibleTiles.push({ id: tile.id, width, height })
|
|
15
|
+
}
|
|
16
|
+
/// check all options, find best fill
|
|
17
|
+
console.log("SEARCH FOR BEST FILL FOR AREA", width, height, "FOR TILES", visibleTiles)
|
|
18
|
+
if(visibleTiles.length === 0) return
|
|
19
|
+
const aspectRatio = width / height
|
|
20
|
+
const availableArea = width * height
|
|
21
|
+
let bestFill = { area: 0 }
|
|
22
|
+
for(let rows = 1; rows <= tiles.length; rows++) {
|
|
23
|
+
const breakingPoint = (allRatioSum / rows)
|
|
24
|
+
let ratioSum = 0
|
|
25
|
+
let maxRatioSum = 0
|
|
26
|
+
let row = 0
|
|
27
|
+
for(const tile of visibleTiles) { // find maximal aspect ratio sum (maximal row width)
|
|
28
|
+
const canBreak = (row < rows - 1)
|
|
29
|
+
const ratio = tile.width / tile.height
|
|
30
|
+
if(ratioSum + ratio * 0.5 > breakingPoint && canBreak) { // break!
|
|
31
|
+
//console.log("BREAK ROW BEFORE SUM!")
|
|
32
|
+
row += 1
|
|
33
|
+
if(ratioSum > maxRatioSum) maxRatioSum = ratioSum
|
|
34
|
+
ratioSum = 0
|
|
35
|
+
}
|
|
36
|
+
ratioSum += ratio
|
|
37
|
+
//console.log("RATIO SUM", ratioSum, "ROW", row)
|
|
38
|
+
if(ratioSum > breakingPoint && canBreak) { // break!
|
|
39
|
+
//console.log("BREAK ROW AFTER SUM!")
|
|
40
|
+
row += 1
|
|
41
|
+
if(ratioSum > maxRatioSum) maxRatioSum = ratioSum
|
|
42
|
+
ratioSum = 0
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if(ratioSum > maxRatioSum) maxRatioSum = ratioSum
|
|
46
|
+
// compute area and fill:
|
|
47
|
+
const ratio = maxRatioSum / rows
|
|
48
|
+
let filledWidth, filledHeight
|
|
49
|
+
if(ratio > aspectRatio) { // empty bottom and top
|
|
50
|
+
filledWidth = width
|
|
51
|
+
filledHeight = filledWidth / ratio
|
|
52
|
+
} else { // empty left and right
|
|
53
|
+
filledHeight = height
|
|
54
|
+
filledWidth = filledHeight * ratio
|
|
55
|
+
}
|
|
56
|
+
const filledArea = filledWidth * filledHeight
|
|
57
|
+
if(filledArea > bestFill.area) {
|
|
58
|
+
bestFill = { rows, area: filledArea, filledWidth, filledHeight }
|
|
59
|
+
} else {
|
|
60
|
+
console.log("ROWS", rows, "RATIO", ratio, "FILL", filledArea / availableArea)
|
|
61
|
+
console.log("TILES RATIO SUM", maxRatioSum, "ASPECT RATIO", aspectRatio)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//console.log("BEST FILL", bestFill)
|
|
65
|
+
|
|
66
|
+
if(!bestFill.rows) throw new Error("Couldn't find best fill!?!")
|
|
67
|
+
|
|
68
|
+
/// we determined rows count, time to place tiles
|
|
69
|
+
let ratioSum = 0
|
|
70
|
+
let row = 0
|
|
71
|
+
let rowTiles = []
|
|
72
|
+
let leftSum = 0
|
|
73
|
+
const { rows, filledWidth, filledHeight } = bestFill
|
|
74
|
+
const leftMargin = (width - filledWidth) / 2
|
|
75
|
+
const topMargin = (height - filledHeight) / 2
|
|
76
|
+
const rowHeight = filledHeight / rows
|
|
77
|
+
const breakingPoint = (allRatioSum / rows)
|
|
78
|
+
|
|
79
|
+
//console.log("rowHeight", rowHeight)
|
|
80
|
+
|
|
81
|
+
const placeTilesInRow = (rowLeftMargin, rowTiles) => {
|
|
82
|
+
for(const tile of rowTiles) {
|
|
83
|
+
const { left, width } = tile
|
|
84
|
+
//console.log("PLACE TILE", tile)
|
|
85
|
+
styles[tile.id] = {
|
|
86
|
+
width: width + 'px',
|
|
87
|
+
height: rowHeight + 'px',
|
|
88
|
+
left: (left + leftMargin + rowLeftMargin) + 'px',
|
|
89
|
+
top: (top + topMargin + rowHeight * row) + 'px'
|
|
90
|
+
}
|
|
91
|
+
//console.log("TILE STYLE", tile.id, styles[tile.id])
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
for(const tile of visibleTiles) {
|
|
96
|
+
const canBreak = (row < rows - 1)
|
|
97
|
+
const ratio = tile.width / tile.height
|
|
98
|
+
if(ratioSum + ratio * 0.5 > breakingPoint && canBreak) { // break!
|
|
99
|
+
//console.log("BREAK ROW BEFORE SUM!")
|
|
100
|
+
const rowLeftMargin = (filledWidth - leftSum) / 2
|
|
101
|
+
//console.log("ROW LEFT MARGIN", rowLeftMargin)
|
|
102
|
+
placeTilesInRow(rowLeftMargin, rowTiles)
|
|
103
|
+
row += 1
|
|
104
|
+
leftSum = 0
|
|
105
|
+
ratioSum = 0
|
|
106
|
+
rowTiles = []
|
|
107
|
+
}
|
|
108
|
+
ratioSum += ratio
|
|
109
|
+
const width = rowHeight * ratio
|
|
110
|
+
rowTiles.push({ id: tile.id, left: leftSum, width })
|
|
111
|
+
leftSum += width
|
|
112
|
+
//console.log("RATIO SUM", ratioSum, "ROW", row)
|
|
113
|
+
if(ratioSum > breakingPoint && canBreak) { // break!
|
|
114
|
+
//console.log("BREAK ROW AFTER SUM!")
|
|
115
|
+
const rowLeftMargin = (filledWidth - leftSum) / 2
|
|
116
|
+
//console.log("ROW LEFT MARGIN", rowLeftMargin)
|
|
117
|
+
placeTilesInRow(rowLeftMargin, rowTiles)
|
|
118
|
+
row += 1
|
|
119
|
+
leftSum = 0
|
|
120
|
+
ratioSum = 0
|
|
121
|
+
rowTiles = []
|
|
122
|
+
}
|
|
123
|
+
if(ratioSum >= (allRatioSum / rows) * (row + 1) && row < rows - 1) {
|
|
124
|
+
// break!
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if(rowTiles.length > 0) {
|
|
128
|
+
const rowLeftMargin = (filledWidth - leftSum) / 2
|
|
129
|
+
placeTilesInRow(rowLeftMargin, rowTiles)
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export default allocateSpace
|
|
@@ -0,0 +1,48 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createMemoryHistory,
|
|
3
|
+
createRouter as _createRouter,
|
|
4
|
+
createWebHistory
|
|
5
|
+
} from 'vue-router'
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
installRouterAnalytics
|
|
9
|
+
} from '@live-change/vue3-components'
|
|
10
|
+
|
|
11
|
+
import { dbAdminRoutes } from "@live-change/db-admin"
|
|
12
|
+
import { peerConnectionRoutes } from "@live-change/peer-connection-frontend"
|
|
13
|
+
import { userRoutes } from '@live-change/user-frontend'
|
|
14
|
+
|
|
15
|
+
export function videoCallRoutes(config = {}) {
|
|
16
|
+
const { prefix = '/', route = (r) => r } = config
|
|
17
|
+
return [
|
|
18
|
+
route({
|
|
19
|
+
name: 'video-call:room', path: prefix+ '/room/:room', meta: { },
|
|
20
|
+
component: () => import("./room/Room.vue"),
|
|
21
|
+
}),
|
|
22
|
+
|
|
23
|
+
]
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function sitemap(route, api) {
|
|
27
|
+
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
import { client as useClient } from '@live-change/vue3-ssr'
|
|
31
|
+
|
|
32
|
+
export function createRouter(app, config) {
|
|
33
|
+
const client = useClient(app._context)
|
|
34
|
+
|
|
35
|
+
const router = _createRouter({
|
|
36
|
+
// use appropriate history implementation for server/client
|
|
37
|
+
// import.meta.env.SSR is injected by Vite.
|
|
38
|
+
history: import.meta.env.SSR ? createMemoryHistory() : createWebHistory(),
|
|
39
|
+
routes: [
|
|
40
|
+
...userRoutes({ ...config, prefix: '/user/' }),
|
|
41
|
+
...peerConnectionRoutes({ ...config, prefix: '/peer-connection/' }),
|
|
42
|
+
...dbAdminRoutes({ prefix: '/_db', route: r => ({ ...r, meta: { ...r.meta, raw: true }}) }),
|
|
43
|
+
...videoCallRoutes(config),
|
|
44
|
+
{
|
|
45
|
+
name: 'video-call:test-room', path: '/', meta: { },
|
|
46
|
+
component: () => import("./room/Room.vue"),
|
|
47
|
+
props: {
|
|
48
|
+
room: '[test-room]'
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
})
|
|
53
|
+
installRouterAnalytics(router)
|
|
54
|
+
router.beforeEach(async (to, from) => {
|
|
55
|
+
if(to?.matched.find(m => m?.meta.signedIn)) {
|
|
56
|
+
if(!client.value.user) {
|
|
57
|
+
console.log("REDIRECT TO LOGIN BECAUSE PAGE REQUIRES LOGIN!")
|
|
58
|
+
router.redirectAfterSignIn = to.fullPath
|
|
59
|
+
return { name: 'user:signInEmail' }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
if(to?.matched.find(m => m?.meta.signedOut)) {
|
|
63
|
+
if(client.value.user) {
|
|
64
|
+
console.log("REDIRECT TO USER INDEX BECAUSE PAGE REQUIRES LOGOUT!")
|
|
65
|
+
return { name: 'user:settings' }
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if(to && to.name === 'user:signInEmail' && from?.matched.find(m => m?.meta.saveForSignIn)) {
|
|
69
|
+
console.log("SAVE FOR LOGIN", from.fullPath)
|
|
70
|
+
localStorage.redirectAfterLogin = from.fullPath
|
|
71
|
+
}
|
|
72
|
+
})
|
|
73
|
+
return router
|
|
74
|
+
}
|
|
75
|
+
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"module": "ESNext",
|
|
6
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
/* Bundler mode */
|
|
10
|
+
"moduleResolution": "bundler",
|
|
11
|
+
"allowImportingTsExtensions": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
"jsx": "preserve",
|
|
16
|
+
|
|
17
|
+
/* Linting */
|
|
18
|
+
"strict": true,
|
|
19
|
+
"noUnusedLocals": true,
|
|
20
|
+
"noUnusedParameters": true,
|
|
21
|
+
"noFallthroughCasesInSwitch": true
|
|
22
|
+
},
|
|
23
|
+
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
|
|
24
|
+
"references": [{ "path": "./tsconfig.node.json" }]
|
|
25
|
+
}
|
|
26
|
+
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { defineConfig } from 'vite'
|
|
2
|
+
import Pages from 'vite-plugin-pages'
|
|
3
|
+
|
|
4
|
+
import { fileURLToPath } from 'url'
|
|
5
|
+
import { dirname, join } from 'path'
|
|
6
|
+
import { accessSync, readFileSync } from 'fs'
|
|
7
|
+
const currentModuleDir = dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const packageJsonPath = dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
.split('/').map((part, i, arr) =>
|
|
10
|
+
join(arr.slice(0, arr.length - i).join('/'), 'package.json')
|
|
11
|
+
).find(p => { try { accessSync(p); return true } catch(e) { return false }})
|
|
12
|
+
const packageJson = packageJsonPath ? JSON.parse(readFileSync(packageJsonPath, 'utf-8')) : {}
|
|
13
|
+
const name = packageJson.name ?? "Example"
|
|
14
|
+
const version = packageJson.version ?? process.env.VERSION ?? 'unknown'
|
|
15
|
+
const homepage = process.env.BASE_HREF ?? packageJson.homepage
|
|
16
|
+
const domain = (homepage && homepage.match(/https\:\/\/([^\/]+)/)?.[1]) || 'example.com'
|
|
17
|
+
|
|
18
|
+
// @ts-ignore
|
|
19
|
+
import baseViteConfig from '@live-change/frontend-base/vite-config.js'
|
|
20
|
+
|
|
21
|
+
export default defineConfig(async ({ command, mode }) => {
|
|
22
|
+
const baseConfig = (await baseViteConfig({ command, mode }))
|
|
23
|
+
return {
|
|
24
|
+
...baseConfig,
|
|
25
|
+
|
|
26
|
+
define: {
|
|
27
|
+
...baseConfig.define,
|
|
28
|
+
ENV_VERSION: JSON.stringify(version),
|
|
29
|
+
ENV_BRAND_NAME: JSON.stringify(name[0].toUpperCase() + name.slice(1)),
|
|
30
|
+
ENV_BRAND_DOMAIN: JSON.stringify(domain),
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
plugins: [
|
|
34
|
+
...baseConfig.plugins,
|
|
35
|
+
Pages({
|
|
36
|
+
dirs: [
|
|
37
|
+
// basic
|
|
38
|
+
{ dir: 'src/pages', baseRoute: '' },
|
|
39
|
+
// blog
|
|
40
|
+
// { dir: 'src/blog', baseRoute: 'blog' },
|
|
41
|
+
],
|
|
42
|
+
extensions: ['vue', 'md'],
|
|
43
|
+
}),
|
|
44
|
+
],
|
|
45
|
+
|
|
46
|
+
resolve: {
|
|
47
|
+
...baseConfig.resolve,
|
|
48
|
+
alias: [
|
|
49
|
+
...baseConfig.resolve.alias,
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
})
|
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@live-change/video-call-frontend",
|
|
3
|
+
"version": "0.8.37",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"memDev": "node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess",
|
|
6
|
+
"localDevInit": "rm tmp.db; node server/start.js localDev --enableSessions --initScript ./init.js",
|
|
7
|
+
"localDev": "node server/start.js localDev --enableSessions --dbAccess",
|
|
8
|
+
"dev": "node server/start.js dev --enableSessions",
|
|
9
|
+
"ssrDev": "node server/start.js ssrDev --enableSessions",
|
|
10
|
+
"serveAllMem": "cross-env NODE_ENV=production node server/start.js ssrServer --withApi --withServices --updateServices --enableSessions --withDb --dbBackend mem --createDb",
|
|
11
|
+
"serveAll": "cross-env NODE_ENV=production node server/start.js ssrServer --withApi --withServices --updateServices --enableSessions",
|
|
12
|
+
"serve": "cross-env NODE_ENV=production node server/start.js ssrServer --enableSessions",
|
|
13
|
+
"memDev:spa": "node server/start.js memDev --enableSessions --initScript ./init.js --dbAccess --spa",
|
|
14
|
+
"localDevInit:spa": "rm tmp.db; node server/start.js localDev --enableSessions --initScript ./init.js --spa",
|
|
15
|
+
"localDev:spa": "node server/start.js localDev --enableSessions --spa",
|
|
16
|
+
"dev:spa": "node server/start.js dev --enableSessions --spa",
|
|
17
|
+
"ssrDev:spa": "node server/start.js ssrDev --enableSessions --spa",
|
|
18
|
+
"serveAllMem:spa": "cross-env NODE_ENV=production node server/start.js server --withApi --withServices --updateServices --enableSessions --withDb --dbBackend mem --createDb --spa",
|
|
19
|
+
"serveAll:spa": "cross-env NODE_ENV=production node server/start.js server --withApi --withServices --updateServices --enableSessions --spa",
|
|
20
|
+
"serve:spa": "cross-env NODE_ENV=production node server/start.js server --enableSessions --spa",
|
|
21
|
+
"apiServer": "node server/start.js apiServer --enableSessions",
|
|
22
|
+
"devApiServer": "node server/start.js devApiServer --enableSessions",
|
|
23
|
+
"memApiServer": "node server/start.js memApiServer --enableSessions",
|
|
24
|
+
"build": "cd front; yarn build:client && yarn build:server",
|
|
25
|
+
"build:client": "cd front; dotenvx run -f ../.env -- vite build --ssrManifest --outDir dist/client",
|
|
26
|
+
"build:server": "cd front; dotenvx run -f ../.env -- vite build --ssr src/entry-server.js --outDir dist/server",
|
|
27
|
+
"build:spa": "cd front; dotenvx run -f ../.env -- vite build --outDir dist/spa",
|
|
28
|
+
"generate": "vite build --ssrManifest --outDir dist/static && yarn build:server && node prerender",
|
|
29
|
+
"debug": "node --inspect-brk server",
|
|
30
|
+
"describe": "node server/start.js describe",
|
|
31
|
+
"changes": "node server/start.js changes"
|
|
32
|
+
},
|
|
33
|
+
"type": "module",
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@codemirror/language": "6.10.1",
|
|
36
|
+
"@dotenvx/dotenvx": "0.27.0",
|
|
37
|
+
"@fortawesome/fontawesome-free": "^6.5.2",
|
|
38
|
+
"@live-change/access-control-frontend": "^0.8.37",
|
|
39
|
+
"@live-change/access-control-service": "^0.8.37",
|
|
40
|
+
"@live-change/backup-service": "^0.8.37",
|
|
41
|
+
"@live-change/blog-frontend": "^0.8.37",
|
|
42
|
+
"@live-change/blog-service": "^0.8.37",
|
|
43
|
+
"@live-change/cli": "^0.8.37",
|
|
44
|
+
"@live-change/content-frontend": "^0.8.37",
|
|
45
|
+
"@live-change/content-service": "^0.8.37",
|
|
46
|
+
"@live-change/dao": "^0.8.37",
|
|
47
|
+
"@live-change/dao-vue3": "^0.8.37",
|
|
48
|
+
"@live-change/dao-websocket": "^0.8.37",
|
|
49
|
+
"@live-change/db-client": "^0.8.37",
|
|
50
|
+
"@live-change/email-service": "^0.8.37",
|
|
51
|
+
"@live-change/framework": "^0.8.37",
|
|
52
|
+
"@live-change/frontend-auto-form": "^0.8.37",
|
|
53
|
+
"@live-change/frontend-base": "^0.8.37",
|
|
54
|
+
"@live-change/geoip-service": "^0.8.37",
|
|
55
|
+
"@live-change/image-frontend": "^0.8.37",
|
|
56
|
+
"@live-change/locale-settings-service": "^0.8.37",
|
|
57
|
+
"@live-change/password-authentication-service": "^0.8.37",
|
|
58
|
+
"@live-change/peer-connection-service": "^0.8.37",
|
|
59
|
+
"@live-change/prosemirror-service": "^0.8.37",
|
|
60
|
+
"@live-change/secret-code-service": "^0.8.37",
|
|
61
|
+
"@live-change/secret-link-service": "^0.8.37",
|
|
62
|
+
"@live-change/session-service": "^0.8.37",
|
|
63
|
+
"@live-change/task-service": "^0.8.37",
|
|
64
|
+
"@live-change/upload-frontend": "^0.8.37",
|
|
65
|
+
"@live-change/url-frontend": "^0.8.37",
|
|
66
|
+
"@live-change/url-service": "^0.8.37",
|
|
67
|
+
"@live-change/user-frontend": "^0.8.37",
|
|
68
|
+
"@live-change/user-identification-service": "^0.8.37",
|
|
69
|
+
"@live-change/user-service": "^0.8.37",
|
|
70
|
+
"@live-change/vote-service": "^0.8.37",
|
|
71
|
+
"@live-change/vue3-components": "^0.8.37",
|
|
72
|
+
"@live-change/vue3-ssr": "^0.8.37",
|
|
73
|
+
"@vueuse/core": "^10.11.0",
|
|
74
|
+
"boxicons": "^2.1.4",
|
|
75
|
+
"codeceptjs-assert": "^0.0.5",
|
|
76
|
+
"compression": "^1.7.4",
|
|
77
|
+
"cross-env": "^7.0.3",
|
|
78
|
+
"feather-icons": "^4.29.2",
|
|
79
|
+
"get-port-sync": "1.0.1",
|
|
80
|
+
"pica": "^9.0.1",
|
|
81
|
+
"pretty-bytes": "^6.1.1",
|
|
82
|
+
"primeflex": "^3.3.1",
|
|
83
|
+
"primeicons": "^7.0.0",
|
|
84
|
+
"primevue": "^3.52.0",
|
|
85
|
+
"rollup-plugin-node-builtins": "^2.1.2",
|
|
86
|
+
"rollup-plugin-visualizer": "5.12.0",
|
|
87
|
+
"serialize-javascript": "^6.0.2",
|
|
88
|
+
"serve-static": "^1.15.0",
|
|
89
|
+
"v-shared-element": "3.1.1",
|
|
90
|
+
"vue": "^3.4.29",
|
|
91
|
+
"vue-i18n": "^9.10.1",
|
|
92
|
+
"vue-router": "^4.3.3",
|
|
93
|
+
"vue3-scroll-border": "0.1.6"
|
|
94
|
+
},
|
|
95
|
+
"devDependencies": {
|
|
96
|
+
"@live-change/codeceptjs-helper": "^0.8.37",
|
|
97
|
+
"codeceptjs": "^3.5.12",
|
|
98
|
+
"generate-password": "1.7.1",
|
|
99
|
+
"playwright": "^1.41.2",
|
|
100
|
+
"random-profile-generator": "^2.3.0",
|
|
101
|
+
"txtgen": "^3.0.6",
|
|
102
|
+
"webdriverio": "^8.31.1"
|
|
103
|
+
},
|
|
104
|
+
"author": "Michał Łaszczewski <michal@laszczewski.pl>",
|
|
105
|
+
"license": "ISC",
|
|
106
|
+
"description": "",
|
|
107
|
+
"gitHead": "8b97a83258a3eccd08534d0376015781c4eefdec"
|
|
108
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import App from "@live-change/framework"
|
|
2
|
+
const app = App.app()
|
|
3
|
+
|
|
4
|
+
const contactTypes = ['email', 'phone']
|
|
5
|
+
const remoteAccountTypes = ['google']
|
|
6
|
+
|
|
7
|
+
import securityConfig from './security.config.js'
|
|
8
|
+
|
|
9
|
+
app.config = {
|
|
10
|
+
services: [
|
|
11
|
+
{
|
|
12
|
+
name: 'timer',
|
|
13
|
+
path: '@live-change/timer-service'
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
name: 'session',
|
|
17
|
+
path: '@live-change/session-service',
|
|
18
|
+
createSessionOnUpdate: true
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
name: 'user',
|
|
22
|
+
path: '@live-change/user-service',
|
|
23
|
+
remoteAccountTypes
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'email',
|
|
27
|
+
path: '@live-change/email-service'
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
name: 'phone',
|
|
31
|
+
path: '@live-change/phone-service'
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
name: 'secretLink',
|
|
35
|
+
path: '@live-change/secret-link-service'
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
name: 'secretCode',
|
|
39
|
+
path: '@live-change/secret-code-service'
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
name: 'messageAuthentication',
|
|
43
|
+
path: '@live-change/message-authentication-service',
|
|
44
|
+
contactTypes,
|
|
45
|
+
signUp: true,
|
|
46
|
+
signIn: true,
|
|
47
|
+
connect: true
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
name: 'passwordAuthentication',
|
|
51
|
+
path: '@live-change/password-authentication-service',
|
|
52
|
+
contactTypes,
|
|
53
|
+
signInWithoutPassword: true
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'googleAuthentication',
|
|
57
|
+
path: '@live-change/google-authentication-service',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'security',
|
|
61
|
+
path: '@live-change/security-service',
|
|
62
|
+
...securityConfig
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: 'userIdentification',
|
|
66
|
+
path: '@live-change/user-identification-service'
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: 'identicon',
|
|
70
|
+
path: '@live-change/identicon-service'
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'localeSettings'
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
name: 'notification',
|
|
77
|
+
path: '@live-change/notification-service',
|
|
78
|
+
contactTypes,
|
|
79
|
+
notificationTypes: ['example_TestNotification']
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
name: 'upload',
|
|
83
|
+
path: '@live-change/upload-service'
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'image',
|
|
87
|
+
path: '@live-change/image-service'
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
name: 'session',
|
|
91
|
+
path: '@live-change/session-service',
|
|
92
|
+
createSessionOnUpdate: true
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
name: 'online',
|
|
96
|
+
path: '@live-change/online-service',
|
|
97
|
+
createSessionOnUpdate: true
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
name: 'accessControl',
|
|
101
|
+
path: '@live-change/access-control-service',
|
|
102
|
+
createSessionOnUpdate: true,
|
|
103
|
+
contactTypes,
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'peerConnection',
|
|
107
|
+
path: '@live-change/peer-connection-service',
|
|
108
|
+
turn: {
|
|
109
|
+
urls: 'turn:turn.chaosu.pl:4433'
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: 'videoCall',
|
|
114
|
+
path: '@live-change/video-call-service'
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
export default app.config
|
package/server/init.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import App from '@live-change/framework'
|
|
2
|
+
const app = App.app()
|
|
3
|
+
|
|
4
|
+
export default async function(services) {
|
|
5
|
+
|
|
6
|
+
const { Room } = services.videoCall.models
|
|
7
|
+
|
|
8
|
+
await Room.create({
|
|
9
|
+
id: '[test-room]',
|
|
10
|
+
name: 'Test Room',
|
|
11
|
+
description: 'This is a test room',
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const { PublicAccess, Access, AccessRequest, AccessInvitation } = services.accessControl.models
|
|
15
|
+
|
|
16
|
+
await PublicAccess.create({
|
|
17
|
+
id: App.encodeIdentifier(['videoCall_Room', '[test-room]']),
|
|
18
|
+
objectType: 'Room', object: '[test-room]',
|
|
19
|
+
userRoles: ['speaker'],
|
|
20
|
+
sessionRoles: ['speaker']
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
}
|