Compare commits
No commits in common. "7ffb691922a95d86d791f29316eaa64b9a2f38b4" and "3ab6fc97e92993cc29f4cb341abf8e3fbdd195e7" have entirely different histories.
7ffb691922
...
3ab6fc97e9
@ -4,7 +4,7 @@ root = true
|
|||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
|
|
||||||
[*.{js,ts,json,yml,mjs,svelte}]
|
[*.{js,json,yml,mjs}]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 3
|
indent_size = 3
|
||||||
|
363
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
363
.yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
vendored
File diff suppressed because one or more lines are too long
@ -1,9 +1,3 @@
|
|||||||
nodeLinker: node-modules
|
|
||||||
|
|
||||||
npmRegistryServer: "https://npm.hibas123.de"
|
npmRegistryServer: "https://npm.hibas123.de"
|
||||||
|
nodeLinker: "node-modules"
|
||||||
plugins:
|
|
||||||
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
|
|
||||||
spec: "@yarnpkg/plugin-interactive-tools"
|
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-3.1.1.cjs
|
yarnPath: .yarn/releases/yarn-3.1.1.cjs
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
"pages": "src/pages",
|
|
||||||
"sourceDir": "public",
|
|
||||||
"routifyDir": ".routify",
|
|
||||||
"ignore": "",
|
|
||||||
"dynamicImports": true,
|
|
||||||
"singleBuild": false,
|
|
||||||
"noHashScroll": false,
|
|
||||||
"distDir": "dist",
|
|
||||||
"hashScroll": true,
|
|
||||||
"extensions": [
|
|
||||||
"html",
|
|
||||||
"svelte",
|
|
||||||
"md",
|
|
||||||
"svx"
|
|
||||||
],
|
|
||||||
"started": "2022-01-22T20:07:08.621Z"
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* @roxi/routify 2.18.4
|
|
||||||
* File generated Sat Jan 22 2022 21:07:08 GMT+0100 (Mitteleuropäische Normalzeit)
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const __version = "2.18.4"
|
|
||||||
export const __timestamp = "2022-01-22T20:07:08.628Z"
|
|
||||||
|
|
||||||
//buildRoutes
|
|
||||||
import { buildClientTree } from "@roxi/routify/runtime/buildRoutes"
|
|
||||||
|
|
||||||
//imports
|
|
||||||
|
|
||||||
|
|
||||||
//options
|
|
||||||
export const options = {}
|
|
||||||
|
|
||||||
//tree
|
|
||||||
export const _tree = {
|
|
||||||
"name": "root",
|
|
||||||
"filepath": "/",
|
|
||||||
"root": true,
|
|
||||||
"ownMeta": {},
|
|
||||||
"absolutePath": "src/pages",
|
|
||||||
"children": [],
|
|
||||||
"isLayout": false,
|
|
||||||
"isReset": false,
|
|
||||||
"isIndex": false,
|
|
||||||
"isFallback": false,
|
|
||||||
"meta": {
|
|
||||||
"recursive": true,
|
|
||||||
"preload": false,
|
|
||||||
"prerender": true
|
|
||||||
},
|
|
||||||
"path": "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const {tree, routes} = buildClientTree(_tree)
|
|
||||||
|
|
@ -1 +0,0 @@
|
|||||||
[]
|
|
@ -1 +0,0 @@
|
|||||||
# Client
|
|
@ -1,32 +0,0 @@
|
|||||||
<!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>Hibas123 Screen Share</title>
|
|
||||||
<script defer type="module" src="./src/bootstrap.ts"></script>
|
|
||||||
|
|
||||||
<link id="theme" rel="stylesheet" href="/smui.css" />
|
|
||||||
|
|
||||||
<!-- <link rel="stylesheet" href="/styles.css" /> -->
|
|
||||||
|
|
||||||
<!-- Material Icons -->
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
|
|
||||||
<!-- Roboto -->
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,600,700" />
|
|
||||||
<!-- Roboto Mono -->
|
|
||||||
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto+Mono" />
|
|
||||||
|
|
||||||
<style>
|
|
||||||
html,
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body></body>
|
|
||||||
|
|
||||||
</html>
|
|
@ -1,65 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@hibas123/screen-client",
|
|
||||||
"packageManager": "yarn@3.1.1",
|
|
||||||
"scripts": {
|
|
||||||
"dev": "run-p dev:routify dev:vite",
|
|
||||||
"dev:vite": "vite --host",
|
|
||||||
"dev:routify": "routify",
|
|
||||||
"build": "run-s prepare build:routify build:vite",
|
|
||||||
"build:routify": "routify -b",
|
|
||||||
"build:vite": "vite build",
|
|
||||||
"prepare": "npm run smui-theme-light && npm run smui-theme-dark",
|
|
||||||
"smui-theme-light": "smui-theme compile public/smui.css -i src/theme",
|
|
||||||
"smui-theme-dark": "smui-theme compile public/smui-dark.css -i src/theme/dark"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@hibas123/screen-api": "workspace:^",
|
|
||||||
"@hibas123/utils": "^2.2.18",
|
|
||||||
"@material/theme": "^13.0.0",
|
|
||||||
"@rtdb2/sdk": "^3.0.0-beta.7",
|
|
||||||
"@smui-extra/accordion": "^6.0.0-beta.13",
|
|
||||||
"@smui-extra/badge": "^6.0.0-beta.13",
|
|
||||||
"@smui/banner": "^6.0.0-beta.13",
|
|
||||||
"@smui/button": "^6.0.0-beta.13",
|
|
||||||
"@smui/card": "^6.0.0-beta.13",
|
|
||||||
"@smui/checkbox": "^6.0.0-beta.13",
|
|
||||||
"@smui/circular-progress": "^6.0.0-beta.13",
|
|
||||||
"@smui/common": "^6.0.0-beta.13",
|
|
||||||
"@smui/data-table": "^6.0.0-beta.13",
|
|
||||||
"@smui/dialog": "^6.0.0-beta.13",
|
|
||||||
"@smui/drawer": "^6.0.0-beta.13",
|
|
||||||
"@smui/fab": "^6.0.0-beta.13",
|
|
||||||
"@smui/floating-label": "^6.0.0-beta.13",
|
|
||||||
"@smui/icon-button": "^6.0.0-beta.13",
|
|
||||||
"@smui/layout-grid": "^6.0.0-beta.13",
|
|
||||||
"@smui/line-ripple": "^6.0.0-beta.13",
|
|
||||||
"@smui/linear-progress": "^6.0.0-beta.13",
|
|
||||||
"@smui/list": "^6.0.0-beta.13",
|
|
||||||
"@smui/menu": "^6.0.0-beta.13",
|
|
||||||
"@smui/menu-surface": "^6.0.0-beta.13",
|
|
||||||
"@smui/notched-outline": "^6.0.0-beta.13",
|
|
||||||
"@smui/paper": "^6.0.0-beta.13",
|
|
||||||
"@smui/radio": "^6.0.0-beta.13",
|
|
||||||
"@smui/ripple": "^6.0.0-beta.13",
|
|
||||||
"@smui/select": "^6.0.0-beta.13",
|
|
||||||
"@smui/snackbar": "^6.0.0-beta.13",
|
|
||||||
"@smui/tab": "^6.0.0-beta.13",
|
|
||||||
"@smui/tab-indicator": "^6.0.0-beta.13",
|
|
||||||
"@smui/tab-scroller": "^6.0.0-beta.13",
|
|
||||||
"@smui/textfield": "^6.0.0-beta.13",
|
|
||||||
"@smui/top-app-bar": "^6.0.0-beta.13",
|
|
||||||
"dayjs": "^1.10.7",
|
|
||||||
"nanoid": "^3.2.0",
|
|
||||||
"peerjs": "^1.3.2",
|
|
||||||
"svelte": "^3.46.2"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@roxi/routify": "^2.18.4",
|
|
||||||
"@sveltejs/vite-plugin-svelte": "^1.0.0-next.34",
|
|
||||||
"@tsconfig/svelte": "^3.0.0",
|
|
||||||
"npm-run-all": "^4.1.5",
|
|
||||||
"smui-theme": "^6.0.0-beta.13",
|
|
||||||
"svelte-preprocess": "^4.10.2",
|
|
||||||
"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
@ -1,5 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
routifyDir: "src/.routify",
|
|
||||||
dynamicImports: true,
|
|
||||||
extensions: ["svelte"],
|
|
||||||
};
|
|
@ -1,15 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
"pages": "src/pages",
|
|
||||||
"sourceDir": "public",
|
|
||||||
"routifyDir": "src/.routify",
|
|
||||||
"ignore": "",
|
|
||||||
"dynamicImports": true,
|
|
||||||
"singleBuild": false,
|
|
||||||
"noHashScroll": false,
|
|
||||||
"distDir": "dist",
|
|
||||||
"hashScroll": true,
|
|
||||||
"extensions": [
|
|
||||||
"svelte"
|
|
||||||
],
|
|
||||||
"started": "2022-02-17T23:53:42.346Z"
|
|
||||||
}
|
|
@ -1,140 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* @roxi/routify 2.18.4
|
|
||||||
* File generated Thu Feb 17 2022 23:53:42 GMT+0000 (Coordinated Universal Time)
|
|
||||||
*/
|
|
||||||
|
|
||||||
export const __version = "2.18.4"
|
|
||||||
export const __timestamp = "2022-02-17T23:53:42.361Z"
|
|
||||||
|
|
||||||
//buildRoutes
|
|
||||||
import { buildClientTree } from "@roxi/routify/runtime/buildRoutes"
|
|
||||||
|
|
||||||
//imports
|
|
||||||
|
|
||||||
|
|
||||||
//options
|
|
||||||
export const options = {}
|
|
||||||
|
|
||||||
//tree
|
|
||||||
export const _tree = {
|
|
||||||
"name": "root",
|
|
||||||
"filepath": "/",
|
|
||||||
"root": true,
|
|
||||||
"ownMeta": {},
|
|
||||||
"absolutePath": "src/pages",
|
|
||||||
"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,
|
|
||||||
"isFallback": false,
|
|
||||||
"isPage": true,
|
|
||||||
"ownMeta": {},
|
|
||||||
"meta": {
|
|
||||||
"recursive": true,
|
|
||||||
"preload": false,
|
|
||||||
"prerender": true
|
|
||||||
},
|
|
||||||
"path": "/index",
|
|
||||||
"id": "_index",
|
|
||||||
"component": () => import('../pages/index.svelte').then(m => m.default)
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"isFile": false,
|
|
||||||
"isDir": true,
|
|
||||||
"file": "session",
|
|
||||||
"filepath": "/session",
|
|
||||||
"name": "session",
|
|
||||||
"ext": "",
|
|
||||||
"badExt": false,
|
|
||||||
"absolutePath": "/root/Projects/ScreenSharingThing/Client/src/pages/session",
|
|
||||||
"children": [
|
|
||||||
{
|
|
||||||
"isFile": false,
|
|
||||||
"isDir": true,
|
|
||||||
"file": "[sessionid]",
|
|
||||||
"filepath": "/session/[sessionid]",
|
|
||||||
"name": "[sessionid]",
|
|
||||||
"ext": "",
|
|
||||||
"badExt": false,
|
|
||||||
"absolutePath": "/root/Projects/ScreenSharingThing/Client/src/pages/session/[sessionid]",
|
|
||||||
"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,
|
|
||||||
"isFallback": false,
|
|
||||||
"isPage": true,
|
|
||||||
"ownMeta": {},
|
|
||||||
"meta": {
|
|
||||||
"recursive": true,
|
|
||||||
"preload": false,
|
|
||||||
"prerender": true
|
|
||||||
},
|
|
||||||
"path": "/session/:sessionid/index",
|
|
||||||
"id": "_session__sessionid_index",
|
|
||||||
"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"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"isLayout": false,
|
|
||||||
"isReset": false,
|
|
||||||
"isIndex": false,
|
|
||||||
"isFallback": false,
|
|
||||||
"isPage": false,
|
|
||||||
"ownMeta": {},
|
|
||||||
"meta": {
|
|
||||||
"recursive": true,
|
|
||||||
"preload": false,
|
|
||||||
"prerender": true
|
|
||||||
},
|
|
||||||
"path": "/session"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"isLayout": false,
|
|
||||||
"isReset": false,
|
|
||||||
"isIndex": false,
|
|
||||||
"isFallback": false,
|
|
||||||
"meta": {
|
|
||||||
"recursive": true,
|
|
||||||
"preload": false,
|
|
||||||
"prerender": true
|
|
||||||
},
|
|
||||||
"path": "/"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const {tree, routes} = buildClientTree(_tree)
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
|||||||
[
|
|
||||||
"/index"
|
|
||||||
]
|
|
@ -1,6 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { Router } from "@roxi/routify";
|
|
||||||
import { routes } from "./.routify/routes";
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<Router {routes} />
|
|
@ -1,105 +0,0 @@
|
|||||||
import {
|
|
||||||
type ICollectionRef,
|
|
||||||
type IDocumentRef,
|
|
||||||
UpdateTypes,
|
|
||||||
} from "@rtdb2/sdk";
|
|
||||||
import { nanoid } from "nanoid";
|
|
||||||
import { Peer } from "peerjs/lib/peer";
|
|
||||||
import {
|
|
||||||
collectionToStore,
|
|
||||||
Sessions,
|
|
||||||
type IMember,
|
|
||||||
type IMessage,
|
|
||||||
type ISession,
|
|
||||||
} from "./db";
|
|
||||||
|
|
||||||
import type { Readable } from "svelte/store";
|
|
||||||
import { Signal } from "@hibas123/utils";
|
|
||||||
|
|
||||||
export class Session {
|
|
||||||
#client_id = nanoid(22);
|
|
||||||
#peer: Peer;
|
|
||||||
|
|
||||||
#session: IDocumentRef<ISession>;
|
|
||||||
#members: ICollectionRef<IMember>;
|
|
||||||
#messages: ICollectionRef<IMessage>;
|
|
||||||
#self: IDocumentRef<IMember>;
|
|
||||||
|
|
||||||
#name: string;
|
|
||||||
#iv: any;
|
|
||||||
|
|
||||||
#closeSignal = new Signal();
|
|
||||||
|
|
||||||
members: Readable<(IMember & { $id: string })[]>;
|
|
||||||
messages: Readable<(IMessage & { $id: string })[]>;
|
|
||||||
|
|
||||||
get name() {
|
|
||||||
return this.#name;
|
|
||||||
}
|
|
||||||
|
|
||||||
set name(value) {
|
|
||||||
this.#name = value;
|
|
||||||
this.#self.update({ name: UpdateTypes.Value(value) });
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(id: string, name: string) {
|
|
||||||
this.#name = name;
|
|
||||||
|
|
||||||
this.#peer = new Peer(this.#client_id, {
|
|
||||||
host: window.location.hostname,
|
|
||||||
port: window.location.port as any,
|
|
||||||
path: "/peerjs",
|
|
||||||
config: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.#session = Sessions.doc(id);
|
|
||||||
this.#members = this.#session.collection("members");
|
|
||||||
this.#messages = this.#session.collection("messages");
|
|
||||||
this.#self = this.#members.doc(this.#client_id);
|
|
||||||
this.members = collectionToStore(this.#members);
|
|
||||||
this.messages = collectionToStore(this.#messages);
|
|
||||||
|
|
||||||
this.registerSelf();
|
|
||||||
this.#iv = setInterval(() => this.tick(), 5000);
|
|
||||||
}
|
|
||||||
|
|
||||||
tick() {
|
|
||||||
this.#self.update({ lastActive: UpdateTypes.Value(Date.now()) });
|
|
||||||
}
|
|
||||||
|
|
||||||
registerSelf() {
|
|
||||||
this.#self.set({
|
|
||||||
name: this.#name,
|
|
||||||
lastActive: Date.now(),
|
|
||||||
offline: false,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
close() {
|
|
||||||
this.#closeSignal.sendSignal();
|
|
||||||
clearInterval(this.#iv);
|
|
||||||
this.#self.update({ offline: UpdateTypes.Value(true) });
|
|
||||||
this.#peer.destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let bitrate = new URL(window.location.href).searchParams.get("br") || 50000;
|
|
||||||
|
|
||||||
function bitrateTransform(sdp: string) {
|
|
||||||
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;
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
import App from "./App.svelte";
|
|
||||||
|
|
||||||
new App({
|
|
||||||
target: document.body,
|
|
||||||
});
|
|
@ -1,43 +0,0 @@
|
|||||||
import { AwaitStore } from "@hibas123/utils";
|
|
||||||
import Client, { type ICollectionRef } from "@rtdb2/sdk";
|
|
||||||
import { readable } from "svelte/store";
|
|
||||||
|
|
||||||
const client = new Client(
|
|
||||||
"https://rtdb.hibas123.de",
|
|
||||||
"screen_share",
|
|
||||||
"screen_share"
|
|
||||||
);
|
|
||||||
|
|
||||||
(window as any).db = client;
|
|
||||||
|
|
||||||
export const Sessions = client.collection<ISession>("sessions");
|
|
||||||
|
|
||||||
export interface ISession {}
|
|
||||||
|
|
||||||
export interface IMember {
|
|
||||||
lastActive: number;
|
|
||||||
offline: boolean;
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IMessage {
|
|
||||||
sender: string;
|
|
||||||
message: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function collectionToStore<T>(coll: ICollectionRef<T>) {
|
|
||||||
return readable<(T & { $id: string })[]>([], (set) => {
|
|
||||||
const cancel = new AwaitStore(false);
|
|
||||||
(async () => {
|
|
||||||
const itr = await coll.onSnapshot();
|
|
||||||
cancel.awaitValue(true).then(() => itr.close());
|
|
||||||
for await (const snapshot of itr) {
|
|
||||||
set(snapshot.docs.map((doc) => ({ ...doc.data(), $id: doc.id })));
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
cancel.send(true);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import Button from "@smui/button";
|
|
||||||
import Textfield from "@smui/textfield";
|
|
||||||
import Paper, { Title as PTitle, Content as PContent } from "@smui/paper";
|
|
||||||
import { nanoid } from "nanoid";
|
|
||||||
import { url } from "@roxi/routify";
|
|
||||||
import Snackbar, { Actions, Label } from "@smui/snackbar";
|
|
||||||
import type { SnackbarComponentDev } from "@smui/snackbar";
|
|
||||||
import IconButton from "@smui/icon-button";
|
|
||||||
|
|
||||||
let sessionID = "";
|
|
||||||
let errorSnack: SnackbarComponentDev;
|
|
||||||
|
|
||||||
function create() {
|
|
||||||
sessionID = nanoid(22);
|
|
||||||
connect();
|
|
||||||
}
|
|
||||||
|
|
||||||
function connect() {
|
|
||||||
if (sessionID.length < 22) {
|
|
||||||
errorSnack.open();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.history.pushState(
|
|
||||||
undefined,
|
|
||||||
undefined,
|
|
||||||
$url(`/session/${sessionID}`)
|
|
||||||
);
|
|
||||||
sessionID = "";
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="outer">
|
|
||||||
<div class="inner">
|
|
||||||
<Paper elevation={6}>
|
|
||||||
<PContent>
|
|
||||||
<PTitle>Create Session</PTitle>
|
|
||||||
<div style="margin-top: 1rem" />
|
|
||||||
<Button variant="raised" on:click={create}>Create</Button>
|
|
||||||
</PContent>
|
|
||||||
</Paper>
|
|
||||||
<Paper elevation={6}>
|
|
||||||
<PContent>
|
|
||||||
<PTitle>Join Session</PTitle>
|
|
||||||
<Textfield
|
|
||||||
label="Session ID"
|
|
||||||
bind:value={sessionID}
|
|
||||||
style="width: 100%;"
|
|
||||||
/>
|
|
||||||
<div style="margin-top: 1rem" />
|
|
||||||
<Button variant="raised" on:click={connect}>Connect</Button>
|
|
||||||
</PContent>
|
|
||||||
</Paper>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Snackbar bind:this={errorSnack}>
|
|
||||||
<Label>Invalid Session!</Label>
|
|
||||||
<Actions>
|
|
||||||
<IconButton class="material-icons" title="Dismiss">close</IconButton>
|
|
||||||
</Actions>
|
|
||||||
</Snackbar>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.outer {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
height: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.inner {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, minmax(150px, 300px));
|
|
||||||
grid-template-rows: auto;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,42 +0,0 @@
|
|||||||
<script lang="ts">
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
|
|
||||||
import { Session } from "../../../api";
|
|
||||||
export let sessionid: string;
|
|
||||||
|
|
||||||
let session = new Session(sessionid, "");
|
|
||||||
let members = session.members;
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
return () => {
|
|
||||||
session.close();
|
|
||||||
};
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- {sessionid} -->
|
|
||||||
|
|
||||||
<div class="outer">
|
|
||||||
<div class="members">
|
|
||||||
{#each $members as member (member.$id)}
|
|
||||||
<div class="member">
|
|
||||||
<div class="name">{member.name || "anon"}</div>
|
|
||||||
<div class="id">{member.$id}</div>
|
|
||||||
</div>
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
<div class="content">Content</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.outer {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 200px 1fr;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,28 +0,0 @@
|
|||||||
@use "sass:color";
|
|
||||||
|
|
||||||
@use "@material/theme/color-palette";
|
|
||||||
|
|
||||||
// Svelte Colors!
|
|
||||||
@use "@material/theme/index" as theme with
|
|
||||||
(
|
|
||||||
$primary: #1e88e5,
|
|
||||||
$secondary: #d8701b,
|
|
||||||
$surface: #fff,
|
|
||||||
$background: #fff,
|
|
||||||
$error: color-palette.$red-900
|
|
||||||
);
|
|
||||||
|
|
||||||
@import "@material/typography/mdc-typography";
|
|
||||||
|
|
||||||
// html,
|
|
||||||
// body {
|
|
||||||
// background-color: theme.$surface;
|
|
||||||
// color: theme.$on-surface;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// a {
|
|
||||||
// color: #40b3ff;
|
|
||||||
// }
|
|
||||||
// a:visited {
|
|
||||||
// color: color.scale(#40b3ff, $lightness: -35%);
|
|
||||||
// }
|
|
@ -1,28 +0,0 @@
|
|||||||
@use "sass:color";
|
|
||||||
|
|
||||||
@use "@material/theme/color-palette";
|
|
||||||
|
|
||||||
// Svelte Colors! (Dark Theme)
|
|
||||||
@use "@material/theme/index" as theme with
|
|
||||||
(
|
|
||||||
$primary: #1e88e5,
|
|
||||||
$secondary: #d8701b,
|
|
||||||
$surface: color.adjust(color-palette.$grey-900, $blue: +4),
|
|
||||||
$background: #000,
|
|
||||||
$error: color-palette.$red-700
|
|
||||||
);
|
|
||||||
|
|
||||||
@import "@material/typography/mdc-typography";
|
|
||||||
|
|
||||||
// html,
|
|
||||||
// body {
|
|
||||||
// background-color: #000;
|
|
||||||
// color: theme.$on-surface;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// a {
|
|
||||||
// color: #40b3ff;
|
|
||||||
// }
|
|
||||||
// a:visited {
|
|
||||||
// color: color.scale(#40b3ff, $lightness: -35%);
|
|
||||||
// }
|
|
@ -1,5 +0,0 @@
|
|||||||
const autoPreprocess = require("svelte-preprocess");
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
preprocess: autoPreprocess(),
|
|
||||||
};
|
|
@ -1,24 +0,0 @@
|
|||||||
{
|
|
||||||
"extends": "@tsconfig/svelte/tsconfig.json",
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "esnext",
|
|
||||||
"module": "esnext",
|
|
||||||
"resolveJsonModule": true,
|
|
||||||
"baseUrl": ".",
|
|
||||||
"outDir": "tout",
|
|
||||||
/**
|
|
||||||
* Typecheck JS in `.svelte` and `.js` files by default.
|
|
||||||
* Disable checkJs if you'd like to use dynamic types in JS.
|
|
||||||
* Note that setting allowJs false does not prevent the use
|
|
||||||
* of JS in `.svelte` files.
|
|
||||||
*/
|
|
||||||
"allowJs": true,
|
|
||||||
"checkJs": true,
|
|
||||||
},
|
|
||||||
"include": [
|
|
||||||
"src/**/*.d.ts",
|
|
||||||
"src/**/*.ts",
|
|
||||||
"src/**/*.js",
|
|
||||||
"src/**/*.svelte",
|
|
||||||
]
|
|
||||||
}
|
|
@ -1,80 +0,0 @@
|
|||||||
const { defineConfig } = require("vite");
|
|
||||||
const { svelte } = require("@sveltejs/vite-plugin-svelte");
|
|
||||||
const zlib = require("zlib");
|
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
|
||||||
module.exports = defineConfig({
|
|
||||||
optimizeDeps: {
|
|
||||||
exclude: ["@roxi/routify"],
|
|
||||||
},
|
|
||||||
server: {
|
|
||||||
proxy: {
|
|
||||||
"/peerjs": {
|
|
||||||
target: "http://localhost:5000/",
|
|
||||||
changeOrigin: true,
|
|
||||||
ws: true,
|
|
||||||
rewrite: (path) => path.replace(/^\/peerjs/, ""),
|
|
||||||
},
|
|
||||||
"*": "/index.html",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [svelte()],
|
|
||||||
build: {
|
|
||||||
sourcemap: false,
|
|
||||||
rollupOptions: {
|
|
||||||
plugins: [
|
|
||||||
{
|
|
||||||
name: "pregzip-files",
|
|
||||||
generateBundle: async function (options, bundle) {
|
|
||||||
let prms = [];
|
|
||||||
for (const fileName in bundle) {
|
|
||||||
const file = bundle[fileName];
|
|
||||||
// if (fileName.startsWith("assets/")) {
|
|
||||||
let src;
|
|
||||||
if (file.type === "asset") {
|
|
||||||
src = file.source;
|
|
||||||
} else {
|
|
||||||
src = file.code;
|
|
||||||
}
|
|
||||||
// console.log("Compressing asset:", typeof file.source == "undefined" ? file : undefined)
|
|
||||||
|
|
||||||
prms.push(
|
|
||||||
new Promise((yes, no) =>
|
|
||||||
zlib.gzip(
|
|
||||||
src,
|
|
||||||
{
|
|
||||||
level: 6,
|
|
||||||
},
|
|
||||||
(err, res) => (err ? no(err) : yes(res))
|
|
||||||
)
|
|
||||||
).then((gzip) => {
|
|
||||||
this.emitFile({
|
|
||||||
type: "asset",
|
|
||||||
name: file.name + ".gz",
|
|
||||||
fileName: file.fileName + ".gz",
|
|
||||||
source: gzip,
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
new Promise((yes, no) =>
|
|
||||||
zlib.brotliCompress(src, (err, res) =>
|
|
||||||
err ? no(err) : yes(res)
|
|
||||||
)
|
|
||||||
).then((br) => {
|
|
||||||
this.emitFile({
|
|
||||||
type: "asset",
|
|
||||||
name: file.name + ".br",
|
|
||||||
fileName: file.fileName + ".br",
|
|
||||||
source: br,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
);
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(prms);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
@ -7,11 +7,11 @@ WORKDIR /usr/src/app
|
|||||||
|
|
||||||
RUN npm config set registry https://npm.hibas123.de
|
RUN npm config set registry https://npm.hibas123.de
|
||||||
|
|
||||||
COPY ["Server/package.json", "Server/tsconfig.json", "/usr/src/app/"]
|
COPY ["package.json", "tsconfig.json", "/usr/src/app/"]
|
||||||
|
|
||||||
RUN npm install
|
RUN npm install
|
||||||
COPY Server/lib/ /usr/src/app/lib
|
COPY src/ /usr/src/app/src
|
||||||
COPY Client/dist/ /usr/src/app/public
|
COPY public/ /usr/src/app/public
|
||||||
|
|
||||||
EXPOSE 3000/tcp
|
EXPOSE 3000/tcp
|
||||||
CMD ["npm", "run", "start"]
|
CMD ["npm", "run", "start"]
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "@hibas123/screen-server",
|
|
||||||
"packageManager": "yarn@3.1.1",
|
|
||||||
"scripts": {
|
|
||||||
"start": "ts-node src/index.ts",
|
|
||||||
"dev": "nodemon -e ts --exec ts-node src/index.ts"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"@types/node": "^16.11.11",
|
|
||||||
"ts-node": "^10.4.0",
|
|
||||||
"typescript": "^4.5.5"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"express": "^4.17.1",
|
|
||||||
"peer": "^0.6.1"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"compilerOptions": {
|
|
||||||
"module": "commonjs",
|
|
||||||
"target": "esnext",
|
|
||||||
"outDir": "lib/",
|
|
||||||
"sourceMap": true,
|
|
||||||
"declaration": true,
|
|
||||||
"noImplicitAny": false
|
|
||||||
},
|
|
||||||
"exclude": ["node_modules"],
|
|
||||||
"include": ["src"]
|
|
||||||
}
|
|
20
package.json
20
package.json
@ -2,23 +2,15 @@
|
|||||||
"name": "ScreenSharingThing",
|
"name": "ScreenSharingThing",
|
||||||
"packageManager": "yarn@3.1.1",
|
"packageManager": "yarn@3.1.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:api": "jrpc compile API/main.jrpc -o=ts-node:_API/src && yarn workspace @hibas123/screen-api build",
|
"dev": "ts-node src/index.ts"
|
||||||
"build:client": "yarn workspace @hibas123/screen-client build",
|
|
||||||
"build:server": "yarn workspace @hibas123/screen-server run build",
|
|
||||||
"build": "run-s build:api build:server build:client",
|
|
||||||
"dev:client": "yarn workspace @hibas123/screen-client dev",
|
|
||||||
"dev:server": "yarn workspace @hibas123/screen-server dev",
|
|
||||||
"dev": "run-p dev:client dev:server"
|
|
||||||
},
|
},
|
||||||
"workspaces": [
|
|
||||||
"Server",
|
|
||||||
"Client",
|
|
||||||
"_API"
|
|
||||||
],
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"npm-run-all": "^4.1.5"
|
"@types/node": "^16.11.11",
|
||||||
|
"ts-node": "^10.4.0",
|
||||||
|
"typescript": "^4.5.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hibas123/jrpcgen": "~1.0.26"
|
"express": "^4.17.1",
|
||||||
|
"peer": "^0.6.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,6 +78,7 @@ var peer = new Peer({
|
|||||||
});
|
});
|
||||||
|
|
||||||
function bitrateTransform(sdp) {
|
function bitrateTransform(sdp) {
|
||||||
|
// return sdp;
|
||||||
var arr = sdp.split("\r\n");
|
var arr = sdp.split("\r\n");
|
||||||
arr.forEach((str, i) => {
|
arr.forEach((str, i) => {
|
||||||
if (/^a=fmtp:\d*/.test(str)) {
|
if (/^a=fmtp:\d*/.test(str)) {
|
||||||
@ -97,45 +98,64 @@ function bitrateTransform(sdp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let currentStream = undefined;
|
let currentStream = undefined;
|
||||||
|
|
||||||
|
let connections = [];
|
||||||
|
|
||||||
|
function sendStream(id) {
|
||||||
|
const conn = peer.call(id, currentStream, {
|
||||||
|
sdpTransform: bitrateTransform,
|
||||||
|
});
|
||||||
|
|
||||||
|
conn.on("stream", console.log);
|
||||||
|
conn.on("close", console.log);
|
||||||
|
conn.on("error", console.log);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
|
||||||
|
connections.forEach((id) => {
|
||||||
|
sendStream(id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
peer.on("open", (id) => {
|
peer.on("open", (id) => {
|
||||||
console.log("ID", id);
|
console.log("ID", id);
|
||||||
sf.streamId_text = id;
|
sf.streamId_text = id;
|
||||||
|
|
||||||
let url = new URL(window.location.href);
|
let url = new URL(window.location.href);
|
||||||
url.searchParams.set("id", id);
|
url.searchParams.set("id", id);
|
||||||
sf.streamURL_text = url.href;
|
sf.streamURL_text = url.href;
|
||||||
sf.streamURL_href = 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) {
|
if (connectToId) {
|
||||||
sf.startStramBTN_click = () => {
|
let con = peer.connect(connectToId);
|
||||||
navigator.mediaDevices
|
con.on("data", console.log);
|
||||||
.getDisplayMedia({
|
con.on("open", () => con.send("Hello"));
|
||||||
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) => {
|
peer.on("connection", (conn) => {
|
||||||
console.log("connection", conn);
|
console.log("connection", conn);
|
||||||
conn.on("data", console.log);
|
conn.on("data", console.log);
|
||||||
|
connections.push(conn.peer);
|
||||||
|
if (currentStream) {
|
||||||
|
sendStream(conn.peer);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
peer.on("error", console.error);
|
peer.on("error", console.error);
|
@ -2,7 +2,7 @@ import { ExpressPeerServer } from "peer";
|
|||||||
import * as express from "express";
|
import * as express from "express";
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
const server = app.listen(5000);
|
const server = app.listen(3000);
|
||||||
const peerServer = ExpressPeerServer(server, {
|
const peerServer = ExpressPeerServer(server, {
|
||||||
path: "/",
|
path: "/",
|
||||||
});
|
});
|
Loading…
Reference in New Issue
Block a user