123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385 |
- (function() {
- 'use strict';
- var initialized = false;
- var i18n;
- // i18n key prefix for MUC ("muc.") or 1:1 chat ("chat.")
- var key_prefix;
- var display_data = null;
- function get_platform() {
- var ua = navigator.userAgent;
- switch (true) {
- case (ua.indexOf("Windows") >= 0):
- return "windows";
- case (ua.indexOf("Android") >= 0):
- case (ua.indexOf("CrOS") >= 0):
- return "android";
- case (ua.indexOf("iPad") >= 0):
- case (ua.indexOf("iPhone") >= 0):
- return "ios";
- case (ua.indexOf("Mac OS X") >= 0):
- case (ua.indexOf("Macintosh") >= 0):
- return "macos";
- case (ua.indexOf("Linux") >= 0):
- return "linux";
- case (true):
- }
- return "web";
- }
- function get_client_link_element(client_id, client_info, platform) {
- let item = document.createElement("div");
- let link = document.createElement("a");
- let img = document.createElement("img");
- link.setAttribute("href", client_info[platform]);
- let logo_url = client_info.logo || ("assets/" + client_id + ".svg");
- img.setAttribute("src", logo_url);
- if(star_apps && star_apps.includes(client_id)) {
- let star_el = document.createElement("div");
- star_el.innerText = "\u2B50";
- star_el.classList.add("star");
- item.classList.add("starred");
- link.append(star_el);
- }
- link.append(img, client_info.title);
- item.append(link);
- item.classList.add("client-link");
- return item;
- }
- function show_clients(all_clients) {
- var list = document.getElementById('client_list');
- let platform = get_platform();
- let clients = [];
- console.log(all_clients);
- // Filter to clients suitable for our platform
- for (var id in all_clients) {
- if(hidden_apps.includes(id)) {
- // Configured to never show this app
- continue;
- }
- let client_info = all_clients[id];
- if(client_info[platform] || client_info.web) {
- clients.push(id);
- }
- }
- // Sort the clients
- clients.sort(function (a, b) {
- let a_info = all_clients[a];
- let b_info = all_clients[b];
- // Prefer native clients
- let a_is_native = !!a_info[platform];
- let b_is_native = !!b_info[platform];
- if(a_is_native && !b_is_native) {
- return -1;
- } else if(b_is_native && !a_is_native) {
- return 1;
- }
- // Prefer starred clients
- if(star_apps && star_apps.length > 0) {
- let a_is_starred = star_apps.includes(a);
- let b_is_starred = star_apps.includes(b);
- if(a_is_starred && !b_is_starred) {
- return -1;
- } else if(b_is_starred && !a_is_starred) {
- return 1;
- }
- }
- // Sort lexically by title
- if(a_info.title < b_info.title) {
- return -1;
- } else if(b_info.title < a_info.title) {
- return 1;
- }
- return 0;
- });
- // Empty any existing content from the list element
- list.replaceChildren();
- // Generate links and add them to the list element
- for(var id of clients) {
- let el = get_client_link_element(id, all_clients[id], platform);
- list.append(el);
- }
- }
- function load_clients() {
- var request = new XMLHttpRequest();
- request.open('GET', "clients.json");
- request.onreadystatechange = function () {
- if (request.readyState === 4) {
- if (request.status === 200 || (isLocalFileRequest(url) && request.responseText.length > 0)) {
- let loaded_clients = JSON.parse(request.responseText);
- if(custom_apps && custom_apps.length > 0) {
- for(let custom_app in custom_apps) {
- loaded_clients[custom_app] = custom_apps[custom_app];
- }
- }
- if(only_apps && only_apps.length > 0) {
- for(let id in loaded_clients) {
- if(!only_apps.includes(id)) {
- delete loaded_clients[id];
- }
- }
- }
- show_clients(loaded_clients);
- }
- }
- };
- request.send(null);
- }
- function load_hash() {
- key_prefix = "chat";
- var xmpp_uri = window.location.search || window.location.hash;
- xmpp_uri = decodeURIComponent(xmpp_uri.substring(xmpp_uri.indexOf('#') + 1, xmpp_uri.length));
- if (xmpp_uri.indexOf("xmpp:") === 0) {
- xmpp_uri = xmpp_uri.slice(5);
- }
- try {
- base_decoded = window.atob(xmpp_uri);
- if (base_decoded.search('@') >= 0)
- xmpp_uri = base_decoded;
- } catch (err) {
- // ignore error, JID wasn't base64 encoded
- }
- if (xmpp_uri.search("\\?join") >= 0) {
- key_prefix = "muc";
- } else if(xmpp_uri.search("\\?register") >= 0) {
- key_prefix = "register";
- }
- // TODO: proper error checking / display / Creation of invitations
- if (xmpp_uri.search("@") <= 0) return {xmpp_uri:xmpp_uri, xmpp_uri_encoded:xmpp_uri, name: xmpp_uri.split("?")[0]};
- var xmpp_params = {};
- var xmpp_uri_parts = xmpp_uri.split("?");
- if (xmpp_uri_parts.length > 1) {
- let parameter, parameters = xmpp_uri_parts[1].split(";")
- for (parameter of parameters) {
- let key_value = parameter.split("=")
- xmpp_params[key_value[0]] = key_value.length > 1 ? key_value[1] : "";
- }
- }
- const jid_parts = xmpp_uri_parts[0].split("@");
- const local_part = jid_parts[0];
- xmpp_params["name"] = local_part.charAt(0).toUpperCase() + local_part.slice(1);
- const domain_part = jid_parts[1];
- const jid_encoded = encodeURIComponent(local_part) + "@" + encodeURIComponent(domain_part)
- xmpp_uri_parts[0] = jid_encoded
- const xmpp_uri_encoded = xmpp_uri_parts.join("?")
- return {xmpp_uri: xmpp_uri, xmpp_uri_encoded: xmpp_uri_encoded, name: xmpp_params["name"]};
- }
- let fallbackLocale = "en";
- let requested_fallback_locale = false;
- function get_translated_string(key, data) {
- return new Promise(function (resolve, reject) {
- try {
- return resolve(i18n.text(key, data));
- } catch {
- if(i18n.hasLocale(fallbackLocale)) {
- return resolve(i18n.text(key, data, fallbackLocale));
- }
- i18n.once(I18nText.event.LOCALE_LOAD, function () {
- try {
- return resolve(i18n.text(key, data, fallbackLocale));
- } catch {
- return resolve("UNTRANSLATED[" + key + "]");
- }
- });
- if(!requested_fallback_locale) {
- i18n.loadLocale(fallbackLocale);
- requested_fallback_locale = true;
- }
- }
- });
- }
- function translate_ui() {
- // translation
- get_translated_string(key_prefix + '.title', display_data).then(function (text) {
- document.title = text;
- });
- let translatable_els = document.querySelectorAll("[data-i18n]");
- translatable_els.forEach(function (el) {
- let key = el.dataset.i18n;
- if(key.startsWith(".")) {
- key = key_prefix + key;
- }
- get_translated_string(key, display_data).then(function (text) {
- let target = el.dataset.i18nTarget || "innerText";
- if(target.startsWith("@")) {
- el.setAttribute(target.substr(1), text);
- } else {
- el[target] = text;
- }
- });
- });
- }
- function rehash() {
- let hash = window.location.search || window.location.hash;
- if(!hash || hash == "#") {
- // Input mode
- document.getElementById("display-uri").style.display = "none";
- document.getElementById("enter-uri").style.display = "block";
- initialize_uri_input();
- key_prefix = "create";
- } else {
- document.getElementById("display-uri").style.display = "block";
- document.getElementById("enter-uri").style.display = "none";
- display_data = load_hash();
- document.getElementById('button').href = "xmpp:" + display_data.xmpp_uri_encoded;
- document.getElementById('url_in').value = "xmpp:" + display_data.xmpp_uri;
- }
- translate_ui();
- }
- function createQR() {
- display_data = load_hash();
- new QRCode(document.getElementById("qrcode"), "xmpp:" + display_data.xmpp_uri_encoded);
- }
- function generate_link() {
- let input_el = document.getElementById("uri_input");
- let output_el = document.getElementById("generated-link");
- let is_muc_el = document.getElementById("is_muc");
- let input = input_el.value;
- var uri;
- if(!(input.indexOf("xmpp:") == 0)) {
- uri = "xmpp:" + input;
- if(is_muc_el.checked) {
- uri += "?join";
- }
- is_muc_el.disabled = false;
- } else {
- uri = decodeURIComponent(input);
- is_muc_el.disabled = true;
- is_muc_el.checked = uri.endsWith("?join");
- }
- let encoded_uri = uri.substr(5).split("@").map(encodeURIComponent).join("@");
- let link = document.location.origin + document.location.pathname + "#" + encoded_uri;
- output_el.href = link;
- output_el.innerText = link;
- }
- function copy_to_clipboard() {
- let link = document.getElementById("generated-link");
- let copy_result_el = document.getElementById("copy-result");
- Promise.resolve().then(function () {
- return navigator.clipboard.writeText(link.href);
- }).then(function () {
- get_translated_string('copy-success', {}).then(function (text) {
- copy_result_el.innerText = text;
- });
- }, function () {
- get_translated_string('copy-failure', {}).then(function (text) {
- copy_result_el.innerText = text;
- });
- }).finally(function () {
- copy_result_el.style.visibility = "visible";
- });
- }
- function initialize_uri_input() {
- document.getElementById("generate-link-btn").addEventListener("click", function () {
- generate_link();
- document.getElementById("display-link").style.display = "block";
- });
- document.getElementById("uri_input").addEventListener("input", generate_link);
- document.getElementById("uri_input").addEventListener("keyup", function(event) {
- event.preventDefault();
- if (event.keyCode === 13) {
- document.getElementById("generate-link-btn").click();
- }
- });
- document.getElementById("is_muc").addEventListener("change", generate_link);
- document.getElementById("copy-link").addEventListener("click", copy_to_clipboard);
- }
- function load_done() {
- if (initialized) return;
- initialized = true;
- // load i18n and perform translation
- i18n = new I18nText({path: 'lang'});
- i18n.once(I18nText.event.LOCALE_CHANGE, function (data) {
- rehash();
- });
- var preferredLocale, setLocale = false;
- for (preferredLocale of navigator.languages) {
- if (supportedLocales.includes(preferredLocale)) {
- i18n.setLocale(preferredLocale);
- setLocale = true;
- break;
- }
- }
- if (!setLocale) {
- i18n.setLocale(defaultLocale);
- }
- var rtlLangs = "ar, fa, he, ur"
- if (rtlLangs.includes(navigator.language)) {
- document.querySelector("body").dir = "rtl";
- }
- // functionality
- var ua = navigator.userAgent;
- load_clients();
- window.addEventListener("hashchange", rehash, false);
- document.getElementById("url_in").addEventListener("focus", function(event) {
- event.target.select();
- });
- }
- // Wait for the DOM to be ready
- document.addEventListener('DOMContentLoaded', load_done, false);
- document.onreadystatechange = function() {
- if (document.readyState === 'interactive') {
- load_done();
- }
- };
- var logo = document.createElement('img');
- logo.src = 'assets/xmpp.svg';
- logo.alt= 'XMPP logo';
- logo.width = 60;
- var link = document.createElement('a');
- link.href = 'https://xmpp.org/';
- link.append(logo)
- var brand = document.getElementById('xmpp');
- brand.append(link)
- })();
|