Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a47ce3650b | ||
|
|
34df35d54c |
+937
@@ -0,0 +1,937 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Jitsi Meeting</title>
|
||||
|
||||
<style>
|
||||
:root {
|
||||
color-scheme: light dark;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
|
||||
background: #f5f5f5;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.card {
|
||||
box-sizing: border-box;
|
||||
width: min(600px, calc(100% - 32px));
|
||||
padding: 32px;
|
||||
background: white;
|
||||
border-radius: 14px;
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.10);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
button, .button {
|
||||
display: inline-block;
|
||||
border: 0;
|
||||
border-radius: 8px;
|
||||
padding: 12px 20px;
|
||||
margin: 6px;
|
||||
font-size: 16px;
|
||||
font-family: inherit;
|
||||
cursor: pointer;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.primary {
|
||||
background: #1f73e8;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.secondary {
|
||||
background: #e9e9e9;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.status {
|
||||
margin-top: 24px;
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
background: #f0f0f0;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
border: 2px solid #ccc;
|
||||
border-top-color: #333;
|
||||
border-radius: 50%;
|
||||
animation: spin 0.7s linear infinite;
|
||||
vertical-align: -3px;
|
||||
}
|
||||
|
||||
.download {
|
||||
margin-top: 24px;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
background: #f5f5f5;
|
||||
}
|
||||
|
||||
.room {
|
||||
font-family: monospace;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.error {
|
||||
padding: 16px;
|
||||
border-radius: 8px;
|
||||
background: #fff0f0;
|
||||
color: #900;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to {
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: #181818;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #242424;
|
||||
}
|
||||
|
||||
p {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
.secondary {
|
||||
background: #444;
|
||||
color: #eee;
|
||||
}
|
||||
|
||||
.status, .download {
|
||||
background: #303030;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
border-color: #555;
|
||||
border-top-color: #ddd;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="card">
|
||||
|
||||
<!-- NORMALER LAUNCHER -->
|
||||
<div id="launcher" class="hidden">
|
||||
<h1 data-i18n="launcher.title">Jitsi Meeting</h1>
|
||||
|
||||
<p>
|
||||
<span data-i18n="launcher.meetingPrefix">
|
||||
The meeting
|
||||
</span>
|
||||
<span class="room">
|
||||
<strong id="roomName"></strong>
|
||||
</span>
|
||||
<span data-i18n="launcher.meetingSuffix">
|
||||
will be opened.
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<button id="openButton" class="button primary" type="button" data-i18n="launcher.openButton">
|
||||
Open meeting
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- STARTVORGANG -->
|
||||
<div id="starting" class="hidden">
|
||||
<h1 data-i18n="starting.title">
|
||||
Starting Jitsi Meet …
|
||||
</h1>
|
||||
|
||||
<div class="status">
|
||||
<span class="spinner"></span>
|
||||
<span data-i18n="starting.status">
|
||||
The Jitsi Meet desktop client is being opened.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FALLBACK -->
|
||||
<div id="fallback" class="hidden">
|
||||
<h1 data-i18n="fallback.title">
|
||||
Jitsi Meet could not be opened
|
||||
</h1>
|
||||
|
||||
<p data-i18n="fallback.description">
|
||||
The Jitsi Meet desktop client may not have been started.
|
||||
</p>
|
||||
|
||||
<button id="retryButton" class="button primary" type="button" data-i18n="fallback.retryButton">
|
||||
Try again
|
||||
</button>
|
||||
|
||||
<!-- Windows -->
|
||||
<div id="windowsDownload" class="download hidden">
|
||||
<h2 data-i18n="downloads.windows.title">
|
||||
Jitsi Meet for Windows
|
||||
</h2>
|
||||
|
||||
<p data-i18n="downloads.windows.description">
|
||||
Install the Jitsi Meet desktop client and then try opening the
|
||||
meeting again.
|
||||
</p>
|
||||
|
||||
<a id="windowsLink" class="button secondary" target="_blank" rel="noopener noreferrer" data-i18n="downloads.windows.button">
|
||||
Download Jitsi for Windows
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- macOS -->
|
||||
<div id="macosDownload" class="download hidden">
|
||||
<h2 data-i18n="downloads.macos.title">
|
||||
Jitsi Meet for macOS
|
||||
</h2>
|
||||
|
||||
<p data-i18n="downloads.macos.description">
|
||||
Install the Jitsi Meet desktop client and then try opening the
|
||||
meeting again.
|
||||
</p>
|
||||
|
||||
<a id="macosLink" class="button secondary" target="_blank" rel="noopener noreferrer" data-i18n="downloads.macos.button">
|
||||
Download Jitsi for macOS
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Linux / unbekannt -->
|
||||
<div id="otherDownload" class="download hidden">
|
||||
<h2 data-i18n="downloads.other.title">
|
||||
Jitsi Meet Desktop
|
||||
</h2>
|
||||
|
||||
<p data-i18n="downloads.other.description">
|
||||
No desktop download is configured for your operating system.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Browser -->
|
||||
<div class="download">
|
||||
<h2 data-i18n="browser.title">
|
||||
Join in browser
|
||||
</h2>
|
||||
|
||||
<p data-i18n="browser.description">
|
||||
You can also join the meeting directly in your browser.
|
||||
</p>
|
||||
|
||||
<a id="browserLink" class="button secondary" data-i18n="browser.button">
|
||||
Join in browser
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- FEHLER -->
|
||||
<div id="invalidRoom" class="hidden">
|
||||
<h1 data-i18n="error.title">
|
||||
No meeting specified
|
||||
</h1>
|
||||
|
||||
<div class="error">
|
||||
<span data-i18n="error.description">
|
||||
Please specify a meeting using the
|
||||
</span>
|
||||
<code>?room=...</code>
|
||||
<span data-i18n="error.descriptionSuffix">
|
||||
parameter.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
/* ============================================================
|
||||
* KONFIGURATION
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
const CONFIG = {
|
||||
/*
|
||||
* Your Jitsi Domain.
|
||||
*/
|
||||
jitsiHost: "<YOURJITSIINSTANCEADDRESS>",
|
||||
|
||||
/*
|
||||
* Timeout trying to start the jitsi-meet-electron client
|
||||
*/
|
||||
launchTimeout: 2000,
|
||||
|
||||
/*
|
||||
* Download URLs for jitsi-meet-electron client
|
||||
*/
|
||||
downloads: {
|
||||
windows: "https://github.com/jitsi/jitsi-meet-electron/releases",
|
||||
macos: "https://github.com/jitsi/jitsi-meet-electron/releases"
|
||||
}
|
||||
};
|
||||
|
||||
/* ============================================================
|
||||
* Translations
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
const TRANSLATIONS = {
|
||||
en: {
|
||||
pageTitle: "Jitsi Meeting",
|
||||
|
||||
launcher: {
|
||||
title: "Jitsi Meeting",
|
||||
meetingPrefix: "The meeting",
|
||||
meetingSuffix: "will be joined.",
|
||||
openButton: "Join meeting"
|
||||
},
|
||||
|
||||
starting: {
|
||||
title: "Starting Jitsi Meet …",
|
||||
status: "The Jitsi Meet desktop client is being opened."
|
||||
},
|
||||
|
||||
fallback: {
|
||||
title: "Jitsi Meet could not be opened",
|
||||
description: "The Jitsi Meet desktop client may not have been started.",
|
||||
retryButton: "Try again"
|
||||
},
|
||||
|
||||
downloads: {
|
||||
windows: {
|
||||
title: "Jitsi Meet for Windows",
|
||||
description:
|
||||
"Install the Jitsi Meet desktop client and then try opening the meeting again.",
|
||||
button: "Download Jitsi for Windows"
|
||||
},
|
||||
|
||||
macos: {
|
||||
title: "Jitsi Meet for macOS",
|
||||
description:
|
||||
"Install the Jitsi Meet desktop client and then try opening the meeting again.",
|
||||
button: "Download Jitsi for macOS"
|
||||
},
|
||||
|
||||
other: {
|
||||
title: "Jitsi Meet Desktop",
|
||||
description:
|
||||
"No desktop download is configured for your operating system."
|
||||
}
|
||||
},
|
||||
|
||||
browser: {
|
||||
title: "Join in browser",
|
||||
description:
|
||||
"You can also join the meeting directly in your browser.",
|
||||
button: "Join in browser"
|
||||
},
|
||||
|
||||
error: {
|
||||
title: "No meeting specified",
|
||||
description: "Please specify a meeting using the",
|
||||
descriptionSuffix: "parameter."
|
||||
}
|
||||
},
|
||||
|
||||
de: {
|
||||
pageTitle: "Jitsi Meeting öffnen",
|
||||
|
||||
launcher: {
|
||||
title: "Jitsi Meeting",
|
||||
meetingPrefix: "Das Meeting",
|
||||
meetingSuffix: "wird geöffnet.",
|
||||
openButton: "An Meeting teilnehmen"
|
||||
},
|
||||
|
||||
starting: {
|
||||
title: "Jitsi Meet wird gestartet …",
|
||||
status: "Der Jitsi Meet Desktop-Client wird geöffnet."
|
||||
},
|
||||
|
||||
fallback: {
|
||||
title: "Jitsi Meet konnte nicht geöffnet werden",
|
||||
description:
|
||||
"Der Jitsi Meet Desktop-Client wurde möglicherweise nicht gestartet.",
|
||||
retryButton: "Erneut versuchen"
|
||||
},
|
||||
|
||||
downloads: {
|
||||
windows: {
|
||||
title: "Jitsi Meet für Windows",
|
||||
description:
|
||||
"Installiere den Jitsi Meet Desktop-Client und versuche anschließend erneut, das Meeting zu öffnen.",
|
||||
button: "Jitsi für Windows herunterladen"
|
||||
},
|
||||
|
||||
macos: {
|
||||
title: "Jitsi Meet für macOS",
|
||||
description:
|
||||
"Installiere den Jitsi Meet Desktop-Client und versuche anschließend erneut, das Meeting zu öffnen.",
|
||||
button: "Jitsi für macOS herunterladen"
|
||||
},
|
||||
|
||||
other: {
|
||||
title: "Jitsi Meet Desktop",
|
||||
description:
|
||||
"Für dein Betriebssystem ist kein Desktop-Download hinterlegt."
|
||||
}
|
||||
},
|
||||
|
||||
browser: {
|
||||
title: "Im Browser teilnehmen",
|
||||
description:
|
||||
"Du kannst dem Meeting auch direkt über deinen Browser beitreten.",
|
||||
button: "Im Browser beitreten"
|
||||
},
|
||||
|
||||
error: {
|
||||
title: "Kein Meeting angegeben",
|
||||
description:
|
||||
"Bitte gib ein Meeting über den Parameter",
|
||||
descriptionSuffix: "an."
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* ============================================================
|
||||
* Detect language
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function detectLanguage() {
|
||||
const languages = navigator.languages || [navigator.language];
|
||||
|
||||
for (const language of languages) {
|
||||
if (!language) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const languageCode = language
|
||||
.toLowerCase()
|
||||
.split("-")[0];
|
||||
|
||||
if (TRANSLATIONS[languageCode]) {
|
||||
return languageCode;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Englisch ist der Standard/Fallback.
|
||||
*/
|
||||
return "en";
|
||||
}
|
||||
|
||||
const currentLanguage = detectLanguage();
|
||||
const translation = TRANSLATIONS[currentLanguage];
|
||||
|
||||
/* ============================================================
|
||||
* Apply translations to webpage
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function applyTranslations() {
|
||||
document.documentElement.lang = currentLanguage;
|
||||
document.title = translation.pageTitle;
|
||||
|
||||
document
|
||||
.querySelectorAll("[data-i18n]")
|
||||
.forEach((element) => {
|
||||
const key = element.dataset.i18n;
|
||||
const value = getTranslation(key);
|
||||
|
||||
if (value !== null) {
|
||||
element.textContent = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* Übersetzung anhand eines Pfades lesen.
|
||||
*
|
||||
* Beispiel:
|
||||
*
|
||||
* "downloads.windows.title"
|
||||
*
|
||||
* ergibt:
|
||||
*
|
||||
* translation.downloads.windows.title
|
||||
*/
|
||||
function getTranslation(key) {
|
||||
const parts = key.split(".");
|
||||
let value = translation;
|
||||
|
||||
for (const part of parts) {
|
||||
if (
|
||||
value === null ||
|
||||
value === undefined ||
|
||||
typeof value !== "object" ||
|
||||
!(part in value)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
value = value[part];
|
||||
}
|
||||
|
||||
return typeof value === "string" ? value : null;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* DOM elements
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
const launcher = document.getElementById("launcher");
|
||||
const starting = document.getElementById("starting");
|
||||
const fallback = document.getElementById("fallback");
|
||||
const invalidRoom = document.getElementById("invalidRoom");
|
||||
const roomName = document.getElementById("roomName");
|
||||
const openButton = document.getElementById("openButton");
|
||||
const retryButton = document.getElementById("retryButton");
|
||||
const browserLink = document.getElementById("browserLink");
|
||||
const windowsDownload = document.getElementById("windowsDownload");
|
||||
const macosDownload = document.getElementById("macosDownload");
|
||||
const otherDownload = document.getElementById("otherDownload");
|
||||
const windowsLink = document.getElementById("windowsLink");
|
||||
const macosLink = document.getElementById("macosLink");
|
||||
|
||||
/* ============================================================
|
||||
* GET ROOM FROM QUERY-PARAMETER
|
||||
* ============================================================
|
||||
*
|
||||
* Beispiel:
|
||||
*
|
||||
* https://<YOURJITSIINSTANCEADDRESS>/launch.html?room=abc-defg-hij
|
||||
*
|
||||
* ergibt:
|
||||
*
|
||||
* abc-defg-hij
|
||||
*
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function getRoom() {
|
||||
const params = new URLSearchParams(
|
||||
window.location.search
|
||||
);
|
||||
|
||||
const room = params.get("room");
|
||||
|
||||
if (!room) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
* Leerzeichen etc. verhindern.
|
||||
*/
|
||||
const trimmed = room.trim();
|
||||
|
||||
if (!trimmed) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* VALIDATE ROOM
|
||||
* ============================================================
|
||||
*
|
||||
* Jitsi-Roomnamen können je nach Konfiguration relativ
|
||||
* unterschiedliche Zeichen enthalten.
|
||||
*
|
||||
* Wir verhindern hier lediglich Steuerzeichen und
|
||||
* offensichtliche URL-Manipulation.
|
||||
*
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function isValidRoom(room) {
|
||||
if (!room) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keine Steuerzeichen.
|
||||
*/
|
||||
if (/[\u0000-\u001F\u007F]/.test(room)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Keine Slash-Zeichen.
|
||||
*
|
||||
* Falls deine Jitsi-Konfiguration Räume mit Slashes
|
||||
* unterstützt, diese Prüfung entsprechend entfernen.
|
||||
*/
|
||||
if (room.includes("/")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* JITSI WEB URL
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function createBrowserUrl(room) {
|
||||
return (
|
||||
"https://" +
|
||||
CONFIG.jitsiHost +
|
||||
"/" +
|
||||
encodeURIComponent(room)
|
||||
);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* JITSI DESKTOP PROTOCOL URL
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function createAppUrl(room) {
|
||||
return (
|
||||
"jitsi-meet://" +
|
||||
CONFIG.jitsiHost +
|
||||
"/" +
|
||||
encodeURIComponent(room)
|
||||
);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* DETECT OPERATING SYSTEM
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function detectOperatingSystem() {
|
||||
const ua = navigator.userAgent;
|
||||
|
||||
/* iPhone / iPad / iPod */
|
||||
if (
|
||||
/iPhone|iPad|iPod/i.test(ua) ||
|
||||
(
|
||||
navigator.platform === "MacIntel" &&
|
||||
navigator.maxTouchPoints > 1
|
||||
)
|
||||
) {
|
||||
return "ios";
|
||||
}
|
||||
|
||||
/* Android */
|
||||
if (/Android/i.test(ua)) {
|
||||
return "android";
|
||||
}
|
||||
|
||||
/* Windows */
|
||||
if (/Windows/i.test(ua)) {
|
||||
return "windows";
|
||||
}
|
||||
|
||||
/* macOS */
|
||||
if (/Macintosh|Mac OS X/i.test(ua)) {
|
||||
return "macos";
|
||||
}
|
||||
|
||||
/* Linux */
|
||||
if (/Linux/i.test(ua)) {
|
||||
return "linux";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* BROWSER ERKENNEN
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function detectBrowser() {
|
||||
const ua = navigator.userAgent;
|
||||
|
||||
if (/Edg\//i.test(ua)) {
|
||||
return "edge";
|
||||
}
|
||||
|
||||
if (/Firefox\//i.test(ua)) {
|
||||
return "firefox";
|
||||
}
|
||||
|
||||
if (
|
||||
/Chrome\//i.test(ua) &&
|
||||
!/Edg\//i.test(ua)
|
||||
) {
|
||||
return "chrome";
|
||||
}
|
||||
|
||||
if (
|
||||
/Safari\//i.test(ua) &&
|
||||
!/Chrome\//i.test(ua) &&
|
||||
!/Chromium\//i.test(ua)
|
||||
) {
|
||||
return "safari";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* DOWNLOADS
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function configureDownloads() {
|
||||
const os = detectOperatingSystem();
|
||||
|
||||
windowsDownload.classList.add("hidden");
|
||||
macosDownload.classList.add("hidden");
|
||||
otherDownload.classList.add("hidden");
|
||||
|
||||
/* Windows */
|
||||
if (os === "windows") {
|
||||
windowsLink.href = CONFIG.downloads.windows;
|
||||
windowsDownload.classList.remove("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
/* macOS */
|
||||
if (os === "macos") {
|
||||
macosLink.href = CONFIG.downloads.macos;
|
||||
macosDownload.classList.remove("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Alles andere */
|
||||
otherDownload.classList.remove("hidden");
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* FALLBACK ANZEIGEN
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function showFallback() {
|
||||
starting.classList.add("hidden");
|
||||
launcher.classList.add("hidden");
|
||||
fallback.classList.remove("hidden");
|
||||
|
||||
configureDownloads();
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* JITSI DESKTOP STARTEN
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function launchJitsi() {
|
||||
const room = getRoom();
|
||||
|
||||
if (!isValidRoom(room)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const protocolUrl = createAppUrl(room);
|
||||
const browserUrl = createBrowserUrl(room);
|
||||
|
||||
/*
|
||||
* Browser-Fallback vorbereiten.
|
||||
*/
|
||||
browserLink.href = browserUrl;
|
||||
|
||||
/*
|
||||
* UI auf "Startvorgang" setzen.
|
||||
*/
|
||||
launcher.classList.add("hidden");
|
||||
fallback.classList.add("hidden");
|
||||
starting.classList.remove("hidden");
|
||||
|
||||
let completed = false;
|
||||
let timeout = null;
|
||||
|
||||
/*
|
||||
* Unsichtbarer iframe für den Protocol Handler.
|
||||
*/
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.style.display = "none";
|
||||
|
||||
/*
|
||||
* Aufräumen.
|
||||
*/
|
||||
function cleanup() {
|
||||
if (completed) {
|
||||
return;
|
||||
}
|
||||
|
||||
completed = true;
|
||||
|
||||
if (timeout !== null) {
|
||||
clearTimeout(timeout);
|
||||
}
|
||||
|
||||
iframe.remove();
|
||||
}
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------
|
||||
* WICHTIG:
|
||||
*
|
||||
* Kein "blur" mehr als Erfolgskriterium verwenden.
|
||||
*
|
||||
* Der Browser kann beim Protocol-Dialog ebenfalls
|
||||
* blur auslösen.
|
||||
*
|
||||
* Wenn der Benutzer den Dialog abbricht, bleibt die
|
||||
* Seite sichtbar und unser Timeout läuft weiter.
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
/*
|
||||
* Protocol Handler starten.
|
||||
*/
|
||||
try {
|
||||
iframe.src = protocolUrl;
|
||||
} catch (error) {
|
||||
console.error(
|
||||
"Error opening the Jitsi Protocol Handler:",
|
||||
error
|
||||
);
|
||||
|
||||
cleanup();
|
||||
showFallback();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------
|
||||
* FALLBACK
|
||||
* --------------------------------------------------------
|
||||
*
|
||||
* Wir warten unabhängig davon, ob der Browser kurz
|
||||
* den Fokus verliert.
|
||||
*
|
||||
* Wenn Jitsi erfolgreich startet:
|
||||
*
|
||||
* -> Jitsi kommt in den Vordergrund
|
||||
* -> Benutzer sieht diese Seite nicht mehr
|
||||
*
|
||||
* Wenn der Benutzer den Browser-Dialog abbricht:
|
||||
*
|
||||
* -> diese Seite bleibt sichtbar
|
||||
* -> Timeout läuft ab
|
||||
* -> Fallback wird angezeigt
|
||||
* --------------------------------------------------------
|
||||
*/
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
if (completed) {
|
||||
return;
|
||||
}
|
||||
|
||||
cleanup();
|
||||
showFallback();
|
||||
}, CONFIG.launchTimeout);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* INITIALISIERUNG
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
function initialize() {
|
||||
const room = getRoom();
|
||||
|
||||
/*
|
||||
* Kein room-Parameter
|
||||
*/
|
||||
if (!isValidRoom(room)) {
|
||||
invalidRoom.classList.remove("hidden");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Room anzeigen.
|
||||
*/
|
||||
roomName.textContent = room;
|
||||
|
||||
/*
|
||||
* Browser-Fallback vorbereiten.
|
||||
*/
|
||||
browserLink.href = createBrowserUrl(room);
|
||||
|
||||
/*
|
||||
* Launcher anzeigen.
|
||||
*/
|
||||
launcher.classList.remove("hidden");
|
||||
|
||||
/*
|
||||
* Debug-Informationen.
|
||||
*/
|
||||
console.log(
|
||||
"Jitsi Launcher",
|
||||
{
|
||||
language: currentLanguage,
|
||||
room: room,
|
||||
operatingSystem: detectOperatingSystem(),
|
||||
browser: detectBrowser(),
|
||||
protocol: createAppUrl(room),
|
||||
browserUrl: createBrowserUrl(room)
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
* EVENTS
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
openButton.addEventListener(
|
||||
"click",
|
||||
launchJitsi
|
||||
);
|
||||
|
||||
retryButton.addEventListener(
|
||||
"click",
|
||||
launchJitsi
|
||||
);
|
||||
|
||||
/* ============================================================
|
||||
* START
|
||||
* ============================================================
|
||||
*/
|
||||
|
||||
applyTranslations();
|
||||
initialize();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in new issue
Block a user