Compare commits

..
3 Commits
3 changed files with 113 additions and 59 deletions

No files matched your search

+5 -1
View File
@@ -1,3 +1,7 @@
# jitsi-start # jitsi-start
A small html/js project to nudge a user to use the desktop client for Jitsi. A small html/js project to nudge a user to use the desktop client for Jitsi.
## Third-party assets
- `assets/ua-parser.min.js` — [ua-parser-js](https://github.com/faisalman/ua-parser-js) v2.0.10, © Faisal Salman, licensed under AGPL-3.0.
+4
View File
@@ -0,0 +1,4 @@
/* UAParser.js v2.0.10
Copyright © 2012-2026 Faisal Salman <f@faisalman.com>
AGPLv3 License */
(function(window,undefined){"use strict";var LIBVERSION="2.0.10",UA_MAX_LENGTH=500,USER_AGENT="user-agent",EMPTY="",UNKNOWN="?",TYPEOF={FUNCTION:"function",OBJECT:"object",STRING:"string",UNDEFINED:"undefined"},BROWSER="browser",CPU="cpu",DEVICE="device",ENGINE="engine",OS="os",RESULT="result",NAME="name",TYPE="type",VENDOR="vendor",VERSION="version",ARCHITECTURE="architecture",MAJOR="major",MODEL="model",CONSOLE="console",MOBILE="mobile",TABLET="tablet",SMARTTV="smarttv",WEARABLE="wearable",XR="xr",EMBEDDED="embedded",FETCHER="fetcher",INAPP="inapp",BRANDS="brands",FORMFACTORS="formFactors",FULLVERLIST="fullVersionList",PLATFORM="platform",PLATFORMVER="platformVersion",BITNESS="bitness",CH="sec-ch-ua",CH_FULL_VER_LIST=CH+"-full-version-list",CH_ARCH=CH+"-arch",CH_BITNESS=CH+"-"+BITNESS,CH_FORM_FACTORS=CH+"-form-factors",CH_MOBILE=CH+"-"+MOBILE,CH_MODEL=CH+"-"+MODEL,CH_PLATFORM=CH+"-"+PLATFORM,CH_PLATFORM_VER=CH_PLATFORM+"-version",CH_ALL_VALUES=[BRANDS,FULLVERLIST,MOBILE,MODEL,PLATFORM,PLATFORMVER,ARCHITECTURE,FORMFACTORS,BITNESS],AMAZON="Amazon",APPLE="Apple",ASUS="ASUS",BLACKBERRY="BlackBerry",GOOGLE="Google",HUAWEI="Huawei",LENOVO="Lenovo",HONOR="Honor",LG="LG",MICROSOFT="Microsoft",MOTOROLA="Motorola",NVIDIA="Nvidia",ONEPLUS="OnePlus",OPPO="OPPO",SAMSUNG="Samsung",SHARP="Sharp",SONY="Sony",XIAOMI="Xiaomi",ZEBRA="Zebra",CHROME="Chrome",CHROMIUM="Chromium",CHROMECAST="Chromecast",EDGE="Edge",FIREFOX="Firefox",OPERA="Opera",FACEBOOK="Facebook",SOGOU="Sogou",PREFIX_MOBILE="Mobile ",SUFFIX_BROWSER=" Browser",WINDOWS="Windows";var isWindow=typeof window!==TYPEOF.UNDEFINED,NAVIGATOR=isWindow&&window.navigator?window.navigator:undefined,NAVIGATOR_UADATA=NAVIGATOR&&NAVIGATOR.userAgentData?NAVIGATOR.userAgentData:undefined;var extend=function(defaultRgx,extensions){var mergedRgx={};var extraRgx=extensions;if(!isExtensions(extensions)){extraRgx={};for(var i in extensions){for(var j in extensions[i]){extraRgx[j]=extensions[i][j].concat(extraRgx[j]?extraRgx[j]:[])}}}for(var k in defaultRgx){mergedRgx[k]=extraRgx[k]&&extraRgx[k].length%2===0?extraRgx[k].concat(defaultRgx[k]):defaultRgx[k]}return mergedRgx},enumerize=function(arr){var enums={};for(var i=0;i<arr.length;i++){enums[arr[i].toUpperCase()]=arr[i]}return enums},has=function(str1,str2){if(typeof str1===TYPEOF.OBJECT&&str1.length>0){for(var i in str1){if(lowerize(str2)==lowerize(str1[i]))return true}return false}return isString(str1)?lowerize(str2)==lowerize(str1):false},isExtensions=function(obj,deep){for(var prop in obj){return/^(browser|cpu|device|engine|os)$/.test(prop)||(deep?isExtensions(obj[prop]):false)}},isString=function(val){return typeof val===TYPEOF.STRING},itemListToArray=function(header){if(!header)return undefined;var arr=[];var tokens=normalizeHeaderValue(header).split(",");for(var i=0;i<tokens.length;i++){if(tokens[i].indexOf(";")>-1){var token=trim(tokens[i]).split(";v=");arr[i]={brand:token[0],version:token[1]}}else{arr[i]=trim(tokens[i])}}return arr},lowerize=function(str){return isString(str)?str.toLowerCase():str},majorize=function(version){return isString(version)?strip(/[^\d\.]/g,version).split(".")[0]:undefined},normalizeHeaderValue=function(str){return isString(str)?trim(strip(/\\?\"/g,str),UA_MAX_LENGTH):undefined},setProps=function(arr){for(var i in arr){if(!arr.hasOwnProperty(i))continue;var propName=arr[i];if(typeof propName==TYPEOF.OBJECT&&propName.length==2){this[propName[0]]=propName[1]}else{this[propName]=undefined}}return this},strip=function(pattern,str){return isString(str)?str.replace(pattern,EMPTY):str},trim=function(str,len){str=strip(/^\s\s*/,String(str));return typeof len===TYPEOF.UNDEFINED?str:str.substring(0,len)};var rgxMapper=function(ua,arrays){if(!ua||!arrays)return;var i=0,j,k,p,q,matches,match;while(i<arrays.length&&!matches){var regex=arrays[i],props=arrays[i+1];j=k=0;while(j<regex.length&&!matches){if(!regex[j]){break}matches=regex[j++].exec(ua);if(!!matches){for(p=0;p<props.length;p++){match=matches[++k];q=props[p];if(typeof q===TYPEOF.OBJECT&&q.length>0){if(q.length===2){if(typeof q[1]==TYPEOF.FUNCTION){this[q[0]]=q[1].call(this,match)}else{this[q[0]]=q[1]}}else if(q.length>=3){if(typeof q[1]===TYPEOF.FUNCTION&&!(q[1].exec&&q[1].test)){if(q.length>3){this[q[0]]=match?q[1].apply(this,q.slice(2)):undefined}else{this[q[0]]=match?q[1].call(this,match,q[2]):undefined}}else{if(q.length==3){this[q[0]]=match?match.replace(q[1],q[2]):undefined}else if(q.length==4){this[q[0]]=match?q[3].call(this,match.replace(q[1],q[2])):undefined}else if(q.length>4){this[q[0]]=match?q[3].apply(this,[match.replace(q[1],q[2])].concat(q.slice(4))):undefined}}}}else{this[q]=match?match:undefined}}}}i+=2}},strTest=function(str,map){return map.test.test(str)?map.ifTrue:map.ifFalse},strMapper=function(str,map){for(var i in map){if(typeof map[i]===TYPEOF.OBJECT&&map[i].length>0){for(var j=0;j<map[i].length;j++){if(has(map[i][j],str)){return i===UNKNOWN?undefined:i}}}else if(has(map[i],str)){return i===UNKNOWN?undefined:i}}return map.hasLine truncated
+104 -58
View File
@@ -547,6 +547,9 @@
<a class="button secondary" href="https://www.bnvb-ingenieure.de/impressum" target="_blank" rel="noopener noreferrer" data-i18n="impressum"> <a class="button secondary" href="https://www.bnvb-ingenieure.de/impressum" target="_blank" rel="noopener noreferrer" data-i18n="impressum">
Impressum Impressum
</a> </a>
<a class="button secondary" href="https://git.bnvb.eu/stefan.tollkuehn/jitsi-launch" target="_blank" rel="noopener noreferrer" data-i18n="source">
Source
</a>
<div id="langMenu" class="lang-menu"> <div id="langMenu" class="lang-menu">
<button id="langButton" class="button secondary" type="button" aria-haspopup="true" aria-expanded="false"> <button id="langButton" class="button secondary" type="button" aria-haspopup="true" aria-expanded="false">
<img id="langFlag" class="lang-flag" src="assets/uk.svg" alt=""> <img id="langFlag" class="lang-flag" src="assets/uk.svg" alt="">
@@ -793,6 +796,7 @@
</div> </div>
</div> </div>
<script src="assets/ua-parser.min.js"></script>
<script> <script>
"use strict"; "use strict";
@@ -841,6 +845,7 @@
en: { en: {
pageTitle: "Jitsi Meeting", pageTitle: "Jitsi Meeting",
impressum: "Legal Notice", impressum: "Legal Notice",
source: "Source",
launcher: { launcher: {
title: "Jitsi Meeting", title: "Jitsi Meeting",
@@ -933,6 +938,7 @@
de: { de: {
pageTitle: "Jitsi Meeting öffnen", pageTitle: "Jitsi Meeting öffnen",
impressum: "Impressum", impressum: "Impressum",
source: "Quellcode",
launcher: { launcher: {
title: "Jitsi Meeting", title: "Jitsi Meeting",
@@ -1027,6 +1033,7 @@
fr: { fr: {
pageTitle: "Réunion Jitsi", pageTitle: "Réunion Jitsi",
impressum: "Mentions légales", impressum: "Mentions légales",
source: "Code source",
launcher: { launcher: {
title: "Réunion Jitsi", title: "Réunion Jitsi",
@@ -1120,6 +1127,7 @@
zh: { zh: {
pageTitle: "Jitsi 会议", pageTitle: "Jitsi 会议",
impressum: "法律声明", impressum: "法律声明",
source: "源代码",
launcher: { launcher: {
title: "Jitsi 会议", title: "Jitsi 会议",
@@ -1631,46 +1639,109 @@
); );
} }
/* ============================================================
* JITSI ANDROID URL
* ============================================================ */
/*
* Die Android-App registriert "org.jitsi.meet", nicht das
* Desktop-Schema. Chrome & Co. verlangen intent://, ohne App
* bietet Chrome den Play-Store-Eintrag aus "package=" an.
* Firefox ignoriert intent://, kennt aber das Custom-Schema.
*/
function createAndroidIntentUrl(room) {
return (
"intent://" +
CONFIG.jitsiHost +
"/" +
encodeURIComponent(room) +
"#Intent;scheme=org.jitsi.meet;package=org.jitsi.meet;end"
);
}
function createAndroidAppUrl(room) {
return (
"org.jitsi.meet://" +
CONFIG.jitsiHost +
"/" +
encodeURIComponent(room)
);
}
/* ============================================================
* URL NACH PLATTFORM/BROWSER
* ============================================================ */
function selectProtocolUrl(room) {
if (detectOperatingSystem() !== "android") {
return createAppUrl(room);
}
return detectBrowser() === "firefox"
? createAndroidAppUrl(room)
: createAndroidIntentUrl(room);
}
/* ============================================================ /* ============================================================
* DETECT OPERATING SYSTEM * DETECT OPERATING SYSTEM
* ============================================================ * ============================================================
*/ */
/*
* Einmal parsen (assets/ua-parser.min.js).
* Fällt die Bibliothek aus, bleibt die Seite bedienbar.
*/
const uaResult =
typeof UAParser === "function"
? new UAParser().getResult()
: { os: {}, browser: {} };
/*
* UAParser-Namen -> interne Kürzel.
* iPadOS meldet sich als macOS – Touchpunkte gelten als iOS.
*/
const OS_NAMES = {
Android: "android",
iOS: "ios",
Windows: "windows",
macOS: "macos",
Linux: "linux",
Ubuntu: "linux",
Debian: "linux",
Fedora: "linux",
Mint: "linux",
CentOS: "linux",
openSUSE: "linux",
Raspbian: "linux"
};
const BROWSER_NAMES = {
Edge: "edge",
"Mobile Edge": "edge",
Firefox: "firefox",
"Mobile Firefox": "firefox",
Chrome: "chrome",
"Mobile Chrome": "chrome",
"Chrome Headless": "chrome",
"Chrome WebView": "chrome",
"Samsung Internet": "chrome",
Safari: "safari",
"Mobile Safari": "safari"
};
function detectOperatingSystem() { function detectOperatingSystem() {
const ua = navigator.userAgent; /*
* iPadOS tarnt sich als macOS.
/* iPhone / iPad / iPod */ */
if ( if (
/iPhone|iPad|iPod/i.test(ua) || uaResult.os.name === "macOS" &&
( navigator.maxTouchPoints > 1
navigator.platform === "MacIntel" &&
navigator.maxTouchPoints > 1
)
) { ) {
return "ios"; return OS_NAMES.iOS;
} }
/* Android */ return OS_NAMES[uaResult.os.name] || "unknown";
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";
} }
/* ============================================================ /* ============================================================
@@ -1679,32 +1750,7 @@
*/ */
function detectBrowser() { function detectBrowser() {
const ua = navigator.userAgent; return BROWSER_NAMES[uaResult.browser.name] || "unknown";
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";
} }
/* ============================================================ /* ============================================================
@@ -1770,7 +1816,7 @@
return; return;
} }
const protocolUrl = createAppUrl(room); const protocolUrl = selectProtocolUrl(room);
const browserUrl = createBrowserUrl(room); const browserUrl = createBrowserUrl(room);
/* /*
@@ -2286,7 +2332,7 @@ END:VCALENDAR`;
room: room, room: room,
operatingSystem: detectOperatingSystem(), operatingSystem: detectOperatingSystem(),
browser: detectBrowser(), browser: detectBrowser(),
protocol: createAppUrl(room), protocol: selectProtocolUrl(room),
browserUrl: createBrowserUrl(room) browserUrl: createBrowserUrl(room)
} }
); );