diff options
-rw-r--r-- | assets/js/lang/bundle.js | 2 | ||||
-rw-r--r-- | assets/js/lib/themes.js | 32 | ||||
-rw-r--r-- | assets/js/messaging.js | 1020 | ||||
-rw-r--r-- | assets/pages-src/messaging.bvr | 144 | ||||
-rw-r--r-- | assets/pages-src/settings.bvr | 113 | ||||
-rwxr-xr-x | dist/js/app.js | 2 | ||||
-rw-r--r-- | dist/js/lang/bundle.js | 2 | ||||
-rw-r--r-- | dist/js/lib/themes.js | 32 | ||||
-rw-r--r-- | dist/js/messaging.js | 1020 | ||||
-rwxr-xr-x | dist/pages/about.html | 2 | ||||
-rwxr-xr-x | dist/pages/messaging.html | 162 | ||||
-rwxr-xr-x | dist/pages/settings.html | 123 | ||||
-rwxr-xr-x | dist/sw.js | 4 |
13 files changed, 1360 insertions, 1298 deletions
diff --git a/assets/js/lang/bundle.js b/assets/js/lang/bundle.js index 9f0497b..75fae14 100644 --- a/assets/js/lang/bundle.js +++ b/assets/js/lang/bundle.js @@ -290,6 +290,7 @@ var langstrings = { theme: "theme", themeLight: "light theme (default)", themeDark: "dark theme", + themeNight: "night theme", selectTheme: "select a theme", themeSet: "theme set, open another page for the changes to take effect", errorReportingSet: "error reporting preference set", @@ -486,6 +487,7 @@ var langstrings = { theme: "izgled", themeLight: "svetel izgled (privzeto)", themeDark: "temen izgled", + themeNight: "nočni izgled", themeSet: "izgled nastavljen, odprite neko drugo stran da se spremembe uveljavijo", selectTheme: "izberite željen izgled", errorReportingSet: "nastavitev pošiljanja napak izbrana", diff --git a/assets/js/lib/themes.js b/assets/js/lib/themes.js index 14ef436..75dedfd 100644 --- a/assets/js/lib/themes.js +++ b/assets/js/lib/themes.js @@ -25,7 +25,7 @@ const THEME_COLOR_SCHEMES = { "color-divider": "rgba(224, 224, 224, 1)", "color-btn-flat": "rgba(52, 52, 52, 1)", - "color-btn-flat-disabled": "rgba(178, 178, 178, 1)", + "color-btn-flat-disabled": "rgba(178, 178, 178, 1)" }, dark: { @@ -54,7 +54,35 @@ const THEME_COLOR_SCHEMES = { "color-divider": "rgba(80, 80, 80, 1)", "color-btn-flat": "rgba(178, 178, 178, 1)", - "color-btn-flat-disabled": "rgba(52, 52, 52, 1)", + "color-btn-flat-disabled": "rgba(52, 52, 52, 1)" + }, + black: { + "color-primary": "rgba(0, 79, 51, 1)", + "color-secondary": "rgba(0, 94, 61, 1)", + "color-accent": "rgba(28, 107, 79, 1)", + "color-primary-light": "rgba(0, 77, 2, 1)", // it's not really light anymore, is it? + "color-invalid": "rgba(138, 0, 0, 1)", + "color-primary-transparent": "rgba(0, 79, 51, 0.3)", + + "background-color": "rgba(0, 0, 0, 1)", + "background-accent": "rgba(0, 38, 18, 0.2)", + "background-accent-1": "rgb(20, 33, 25, 1)", + + "color-header-bold": "rgba(255, 255, 255, 1)", + "color-header-span": "rgba(255, 255, 255, 1)", + + "color-text": "rgba(189, 189, 189, 1)", + "color-text-light": "rgba(160, 160, 160, 1)", + "color-label-text": "rgba(158, 158, 158, 1)", + "color-table-hover": "rgba(43, 43, 43, 0.5)", + + "color-sidenav-background": "rgba(0, 0, 0, 1)", + "color-sidenav-text": "rgba(189, 189, 189, 1)", + "color-sidenav-header": "rgba(189, 189, 189, 0.54)", + "color-divider": "rgba(50, 50, 50, 1)", + + "color-btn-flat": "rgba(178, 178, 178, 1)", + "color-btn-flat-disabled": "rgba(52, 52, 52, 1)" } } diff --git a/assets/js/messaging.js b/assets/js/messaging.js index dba57ef..305b355 100644 --- a/assets/js/messaging.js +++ b/assets/js/messaging.js @@ -6,34 +6,34 @@ const ENCRYPTED_MESSAGE_REGEX = /<!-- ba-e2eemsg-(\d{4}) -->(\S+?)<!-- end-msg - // "Global" object for name directory and messages var directory = null; var messages = { - "0": [], - "1": [], - "2": [] + "0": [], + "1": [], + "2": [] } var current_tab = 0; async function checkLogin() { - localforage.getItem("logged_in").then(function (value) { - // This code runs once the value has been loaded - // from the offline store. - if (value !== true) { - window.location.replace("/index.html"); - } - }).catch(function (err) { - // This code runs if there were any errors - console.log(err); - }); + localforage.getItem("logged_in").then(function (value) { + // This code runs once the value has been loaded + // from the offline store. + if (value !== true) { + window.location.replace("/index.html"); + } + }).catch(function (err) { + // This code runs if there were any errors + console.log(err); + }); } // -----------HTML HELPERS----------- function htmlEncode(value) { - // Create a in-memory element, set its inner text (which is automatically encoded) - // Then grab the encoded contents back out. The element never exists on the DOM. - return $("<textarea/>").text(value).html(); + // Create a in-memory element, set its inner text (which is automatically encoded) + // Then grab the encoded contents back out. The element never exists on the DOM. + return $("<textarea/>").text(value).html(); } function htmlDecode(value) { - return $("<textarea/>").html(value).text(); + return $("<textarea/>").html(value).text(); } // --------------------------------- @@ -97,302 +97,302 @@ async function loadDirectory() { } function populateAutocomplete() { - let elems = document.querySelectorAll(".autocomplete-fullname"); - // če se uporablja globalna var directory, ki je shranjena kot objekt (vedno shranjen kot reference), bo pri let x=y x le pointer na object y - // in se bo spremenil z spremembo "originala". spodnja stvar itak ni preveč efficent, loop čez vseh 7000 ljudi bi lahko delal težave... - // kakšen Object.keys bi bila boljša varianta ampak raje napišem tale komentar... idk, to se mi je zdelo uporabno ampak sedaj obžalujem - // samo guglal sem "copying an object js" - let autocomplete_entries = Object.assign({}, directory); - for (let variableKey in autocomplete_entries) { - autocomplete_entries[variableKey] = null; - } - - M.Autocomplete.init(elems, { - data: autocomplete_entries, - onAutocomplete: validateName, - minLength: 0 - }); - - $(document).ready(function () { - if (window.location.hash.length > 1 && !window.location.hash.substring(1).startsWith("beziapp")) { - var hashValue = decodeURIComponent(window.location.hash.substring(1)); - $("#full-name").val(hashValue); - if (hashValue in directory) { - $("#msg-send").removeAttr("disabled"); - } - $("#beziapp-new-message").modal(); - $("#beziapp-new-message").modal("open"); - } - }); - - M.updateTextFields(); - validateName(); + let elems = document.querySelectorAll(".autocomplete-fullname"); + // če se uporablja globalna var directory, ki je shranjena kot objekt (vedno shranjen kot reference), bo pri let x=y x le pointer na object y + // in se bo spremenil z spremembo "originala". spodnja stvar itak ni preveč efficent, loop čez vseh 7000 ljudi bi lahko delal težave... + // kakšen Object.keys bi bila boljša varianta ampak raje napišem tale komentar... idk, to se mi je zdelo uporabno ampak sedaj obžalujem + // samo guglal sem "copying an object js" + let autocomplete_entries = Object.assign({}, directory); + for (let variableKey in autocomplete_entries) { + autocomplete_entries[variableKey] = null; + } + + M.Autocomplete.init(elems, { + data: autocomplete_entries, + onAutocomplete: validateName, + minLength: 0 + }); + + $(document).ready(function () { + if (window.location.hash.length > 1 && !window.location.hash.substring(1).startsWith("beziapp")) { + var hashValue = decodeURIComponent(window.location.hash.substring(1)); + $("#full-name").val(hashValue); + if (hashValue in directory) { + $("#msg-send").removeAttr("disabled"); + } + $("#beziapp-new-message").modal(); + $("#beziapp-new-message").modal("open"); + } + }); + + M.updateTextFields(); + validateName(); } // Function to toggle loading bar function setLoading(state) { - if (state) { - $("#loading-bar").removeClass("hidden"); - } else { - $("#loading-bar").addClass("hidden"); - } + if (state) { + $("#loading-bar").removeClass("hidden"); + } else { + $("#loading-bar").addClass("hidden"); + } } // Function, responsible for fetching and displaying data async function loadMessages(force_refresh = true, messageType = 0) { - setLoading(true); - // Load required data - let promises_to_run = [ - localforage.getItem("username").then((value) => { - username = value; - }), - localforage.getItem("password").then((value) => { - password = value; - }), - localforage.getItem("messages").then((value) => { - messages = value; - }) - ]; - - Promise.all(promises_to_run).then(() => { - - if (messages[messageType] == null || messages[messageType].length === 0 || force_refresh) { - $.ajax({ - url: API_ENDPOINT, - crossDomain: true, - data: { - "u": username, - "p": password, - "m": "fetchsporocilaseznam", - "a": messageType // Message type, see API doc for details - }, - dataType: "json", - cache: false, - type: "GET", - - success: (data) => { - // If data is null, the request failed - if (data === null) { - UIAlert( D("requestFailed") ); - setLoading(false); - } else { - // Save messages & populate view - // console.log(data); // debug - messages[messageType.toString()] = data; - localforage.setItem("messages", messages).then((value) => { - displayData(messageType); - setLoading(false); - }); - } - }, - - error: () => { - UIAlert( D("errorFetchingMessages") ); - setLoading(false); - } - }) - } else { - displayData(messageType); - setLoading(false); - } - }); + setLoading(true); + // Load required data + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), + localforage.getItem("password").then((value) => { + password = value; + }), + localforage.getItem("messages").then((value) => { + messages = value; + }) + ]; + + Promise.all(promises_to_run).then(() => { + + if (messages[messageType] == null || messages[messageType].length === 0 || force_refresh) { + $.ajax({ + url: API_ENDPOINT, + crossDomain: true, + data: { + "u": username, + "p": password, + "m": "fetchsporocilaseznam", + "a": messageType // Message type, see API doc for details + }, + dataType: "json", + cache: false, + type: "GET", + + success: (data) => { + // If data is null, the request failed + if (data === null) { + UIAlert( D("requestFailed") ); + setLoading(false); + } else { + // Save messages & populate view + // console.log(data); // debug + messages[messageType.toString()] = data; + localforage.setItem("messages", messages).then((value) => { + displayData(messageType); + setLoading(false); + }); + } + }, + + error: () => { + UIAlert( D("errorFetchingMessages") ); + setLoading(false); + } + }) + } else { + displayData(messageType); + setLoading(false); + } + }); } async function loadMsg(id) { - setLoading(true); - // Load required data - let promises_to_run = [ - localforage.getItem("username").then((value) => { - username = value; - }), - localforage.getItem("password").then((value) => { - password = value; - }), - ]; - - Promise.all(promises_to_run).then(() => { - $.ajax({ - url: API_ENDPOINT, - crossDomain: true, - data: { - "u": username, - "p": password, - "m": "fetchsporocilo", - "a": id.replace(/_/g, "|") - }, - dataType: "json", - cache: false, - type: "GET", - success: (data) => { - // If data is null, the request failed - if (data === null) { - UIAlert( `${D("unableToReceiveTheMessage")} ${D("requestFailed")}` ); - } else { - displayMessage(id, data); - } - setLoading(false); - }, - - error: () => { - UIAlert( `${D("unableToReceiveTheMessage")} ${D("noInternetConnection")}` ); - setLoading(false); - } - - }) - }); + setLoading(true); + // Load required data + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), + localforage.getItem("password").then((value) => { + password = value; + }), + ]; + + Promise.all(promises_to_run).then(() => { + $.ajax({ + url: API_ENDPOINT, + crossDomain: true, + data: { + "u": username, + "p": password, + "m": "fetchsporocilo", + "a": id.replace(/_/g, "|") + }, + dataType: "json", + cache: false, + type: "GET", + success: (data) => { + // If data is null, the request failed + if (data === null) { + UIAlert( `${D("unableToReceiveTheMessage")} ${D("requestFailed")}` ); + } else { + displayMessage(id, data); + } + setLoading(false); + }, + + error: () => { + UIAlert( `${D("unableToReceiveTheMessage")} ${D("noInternetConnection")}` ); + setLoading(false); + } + + }) + }); } async function deleteMsg(id) { - setLoading(true); - // Load required data - let promises_to_run = [ - localforage.getItem("username").then((value) => { - username = value; - }), localforage.getItem("password").then((value) => { - password = value; - }), - ]; - Promise.all(promises_to_run).then(() => { - $.ajax({ - url: API_ENDPOINT, - crossDomain: true, - data: { - "u": username, - "p": password, - "m": "izbrisisporocilo", - "a": id - }, - dataType: "json", - cache: false, - type: "GET", - success: (data) => { - // If data is null, the request failed - if (data === null) { - UIAlert( `${D("unableToDeleteTheMessage")} ${D("requestFailed")}` ); - } else { - document.getElementById("msg_box-" + id).remove(); - } - setLoading(false); - }, - - error: () => { - UIAlert( `${D("unableToDeleteTheMessage")} ${D("noInternetConnection")}` ); - setLoading(false); - } - - }) - }); + setLoading(true); + // Load required data + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), localforage.getItem("password").then((value) => { + password = value; + }), + ]; + Promise.all(promises_to_run).then(() => { + $.ajax({ + url: API_ENDPOINT, + crossDomain: true, + data: { + "u": username, + "p": password, + "m": "izbrisisporocilo", + "a": id + }, + dataType: "json", + cache: false, + type: "GET", + success: (data) => { + // If data is null, the request failed + if (data === null) { + UIAlert( `${D("unableToDeleteTheMessage")} ${D("requestFailed")}` ); + } else { + document.getElementById("msg_box-" + id).remove(); + } + setLoading(false); + }, + + error: () => { + UIAlert( `${D("unableToDeleteTheMessage")} ${D("noInternetConnection")}` ); + setLoading(false); + } + + }) + }); } function displayMessage(id, data) { - let regex_results = ENCRYPTED_MESSAGE_REGEX.exec(data["telo"]); - if (regex_results != null) { - var datatodecrypt = regex_results[2]; - var randomencdivid = Math.floor(Math.random() * 9999).toString().padStart(4, "0"); - - var msgcontent = ` - <div id='ba-msg-e2ee-form-${randomencdivid}'> - ${D("thisMessageWasEncrypted")} - <input type="password" autocomplete="new-password" id="ba-msg-e2ee-password-${randomencdivid}" placeholder="${S("password")} ..."> - <button - type="button" - value="Decrypt" - class="btn waves-effect waves-light" - onclick=" - try { - $('#ba-msg-e2ee-content-${randomencdivid}').html( - filterXSS( - sjcl.decrypt( - $('#ba-msg-e2ee-password-${randomencdivid}').val(), - $('#ba-msg-e2ee-content-${randomencdivid}').html() - ) - ) - ); - $('#ba-msg-e2ee-content-${randomencdivid}').show(); - $('#ba-msg-e2ee-form-${randomencdivid}').hide(); - } catch (err) { - alert('${D("incorrectPassword")}'); - } - " - > - ${S("decrypt")} - </button> - </div> - <div id="ba-msg-e2ee-content-${randomencdivid}" hidden> - ${datatodecrypt} - </div> - ` - $(`#msg_body-${id.replace(/\|/g, "_")}`).html(msgcontent); - } else { - $(`#msg_body-${id.replace(/\|/g, "_")}`).html(filterXSS(data["telo"])); - } + let regex_results = ENCRYPTED_MESSAGE_REGEX.exec(data["telo"]); + if (regex_results != null) { + var datatodecrypt = regex_results[2]; + var randomencdivid = Math.floor(Math.random() * 9999).toString().padStart(4, "0"); + + var msgcontent = ` + <div id='ba-msg-e2ee-form-${randomencdivid}'> + ${D("thisMessageWasEncrypted")} + <input type="password" autocomplete="new-password" id="ba-msg-e2ee-password-${randomencdivid}" placeholder="${S("password")} ..."> + <button + type="button" + value="Decrypt" + class="btn waves-effect waves-light" + onclick=" + try { + $('#ba-msg-e2ee-content-${randomencdivid}').html( + filterXSS( + sjcl.decrypt( + $('#ba-msg-e2ee-password-${randomencdivid}').val(), + $('#ba-msg-e2ee-content-${randomencdivid}').html() + ) + ) + ); + $('#ba-msg-e2ee-content-${randomencdivid}').show(); + $('#ba-msg-e2ee-form-${randomencdivid}').hide(); + } catch (err) { + alert('${D("incorrectPassword")}'); + } + " + > + ${S("decrypt")} + </button> + </div> + <div id="ba-msg-e2ee-content-${randomencdivid}" hidden> + ${datatodecrypt} + </div> + ` + $(`#msg_body-${id.replace(/\|/g, "_")}`).html(msgcontent); + } else { + $(`#msg_body-${id.replace(/\|/g, "_")}`).html(filterXSS(data["telo"])); + } } // Function for displaying data function displayData(messageType) { - let div_selector = ""; - switch (messageType) { - case 0: - div_selector = "#beziapp-received"; - break; - case 1: - div_selector = "#beziapp-sent"; - break; - case 2: - div_selector = "#beziapp-deleted"; - break; - } - - // $("#storage-bar").show(); - $("#storage-progressbar").width(Number(Number(getNumMessages(messageType) / 120) * 100).toFixed(2) + "%"); - $("#storage-stats").text(`${getNumMessages(messageType)}/120`); - - let msg_list = $(div_selector); - msg_list.html(""); - messages[messageType.toString()].forEach(element => { - if (!element["zadeva"].startsWith("ba-ctlmsg")) { - - msg_list.append(` - <div class="col s12 m12" id="msg_box-${filterXSS(element["id"])}"> - <div class="card blue-grey darken-1"> - <div class="card-content white-text"> - <span class="card-title"> - ${filterXSS(element["zadeva"])} - </span> - <p id="msg_body-${filterXSS(element["id"]).replace(/\|/g, "_")}"> - <button - class="btn waves-effect waves-light" - onclick="loadMsg('${filterXSS(element["id"])}')" - type="submit" - > - Load message - <i class="material-icons right">move_to_inbox</i> - </button> - <p> - </div> - <div class="card-action general-text"> - <a onclick="deleteMsg('${filterXSS(element["id"])}')"> - <i class="material-icons">delete</i> - </a> - <a onclick=" - $('#full-name').val('${filterXSS(element["posiljatelj"])}'); - $('#msg-subject').val('Re: ${filterXSS(element["zadeva"])}'); - M.updateTextFields(); - " - data-target="beziapp-new-message" - class="modal-trigger" - > - <i class="material-icons">reply</i> - </a> - ${filterXSS(element["posiljatelj"])} » ${filterXSS(element["datum"]["dan"])}. ${filterXSS(element["datum"]["mesec"])}. ${filterXSS(element["datum"]["leto"])} at ${filterXSS(element["cas"]["ura"]).padStart(2, "0")}:${filterXSS(element["cas"]["minuta"]).padStart(2, "0")} - </div> - </div> - </div> - `); - } - }); + let div_selector = ""; + switch (messageType) { + case 0: + div_selector = "#beziapp-received"; + break; + case 1: + div_selector = "#beziapp-sent"; + break; + case 2: + div_selector = "#beziapp-deleted"; + break; + } + + // $("#storage-bar").show(); + $("#storage-progressbar").width(Number(Number(getNumMessages(messageType) / 120) * 100).toFixed(2) + "%"); + $("#storage-stats").text(`${getNumMessages(messageType)}/120`); + + let msg_list = $(div_selector); + msg_list.html(""); + messages[messageType.toString()].forEach(element => { + if (!element["zadeva"].startsWith("ba-ctlmsg")) { + + msg_list.append(` + <div class="col s12 m12" id="msg_box-${filterXSS(element["id"])}"> + <div class="card blue-grey darken-1"> + <div class="card-content white-text"> + <span class="card-title"> + ${filterXSS(element["zadeva"])} + </span> + <p id="msg_body-${filterXSS(element["id"]).replace(/\|/g, "_")}"> + <button + class="btn waves-effect waves-light" + onclick="loadMsg('${filterXSS(element["id"])}')" + type="submit" + > + Load message + <i class="material-icons right">move_to_inbox</i> + </button> + <p> + </div> + <div class="card-action general-text"> + <a onclick="deleteMsg('${filterXSS(element["id"])}')"> + <i class="material-icons">delete</i> + </a> + <a onclick=" + $('#full-name').val('${filterXSS(element["posiljatelj"])}'); + $('#msg-subject').val('Re: ${filterXSS(element["zadeva"])}'); + M.updateTextFields(); + " + data-target="beziapp-new-message" + class="modal-trigger" + > + <i class="material-icons">reply</i> + </a> + ${filterXSS(element["posiljatelj"])} » ${filterXSS(element["datum"]["dan"])}. ${filterXSS(element["datum"]["mesec"])}. ${filterXSS(element["datum"]["leto"])} at ${filterXSS(element["cas"]["ura"]).padStart(2, "0")}:${filterXSS(element["cas"]["minuta"]).padStart(2, "0")} + </div> + </div> + </div> + `); + } + }); } // -1 = cumulative @@ -412,239 +412,239 @@ function getNumMessages(messageType = -1) { } async function sendMessage(recipient_number, subject, body) { - setLoading(true); - let promises_to_run = [ - localforage.getItem("username").then((value) => { - username = value; - }), - localforage.getItem("password").then((value) => { - password = value; - }), - ]; - Promise.all(promises_to_run).then(() => { - $.ajax({ - url: API_ENDPOINT, - crossDomain: true, - data: { - "u": username, - "p": password, - "m": "posljisporocilo", - "a": recipient_number, - "b": subject, - "c": body - }, - - dataType: "json", - cache: false, - - type: "POST", - success: () => { - // we CAN'T know wether the message was delievered - UIAlert(D("messageWasProbablySent")); - setLoading(false); - }, - error: () => { - UIAlert(D("errorSendingMessage"), D("noInternetConnection")); - setLoading(false); - } - }) - }); + setLoading(true); + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), + localforage.getItem("password").then((value) => { + password = value; + }), + ]; + Promise.all(promises_to_run).then(() => { + $.ajax({ + url: API_ENDPOINT, + crossDomain: true, + data: { + "u": username, + "p": password, + "m": "posljisporocilo", + "a": recipient_number, + "b": subject, + "c": body + }, + + dataType: "json", + cache: false, + + type: "POST", + success: () => { + // we CAN'T know wether the message was delievered + UIAlert(D("messageWasProbablySent")); + setLoading(false); + }, + error: () => { + UIAlert(D("errorSendingMessage"), D("noInternetConnection")); + setLoading(false); + } + }) + }); } async function validateName() { - if (directory !== null) { - if ($("#full-name").val() in directory) { - $("#full-name").addClass("valid"); - $("#full-name").removeClass("invalid"); - $("#msg-send").removeAttr("disabled"); - } else { - $("#full-name").addClass("invalid"); - $("#full-name").removeClass("valid"); - $("#msg-send").attr("disabled", "disabled"); - } - } + if (directory !== null) { + if ($("#full-name").val() in directory) { + $("#full-name").addClass("valid"); + $("#full-name").removeClass("invalid"); + $("#msg-send").removeAttr("disabled"); + } else { + $("#full-name").addClass("invalid"); + $("#full-name").removeClass("valid"); + $("#msg-send").attr("disabled", "disabled"); + } + } } // Setup event listeners for buttons function setupEventListeners() { - // Button to add a photo - $("#msg-add-photo").click(() => { - let input = document.createElement("input"); - input.type = "file"; - input.onchange = (e) => { - // getting a hold of the file reference - let file = e.target.files[0]; - // setting up the reader - let reader = new FileReader(); - reader.readAsDataURL(file); // this is reading as data url - - // here we tell the reader what to do when it's done reading... - reader.onload = readerEvent => { - additionalstufftoaddtomessage += `<br><img src="${readerEvent.target.result}" />`; // this is the content! - if ($("#msg-added-image").html().length > 1) { - $("#msg-added-image").append(`<img style="width: 20mm" src="${readerEvent.target.result}" />`); - } else { - $("#msg-added-image").html(` - <input - type="button" - value="${S("removeImages")}" - class="btn waves-effect waves-light" - onclick=" - additionalstufftoaddtomessage = ''; - $('#msg-added-image').html(''); - " - /> - <br> - ${D("largeImagesNote")} - <br> - ${S("attachedImages")}: - <br> - <img style="width:20mm" src="${readerEvent.target.result}" /> - `); - // ravno obratni narekovaji - } - UIAlert(D("imageAddedAsAnAttachment")); - } - } - input.click(); - }); - - // Verify recipient when input loses focus - $("#full-name").on("blur", validateName); - - // Setup refresh icon - $("#refresh-icon").click(() => { - loadMessages(true, current_tab); - }); - - // Setup checkbox handler - $("#encrypt-checkbox").change(function() { - if (this.checked) { - $("#encryption-key-input").prop("hidden", false); - } else { - $("#encryption-key-input").prop("hidden", true); - } - }); - - // Button to send message - $("#msg-send").click(() => { - localforage.getItem("directory").then(function (value) { - var msgcontent = $("#msg-body").val() + additionalstufftoaddtomessage; - var msgsubject = $("#msg-subject").val(); - if ($("#encryption-key-input").prop("hidden") !== true) { - var randomencdivid = Math.floor(Math.random() * 9999).toString().padStart(4, "0"); - var addrparts = window.location.href.split("/"); // engleski - - var encrypted_message = sjcl.encrypt($("#msg-e2ee-pass-input").val(), msgcontent); - msgcontent = ` - <script src="${addrparts[0]}//${addrparts[2]}/js/lib/sjcl.js"></script> - <div id="ba-msg-e2ee-form-${randomencdivid}"> - This message was encrypted by BežiApp. - <input type="password" autocomplete="new-password" id="ba-msg-e2ee-password-${randomencdivid}" placeholder="Enter password ..."> - <input type="button" value="Decrypt" onclick=" - try { - console.log($('ba-msg-e2ee-content-${randomencdivid}').text()); - $('#ba-msg-e2ee-content-${randomencdivid}').html( - sjcl.decrypt( - $('#ba-msg-e2ee-password-${randomencdivid}').val(), - $('#ba-msg-e2ee-content-${randomencdivid}').text() - ) - ); - $('#ba-msg-e2ee-content-${randomencdivid}').show(); - $('#ba-msg-e2ee-form-${randomencdivid}').hide(); - } catch(err) { - alert('${D("incorrectPassword")}'); - } - "> - </div> - <div id="ba-msg-e2ee-content-${randomencdivid}" hidden> - <!-- ba-e2eemsg-${msgcontent.length.toString().padStart(4, "0")} -->${encrypted_message}<!-- end-msg --> - </div> - ` - } - - console.log(msgcontent); - console.log(encrypted_message); - - sendMessage(value[$("#full-name").val()], msgsubject, htmlEncode(msgcontent)); - $("#msg-body").val(""); - $("#full-name").val(""); - $("#msg-subject").val(""); - // $("#msg-send").prop("disabled", true); - $("#msg-send").attr("disabled", "disabled"); - additionalstufftoaddtomessage = ""; - - $("#msg-added-image").html(""); - $("#msg-e2ee-pass").hide(); - - }).catch(function (err) { - UIAlert( `${D("unableToReadDirectory")} ${D("messageCouldNotBeSend")}`, "45245" ); - console.log(err); - }); - }); + // Button to add a photo + $("#msg-add-photo").click(() => { + let input = document.createElement("input"); + input.type = "file"; + input.onchange = (e) => { + // getting a hold of the file reference + let file = e.target.files[0]; + // setting up the reader + let reader = new FileReader(); + reader.readAsDataURL(file); // this is reading as data url + + // here we tell the reader what to do when it's done reading... + reader.onload = readerEvent => { + additionalstufftoaddtomessage += `<br><img src="${readerEvent.target.result}" />`; // this is the content! + if ($("#msg-added-image").html().length > 1) { + $("#msg-added-image").append(`<img style="width: 20mm" src="${readerEvent.target.result}" />`); + } else { + $("#msg-added-image").html(` + <input + type="button" + value="${S("removeImages")}" + class="btn waves-effect waves-light" + onclick=" + additionalstufftoaddtomessage = ''; + $('#msg-added-image').html(''); + " + /> + <br> + ${D("largeImagesNote")} + <br> + ${S("attachedImages")}: + <br> + <img style="width:20mm" src="${readerEvent.target.result}" /> + `); + // ravno obratni narekovaji + } + UIAlert(D("imageAddedAsAnAttachment")); + } + } + input.click(); + }); + + // Verify recipient when input loses focus + $("#full-name").on("blur", validateName); + + // Setup refresh icon + $("#refresh-icon").click(() => { + loadMessages(true, current_tab); + }); + + // Setup checkbox handler + $("#encrypt-checkbox").change(function() { + if (this.checked) { + $("#encryption-key-input").prop("hidden", false); + } else { + $("#encryption-key-input").prop("hidden", true); + } + }); + + // Button to send message + $("#msg-send").click(() => { + localforage.getItem("directory").then(function (value) { + var msgcontent = $("#msg-body").val() + additionalstufftoaddtomessage; + var msgsubject = $("#msg-subject").val(); + if ($("#encryption-key-input").prop("hidden") !== true) { + var randomencdivid = Math.floor(Math.random() * 9999).toString().padStart(4, "0"); + var addrparts = window.location.href.split("/"); // engleski + + var encrypted_message = sjcl.encrypt($("#msg-e2ee-pass-input").val(), msgcontent); + msgcontent = ` + <script src="${addrparts[0]}//${addrparts[2]}/js/lib/sjcl.js"></script> + <div id="ba-msg-e2ee-form-${randomencdivid}"> + This message was encrypted by BežiApp. + <input type="password" autocomplete="new-password" id="ba-msg-e2ee-password-${randomencdivid}" placeholder="Enter password ..."> + <input type="button" value="Decrypt" onclick=" + try { + console.log($('ba-msg-e2ee-content-${randomencdivid}').text()); + $('#ba-msg-e2ee-content-${randomencdivid}').html( + sjcl.decrypt( + $('#ba-msg-e2ee-password-${randomencdivid}').val(), + $('#ba-msg-e2ee-content-${randomencdivid}').text() + ) + ); + $('#ba-msg-e2ee-content-${randomencdivid}').show(); + $('#ba-msg-e2ee-form-${randomencdivid}').hide(); + } catch(err) { + alert('${D("incorrectPassword")}'); + } + "> + </div> + <div id="ba-msg-e2ee-content-${randomencdivid}" hidden> + <!-- ba-e2eemsg-${msgcontent.length.toString().padStart(4, "0")} -->${encrypted_message}<!-- end-msg --> + </div> + ` + } + + console.log(msgcontent); + console.log(encrypted_message); + + sendMessage(value[$("#full-name").val()], msgsubject, htmlEncode(msgcontent)); + $("#msg-body").val(""); + $("#full-name").val(""); + $("#msg-subject").val(""); + // $("#msg-send").prop("disabled", true); + $("#msg-send").attr("disabled", "disabled"); + additionalstufftoaddtomessage = ""; + + $("#msg-added-image").html(""); + $("#msg-e2ee-pass").hide(); + + }).catch(function (err) { + UIAlert( `${D("unableToReadDirectory")} ${D("messageCouldNotBeSend")}`, "45245" ); + console.log(err); + }); + }); } function getUrlParameter(sParam) { - const url_params = new URLSearchParams(window.location.search); - const found_param = url_params.get(sParam); - return found_param + const url_params = new URLSearchParams(window.location.search); + const found_param = url_params.get(sParam); + return found_param } var additionalstufftoaddtomessage = ""; document.addEventListener("DOMContentLoaded", () => { - checkLogin(); - - // Setup modals - const modal_elems = document.querySelectorAll('.modal'); - const modal_options = { - onOpenStart: () => { $("#fab-new").hide() }, - onCloseEnd: () => { $("#fab-new").show() }, - dismissible: false - }; - M.Modal.init(modal_elems, modal_options); - - loadDirectory(); - setupEventListeners(); - - // Setup tabs - const tabs = document.querySelectorAll(".tabs"); - const tab_options = { - // swipeable: true, // TODO: figure out how to fix height when it's enabled (it's good for UX to have it enabled) - onShow: (tab) => { - if ($(tab).hasClass("active")) { - switch (tab.id) { - case "beziapp-received": - current_tab = 0; - loadMessages(false, 0); - break; - case "beziapp-sent": - current_tab = 1; - loadMessages(false, 1); - break; - case "beziapp-deleted": - current_tab = 2; - loadMessages(false, 2); - break; - } - } - } - }; - M.Tabs.init(tabs, tab_options); - - // Setup floating action button - const fab_options = { - hoverEnabled: false, - toolbarEnabled: false - } - const fab_elem = document.querySelectorAll(".fixed-action-btn"); - M.FloatingActionButton.init(fab_elem, fab_options); - - var receivedmessages = null; - loadMessages(true, 0); - M.updateTextFields(); - - // Setup side menu - const menus = document.querySelectorAll(".side-menu"); - M.Sidenav.init(menus, { edge: "right", draggable: true }); + checkLogin(); + + // Setup modals + const modal_elems = document.querySelectorAll('.modal'); + const modal_options = { + onOpenStart: () => { $("#fab-new").hide() }, + onCloseEnd: () => { $("#fab-new").show() }, + dismissible: false + }; + M.Modal.init(modal_elems, modal_options); + + loadDirectory(); + setupEventListeners(); + + // Setup tabs + const tabs = document.querySelectorAll(".tabs"); + const tab_options = { + // swipeable: true, // TODO: figure out how to fix height when it's enabled (it's good for UX to have it enabled) + onShow: (tab) => { + if ($(tab).hasClass("active")) { + switch (tab.id) { + case "beziapp-received": + current_tab = 0; + loadMessages(false, 0); + break; + case "beziapp-sent": + current_tab = 1; + loadMessages(false, 1); + break; + case "beziapp-deleted": + current_tab = 2; + loadMessages(false, 2); + break; + } + } + } + }; + M.Tabs.init(tabs, tab_options); + + // Setup floating action button + const fab_options = { + hoverEnabled: false, + toolbarEnabled: false + } + const fab_elem = document.querySelectorAll(".fixed-action-btn"); + M.FloatingActionButton.init(fab_elem, fab_options); + + var receivedmessages = null; + loadMessages(true, 0); + M.updateTextFields(); + + // Setup side menu + const menus = document.querySelectorAll(".side-menu"); + M.Sidenav.init(menus, { edge: "right", draggable: true }); }); diff --git a/assets/pages-src/messaging.bvr b/assets/pages-src/messaging.bvr index abc7e79..80bb80d 100644 --- a/assets/pages-src/messaging.bvr +++ b/assets/pages-src/messaging.bvr @@ -2,91 +2,91 @@ <!DOCTYPE html> <html> <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> - <meta http-equiv="X-UA-Compatible" content="ie=edge"> - <meta name="google" content="notranslate"> - <title>Messaging « BežiApp</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> + <meta http-equiv="X-UA-Compatible" content="ie=edge"> + <meta name="google" content="notranslate"> + <title>Messaging « BežiApp</title> - <!-- Materialize --> - <link type="text/css" href="/css/materialize.min.css" rel="stylesheet"> - <link href="/css/materialicons.css" rel="stylesheet"> - <script type="text/javascript" src="/js/lib/materialize.min.js"></script> + <!-- Materialize --> + <link type="text/css" href="/css/materialize.min.css" rel="stylesheet"> + <link href="/css/materialicons.css" rel="stylesheet"> + <script type="text/javascript" src="/js/lib/materialize.min.js"></script> - <script src="/js/lib/jquery.min.js"></script> - <script type="text/javascript" src="/js/lib/localforage.min.js"></script> + <script src="/js/lib/jquery.min.js"></script> + <script type="text/javascript" src="/js/lib/localforage.min.js"></script> - <link type="text/css" href="/css/styles.css" rel="stylesheet"> + <link type="text/css" href="/css/styles.css" rel="stylesheet"> - <link rel="manifest" href="/manifest.json"> - <script src="/js/app.js"></script> - <script src="/js/lib/themes.js"></script> - <script src="/js/lang/bundle.js"></script> - <script src="/js/lib/xss.js"></script> - <script src="/js/lib/sjcl.js"></script> - <script src="/js/gsec.js"></script> - <link rel="shortcut icon" type="image/png" href="/favicon.png" /> - <script type="text/javascript" src="/js/messaging.js"></script> + <link rel="manifest" href="/manifest.json"> + <script src="/js/app.js"></script> + <script src="/js/lib/themes.js"></script> + <script src="/js/lang/bundle.js"></script> + <script src="/js/lib/xss.js"></script> + <script src="/js/lib/sjcl.js"></script> + <script src="/js/gsec.js"></script> + <link rel="shortcut icon" type="image/png" href="/favicon.png" /> + <script type="text/javascript" src="/js/messaging.js"></script> - <!-- iOS support --> - <link rel="apple-touch-icon" href="/img/icons/icon_96.png"> - <link rel="apple-touch-icon" href="/img/icons/icon_512.png"> - <meta name="apple-mobile-web-app-status-bar" content="#004d32"> + <!-- iOS support --> + <link rel="apple-touch-icon" href="/img/icons/icon_96.png"> + <link rel="apple-touch-icon" href="/img/icons/icon_512.png"> + <meta name="apple-mobile-web-app-status-bar" content="#004d32"> </head> <body> - <nav class="z-depth-0" id="navigation-main"> - <div class="nav-wrapper container"> - <b class="app-header-bold">Beži</b><span class="app-header-span">App</span> » <x-su>messaging</x-su> - <span class="right white-text"> - <i class="material-icons sidenav-trigger" data-target="side-menu">menu</i> - </span> - <span class="right white-text" id="refresh-icon"> - <a href="#"><i class="material-icons">refresh</i></a> - </span> - </div> - <div id="loading-bar" class="progress hidden"> - <div class="indeterminate"></div> - </div> - </nav> + <nav class="z-depth-0" id="navigation-main"> + <div class="nav-wrapper container"> + <b class="app-header-bold">Beži</b><span class="app-header-span">App</span> » <x-su>messaging</x-su> + <span class="right white-text"> + <i class="material-icons sidenav-trigger" data-target="side-menu">menu</i> + </span> + <span class="right white-text" id="refresh-icon"> + <a href="#"><i class="material-icons">refresh</i></a> + </span> + </div> + <div id="loading-bar" class="progress hidden"> + <div class="indeterminate"></div> + </div> + </nav> <@?i navigation@> - <div class="container"> - <div class="row"> + <div class="container"> + <div class="row"> - <br> - <div class="row light-text" id="storage-bar"> - <div class="col s6"> - <x-su>messageStorageUsed</x-su>: <span id="storage-stats">0/120</span> <x-sl>messages</x-sl> - </div> - <div class="progress col s6"> - <div class="determinate" id="storage-progressbar" style="width: 0%"></div> - </div> - </div> + <br> + <div class="row light-text" id="storage-bar"> + <div class="col s6"> + <x-su>messageStorageUsed</x-su>: <span id="storage-stats">0/120</span> <x-sl>messages</x-sl> + </div> + <div class="progress col s6"> + <div class="determinate" id="storage-progressbar" style="width: 0%"></div> + </div> + </div> - <div class="row light-text" style="text-align: center;"> - <x-du>maxMessagesNote</x-du> - </div> + <div class="row light-text" style="text-align: center;"> + <x-du>maxMessagesNote</x-du> + </div> - <div class="col s12 m12"> - <ul class="tabs"> - <li class="tab col s4"><a href="#beziapp-received" class="active">Received</a></li> - <li class="tab col s4"><a href="#beziapp-sent">Sent</a></li> - <li class="tab col s4"><a href="#beziapp-deleted">Deleted</a></li> - </ul> - </div> - <br> - <div id="beziapp-received" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> - <div id="beziapp-sent" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> - <div id="beziapp-deleted" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> - </div> - </div> + <div class="col s12 m12"> + <ul class="tabs"> + <li class="tab col s4"><a href="#beziapp-received" class="active">Received</a></li> + <li class="tab col s4"><a href="#beziapp-sent">Sent</a></li> + <li class="tab col s4"><a href="#beziapp-deleted">Deleted</a></li> + </ul> + </div> + <br> + <div id="beziapp-received" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> + <div id="beziapp-sent" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> + <div id="beziapp-deleted" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> + </div> + </div> - <!-- FAB --> - <div class="fixed-action-btn" id="fab-new"> - <a class="btn-floating btn-large fab-new-message modal-trigger" href="#beziapp-new-message"> - <i class="large material-icons">mode_edit</i> - </a> - </div> + <!-- FAB --> + <div class="fixed-action-btn" id="fab-new"> + <a class="btn-floating btn-large fab-new-message modal-trigger" href="#beziapp-new-message"> + <i class="large material-icons">mode_edit</i> + </a> + </div> <@?i msg-compose-modal@> </body> </html> diff --git a/assets/pages-src/settings.bvr b/assets/pages-src/settings.bvr index d460093..6fa0a64 100644 --- a/assets/pages-src/settings.bvr +++ b/assets/pages-src/settings.bvr @@ -2,71 +2,71 @@ <!DOCTYPE html> <html> <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> - <meta http-equiv="X-UA-Compatible" content="ie=edge"> - <meta name="google" content="notranslate"> - <title>Settings « BežiApp</title> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> + <meta http-equiv="X-UA-Compatible" content="ie=edge"> + <meta name="google" content="notranslate"> + <title>Settings « BežiApp</title> - <!-- Materialize --> - <link type="text/css" href="/css/materialize.min.css" rel="stylesheet"> - <link href="/css/materialicons.css" rel="stylesheet"> - <link href="/css/fontawesome.min.css" rel="stylesheet"> - <script type="text/javascript" src="/js/lib/materialize.min.js"></script> + <!-- Materialize --> + <link type="text/css" href="/css/materialize.min.css" rel="stylesheet"> + <link href="/css/materialicons.css" rel="stylesheet"> + <link href="/css/fontawesome.min.css" rel="stylesheet"> + <script type="text/javascript" src="/js/lib/materialize.min.js"></script> - <script src="/js/lib/jquery.min.js"></script> - <script type="text/javascript" src="/js/lib/localforage.min.js"></script> + <script src="/js/lib/jquery.min.js"></script> + <script type="text/javascript" src="/js/lib/localforage.min.js"></script> - <link type="text/css" href="/css/styles.css" rel="stylesheet"> + <link type="text/css" href="/css/styles.css" rel="stylesheet"> - <link rel="manifest" href="/manifest.json"> - <script src="/js/app.js"></script> - <script src="/js/lib/themes.js"></script> - <script src="/js/lang/bundle.js"></script> - <script type="text/javascript" src="/js/settings.js"></script> - <link rel="shortcut icon" type="image/png" href="/favicon.png" /> + <link rel="manifest" href="/manifest.json"> + <script src="/js/app.js"></script> + <script src="/js/lib/themes.js"></script> + <script src="/js/lang/bundle.js"></script> + <script type="text/javascript" src="/js/settings.js"></script> + <link rel="shortcut icon" type="image/png" href="/favicon.png" /> - <!-- iOS support --> - <link rel="apple-touch-icon" href="/img/icons/icon_96.png"> - <link rel="apple-touch-icon" href="/img/icons/icon_512.png"> - <meta name="apple-mobile-web-app-status-bar" content="#004d32"> + <!-- iOS support --> + <link rel="apple-touch-icon" href="/img/icons/icon_96.png"> + <link rel="apple-touch-icon" href="/img/icons/icon_512.png"> + <meta name="apple-mobile-web-app-status-bar" content="#004d32"> </head> <body> - <nav class="z-depth-0" id="navigation-main"> - <div class="nav-wrapper container"> - <b class="app-header-bold">Beži</b><span class="app-header-span">App</span> » <x-su>settings</x-su> - <span class="right white-text"> - <i class="material-icons sidenav-trigger" data-target="side-menu">menu</i> - </span> - </div> - <div id="loading-bar" class="progress hidden"> - <div class="indeterminate"></div> - </div> - </nav> + <nav class="z-depth-0" id="navigation-main"> + <div class="nav-wrapper container"> + <b class="app-header-bold">Beži</b><span class="app-header-span">App</span> » <x-su>settings</x-su> + <span class="right white-text"> + <i class="material-icons sidenav-trigger" data-target="side-menu">menu</i> + </span> + </div> + <div id="loading-bar" class="progress hidden"> + <div class="indeterminate"></div> + </div> + </nav> <@?i navigation@> - <div class="container"> - <div class="row"> - <div class="col s12"> - <h3><b class="title-secondary">Beži</b><span class="title-primary">App</span> - </h3> - <h4 class="subheader general-text"><x-su>settings</x-su></h4> - </div> - </div> - <div class="row"> - <div class="col s12"> - <h5 class="general-text"><x-su>language</x-su></h5> - </div> - <div class="input-field col s12"> - <i class="material-icons prefix">translate</i> - <select class="lang-select icons input-select" id="select-language"> - <option value="sl" id="option-sl" data-icon="/img/flags/sl.svg" selected>Slovenščina</option> - <option value="en" id="option-en" data-icon="/img/flags/en.svg">English</option> - </select> - <label><x-su>selectLanguage</x-su></label> - </div> - </div> + <div class="container"> + <div class="row"> + <div class="col s12"> + <h3><b class="title-secondary">Beži</b><span class="title-primary">App</span> + </h3> + <h4 class="subheader general-text"><x-su>settings</x-su></h4> + </div> + </div> + <div class="row"> + <div class="col s12"> + <h5 class="general-text"><x-su>language</x-su></h5> + </div> + <div class="input-field col s12"> + <i class="material-icons prefix">translate</i> + <select class="lang-select icons input-select" id="select-language"> + <option value="sl" id="option-sl" data-icon="/img/flags/sl.svg" selected>Slovenščina</option> + <option value="en" id="option-en" data-icon="/img/flags/en.svg">English</option> + </select> + <label><x-su>selectLanguage</x-su></label> + </div> + </div> <div class="row"> <div class="col s12"> @@ -76,7 +76,8 @@ <i class="material-icons prefix">palette</i> <select class="theme-select input-select" id="select-theme"> <option value="light" id="option-light" data-theme="light" selected>Light / svetla</option> - <option value="dark" id="option-dark" data-theme="dark">Dark / temna</option> + <option value="dark" id="option-dark" data-theme="dark">Dark / temna</option> + <option value="night" id="option-night" data-theme="night">Night / nočna</x-su></option> </select> <label><x-su>selectTheme</x-su></label> </div> diff --git a/dist/js/app.js b/dist/js/app.js index 84a4c3a..8c82665 100755 --- a/dist/js/app.js +++ b/dist/js/app.js @@ -3,7 +3,7 @@ const app_version = "1.0.13-beta"; -const previous_commit = "448708182490d551721767bffc34ef35375f5082"; +const previous_commit = "cbef4f9e7f6b39469d9e6ac77b5a7237f69022ee"; if ("serviceWorker" in navigator) { navigator.serviceWorker.register("/sw.js") diff --git a/dist/js/lang/bundle.js b/dist/js/lang/bundle.js index 9f0497b..75fae14 100644 --- a/dist/js/lang/bundle.js +++ b/dist/js/lang/bundle.js @@ -290,6 +290,7 @@ var langstrings = { theme: "theme", themeLight: "light theme (default)", themeDark: "dark theme", + themeNight: "night theme", selectTheme: "select a theme", themeSet: "theme set, open another page for the changes to take effect", errorReportingSet: "error reporting preference set", @@ -486,6 +487,7 @@ var langstrings = { theme: "izgled", themeLight: "svetel izgled (privzeto)", themeDark: "temen izgled", + themeNight: "nočni izgled", themeSet: "izgled nastavljen, odprite neko drugo stran da se spremembe uveljavijo", selectTheme: "izberite željen izgled", errorReportingSet: "nastavitev pošiljanja napak izbrana", diff --git a/dist/js/lib/themes.js b/dist/js/lib/themes.js index 14ef436..75dedfd 100644 --- a/dist/js/lib/themes.js +++ b/dist/js/lib/themes.js @@ -25,7 +25,7 @@ const THEME_COLOR_SCHEMES = { "color-divider": "rgba(224, 224, 224, 1)", "color-btn-flat": "rgba(52, 52, 52, 1)", - "color-btn-flat-disabled": "rgba(178, 178, 178, 1)", + "color-btn-flat-disabled": "rgba(178, 178, 178, 1)" }, dark: { @@ -54,7 +54,35 @@ const THEME_COLOR_SCHEMES = { "color-divider": "rgba(80, 80, 80, 1)", "color-btn-flat": "rgba(178, 178, 178, 1)", - "color-btn-flat-disabled": "rgba(52, 52, 52, 1)", + "color-btn-flat-disabled": "rgba(52, 52, 52, 1)" + }, + black: { + "color-primary": "rgba(0, 79, 51, 1)", + "color-secondary": "rgba(0, 94, 61, 1)", + "color-accent": "rgba(28, 107, 79, 1)", + "color-primary-light": "rgba(0, 77, 2, 1)", // it's not really light anymore, is it? + "color-invalid": "rgba(138, 0, 0, 1)", + "color-primary-transparent": "rgba(0, 79, 51, 0.3)", + + "background-color": "rgba(0, 0, 0, 1)", + "background-accent": "rgba(0, 38, 18, 0.2)", + "background-accent-1": "rgb(20, 33, 25, 1)", + + "color-header-bold": "rgba(255, 255, 255, 1)", + "color-header-span": "rgba(255, 255, 255, 1)", + + "color-text": "rgba(189, 189, 189, 1)", + "color-text-light": "rgba(160, 160, 160, 1)", + "color-label-text": "rgba(158, 158, 158, 1)", + "color-table-hover": "rgba(43, 43, 43, 0.5)", + + "color-sidenav-background": "rgba(0, 0, 0, 1)", + "color-sidenav-text": "rgba(189, 189, 189, 1)", + "color-sidenav-header": "rgba(189, 189, 189, 0.54)", + "color-divider": "rgba(50, 50, 50, 1)", + + "color-btn-flat": "rgba(178, 178, 178, 1)", + "color-btn-flat-disabled": "rgba(52, 52, 52, 1)" } } diff --git a/dist/js/messaging.js b/dist/js/messaging.js index dba57ef..305b355 100644 --- a/dist/js/messaging.js +++ b/dist/js/messaging.js @@ -6,34 +6,34 @@ const ENCRYPTED_MESSAGE_REGEX = /<!-- ba-e2eemsg-(\d{4}) -->(\S+?)<!-- end-msg - // "Global" object for name directory and messages var directory = null; var messages = { - "0": [], - "1": [], - "2": [] + "0": [], + "1": [], + "2": [] } var current_tab = 0; async function checkLogin() { - localforage.getItem("logged_in").then(function (value) { - // This code runs once the value has been loaded - // from the offline store. - if (value !== true) { - window.location.replace("/index.html"); - } - }).catch(function (err) { - // This code runs if there were any errors - console.log(err); - }); + localforage.getItem("logged_in").then(function (value) { + // This code runs once the value has been loaded + // from the offline store. + if (value !== true) { + window.location.replace("/index.html"); + } + }).catch(function (err) { + // This code runs if there were any errors + console.log(err); + }); } // -----------HTML HELPERS----------- function htmlEncode(value) { - // Create a in-memory element, set its inner text (which is automatically encoded) - // Then grab the encoded contents back out. The element never exists on the DOM. - return $("<textarea/>").text(value).html(); + // Create a in-memory element, set its inner text (which is automatically encoded) + // Then grab the encoded contents back out. The element never exists on the DOM. + return $("<textarea/>").text(value).html(); } function htmlDecode(value) { - return $("<textarea/>").html(value).text(); + return $("<textarea/>").html(value).text(); } // --------------------------------- @@ -97,302 +97,302 @@ async function loadDirectory() { } function populateAutocomplete() { - let elems = document.querySelectorAll(".autocomplete-fullname"); - // če se uporablja globalna var directory, ki je shranjena kot objekt (vedno shranjen kot reference), bo pri let x=y x le pointer na object y - // in se bo spremenil z spremembo "originala". spodnja stvar itak ni preveč efficent, loop čez vseh 7000 ljudi bi lahko delal težave... - // kakšen Object.keys bi bila boljša varianta ampak raje napišem tale komentar... idk, to se mi je zdelo uporabno ampak sedaj obžalujem - // samo guglal sem "copying an object js" - let autocomplete_entries = Object.assign({}, directory); - for (let variableKey in autocomplete_entries) { - autocomplete_entries[variableKey] = null; - } - - M.Autocomplete.init(elems, { - data: autocomplete_entries, - onAutocomplete: validateName, - minLength: 0 - }); - - $(document).ready(function () { - if (window.location.hash.length > 1 && !window.location.hash.substring(1).startsWith("beziapp")) { - var hashValue = decodeURIComponent(window.location.hash.substring(1)); - $("#full-name").val(hashValue); - if (hashValue in directory) { - $("#msg-send").removeAttr("disabled"); - } - $("#beziapp-new-message").modal(); - $("#beziapp-new-message").modal("open"); - } - }); - - M.updateTextFields(); - validateName(); + let elems = document.querySelectorAll(".autocomplete-fullname"); + // če se uporablja globalna var directory, ki je shranjena kot objekt (vedno shranjen kot reference), bo pri let x=y x le pointer na object y + // in se bo spremenil z spremembo "originala". spodnja stvar itak ni preveč efficent, loop čez vseh 7000 ljudi bi lahko delal težave... + // kakšen Object.keys bi bila boljša varianta ampak raje napišem tale komentar... idk, to se mi je zdelo uporabno ampak sedaj obžalujem + // samo guglal sem "copying an object js" + let autocomplete_entries = Object.assign({}, directory); + for (let variableKey in autocomplete_entries) { + autocomplete_entries[variableKey] = null; + } + + M.Autocomplete.init(elems, { + data: autocomplete_entries, + onAutocomplete: validateName, + minLength: 0 + }); + + $(document).ready(function () { + if (window.location.hash.length > 1 && !window.location.hash.substring(1).startsWith("beziapp")) { + var hashValue = decodeURIComponent(window.location.hash.substring(1)); + $("#full-name").val(hashValue); + if (hashValue in directory) { + $("#msg-send").removeAttr("disabled"); + } + $("#beziapp-new-message").modal(); + $("#beziapp-new-message").modal("open"); + } + }); + + M.updateTextFields(); + validateName(); } // Function to toggle loading bar function setLoading(state) { - if (state) { - $("#loading-bar").removeClass("hidden"); - } else { - $("#loading-bar").addClass("hidden"); - } + if (state) { + $("#loading-bar").removeClass("hidden"); + } else { + $("#loading-bar").addClass("hidden"); + } } // Function, responsible for fetching and displaying data async function loadMessages(force_refresh = true, messageType = 0) { - setLoading(true); - // Load required data - let promises_to_run = [ - localforage.getItem("username").then((value) => { - username = value; - }), - localforage.getItem("password").then((value) => { - password = value; - }), - localforage.getItem("messages").then((value) => { - messages = value; - }) - ]; - - Promise.all(promises_to_run).then(() => { - - if (messages[messageType] == null || messages[messageType].length === 0 || force_refresh) { - $.ajax({ - url: API_ENDPOINT, - crossDomain: true, - data: { - "u": username, - "p": password, - "m": "fetchsporocilaseznam", - "a": messageType // Message type, see API doc for details - }, - dataType: "json", - cache: false, - type: "GET", - - success: (data) => { - // If data is null, the request failed - if (data === null) { - UIAlert( D("requestFailed") ); - setLoading(false); - } else { - // Save messages & populate view - // console.log(data); // debug - messages[messageType.toString()] = data; - localforage.setItem("messages", messages).then((value) => { - displayData(messageType); - setLoading(false); - }); - } - }, - - error: () => { - UIAlert( D("errorFetchingMessages") ); - setLoading(false); - } - }) - } else { - displayData(messageType); - setLoading(false); - } - }); + setLoading(true); + // Load required data + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), + localforage.getItem("password").then((value) => { + password = value; + }), + localforage.getItem("messages").then((value) => { + messages = value; + }) + ]; + + Promise.all(promises_to_run).then(() => { + + if (messages[messageType] == null || messages[messageType].length === 0 || force_refresh) { + $.ajax({ + url: API_ENDPOINT, + crossDomain: true, + data: { + "u": username, + "p": password, + "m": "fetchsporocilaseznam", + "a": messageType // Message type, see API doc for details + }, + dataType: "json", + cache: false, + type: "GET", + + success: (data) => { + // If data is null, the request failed + if (data === null) { + UIAlert( D("requestFailed") ); + setLoading(false); + } else { + // Save messages & populate view + // console.log(data); // debug + messages[messageType.toString()] = data; + localforage.setItem("messages", messages).then((value) => { + displayData(messageType); + setLoading(false); + }); + } + }, + + error: () => { + UIAlert( D("errorFetchingMessages") ); + setLoading(false); + } + }) + } else { + displayData(messageType); + setLoading(false); + } + }); } async function loadMsg(id) { - setLoading(true); - // Load required data - let promises_to_run = [ - localforage.getItem("username").then((value) => { - username = value; - }), - localforage.getItem("password").then((value) => { - password = value; - }), - ]; - - Promise.all(promises_to_run).then(() => { - $.ajax({ - url: API_ENDPOINT, - crossDomain: true, - data: { - "u": username, - "p": password, - "m": "fetchsporocilo", - "a": id.replace(/_/g, "|") - }, - dataType: "json", - cache: false, - type: "GET", - success: (data) => { - // If data is null, the request failed - if (data === null) { - UIAlert( `${D("unableToReceiveTheMessage")} ${D("requestFailed")}` ); - } else { - displayMessage(id, data); - } - setLoading(false); - }, - - error: () => { - UIAlert( `${D("unableToReceiveTheMessage")} ${D("noInternetConnection")}` ); - setLoading(false); - } - - }) - }); + setLoading(true); + // Load required data + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), + localforage.getItem("password").then((value) => { + password = value; + }), + ]; + + Promise.all(promises_to_run).then(() => { + $.ajax({ + url: API_ENDPOINT, + crossDomain: true, + data: { + "u": username, + "p": password, + "m": "fetchsporocilo", + "a": id.replace(/_/g, "|") + }, + dataType: "json", + cache: false, + type: "GET", + success: (data) => { + // If data is null, the request failed + if (data === null) { + UIAlert( `${D("unableToReceiveTheMessage")} ${D("requestFailed")}` ); + } else { + displayMessage(id, data); + } + setLoading(false); + }, + + error: () => { + UIAlert( `${D("unableToReceiveTheMessage")} ${D("noInternetConnection")}` ); + setLoading(false); + } + + }) + }); } async function deleteMsg(id) { - setLoading(true); - // Load required data - let promises_to_run = [ - localforage.getItem("username").then((value) => { - username = value; - }), localforage.getItem("password").then((value) => { - password = value; - }), - ]; - Promise.all(promises_to_run).then(() => { - $.ajax({ - url: API_ENDPOINT, - crossDomain: true, - data: { - "u": username, - "p": password, - "m": "izbrisisporocilo", - "a": id - }, - dataType: "json", - cache: false, - type: "GET", - success: (data) => { - // If data is null, the request failed - if (data === null) { - UIAlert( `${D("unableToDeleteTheMessage")} ${D("requestFailed")}` ); - } else { - document.getElementById("msg_box-" + id).remove(); - } - setLoading(false); - }, - - error: () => { - UIAlert( `${D("unableToDeleteTheMessage")} ${D("noInternetConnection")}` ); - setLoading(false); - } - - }) - }); + setLoading(true); + // Load required data + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), localforage.getItem("password").then((value) => { + password = value; + }), + ]; + Promise.all(promises_to_run).then(() => { + $.ajax({ + url: API_ENDPOINT, + crossDomain: true, + data: { + "u": username, + "p": password, + "m": "izbrisisporocilo", + "a": id + }, + dataType: "json", + cache: false, + type: "GET", + success: (data) => { + // If data is null, the request failed + if (data === null) { + UIAlert( `${D("unableToDeleteTheMessage")} ${D("requestFailed")}` ); + } else { + document.getElementById("msg_box-" + id).remove(); + } + setLoading(false); + }, + + error: () => { + UIAlert( `${D("unableToDeleteTheMessage")} ${D("noInternetConnection")}` ); + setLoading(false); + } + + }) + }); } function displayMessage(id, data) { - let regex_results = ENCRYPTED_MESSAGE_REGEX.exec(data["telo"]); - if (regex_results != null) { - var datatodecrypt = regex_results[2]; - var randomencdivid = Math.floor(Math.random() * 9999).toString().padStart(4, "0"); - - var msgcontent = ` - <div id='ba-msg-e2ee-form-${randomencdivid}'> - ${D("thisMessageWasEncrypted")} - <input type="password" autocomplete="new-password" id="ba-msg-e2ee-password-${randomencdivid}" placeholder="${S("password")} ..."> - <button - type="button" - value="Decrypt" - class="btn waves-effect waves-light" - onclick=" - try { - $('#ba-msg-e2ee-content-${randomencdivid}').html( - filterXSS( - sjcl.decrypt( - $('#ba-msg-e2ee-password-${randomencdivid}').val(), - $('#ba-msg-e2ee-content-${randomencdivid}').html() - ) - ) - ); - $('#ba-msg-e2ee-content-${randomencdivid}').show(); - $('#ba-msg-e2ee-form-${randomencdivid}').hide(); - } catch (err) { - alert('${D("incorrectPassword")}'); - } - " - > - ${S("decrypt")} - </button> - </div> - <div id="ba-msg-e2ee-content-${randomencdivid}" hidden> - ${datatodecrypt} - </div> - ` - $(`#msg_body-${id.replace(/\|/g, "_")}`).html(msgcontent); - } else { - $(`#msg_body-${id.replace(/\|/g, "_")}`).html(filterXSS(data["telo"])); - } + let regex_results = ENCRYPTED_MESSAGE_REGEX.exec(data["telo"]); + if (regex_results != null) { + var datatodecrypt = regex_results[2]; + var randomencdivid = Math.floor(Math.random() * 9999).toString().padStart(4, "0"); + + var msgcontent = ` + <div id='ba-msg-e2ee-form-${randomencdivid}'> + ${D("thisMessageWasEncrypted")} + <input type="password" autocomplete="new-password" id="ba-msg-e2ee-password-${randomencdivid}" placeholder="${S("password")} ..."> + <button + type="button" + value="Decrypt" + class="btn waves-effect waves-light" + onclick=" + try { + $('#ba-msg-e2ee-content-${randomencdivid}').html( + filterXSS( + sjcl.decrypt( + $('#ba-msg-e2ee-password-${randomencdivid}').val(), + $('#ba-msg-e2ee-content-${randomencdivid}').html() + ) + ) + ); + $('#ba-msg-e2ee-content-${randomencdivid}').show(); + $('#ba-msg-e2ee-form-${randomencdivid}').hide(); + } catch (err) { + alert('${D("incorrectPassword")}'); + } + " + > + ${S("decrypt")} + </button> + </div> + <div id="ba-msg-e2ee-content-${randomencdivid}" hidden> + ${datatodecrypt} + </div> + ` + $(`#msg_body-${id.replace(/\|/g, "_")}`).html(msgcontent); + } else { + $(`#msg_body-${id.replace(/\|/g, "_")}`).html(filterXSS(data["telo"])); + } } // Function for displaying data function displayData(messageType) { - let div_selector = ""; - switch (messageType) { - case 0: - div_selector = "#beziapp-received"; - break; - case 1: - div_selector = "#beziapp-sent"; - break; - case 2: - div_selector = "#beziapp-deleted"; - break; - } - - // $("#storage-bar").show(); - $("#storage-progressbar").width(Number(Number(getNumMessages(messageType) / 120) * 100).toFixed(2) + "%"); - $("#storage-stats").text(`${getNumMessages(messageType)}/120`); - - let msg_list = $(div_selector); - msg_list.html(""); - messages[messageType.toString()].forEach(element => { - if (!element["zadeva"].startsWith("ba-ctlmsg")) { - - msg_list.append(` - <div class="col s12 m12" id="msg_box-${filterXSS(element["id"])}"> - <div class="card blue-grey darken-1"> - <div class="card-content white-text"> - <span class="card-title"> - ${filterXSS(element["zadeva"])} - </span> - <p id="msg_body-${filterXSS(element["id"]).replace(/\|/g, "_")}"> - <button - class="btn waves-effect waves-light" - onclick="loadMsg('${filterXSS(element["id"])}')" - type="submit" - > - Load message - <i class="material-icons right">move_to_inbox</i> - </button> - <p> - </div> - <div class="card-action general-text"> - <a onclick="deleteMsg('${filterXSS(element["id"])}')"> - <i class="material-icons">delete</i> - </a> - <a onclick=" - $('#full-name').val('${filterXSS(element["posiljatelj"])}'); - $('#msg-subject').val('Re: ${filterXSS(element["zadeva"])}'); - M.updateTextFields(); - " - data-target="beziapp-new-message" - class="modal-trigger" - > - <i class="material-icons">reply</i> - </a> - ${filterXSS(element["posiljatelj"])} » ${filterXSS(element["datum"]["dan"])}. ${filterXSS(element["datum"]["mesec"])}. ${filterXSS(element["datum"]["leto"])} at ${filterXSS(element["cas"]["ura"]).padStart(2, "0")}:${filterXSS(element["cas"]["minuta"]).padStart(2, "0")} - </div> - </div> - </div> - `); - } - }); + let div_selector = ""; + switch (messageType) { + case 0: + div_selector = "#beziapp-received"; + break; + case 1: + div_selector = "#beziapp-sent"; + break; + case 2: + div_selector = "#beziapp-deleted"; + break; + } + + // $("#storage-bar").show(); + $("#storage-progressbar").width(Number(Number(getNumMessages(messageType) / 120) * 100).toFixed(2) + "%"); + $("#storage-stats").text(`${getNumMessages(messageType)}/120`); + + let msg_list = $(div_selector); + msg_list.html(""); + messages[messageType.toString()].forEach(element => { + if (!element["zadeva"].startsWith("ba-ctlmsg")) { + + msg_list.append(` + <div class="col s12 m12" id="msg_box-${filterXSS(element["id"])}"> + <div class="card blue-grey darken-1"> + <div class="card-content white-text"> + <span class="card-title"> + ${filterXSS(element["zadeva"])} + </span> + <p id="msg_body-${filterXSS(element["id"]).replace(/\|/g, "_")}"> + <button + class="btn waves-effect waves-light" + onclick="loadMsg('${filterXSS(element["id"])}')" + type="submit" + > + Load message + <i class="material-icons right">move_to_inbox</i> + </button> + <p> + </div> + <div class="card-action general-text"> + <a onclick="deleteMsg('${filterXSS(element["id"])}')"> + <i class="material-icons">delete</i> + </a> + <a onclick=" + $('#full-name').val('${filterXSS(element["posiljatelj"])}'); + $('#msg-subject').val('Re: ${filterXSS(element["zadeva"])}'); + M.updateTextFields(); + " + data-target="beziapp-new-message" + class="modal-trigger" + > + <i class="material-icons">reply</i> + </a> + ${filterXSS(element["posiljatelj"])} » ${filterXSS(element["datum"]["dan"])}. ${filterXSS(element["datum"]["mesec"])}. ${filterXSS(element["datum"]["leto"])} at ${filterXSS(element["cas"]["ura"]).padStart(2, "0")}:${filterXSS(element["cas"]["minuta"]).padStart(2, "0")} + </div> + </div> + </div> + `); + } + }); } // -1 = cumulative @@ -412,239 +412,239 @@ function getNumMessages(messageType = -1) { } async function sendMessage(recipient_number, subject, body) { - setLoading(true); - let promises_to_run = [ - localforage.getItem("username").then((value) => { - username = value; - }), - localforage.getItem("password").then((value) => { - password = value; - }), - ]; - Promise.all(promises_to_run).then(() => { - $.ajax({ - url: API_ENDPOINT, - crossDomain: true, - data: { - "u": username, - "p": password, - "m": "posljisporocilo", - "a": recipient_number, - "b": subject, - "c": body - }, - - dataType: "json", - cache: false, - - type: "POST", - success: () => { - // we CAN'T know wether the message was delievered - UIAlert(D("messageWasProbablySent")); - setLoading(false); - }, - error: () => { - UIAlert(D("errorSendingMessage"), D("noInternetConnection")); - setLoading(false); - } - }) - }); + setLoading(true); + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), + localforage.getItem("password").then((value) => { + password = value; + }), + ]; + Promise.all(promises_to_run).then(() => { + $.ajax({ + url: API_ENDPOINT, + crossDomain: true, + data: { + "u": username, + "p": password, + "m": "posljisporocilo", + "a": recipient_number, + "b": subject, + "c": body + }, + + dataType: "json", + cache: false, + + type: "POST", + success: () => { + // we CAN'T know wether the message was delievered + UIAlert(D("messageWasProbablySent")); + setLoading(false); + }, + error: () => { + UIAlert(D("errorSendingMessage"), D("noInternetConnection")); + setLoading(false); + } + }) + }); } async function validateName() { - if (directory !== null) { - if ($("#full-name").val() in directory) { - $("#full-name").addClass("valid"); - $("#full-name").removeClass("invalid"); - $("#msg-send").removeAttr("disabled"); - } else { - $("#full-name").addClass("invalid"); - $("#full-name").removeClass("valid"); - $("#msg-send").attr("disabled", "disabled"); - } - } + if (directory !== null) { + if ($("#full-name").val() in directory) { + $("#full-name").addClass("valid"); + $("#full-name").removeClass("invalid"); + $("#msg-send").removeAttr("disabled"); + } else { + $("#full-name").addClass("invalid"); + $("#full-name").removeClass("valid"); + $("#msg-send").attr("disabled", "disabled"); + } + } } // Setup event listeners for buttons function setupEventListeners() { - // Button to add a photo - $("#msg-add-photo").click(() => { - let input = document.createElement("input"); - input.type = "file"; - input.onchange = (e) => { - // getting a hold of the file reference - let file = e.target.files[0]; - // setting up the reader - let reader = new FileReader(); - reader.readAsDataURL(file); // this is reading as data url - - // here we tell the reader what to do when it's done reading... - reader.onload = readerEvent => { - additionalstufftoaddtomessage += `<br><img src="${readerEvent.target.result}" />`; // this is the content! - if ($("#msg-added-image").html().length > 1) { - $("#msg-added-image").append(`<img style="width: 20mm" src="${readerEvent.target.result}" />`); - } else { - $("#msg-added-image").html(` - <input - type="button" - value="${S("removeImages")}" - class="btn waves-effect waves-light" - onclick=" - additionalstufftoaddtomessage = ''; - $('#msg-added-image').html(''); - " - /> - <br> - ${D("largeImagesNote")} - <br> - ${S("attachedImages")}: - <br> - <img style="width:20mm" src="${readerEvent.target.result}" /> - `); - // ravno obratni narekovaji - } - UIAlert(D("imageAddedAsAnAttachment")); - } - } - input.click(); - }); - - // Verify recipient when input loses focus - $("#full-name").on("blur", validateName); - - // Setup refresh icon - $("#refresh-icon").click(() => { - loadMessages(true, current_tab); - }); - - // Setup checkbox handler - $("#encrypt-checkbox").change(function() { - if (this.checked) { - $("#encryption-key-input").prop("hidden", false); - } else { - $("#encryption-key-input").prop("hidden", true); - } - }); - - // Button to send message - $("#msg-send").click(() => { - localforage.getItem("directory").then(function (value) { - var msgcontent = $("#msg-body").val() + additionalstufftoaddtomessage; - var msgsubject = $("#msg-subject").val(); - if ($("#encryption-key-input").prop("hidden") !== true) { - var randomencdivid = Math.floor(Math.random() * 9999).toString().padStart(4, "0"); - var addrparts = window.location.href.split("/"); // engleski - - var encrypted_message = sjcl.encrypt($("#msg-e2ee-pass-input").val(), msgcontent); - msgcontent = ` - <script src="${addrparts[0]}//${addrparts[2]}/js/lib/sjcl.js"></script> - <div id="ba-msg-e2ee-form-${randomencdivid}"> - This message was encrypted by BežiApp. - <input type="password" autocomplete="new-password" id="ba-msg-e2ee-password-${randomencdivid}" placeholder="Enter password ..."> - <input type="button" value="Decrypt" onclick=" - try { - console.log($('ba-msg-e2ee-content-${randomencdivid}').text()); - $('#ba-msg-e2ee-content-${randomencdivid}').html( - sjcl.decrypt( - $('#ba-msg-e2ee-password-${randomencdivid}').val(), - $('#ba-msg-e2ee-content-${randomencdivid}').text() - ) - ); - $('#ba-msg-e2ee-content-${randomencdivid}').show(); - $('#ba-msg-e2ee-form-${randomencdivid}').hide(); - } catch(err) { - alert('${D("incorrectPassword")}'); - } - "> - </div> - <div id="ba-msg-e2ee-content-${randomencdivid}" hidden> - <!-- ba-e2eemsg-${msgcontent.length.toString().padStart(4, "0")} -->${encrypted_message}<!-- end-msg --> - </div> - ` - } - - console.log(msgcontent); - console.log(encrypted_message); - - sendMessage(value[$("#full-name").val()], msgsubject, htmlEncode(msgcontent)); - $("#msg-body").val(""); - $("#full-name").val(""); - $("#msg-subject").val(""); - // $("#msg-send").prop("disabled", true); - $("#msg-send").attr("disabled", "disabled"); - additionalstufftoaddtomessage = ""; - - $("#msg-added-image").html(""); - $("#msg-e2ee-pass").hide(); - - }).catch(function (err) { - UIAlert( `${D("unableToReadDirectory")} ${D("messageCouldNotBeSend")}`, "45245" ); - console.log(err); - }); - }); + // Button to add a photo + $("#msg-add-photo").click(() => { + let input = document.createElement("input"); + input.type = "file"; + input.onchange = (e) => { + // getting a hold of the file reference + let file = e.target.files[0]; + // setting up the reader + let reader = new FileReader(); + reader.readAsDataURL(file); // this is reading as data url + + // here we tell the reader what to do when it's done reading... + reader.onload = readerEvent => { + additionalstufftoaddtomessage += `<br><img src="${readerEvent.target.result}" />`; // this is the content! + if ($("#msg-added-image").html().length > 1) { + $("#msg-added-image").append(`<img style="width: 20mm" src="${readerEvent.target.result}" />`); + } else { + $("#msg-added-image").html(` + <input + type="button" + value="${S("removeImages")}" + class="btn waves-effect waves-light" + onclick=" + additionalstufftoaddtomessage = ''; + $('#msg-added-image').html(''); + " + /> + <br> + ${D("largeImagesNote")} + <br> + ${S("attachedImages")}: + <br> + <img style="width:20mm" src="${readerEvent.target.result}" /> + `); + // ravno obratni narekovaji + } + UIAlert(D("imageAddedAsAnAttachment")); + } + } + input.click(); + }); + + // Verify recipient when input loses focus + $("#full-name").on("blur", validateName); + + // Setup refresh icon + $("#refresh-icon").click(() => { + loadMessages(true, current_tab); + }); + + // Setup checkbox handler + $("#encrypt-checkbox").change(function() { + if (this.checked) { + $("#encryption-key-input").prop("hidden", false); + } else { + $("#encryption-key-input").prop("hidden", true); + } + }); + + // Button to send message + $("#msg-send").click(() => { + localforage.getItem("directory").then(function (value) { + var msgcontent = $("#msg-body").val() + additionalstufftoaddtomessage; + var msgsubject = $("#msg-subject").val(); + if ($("#encryption-key-input").prop("hidden") !== true) { + var randomencdivid = Math.floor(Math.random() * 9999).toString().padStart(4, "0"); + var addrparts = window.location.href.split("/"); // engleski + + var encrypted_message = sjcl.encrypt($("#msg-e2ee-pass-input").val(), msgcontent); + msgcontent = ` + <script src="${addrparts[0]}//${addrparts[2]}/js/lib/sjcl.js"></script> + <div id="ba-msg-e2ee-form-${randomencdivid}"> + This message was encrypted by BežiApp. + <input type="password" autocomplete="new-password" id="ba-msg-e2ee-password-${randomencdivid}" placeholder="Enter password ..."> + <input type="button" value="Decrypt" onclick=" + try { + console.log($('ba-msg-e2ee-content-${randomencdivid}').text()); + $('#ba-msg-e2ee-content-${randomencdivid}').html( + sjcl.decrypt( + $('#ba-msg-e2ee-password-${randomencdivid}').val(), + $('#ba-msg-e2ee-content-${randomencdivid}').text() + ) + ); + $('#ba-msg-e2ee-content-${randomencdivid}').show(); + $('#ba-msg-e2ee-form-${randomencdivid}').hide(); + } catch(err) { + alert('${D("incorrectPassword")}'); + } + "> + </div> + <div id="ba-msg-e2ee-content-${randomencdivid}" hidden> + <!-- ba-e2eemsg-${msgcontent.length.toString().padStart(4, "0")} -->${encrypted_message}<!-- end-msg --> + </div> + ` + } + + console.log(msgcontent); + console.log(encrypted_message); + + sendMessage(value[$("#full-name").val()], msgsubject, htmlEncode(msgcontent)); + $("#msg-body").val(""); + $("#full-name").val(""); + $("#msg-subject").val(""); + // $("#msg-send").prop("disabled", true); + $("#msg-send").attr("disabled", "disabled"); + additionalstufftoaddtomessage = ""; + + $("#msg-added-image").html(""); + $("#msg-e2ee-pass").hide(); + + }).catch(function (err) { + UIAlert( `${D("unableToReadDirectory")} ${D("messageCouldNotBeSend")}`, "45245" ); + console.log(err); + }); + }); } function getUrlParameter(sParam) { - const url_params = new URLSearchParams(window.location.search); - const found_param = url_params.get(sParam); - return found_param + const url_params = new URLSearchParams(window.location.search); + const found_param = url_params.get(sParam); + return found_param } var additionalstufftoaddtomessage = ""; document.addEventListener("DOMContentLoaded", () => { - checkLogin(); - - // Setup modals - const modal_elems = document.querySelectorAll('.modal'); - const modal_options = { - onOpenStart: () => { $("#fab-new").hide() }, - onCloseEnd: () => { $("#fab-new").show() }, - dismissible: false - }; - M.Modal.init(modal_elems, modal_options); - - loadDirectory(); - setupEventListeners(); - - // Setup tabs - const tabs = document.querySelectorAll(".tabs"); - const tab_options = { - // swipeable: true, // TODO: figure out how to fix height when it's enabled (it's good for UX to have it enabled) - onShow: (tab) => { - if ($(tab).hasClass("active")) { - switch (tab.id) { - case "beziapp-received": - current_tab = 0; - loadMessages(false, 0); - break; - case "beziapp-sent": - current_tab = 1; - loadMessages(false, 1); - break; - case "beziapp-deleted": - current_tab = 2; - loadMessages(false, 2); - break; - } - } - } - }; - M.Tabs.init(tabs, tab_options); - - // Setup floating action button - const fab_options = { - hoverEnabled: false, - toolbarEnabled: false - } - const fab_elem = document.querySelectorAll(".fixed-action-btn"); - M.FloatingActionButton.init(fab_elem, fab_options); - - var receivedmessages = null; - loadMessages(true, 0); - M.updateTextFields(); - - // Setup side menu - const menus = document.querySelectorAll(".side-menu"); - M.Sidenav.init(menus, { edge: "right", draggable: true }); + checkLogin(); + + // Setup modals + const modal_elems = document.querySelectorAll('.modal'); + const modal_options = { + onOpenStart: () => { $("#fab-new").hide() }, + onCloseEnd: () => { $("#fab-new").show() }, + dismissible: false + }; + M.Modal.init(modal_elems, modal_options); + + loadDirectory(); + setupEventListeners(); + + // Setup tabs + const tabs = document.querySelectorAll(".tabs"); + const tab_options = { + // swipeable: true, // TODO: figure out how to fix height when it's enabled (it's good for UX to have it enabled) + onShow: (tab) => { + if ($(tab).hasClass("active")) { + switch (tab.id) { + case "beziapp-received": + current_tab = 0; + loadMessages(false, 0); + break; + case "beziapp-sent": + current_tab = 1; + loadMessages(false, 1); + break; + case "beziapp-deleted": + current_tab = 2; + loadMessages(false, 2); + break; + } + } + } + }; + M.Tabs.init(tabs, tab_options); + + // Setup floating action button + const fab_options = { + hoverEnabled: false, + toolbarEnabled: false + } + const fab_elem = document.querySelectorAll(".fixed-action-btn"); + M.FloatingActionButton.init(fab_elem, fab_options); + + var receivedmessages = null; + loadMessages(true, 0); + M.updateTextFields(); + + // Setup side menu + const menus = document.querySelectorAll(".side-menu"); + M.Sidenav.init(menus, { edge: "right", draggable: true }); }); diff --git a/dist/pages/about.html b/dist/pages/about.html index 3d86337..8a2908c 100755 --- a/dist/pages/about.html +++ b/dist/pages/about.html @@ -142,7 +142,7 @@ <div class="row"> <p> <small> - ^HEAD 448708182490d551721767bffc34ef35375f5082 + ^HEAD cbef4f9e7f6b39469d9e6ac77b5a7237f69022ee </small> </p> </div> diff --git a/dist/pages/messaging.html b/dist/pages/messaging.html index e3d98f2..d90e53d 100755 --- a/dist/pages/messaging.html +++ b/dist/pages/messaging.html @@ -5,53 +5,53 @@ <!DOCTYPE html> <html> <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> - <meta http-equiv="X-UA-Compatible" content="ie=edge"> - <meta name="google" content="notranslate"> - <title>Messaging « BežiApp</title> - - <!-- Materialize --> - <link type="text/css" href="/css/materialize.min.css" rel="stylesheet"> - <link href="/css/materialicons.css" rel="stylesheet"> - <script type="text/javascript" src="/js/lib/materialize.min.js"></script> - - <script src="/js/lib/jquery.min.js"></script> - <script type="text/javascript" src="/js/lib/localforage.min.js"></script> - - <link type="text/css" href="/css/styles.css" rel="stylesheet"> - - <link rel="manifest" href="/manifest.json"> - <script src="/js/app.js"></script> - <script src="/js/lib/themes.js"></script> - <script src="/js/lang/bundle.js"></script> - <script src="/js/lib/xss.js"></script> - <script src="/js/lib/sjcl.js"></script> - <script src="/js/gsec.js"></script> - <link rel="shortcut icon" type="image/png" href="/favicon.png" /> - <script type="text/javascript" src="/js/messaging.js"></script> - - <!-- iOS support --> - <link rel="apple-touch-icon" href="/img/icons/icon_96.png"> - <link rel="apple-touch-icon" href="/img/icons/icon_512.png"> - <meta name="apple-mobile-web-app-status-bar" content="#004d32"> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> + <meta http-equiv="X-UA-Compatible" content="ie=edge"> + <meta name="google" content="notranslate"> + <title>Messaging « BežiApp</title> + + <!-- Materialize --> + <link type="text/css" href="/css/materialize.min.css" rel="stylesheet"> + <link href="/css/materialicons.css" rel="stylesheet"> + <script type="text/javascript" src="/js/lib/materialize.min.js"></script> + + <script src="/js/lib/jquery.min.js"></script> + <script type="text/javascript" src="/js/lib/localforage.min.js"></script> + + <link type="text/css" href="/css/styles.css" rel="stylesheet"> + + <link rel="manifest" href="/manifest.json"> + <script src="/js/app.js"></script> + <script src="/js/lib/themes.js"></script> + <script src="/js/lang/bundle.js"></script> + <script src="/js/lib/xss.js"></script> + <script src="/js/lib/sjcl.js"></script> + <script src="/js/gsec.js"></script> + <link rel="shortcut icon" type="image/png" href="/favicon.png" /> + <script type="text/javascript" src="/js/messaging.js"></script> + + <!-- iOS support --> + <link rel="apple-touch-icon" href="/img/icons/icon_96.png"> + <link rel="apple-touch-icon" href="/img/icons/icon_512.png"> + <meta name="apple-mobile-web-app-status-bar" content="#004d32"> </head> <body> - <nav class="z-depth-0" id="navigation-main"> - <div class="nav-wrapper container"> - <b class="app-header-bold">Beži</b><span class="app-header-span">App</span> » <x-su>messaging</x-su> - <span class="right white-text"> - <i class="material-icons sidenav-trigger" data-target="side-menu">menu</i> - </span> - <span class="right white-text" id="refresh-icon"> - <a href="#"><i class="material-icons">refresh</i></a> - </span> - </div> - <div id="loading-bar" class="progress hidden"> - <div class="indeterminate"></div> - </div> - </nav> + <nav class="z-depth-0" id="navigation-main"> + <div class="nav-wrapper container"> + <b class="app-header-bold">Beži</b><span class="app-header-span">App</span> » <x-su>messaging</x-su> + <span class="right white-text"> + <i class="material-icons sidenav-trigger" data-target="side-menu">menu</i> + </span> + <span class="right white-text" id="refresh-icon"> + <a href="#"><i class="material-icons">refresh</i></a> + </span> + </div> + <div id="loading-bar" class="progress hidden"> + <div class="indeterminate"></div> + </div> + </nav> <ul id="side-menu" class="sidenav side-menu"> <li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><b>Beži</b>App</h4></a></li> <li><a href="/pages/timetable.html" class="waves-effect"><i class="material-icons">view_module</i><x-su>timetable</x-su></a></li> @@ -70,43 +70,43 @@ <li><a href="/pages/settings.html" class="waves-effect"><i class="material-icons">settings</i><x-su>settings</x-su></a></li> </ul> - <div class="container"> - <div class="row"> - - <br> - <div class="row light-text" id="storage-bar"> - <div class="col s6"> - <x-su>messageStorageUsed</x-su>: <span id="storage-stats">0/120</span> <x-sl>messages</x-sl> - </div> - <div class="progress col s6"> - <div class="determinate" id="storage-progressbar" style="width: 0%"></div> - </div> - </div> - - <div class="row light-text" style="text-align: center;"> - <x-du>maxMessagesNote</x-du> - </div> - - <div class="col s12 m12"> - <ul class="tabs"> - <li class="tab col s4"><a href="#beziapp-received" class="active">Received</a></li> - <li class="tab col s4"><a href="#beziapp-sent">Sent</a></li> - <li class="tab col s4"><a href="#beziapp-deleted">Deleted</a></li> - </ul> - </div> - <br> - <div id="beziapp-received" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> - <div id="beziapp-sent" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> - <div id="beziapp-deleted" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> - </div> - </div> - - <!-- FAB --> - <div class="fixed-action-btn" id="fab-new"> - <a class="btn-floating btn-large fab-new-message modal-trigger" href="#beziapp-new-message"> - <i class="large material-icons">mode_edit</i> - </a> - </div> + <div class="container"> + <div class="row"> + + <br> + <div class="row light-text" id="storage-bar"> + <div class="col s6"> + <x-su>messageStorageUsed</x-su>: <span id="storage-stats">0/120</span> <x-sl>messages</x-sl> + </div> + <div class="progress col s6"> + <div class="determinate" id="storage-progressbar" style="width: 0%"></div> + </div> + </div> + + <div class="row light-text" style="text-align: center;"> + <x-du>maxMessagesNote</x-du> + </div> + + <div class="col s12 m12"> + <ul class="tabs"> + <li class="tab col s4"><a href="#beziapp-received" class="active">Received</a></li> + <li class="tab col s4"><a href="#beziapp-sent">Sent</a></li> + <li class="tab col s4"><a href="#beziapp-deleted">Deleted</a></li> + </ul> + </div> + <br> + <div id="beziapp-received" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> + <div id="beziapp-sent" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> + <div id="beziapp-deleted" class="col s12"><p class="center-align light-text"><x-su>loadingMessages</x-su></p></div> + </div> + </div> + + <!-- FAB --> + <div class="fixed-action-btn" id="fab-new"> + <a class="btn-floating btn-large fab-new-message modal-trigger" href="#beziapp-new-message"> + <i class="large material-icons">mode_edit</i> + </a> + </div> <!-- Modal Structure --> <div id="beziapp-new-message" class="modal modal-fixed-footer"> diff --git a/dist/pages/settings.html b/dist/pages/settings.html index a41dc4a..1316581 100755 --- a/dist/pages/settings.html +++ b/dist/pages/settings.html @@ -5,48 +5,48 @@ <!DOCTYPE html> <html> <head> - <meta charset="UTF-8"> - <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> - <meta http-equiv="X-UA-Compatible" content="ie=edge"> - <meta name="google" content="notranslate"> - <title>Settings « BežiApp</title> - - <!-- Materialize --> - <link type="text/css" href="/css/materialize.min.css" rel="stylesheet"> - <link href="/css/materialicons.css" rel="stylesheet"> - <link href="/css/fontawesome.min.css" rel="stylesheet"> - <script type="text/javascript" src="/js/lib/materialize.min.js"></script> - - <script src="/js/lib/jquery.min.js"></script> - <script type="text/javascript" src="/js/lib/localforage.min.js"></script> - - <link type="text/css" href="/css/styles.css" rel="stylesheet"> - - <link rel="manifest" href="/manifest.json"> - <script src="/js/app.js"></script> - <script src="/js/lib/themes.js"></script> - <script src="/js/lang/bundle.js"></script> - <script type="text/javascript" src="/js/settings.js"></script> - <link rel="shortcut icon" type="image/png" href="/favicon.png" /> - - <!-- iOS support --> - <link rel="apple-touch-icon" href="/img/icons/icon_96.png"> - <link rel="apple-touch-icon" href="/img/icons/icon_512.png"> - <meta name="apple-mobile-web-app-status-bar" content="#004d32"> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no"> + <meta http-equiv="X-UA-Compatible" content="ie=edge"> + <meta name="google" content="notranslate"> + <title>Settings « BežiApp</title> + + <!-- Materialize --> + <link type="text/css" href="/css/materialize.min.css" rel="stylesheet"> + <link href="/css/materialicons.css" rel="stylesheet"> + <link href="/css/fontawesome.min.css" rel="stylesheet"> + <script type="text/javascript" src="/js/lib/materialize.min.js"></script> + + <script src="/js/lib/jquery.min.js"></script> + <script type="text/javascript" src="/js/lib/localforage.min.js"></script> + + <link type="text/css" href="/css/styles.css" rel="stylesheet"> + + <link rel="manifest" href="/manifest.json"> + <script src="/js/app.js"></script> + <script src="/js/lib/themes.js"></script> + <script src="/js/lang/bundle.js"></script> + <script type="text/javascript" src="/js/settings.js"></script> + <link rel="shortcut icon" type="image/png" href="/favicon.png" /> + + <!-- iOS support --> + <link rel="apple-touch-icon" href="/img/icons/icon_96.png"> + <link rel="apple-touch-icon" href="/img/icons/icon_512.png"> + <meta name="apple-mobile-web-app-status-bar" content="#004d32"> </head> <body> - <nav class="z-depth-0" id="navigation-main"> - <div class="nav-wrapper container"> - <b class="app-header-bold">Beži</b><span class="app-header-span">App</span> » <x-su>settings</x-su> - <span class="right white-text"> - <i class="material-icons sidenav-trigger" data-target="side-menu">menu</i> - </span> - </div> - <div id="loading-bar" class="progress hidden"> - <div class="indeterminate"></div> - </div> - </nav> + <nav class="z-depth-0" id="navigation-main"> + <div class="nav-wrapper container"> + <b class="app-header-bold">Beži</b><span class="app-header-span">App</span> » <x-su>settings</x-su> + <span class="right white-text"> + <i class="material-icons sidenav-trigger" data-target="side-menu">menu</i> + </span> + </div> + <div id="loading-bar" class="progress hidden"> + <div class="indeterminate"></div> + </div> + </nav> <ul id="side-menu" class="sidenav side-menu"> <li><a class="subheader"><h4 class="sidenav-beziapp-subheader"><b>Beži</b>App</h4></a></li> <li><a href="/pages/timetable.html" class="waves-effect"><i class="material-icons">view_module</i><x-su>timetable</x-su></a></li> @@ -66,27 +66,27 @@ </ul> - <div class="container"> - <div class="row"> - <div class="col s12"> - <h3><b class="title-secondary">Beži</b><span class="title-primary">App</span> - </h3> - <h4 class="subheader general-text"><x-su>settings</x-su></h4> - </div> - </div> - <div class="row"> - <div class="col s12"> - <h5 class="general-text"><x-su>language</x-su></h5> - </div> - <div class="input-field col s12"> - <i class="material-icons prefix">translate</i> - <select class="lang-select icons input-select" id="select-language"> - <option value="sl" id="option-sl" data-icon="/img/flags/sl.svg" selected>Slovenščina</option> - <option value="en" id="option-en" data-icon="/img/flags/en.svg">English</option> - </select> - <label><x-su>selectLanguage</x-su></label> - </div> - </div> + <div class="container"> + <div class="row"> + <div class="col s12"> + <h3><b class="title-secondary">Beži</b><span class="title-primary">App</span> + </h3> + <h4 class="subheader general-text"><x-su>settings</x-su></h4> + </div> + </div> + <div class="row"> + <div class="col s12"> + <h5 class="general-text"><x-su>language</x-su></h5> + </div> + <div class="input-field col s12"> + <i class="material-icons prefix">translate</i> + <select class="lang-select icons input-select" id="select-language"> + <option value="sl" id="option-sl" data-icon="/img/flags/sl.svg" selected>Slovenščina</option> + <option value="en" id="option-en" data-icon="/img/flags/en.svg">English</option> + </select> + <label><x-su>selectLanguage</x-su></label> + </div> + </div> <div class="row"> <div class="col s12"> @@ -96,7 +96,8 @@ <i class="material-icons prefix">palette</i> <select class="theme-select input-select" id="select-theme"> <option value="light" id="option-light" data-theme="light" selected>Light / svetla</option> - <option value="dark" id="option-dark" data-theme="dark">Dark / temna</option> + <option value="dark" id="option-dark" data-theme="dark">Dark / temna</option> + <option value="night" id="option-night" data-theme="night">Night / nočna</x-su></option> </select> <label><x-su>selectTheme</x-su></label> </div> @@ -3,8 +3,8 @@ // Change version to cause cache refresh -const static_cache_name = "site-static-1.0.13-beta-4487081"; -// latest commit is 448708182490d551721767bffc34ef35375f5082 +const static_cache_name = "site-static-1.0.13-beta-cbef4f9"; +// latest commit is cbef4f9e7f6b39469d9e6ac77b5a7237f69022ee // Got them with find . -not -path '*/\.*' | sed "s/.*/\"&\",/" | grep -v sw.js // sw.js NE SME BITI CACHAN, ker vsebuje verzijo! |