Compare commits
No commits in common. "35ef2a8ddc68c5a0f3fe7440c320826516e5b774" and "7ffb691922a95d86d791f29316eaa64b9a2f38b4" have entirely different histories.
35ef2a8ddc
...
7ffb691922
36
.github/workflows/ci.yml
vendored
36
.github/workflows/ci.yml
vendored
@ -1,36 +0,0 @@
|
|||||||
# .github/workflows/ci.yml
|
|
||||||
|
|
||||||
name: CI
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
branches: [main]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
MY_DOCKER_USERNAME: ${{ secrets.MY_DOCKER_USERNAME }}
|
|
||||||
MY_DOCKER_PASSWORD: ${{ secrets.MY_DOCKER_PASSWORD }}
|
|
||||||
FORCE_COLOR: 1
|
|
||||||
steps:
|
|
||||||
- uses: https://github.com/earthly/actions-setup@v1
|
|
||||||
with:
|
|
||||||
version: v0.7.0
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Put back the git branch into git (Earthly uses it for tagging)
|
|
||||||
run: |
|
|
||||||
branch=""
|
|
||||||
if [ -n "$GITHUB_HEAD_REF" ]; then
|
|
||||||
branch="$GITHUB_HEAD_REF"
|
|
||||||
else
|
|
||||||
branch="${GITHUB_REF##*/}"
|
|
||||||
fi
|
|
||||||
git checkout -b "$branch" || true
|
|
||||||
- name: Docker Login
|
|
||||||
run: docker login git.hibas.dev --username "$MY_DOCKER_USERNAME" --password "$MY_DOCKER_PASSWORD"
|
|
||||||
- name: Earthly version
|
|
||||||
run: earthly --version
|
|
||||||
- name: Run build
|
|
||||||
run: earthly --push +docker-multi
|
|
1
Client/.gitignore
vendored
1
Client/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
dist/
|
|
@ -13,52 +13,53 @@
|
|||||||
"smui-theme-dark": "smui-theme compile public/smui-dark.css -i src/theme/dark"
|
"smui-theme-dark": "smui-theme compile public/smui-dark.css -i src/theme/dark"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@hibas123/screen-api": "workspace:^",
|
||||||
"@hibas123/utils": "^2.2.18",
|
"@hibas123/utils": "^2.2.18",
|
||||||
"@material/theme": "^14.0.0",
|
"@material/theme": "^13.0.0",
|
||||||
"@rtdb2/sdk": "^3.0.0-beta.7",
|
"@rtdb2/sdk": "^3.0.0-beta.7",
|
||||||
"@smui-extra/accordion": "^7.0.0-beta.14",
|
"@smui-extra/accordion": "^6.0.0-beta.13",
|
||||||
"@smui-extra/badge": "^7.0.0-beta.14",
|
"@smui-extra/badge": "^6.0.0-beta.13",
|
||||||
"@smui/banner": "^7.0.0-beta.14",
|
"@smui/banner": "^6.0.0-beta.13",
|
||||||
"@smui/button": "^7.0.0-beta.14",
|
"@smui/button": "^6.0.0-beta.13",
|
||||||
"@smui/card": "^7.0.0-beta.14",
|
"@smui/card": "^6.0.0-beta.13",
|
||||||
"@smui/checkbox": "^7.0.0-beta.14",
|
"@smui/checkbox": "^6.0.0-beta.13",
|
||||||
"@smui/circular-progress": "^7.0.0-beta.14",
|
"@smui/circular-progress": "^6.0.0-beta.13",
|
||||||
"@smui/common": "^7.0.0-beta.14",
|
"@smui/common": "^6.0.0-beta.13",
|
||||||
"@smui/data-table": "^7.0.0-beta.14",
|
"@smui/data-table": "^6.0.0-beta.13",
|
||||||
"@smui/dialog": "^7.0.0-beta.14",
|
"@smui/dialog": "^6.0.0-beta.13",
|
||||||
"@smui/drawer": "^7.0.0-beta.14",
|
"@smui/drawer": "^6.0.0-beta.13",
|
||||||
"@smui/fab": "^7.0.0-beta.14",
|
"@smui/fab": "^6.0.0-beta.13",
|
||||||
"@smui/floating-label": "^7.0.0-beta.14",
|
"@smui/floating-label": "^6.0.0-beta.13",
|
||||||
"@smui/icon-button": "^7.0.0-beta.14",
|
"@smui/icon-button": "^6.0.0-beta.13",
|
||||||
"@smui/layout-grid": "^7.0.0-beta.14",
|
"@smui/layout-grid": "^6.0.0-beta.13",
|
||||||
"@smui/line-ripple": "^7.0.0-beta.14",
|
"@smui/line-ripple": "^6.0.0-beta.13",
|
||||||
"@smui/linear-progress": "^7.0.0-beta.14",
|
"@smui/linear-progress": "^6.0.0-beta.13",
|
||||||
"@smui/list": "^7.0.0-beta.14",
|
"@smui/list": "^6.0.0-beta.13",
|
||||||
"@smui/menu": "^7.0.0-beta.14",
|
"@smui/menu": "^6.0.0-beta.13",
|
||||||
"@smui/menu-surface": "^7.0.0-beta.14",
|
"@smui/menu-surface": "^6.0.0-beta.13",
|
||||||
"@smui/notched-outline": "^7.0.0-beta.14",
|
"@smui/notched-outline": "^6.0.0-beta.13",
|
||||||
"@smui/paper": "^7.0.0-beta.14",
|
"@smui/paper": "^6.0.0-beta.13",
|
||||||
"@smui/radio": "^7.0.0-beta.14",
|
"@smui/radio": "^6.0.0-beta.13",
|
||||||
"@smui/ripple": "^7.0.0-beta.14",
|
"@smui/ripple": "^6.0.0-beta.13",
|
||||||
"@smui/select": "^7.0.0-beta.14",
|
"@smui/select": "^6.0.0-beta.13",
|
||||||
"@smui/snackbar": "^7.0.0-beta.14",
|
"@smui/snackbar": "^6.0.0-beta.13",
|
||||||
"@smui/tab": "^7.0.0-beta.14",
|
"@smui/tab": "^6.0.0-beta.13",
|
||||||
"@smui/tab-indicator": "^7.0.0-beta.14",
|
"@smui/tab-indicator": "^6.0.0-beta.13",
|
||||||
"@smui/tab-scroller": "^7.0.0-beta.14",
|
"@smui/tab-scroller": "^6.0.0-beta.13",
|
||||||
"@smui/textfield": "^7.0.0-beta.14",
|
"@smui/textfield": "^6.0.0-beta.13",
|
||||||
"@smui/top-app-bar": "^7.0.0-beta.14",
|
"@smui/top-app-bar": "^6.0.0-beta.13",
|
||||||
"dayjs": "^1.11.9",
|
"dayjs": "^1.10.7",
|
||||||
"nanoid": "^3.3.6",
|
"nanoid": "^3.2.0",
|
||||||
"peerjs": "^1.4.7",
|
"peerjs": "^1.3.2",
|
||||||
"svelte": "^4.0.5"
|
"svelte": "^3.46.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@roxi/routify": "^2.18.12",
|
"@roxi/routify": "^2.18.4",
|
||||||
"@sveltejs/vite-plugin-svelte": "^2.4.2",
|
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.34",
|
||||||
"@tsconfig/svelte": "^5.0.0",
|
"@tsconfig/svelte": "^3.0.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"smui-theme": "^7.0.0-beta.14",
|
"smui-theme": "^6.0.0-beta.13",
|
||||||
"svelte-preprocess": "^5.0.4",
|
"svelte-preprocess": "^4.10.2",
|
||||||
"vite": "^4.4.3"
|
"vite": "^2.7.12"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -4,12 +4,12 @@ module.exports = {
|
|||||||
"routifyDir": "src/.routify",
|
"routifyDir": "src/.routify",
|
||||||
"ignore": "",
|
"ignore": "",
|
||||||
"dynamicImports": true,
|
"dynamicImports": true,
|
||||||
"singleBuild": true,
|
"singleBuild": false,
|
||||||
"noHashScroll": false,
|
"noHashScroll": false,
|
||||||
"distDir": "dist",
|
"distDir": "dist",
|
||||||
"hashScroll": true,
|
"hashScroll": true,
|
||||||
"extensions": [
|
"extensions": [
|
||||||
"svelte"
|
"svelte"
|
||||||
],
|
],
|
||||||
"started": "2023-07-13T13:49:48.147Z"
|
"started": "2022-02-17T23:53:42.346Z"
|
||||||
}
|
}
|
@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @roxi/routify 2.18.12
|
* @roxi/routify 2.18.4
|
||||||
* File generated Thu Jul 13 2023 15:49:48 GMT+0200 (Mitteleuropäische Sommerzeit)
|
* File generated Thu Feb 17 2022 23:53:42 GMT+0000 (Coordinated Universal Time)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const __version = "2.18.12"
|
export const __version = "2.18.4"
|
||||||
export const __timestamp = "2023-07-13T13:49:48.159Z"
|
export const __timestamp = "2022-02-17T23:53:42.361Z"
|
||||||
|
|
||||||
//buildRoutes
|
//buildRoutes
|
||||||
import { buildClientTree } from "@roxi/routify/runtime/buildRoutes"
|
import { buildClientTree } from "@roxi/routify/runtime/buildRoutes"
|
||||||
@ -18,37 +18,120 @@ export const options = {}
|
|||||||
|
|
||||||
//tree
|
//tree
|
||||||
export const _tree = {
|
export const _tree = {
|
||||||
|
"name": "root",
|
||||||
|
"filepath": "/",
|
||||||
"root": true,
|
"root": true,
|
||||||
|
"ownMeta": {},
|
||||||
|
"absolutePath": "src/pages",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
|
"isFile": true,
|
||||||
|
"isDir": false,
|
||||||
|
"file": "index.svelte",
|
||||||
|
"filepath": "/index.svelte",
|
||||||
|
"name": "index",
|
||||||
|
"ext": "svelte",
|
||||||
|
"badExt": false,
|
||||||
|
"absolutePath": "/root/Projects/ScreenSharingThing/Client/src/pages/index.svelte",
|
||||||
|
"importPath": "../pages/index.svelte",
|
||||||
|
"isLayout": false,
|
||||||
|
"isReset": false,
|
||||||
"isIndex": true,
|
"isIndex": true,
|
||||||
|
"isFallback": false,
|
||||||
"isPage": true,
|
"isPage": true,
|
||||||
|
"ownMeta": {},
|
||||||
|
"meta": {
|
||||||
|
"recursive": true,
|
||||||
|
"preload": false,
|
||||||
|
"prerender": true
|
||||||
|
},
|
||||||
"path": "/index",
|
"path": "/index",
|
||||||
"id": "_index",
|
"id": "_index",
|
||||||
"component": () => import('../pages/index.svelte').then(m => m.default)
|
"component": () => import('../pages/index.svelte').then(m => m.default)
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"isFile": false,
|
||||||
"isDir": true,
|
"isDir": true,
|
||||||
|
"file": "session",
|
||||||
|
"filepath": "/session",
|
||||||
|
"name": "session",
|
||||||
"ext": "",
|
"ext": "",
|
||||||
|
"badExt": false,
|
||||||
|
"absolutePath": "/root/Projects/ScreenSharingThing/Client/src/pages/session",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
|
"isFile": false,
|
||||||
"isDir": true,
|
"isDir": true,
|
||||||
|
"file": "[sessionid]",
|
||||||
|
"filepath": "/session/[sessionid]",
|
||||||
|
"name": "[sessionid]",
|
||||||
"ext": "",
|
"ext": "",
|
||||||
|
"badExt": false,
|
||||||
|
"absolutePath": "/root/Projects/ScreenSharingThing/Client/src/pages/session/[sessionid]",
|
||||||
"children": [
|
"children": [
|
||||||
{
|
{
|
||||||
|
"isFile": true,
|
||||||
|
"isDir": false,
|
||||||
|
"file": "index.svelte",
|
||||||
|
"filepath": "/session/[sessionid]/index.svelte",
|
||||||
|
"name": "index",
|
||||||
|
"ext": "svelte",
|
||||||
|
"badExt": false,
|
||||||
|
"absolutePath": "/root/Projects/ScreenSharingThing/Client/src/pages/session/[sessionid]/index.svelte",
|
||||||
|
"importPath": "../pages/session/[sessionid]/index.svelte",
|
||||||
|
"isLayout": false,
|
||||||
|
"isReset": false,
|
||||||
"isIndex": true,
|
"isIndex": true,
|
||||||
|
"isFallback": false,
|
||||||
"isPage": true,
|
"isPage": true,
|
||||||
|
"ownMeta": {},
|
||||||
|
"meta": {
|
||||||
|
"recursive": true,
|
||||||
|
"preload": false,
|
||||||
|
"prerender": true
|
||||||
|
},
|
||||||
"path": "/session/:sessionid/index",
|
"path": "/session/:sessionid/index",
|
||||||
"id": "_session__sessionid_index",
|
"id": "_session__sessionid_index",
|
||||||
"component": () => import('../pages/session/[sessionid]/index.svelte').then(m => m.default)
|
"component": () => import('../pages/session/[sessionid]/index.svelte').then(m => m.default)
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"isLayout": false,
|
||||||
|
"isReset": false,
|
||||||
|
"isIndex": false,
|
||||||
|
"isFallback": false,
|
||||||
|
"isPage": false,
|
||||||
|
"ownMeta": {},
|
||||||
|
"meta": {
|
||||||
|
"recursive": true,
|
||||||
|
"preload": false,
|
||||||
|
"prerender": true
|
||||||
|
},
|
||||||
"path": "/session/:sessionid"
|
"path": "/session/:sessionid"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"isLayout": false,
|
||||||
|
"isReset": false,
|
||||||
|
"isIndex": false,
|
||||||
|
"isFallback": false,
|
||||||
|
"isPage": false,
|
||||||
|
"ownMeta": {},
|
||||||
|
"meta": {
|
||||||
|
"recursive": true,
|
||||||
|
"preload": false,
|
||||||
|
"prerender": true
|
||||||
|
},
|
||||||
"path": "/session"
|
"path": "/session"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"isLayout": false,
|
||||||
|
"isReset": false,
|
||||||
|
"isIndex": false,
|
||||||
|
"isFallback": false,
|
||||||
|
"meta": {
|
||||||
|
"recursive": true,
|
||||||
|
"preload": false,
|
||||||
|
"prerender": true
|
||||||
|
},
|
||||||
"path": "/"
|
"path": "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import {
|
|||||||
UpdateTypes,
|
UpdateTypes,
|
||||||
} from "@rtdb2/sdk";
|
} from "@rtdb2/sdk";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { Peer } from "peerjs";
|
import { Peer } from "peerjs/lib/peer";
|
||||||
import {
|
import {
|
||||||
collectionToStore,
|
collectionToStore,
|
||||||
Sessions,
|
Sessions,
|
||||||
|
@ -3,8 +3,7 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"module": "esnext",
|
"module": "esnext",
|
||||||
"moduleResolution": "Node",
|
"resolveJsonModule": true,
|
||||||
// "resolveJsonModule": true,
|
|
||||||
"baseUrl": ".",
|
"baseUrl": ".",
|
||||||
"outDir": "tout",
|
"outDir": "tout",
|
||||||
/**
|
/**
|
||||||
@ -14,7 +13,12 @@
|
|||||||
* of JS in `.svelte` files.
|
* of JS in `.svelte` files.
|
||||||
*/
|
*/
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"checkJs": true
|
"checkJs": true,
|
||||||
},
|
},
|
||||||
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte"]
|
"include": [
|
||||||
|
"src/**/*.d.ts",
|
||||||
|
"src/**/*.ts",
|
||||||
|
"src/**/*.js",
|
||||||
|
"src/**/*.svelte",
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { defineConfig } from "vite";
|
const { defineConfig } = require("vite");
|
||||||
import { svelte } from "@sveltejs/vite-plugin-svelte";
|
const { svelte } = require("@sveltejs/vite-plugin-svelte");
|
||||||
import * as zlib from "zlib";
|
const zlib = require("zlib");
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
module.exports = defineConfig({
|
||||||
optimizeDeps: {
|
optimizeDeps: {
|
||||||
exclude: ["@roxi/routify"],
|
exclude: ["@roxi/routify"],
|
||||||
},
|
},
|
||||||
@ -26,7 +26,7 @@ export default defineConfig({
|
|||||||
{
|
{
|
||||||
name: "pregzip-files",
|
name: "pregzip-files",
|
||||||
generateBundle: async function (options, bundle) {
|
generateBundle: async function (options, bundle) {
|
||||||
let prms: Promise<any>[] = [];
|
let prms = [];
|
||||||
for (const fileName in bundle) {
|
for (const fileName in bundle) {
|
||||||
const file = bundle[fileName];
|
const file = bundle[fileName];
|
||||||
// if (fileName.startsWith("assets/")) {
|
// if (fileName.startsWith("assets/")) {
|
||||||
@ -39,7 +39,7 @@ export default defineConfig({
|
|||||||
// console.log("Compressing asset:", typeof file.source == "undefined" ? file : undefined)
|
// console.log("Compressing asset:", typeof file.source == "undefined" ? file : undefined)
|
||||||
|
|
||||||
prms.push(
|
prms.push(
|
||||||
new Promise<any>((yes, no) =>
|
new Promise((yes, no) =>
|
||||||
zlib.gzip(
|
zlib.gzip(
|
||||||
src,
|
src,
|
||||||
{
|
{
|
||||||
@ -64,7 +64,7 @@ export default defineConfig({
|
|||||||
type: "asset",
|
type: "asset",
|
||||||
name: file.name + ".br",
|
name: file.name + ".br",
|
||||||
fileName: file.fileName + ".br",
|
fileName: file.fileName + ".br",
|
||||||
source: br as Uint8Array,
|
source: br,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
);
|
);
|
17
Dockerfile
Normal file
17
Dockerfile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
FROM node:12
|
||||||
|
|
||||||
|
LABEL maintainer="Fabian Stamm <dev@fabianstamm.de>"
|
||||||
|
|
||||||
|
RUN mkdir -p /usr/src/app
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
RUN npm config set registry https://npm.hibas123.de
|
||||||
|
|
||||||
|
COPY ["Server/package.json", "Server/tsconfig.json", "/usr/src/app/"]
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
COPY Server/lib/ /usr/src/app/lib
|
||||||
|
COPY Client/dist/ /usr/src/app/public
|
||||||
|
|
||||||
|
EXPOSE 3000/tcp
|
||||||
|
CMD ["npm", "run", "start"]
|
39
Earthfile
39
Earthfile
@ -1,39 +0,0 @@
|
|||||||
VERSION 0.7
|
|
||||||
FROM node:lts-alpine3.18
|
|
||||||
WORKDIR /build
|
|
||||||
|
|
||||||
deps:
|
|
||||||
COPY .yarnrc.yml .yarnrc.yml
|
|
||||||
COPY .yarn .yarn
|
|
||||||
COPY package.json .
|
|
||||||
COPY Server/package.json Server/
|
|
||||||
COPY Client/package.json Client/
|
|
||||||
RUN apk add --no-cache git python3 make g++ gcc
|
|
||||||
RUN yarn install
|
|
||||||
|
|
||||||
build:
|
|
||||||
FROM +deps
|
|
||||||
COPY Client ./Client
|
|
||||||
COPY Server ./Server
|
|
||||||
RUN yarn install
|
|
||||||
RUN sh -c "find . -type f -name '*.ts' | grep -v node_modules"
|
|
||||||
RUN yarn build
|
|
||||||
SAVE ARTIFACT Client/dist /dist
|
|
||||||
SAVE ARTIFACT Server/lib /lib
|
|
||||||
|
|
||||||
docker-multi:
|
|
||||||
BUILD +build
|
|
||||||
BUILD --platform linux/amd64 --platform linux/arm64 +docker
|
|
||||||
|
|
||||||
docker:
|
|
||||||
FROM +deps
|
|
||||||
|
|
||||||
COPY +build/lib ./Server/lib
|
|
||||||
COPY +build/dist ./Server/public
|
|
||||||
WORKDIR /build/Server
|
|
||||||
|
|
||||||
ENTRYPOINT ["node", "lib/index.js"]
|
|
||||||
|
|
||||||
ARG EARTHLY_TARGET_TAG
|
|
||||||
ARG TAG=$EARTHLY_TARGET_TAG
|
|
||||||
SAVE IMAGE --push git.hibas.dev/hibas123/screenshare:$TAG
|
|
1
Server/.gitignore
vendored
1
Server/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
lib/
|
|
@ -3,16 +3,15 @@
|
|||||||
"packageManager": "yarn@3.1.1",
|
"packageManager": "yarn@3.1.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "ts-node src/index.ts",
|
"start": "ts-node src/index.ts",
|
||||||
"build": "tsc",
|
|
||||||
"dev": "nodemon -e ts --exec ts-node src/index.ts"
|
"dev": "nodemon -e ts --exec ts-node src/index.ts"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^20.4.2",
|
"@types/node": "^16.11.11",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.4.0",
|
||||||
"typescript": "^5.1.6"
|
"typescript": "^4.5.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.18.2",
|
"express": "^4.17.1",
|
||||||
"peer": "^1.0.0"
|
"peer": "^0.6.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
45
Server/public/index.html
Normal file
45
Server/public/index.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>SimpleStream</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"
|
||||||
|
integrity="sha512-894YE6QWD5I59HgZOGReFYm4dnWc1Qt5NtvYSaNcOP+u1T9qYdvdihz0PPSiiqn/+/3e7Jo4EaG7TubfWGUrMQ=="
|
||||||
|
crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<script src="https://unpkg.com/peerjs@1.3.1"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12">
|
||||||
|
<h1>SimpleStream</h1>
|
||||||
|
<h2>Your ID: <span id="streamId"></span></h2>
|
||||||
|
<div id="streamURLCont">
|
||||||
|
<h2>Connect URL: <a id="streamURL"></a></h2>
|
||||||
|
<button id="startStramBTN">Start Stream</button>
|
||||||
|
</div>
|
||||||
|
<div id="connectToCont">
|
||||||
|
<h2>Connecting to: <span id="connectToID"></span></h2>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<video id="localVideo" style="width: 100%" controls muted></video>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="main.mjs" type="module">
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
171
Server/public/main.mjs
Normal file
171
Server/public/main.mjs
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
function simpleFramwork() {
|
||||||
|
let obj = {};
|
||||||
|
|
||||||
|
return new Proxy(obj, {
|
||||||
|
get(_, prop) {
|
||||||
|
const [id, param] = prop.split("_");
|
||||||
|
let elm = document.getElementById(id);
|
||||||
|
if (!elm) {
|
||||||
|
console.log(`Element with id ${id} not found`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (param) {
|
||||||
|
case "value":
|
||||||
|
return elm.value;
|
||||||
|
case "href":
|
||||||
|
return elm.href;
|
||||||
|
case "style":
|
||||||
|
return elm.getAttribute("style");
|
||||||
|
case "text":
|
||||||
|
return elm.innerText;
|
||||||
|
case undefined:
|
||||||
|
return elm;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
set(_, prop, value) {
|
||||||
|
const [id, param] = prop.split("_");
|
||||||
|
let elm = document.getElementById(id);
|
||||||
|
if (!elm) {
|
||||||
|
console.log(`Element with id ${id} not found`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
switch (param) {
|
||||||
|
case "value":
|
||||||
|
elm.value = value;
|
||||||
|
break;
|
||||||
|
case "href":
|
||||||
|
elm.href = value;
|
||||||
|
break;
|
||||||
|
case "click":
|
||||||
|
elm.addEventListener("click", value);
|
||||||
|
break;
|
||||||
|
case "style":
|
||||||
|
elm.setAttribute("style", value);
|
||||||
|
break;
|
||||||
|
case "text":
|
||||||
|
elm.innerText = value;
|
||||||
|
break;
|
||||||
|
case undefined:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let sf = simpleFramwork();
|
||||||
|
|
||||||
|
sf.streamId_text = "Loading...";
|
||||||
|
sf.streamURL_text = "Loading...";
|
||||||
|
|
||||||
|
let connectToId = new URL(window.location.href).searchParams.get("id");
|
||||||
|
|
||||||
|
let bitrate = new URL(window.location.href).searchParams.get("br") || 50000;
|
||||||
|
|
||||||
|
if (connectToId) {
|
||||||
|
sf.streamURLCont_style = "display:none";
|
||||||
|
sf.connectToCont_style = "display:block";
|
||||||
|
sf.connectToID_text = connectToId;
|
||||||
|
} else {
|
||||||
|
sf.streamURLCont_style = "display:block";
|
||||||
|
sf.connectToCont_style = "display:none";
|
||||||
|
}
|
||||||
|
|
||||||
|
var peer = new Peer({
|
||||||
|
host: window.location.hostname,
|
||||||
|
port: window.location.port,
|
||||||
|
path: "/peerjs",
|
||||||
|
});
|
||||||
|
|
||||||
|
function bitrateTransform(sdp) {
|
||||||
|
var arr = sdp.split("\r\n");
|
||||||
|
arr.forEach((str, i) => {
|
||||||
|
if (/^a=fmtp:\d*/.test(str)) {
|
||||||
|
console.log("found fmtp");
|
||||||
|
arr[i] =
|
||||||
|
str +
|
||||||
|
`;x-google-max-bitrate=${bitrate};x-google-min-bitrate=0;x-google-start-bitrate=12000`;
|
||||||
|
} else if (/^a=mid:(1|video)/.test(str)) {
|
||||||
|
console.log("found mid");
|
||||||
|
arr[i] += "\r\nb=AS:" + bitrate;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let res = arr.join("\r\n");
|
||||||
|
console.log(sdp, res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
let currentStream = undefined;
|
||||||
|
peer.on("open", (id) => {
|
||||||
|
console.log("ID", id);
|
||||||
|
sf.streamId_text = id;
|
||||||
|
let url = new URL(window.location.href);
|
||||||
|
url.searchParams.set("id", id);
|
||||||
|
sf.streamURL_text = url.href;
|
||||||
|
sf.streamURL_href = url.href;
|
||||||
|
|
||||||
|
let con = peer.connect(connectToId);
|
||||||
|
con.on("data", console.log);
|
||||||
|
con.on("open", () => con.send("Hello"));
|
||||||
|
|
||||||
|
if (connectToId) {
|
||||||
|
sf.startStramBTN_click = () => {
|
||||||
|
navigator.mediaDevices
|
||||||
|
.getDisplayMedia({
|
||||||
|
video: true,
|
||||||
|
})
|
||||||
|
.then((stream) => {
|
||||||
|
if (currentStream) {
|
||||||
|
currentStream.getTracks().forEach((track) => track.stop());
|
||||||
|
}
|
||||||
|
currentStream = stream;
|
||||||
|
let v = sf.localVideo;
|
||||||
|
v.srcObject = stream;
|
||||||
|
v.play();
|
||||||
|
const conn = peer.call(connectToId, stream, {
|
||||||
|
sdpTransform: bitrateTransform,
|
||||||
|
});
|
||||||
|
conn.on("stream", console.log);
|
||||||
|
conn.on("close", console.log);
|
||||||
|
conn.on("error", console.log);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
peer.on("connection", (conn) => {
|
||||||
|
console.log("connection", conn);
|
||||||
|
conn.on("data", console.log);
|
||||||
|
});
|
||||||
|
|
||||||
|
peer.on("error", console.error);
|
||||||
|
peer.on("close", console.log);
|
||||||
|
peer.on("disconnected", console.log);
|
||||||
|
peer.on("error", console.log);
|
||||||
|
|
||||||
|
peer.on("call", (call) => {
|
||||||
|
console.log("Call", call);
|
||||||
|
call.answer(undefined);
|
||||||
|
call.on("stream", console.log);
|
||||||
|
call.on("close", console.log);
|
||||||
|
call.on("error", console.log);
|
||||||
|
call.on("stream", (remoteStream) => {
|
||||||
|
console.log("stream", remoteStream);
|
||||||
|
let v = sf.localVideo;
|
||||||
|
v.srcObject = remoteStream;
|
||||||
|
v.play();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function createEmptyVideoTrack({ width, height }) {
|
||||||
|
const canvas = Object.assign(document.createElement("canvas"), {
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
});
|
||||||
|
canvas.getContext("2d").fillRect(0, 0, width, height);
|
||||||
|
|
||||||
|
const stream = canvas.captureStream();
|
||||||
|
const track = stream.getVideoTracks()[0];
|
||||||
|
|
||||||
|
return Object.assign(track, { enabled: false });
|
||||||
|
}
|
@ -1,21 +1,11 @@
|
|||||||
import { ExpressPeerServer } from "peer";
|
import { ExpressPeerServer } from "peer";
|
||||||
import express = require("express");
|
import * as express from "express";
|
||||||
import * as path from "path";
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
const server = app.listen(5000);
|
||||||
const server = app.listen(5000, () => {
|
|
||||||
console.log("Server is running on port 5000");
|
|
||||||
});
|
|
||||||
|
|
||||||
const peerServer = ExpressPeerServer(server, {
|
const peerServer = ExpressPeerServer(server, {
|
||||||
path: "/",
|
path: "/",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
app.use("/peerjs", peerServer as any);
|
app.use("/peerjs", peerServer as any);
|
||||||
app.use("/", express.static("public"));
|
app.use("/", express.static("public"));
|
||||||
|
|
||||||
app.get('*', (req, res) => {
|
|
||||||
res.sendFile(path.resolve(__dirname, "..", "public", "index.html"));
|
|
||||||
});
|
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"target": "esnext",
|
"target": "esnext",
|
||||||
"esModuleInterop": true,
|
|
||||||
"outDir": "lib/",
|
"outDir": "lib/",
|
||||||
"sourceMap": true,
|
"sourceMap": true,
|
||||||
"declaration": true,
|
"declaration": true,
|
||||||
|
12
package.json
12
package.json
@ -1,24 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "ScreenSharingThing",
|
"name": "ScreenSharingThing",
|
||||||
"packageManager": "yarn@3.1.1",
|
"packageManager": "yarn@3.1.1",
|
||||||
"version": "0.1.0",
|
|
||||||
"private": true,
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"build:api": "jrpc compile API/main.jrpc -o=ts-node:_API/src && yarn workspace @hibas123/screen-api build",
|
||||||
"build:client": "yarn workspace @hibas123/screen-client build",
|
"build:client": "yarn workspace @hibas123/screen-client build",
|
||||||
"build:server": "yarn workspace @hibas123/screen-server build",
|
"build:server": "yarn workspace @hibas123/screen-server run build",
|
||||||
"build": "run-s build:server build:client",
|
"build": "run-s build:api build:server build:client",
|
||||||
"dev:client": "yarn workspace @hibas123/screen-client dev",
|
"dev:client": "yarn workspace @hibas123/screen-client dev",
|
||||||
"dev:server": "yarn workspace @hibas123/screen-server dev",
|
"dev:server": "yarn workspace @hibas123/screen-server dev",
|
||||||
"dev": "run-p dev:client dev:server"
|
"dev": "run-p dev:client dev:server"
|
||||||
},
|
},
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"Server",
|
"Server",
|
||||||
"Client"
|
"Client",
|
||||||
|
"_API"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"npm-run-all": "^4.1.5"
|
"npm-run-all": "^4.1.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hibas123/jrpcgen": "~1.2.13"
|
"@hibas123/jrpcgen": "~1.0.26"
|
||||||
}
|
}
|
||||||
}
|
}
|
10
tsconfig.json
Normal file
10
tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "es2016" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
|
||||||
|
"module": "commonjs" /* Specify what module code is generated. */,
|
||||||
|
"moduleResolution": "node" /* Specify how the compiler resolves module names. */,
|
||||||
|
"esModuleInterop": false /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
|
||||||
|
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
|
||||||
|
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user