diff options
Diffstat (limited to '')
-rw-r--r-- | assets/css/styles.css | 15 | ||||
-rw-r--r-- | assets/js/lang/bundle.js | 950 | ||||
-rw-r--r-- | assets/js/lib/themes.js | 4 | ||||
-rw-r--r-- | assets/js/messaging.js | 4 | ||||
-rw-r--r-- | assets/js/settings.js | 160 | ||||
-rw-r--r-- | assets/pages-src/settings.bvr | 2 | ||||
-rwxr-xr-x | dist/css/styles.css | 15 | ||||
-rwxr-xr-x | dist/js/app.js | 4 | ||||
-rw-r--r-- | dist/js/lang/bundle.js | 521 | ||||
-rw-r--r-- | dist/js/lib/themes.js | 154 | ||||
-rw-r--r-- | dist/js/messaging.js | 786 | ||||
-rw-r--r-- | dist/js/settings.js | 138 | ||||
-rwxr-xr-x | dist/pages/about.html | 2 | ||||
-rwxr-xr-x | dist/pages/settings.html | 2 | ||||
-rwxr-xr-x | dist/sw.js | 4 |
15 files changed, 2035 insertions, 726 deletions
diff --git a/assets/css/styles.css b/assets/css/styles.css index 0c00378..4e6050b 100644 --- a/assets/css/styles.css +++ b/assets/css/styles.css @@ -47,6 +47,10 @@ body { background-color: var(--color-primary); } +.color-card { + color: var(--color-primary-light); +} + nav { background: var(--color-primary); border-bottom: 10px solid var(--color-accent); @@ -95,6 +99,10 @@ a { color: var(--color-accent); } +.card-action > a { + color: var(--color-accent) !important; +} + a.collection-item { color: var(--color-primary) !important; } @@ -109,11 +117,12 @@ a.collection-item { .datepicker-table td.is-selected { background-color: var(--color-primary); + color: var(--background-color) !important; } .datepicker-table td.is-selected.is-today { background-color: var(--color-primary); - color: var(--background-color); + color: var(--background-color) !important; } .datepicker-cancel { @@ -148,6 +157,10 @@ a.collection-item { background-color: var(--color-primary) !important; } +.determinate { + background-color: var(--color-primary) !important; +} + .no-select { -webkit-touch-callout: none; -webkit-user-select: none; diff --git a/assets/js/lang/bundle.js b/assets/js/lang/bundle.js index 9545c38..8270527 100644 --- a/assets/js/lang/bundle.js +++ b/assets/js/lang/bundle.js @@ -1,513 +1,513 @@ // there's an DoS backdoor in BežiApp because of this (-:< var chosenLang; var dateString = { - day: (danv) => { - let dnevitedna = [S("sunday"), S("monday"), S("tuesday"), S("wednesday"), S("thursday"), S("friday"), S("saturday")]; - return dnevitedna[danv]; - }, - month: (mesl) => { - let mesecileta = [S("january"), S("february"), S("march"), S("april"), S("may"), S("june"), S("july"), S("august"), S("september"), S("october"), S("november"), S("december")]; - return mesecileta[mesl]; - }, - longFormatted: (dateObject) => { - return dateString.day(dateObject.getDay())+", "+(dateObject.getDate())+". "+dateString.month(dateObject.getMonth())+" "+dateObject.getFullYear(); - } + day: (danv) => { + let dnevitedna = [S("sunday"), S("monday"), S("tuesday"), S("wednesday"), S("thursday"), S("friday"), S("saturday")]; + return dnevitedna[danv]; + }, + month: (mesl) => { + let mesecileta = [S("january"), S("february"), S("march"), S("april"), S("may"), S("june"), S("july"), S("august"), S("september"), S("october"), S("november"), S("december")]; + return mesecileta[mesl]; + }, + longFormatted: (dateObject) => { + return dateString.day(dateObject.getDay())+", "+(dateObject.getDate())+". "+dateString.month(dateObject.getMonth())+" "+dateObject.getFullYear(); + } }; async function refreshLangDOM() { - let promises_to_runn = [ - localforage.getItem("chosenLang").then( (value) => { - chosenLang = value; - }) - // localforage.getItem("chosenCapitalize").then( (value) => { // poor unused code - // chosenCapitalize = value; - // }) - ]; - await Promise.all(promises_to_runn); - // this could be done nicer. p. s.: lahko bi se uporablil x-s in x-S za razločitev med capitalize in !capitalize queryselectorall ni case sensitive za imena elementov - let stringContainerss = document.querySelectorAll("x-sl:not(.langFinished)"); - for (i = 0; i < stringContainerss.length; i++) { - stringContainerss[i].innerHTML = s(stringContainerss[i].innerHTML); - stringContainerss[i].classList.add("langFinished"); - stringContainerss[i].hidden = false; - } - let stringContainersd = document.querySelectorAll("x-dl:not(.langFinished)"); - for (i = 0; i < stringContainersd.length; i++) { - stringContainersd[i].innerHTML = d(stringContainersd[i].innerHTML); - stringContainersd[i].classList.add("langFinished"); - stringContainersd[i].hidden = false; - } - let stringContainersS = document.querySelectorAll("x-su:not(.langFinished)"); - for (i = 0; i < stringContainersS.length; i++) { - stringContainersS[i].innerHTML = S(stringContainersS[i].innerHTML); - stringContainersS[i].classList.add("langFinished"); - stringContainersS[i].hidden = false; - } - let stringContainersD = document.querySelectorAll("x-du:not(.langFinished)"); - for (i = 0; i < stringContainersD.length; i++) { - stringContainersD[i].innerHTML = D(stringContainersD[i].innerHTML); - stringContainersD[i].classList.add("langFinished"); - stringContainersD[i].hidden = false; - } + let promises_to_runn = [ + localforage.getItem("chosenLang").then( (value) => { + chosenLang = value; + }) + // localforage.getItem("chosenCapitalize").then( (value) => { // poor unused code + // chosenCapitalize = value; + // }) + ]; + await Promise.all(promises_to_runn); + // this could be done nicer. p. s.: lahko bi se uporablil x-s in x-S za razločitev med capitalize in !capitalize queryselectorall ni case sensitive za imena elementov + let stringContainerss = document.querySelectorAll("x-sl:not(.langFinished)"); + for (i = 0; i < stringContainerss.length; i++) { + stringContainerss[i].innerHTML = s(stringContainerss[i].innerHTML); + stringContainerss[i].classList.add("langFinished"); + stringContainerss[i].hidden = false; + } + let stringContainersd = document.querySelectorAll("x-dl:not(.langFinished)"); + for (i = 0; i < stringContainersd.length; i++) { + stringContainersd[i].innerHTML = d(stringContainersd[i].innerHTML); + stringContainersd[i].classList.add("langFinished"); + stringContainersd[i].hidden = false; + } + let stringContainersS = document.querySelectorAll("x-su:not(.langFinished)"); + for (i = 0; i < stringContainersS.length; i++) { + stringContainersS[i].innerHTML = S(stringContainersS[i].innerHTML); + stringContainersS[i].classList.add("langFinished"); + stringContainersS[i].hidden = false; + } + let stringContainersD = document.querySelectorAll("x-du:not(.langFinished)"); + for (i = 0; i < stringContainersD.length; i++) { + stringContainersD[i].innerHTML = D(stringContainersD[i].innerHTML); + stringContainersD[i].classList.add("langFinished"); + stringContainersD[i].hidden = false; + } } async function setLangConfigAndReload() { - let promises_to_run = [ - /* localforage.setItem("chosenCapitalize", true), */ // F for unused code - localforage.setItem("chosenLang", "en") - ]; - await Promise.all(promises_to_run); - window.location.reload(); + let promises_to_run = [ + /* localforage.setItem("chosenCapitalize", true), */ // F for unused code + localforage.setItem("chosenLang", "en") + ]; + await Promise.all(promises_to_run); + window.location.reload(); } window.addEventListener("DOMContentLoaded", () => { - localforage.getItem("chosenLang").then( (value) => { - if(value == null) { - setLangConfigAndReload(); - } else { - chosenLang = value; - } - }); - refreshLangDOM(); + localforage.getItem("chosenLang").then( (value) => { + if(value == null) { + setLangConfigAndReload(); + } else { + chosenLang = value; + } + }); + refreshLangDOM(); }); const capitalize = (s) => { - if (typeof s !== 'string') return '' - return s.charAt(0).toUpperCase() + s.slice(1) + if (typeof s !== 'string') return '' + return s.charAt(0).toUpperCase() + s.slice(1) } var s = function(whatString) { - return getLang.s(whatString); + return getLang.s(whatString); }; var d = function(whatString) { - return getLang.d(whatString); + return getLang.d(whatString); }; var S = function(whatString) { - return getLang.S(whatString); + return getLang.S(whatString); }; var D = function(whatString) { - return getLang.D(whatString); + return getLang.D(whatString); }; var getLang = { // language object - s: function(whatString) { // get string - return langstrings[chosenLang][whatString]; - }, - S: function(whatString) { // get capitalized string - return capitalize(langstrings[chosenLang][whatString]); - }, - d: function(whatString) { // add a dot and get string - if(langstrings[chosenLang][whatString].slice(-1) != ".") { - return langstrings[chosenLang][whatString]+"."; - } else { - return langstrings[chosenLang][whatString]; - } - }, - D: function(whatString) { // add a dot and get capitalized string - if(langstrings[chosenLang][whatString].slice(-1) != ".") { - return capitalize(langstrings[chosenLang][whatString]+"."); - } else { - return capitalize(langstrings[chosenLang][whatString]); - } - }, + s: function(whatString) { // get string + return langstrings[chosenLang][whatString]; + }, + S: function(whatString) { // get capitalized string + return capitalize(langstrings[chosenLang][whatString]); + }, + d: function(whatString) { // add a dot and get string + if(langstrings[chosenLang][whatString].slice(-1) != ".") { + return langstrings[chosenLang][whatString]+"."; + } else { + return langstrings[chosenLang][whatString]; + } + }, + D: function(whatString) { // add a dot and get capitalized string + if(langstrings[chosenLang][whatString].slice(-1) != ".") { + return capitalize(langstrings[chosenLang][whatString]+"."); + } else { + return capitalize(langstrings[chosenLang][whatString]); + } + }, } var langstrings = { - en: { - miscTranslationLanguage: "English", - miscTranslationAuthors: "Rok Štular", - "": "", - // date - monday: "monday", - tuesday: "tuesday", - wednesday: "wednesday", - thursday: "thursday", - friday: "friday", - saturday: "saturday", - sunday: "sunday", - am: "am", - pm: "pm", - january: "january", - february: "february", - march: "march", - april: "april", - may: "may", - june: "june", - july: "july", - august: "august", - september: "september", - october: "october", - november: "november", - december: "december", - // login - username: "username", - password: "password", - signIn: "sign in", - bySigningInYouAgreeTo: "by signing in, you agree to", - theToS: "the terms and conditions", - and: "and", - thePrivacyPolicy: "the privacy policy", - loginFailed: "login failed", + en: { + miscTranslationLanguage: "English", + miscTranslationAuthors: "Rok Štular", + "": "", + // date + monday: "monday", + tuesday: "tuesday", + wednesday: "wednesday", + thursday: "thursday", + friday: "friday", + saturday: "saturday", + sunday: "sunday", + am: "am", + pm: "pm", + january: "january", + february: "february", + march: "march", + april: "april", + may: "may", + june: "june", + july: "july", + august: "august", + september: "september", + october: "october", + november: "november", + december: "december", + // login + username: "username", + password: "password", + signIn: "sign in", + bySigningInYouAgreeTo: "by signing in, you agree to", + theToS: "the terms and conditions", + and: "and", + thePrivacyPolicy: "the privacy policy", + loginFailed: "login failed", browserNotSupported: "bežiapp won't work on your device, unless you update your Internet browser", - // index - timetable: "timetable", - gradings: "gradings", - grades: "grades", - teachers: "teachers", - absences: "absences", - messaging: "messaging", - meals: "meals", - about: "about", - logout: "logout", - settings: "settings", - // timetable - noPeriods: "no periods in selected week", - // gradings - requestFailed: "request failed", - noInternetConnection: "no internet connection", - // grades - temporary: "temporary", - useOnlyPermanentGrades: "use only permanent grades", - useOnlyPermanentGradesNote1: "if checked, only permanent grades will be used in the average grade calculation", - useOnlyPermanentGradesNote2: "if left unchecked, the calculation will include every available grade", - type: "type", - term: "term", - teacher: "teacher", - // teachers - name: "name", - schoolSubject: "subject", - tpMeetings: "TP meetings", - // absences - from: "from", - to: "to", - cancel: "cancel", - ok: "ok", - noAbsences: "no absences in the chosen time period", - lesson: "lesson", - notProcessed: "not processed", - authorizedAbsence: "authorized", - unauthorizedAbsence: "unauthorized", - doesNotCount: "does not count", - // messaging - loadingMessages: "Loading messages...", - sendAMessage: "send a message", - recipient: "recipient", - messageSubject: "subject", - messageBody: "message body", - removeImages: "remove images", - note: "note", - largeImagesNote: "GimB servers don't like large messages, so only very small images may be attached or your message will not be delivered", - attachedImages: "attached images", - encryptMessage: "Encrypt message", - passwordForE2EE: "password for encrypting the message", - messages: "messages", - received: "received", - sent: "sent", - deleted: "deleted", - messageStorageUsed: "message storage used in this folder", - maxMessagesNote: "you can only have 120 messages per message folder, older messages will not be shown. Remember to delete read and sent messages regulary to avoid any issues.", - loadMessageBody: "load message body", - thisMessageWasEncrypted: "this message was encrypted", - enterPassword: "enter password", - decrypt: "decrypt", - nameDirectoryNotSet: "name directory not set, sending unavailable", - errorFetchingMessages: "error fetching messages", - unableToReceiveTheMessage: "unable to receive the message", - unableToDeleteTheMessage: "unable to delete the message", - messageWasProbablySent: "message was probably sent, check the Sent folder to be sure", - errorSendingMessage: "error sending message", - imageAddedAsAnAttachment: "image added as an attachment", - unableToReadDirectory: "unable to read directory of people", - messageCouldNotBeSent: "message could to be sent", - incorrectPassword: "incorrect password", - // chats - chat: "chat", - chattingWith: "chatting with", - noMessages: "no messages", - stillLoading: "loading is still in progress", - directory: "directory", - select: "select", - mustSelectRecipient: "you have to select a recipient before chatting. Open directory on the left side by clicking on the top left addressbook button and select a recipient in order to start chatting with them", - recipientNotInDirectory: "recipient is not in directory.", - chatExternalInfo: "you have just received a chat. Chats are not supported by GimSIS, so you must reply by changing the subject to something else. Chat body: ", - // meals + // index + timetable: "timetable", + gradings: "gradings", + grades: "grades", + teachers: "teachers", + absences: "absences", + messaging: "messaging", + meals: "meals", + about: "about", + logout: "logout", + settings: "settings", + // timetable + noPeriods: "no periods in selected week", + // gradings + requestFailed: "request failed", + noInternetConnection: "no internet connection", + // grades + temporary: "temporary", + useOnlyPermanentGrades: "use only permanent grades", + useOnlyPermanentGradesNote1: "if checked, only permanent grades will be used in the average grade calculation", + useOnlyPermanentGradesNote2: "if left unchecked, the calculation will include every available grade", + type: "type", + term: "term", + teacher: "teacher", + // teachers + name: "name", + schoolSubject: "subject", + tpMeetings: "TP meetings", + // absences + from: "from", + to: "to", + cancel: "cancel", + ok: "ok", + noAbsences: "no absences in the chosen time period", + lesson: "lesson", + notProcessed: "not processed", + authorizedAbsence: "authorized", + unauthorizedAbsence: "unauthorized", + doesNotCount: "does not count", + // messaging + loadingMessages: "Loading messages...", + sendAMessage: "send a message", + recipient: "recipient", + messageSubject: "subject", + messageBody: "message body", + removeImages: "remove images", + note: "note", + largeImagesNote: "GimB servers don't like large messages, so only very small images may be attached or your message will not be delivered", + attachedImages: "attached images", + encryptMessage: "Encrypt message", + passwordForE2EE: "password for encrypting the message", + messages: "messages", + received: "received", + sent: "sent", + deleted: "deleted", + messageStorageUsed: "message storage used in this folder", + maxMessagesNote: "you can only have 120 messages per message folder, older messages will not be shown. Remember to delete read and sent messages regulary to avoid any issues.", + loadMessageBody: "load message body", + thisMessageWasEncrypted: "this message was encrypted", + enterPassword: "enter password", + decrypt: "decrypt", + nameDirectoryNotSet: "name directory not set, sending unavailable", + errorFetchingMessages: "error fetching messages", + unableToReceiveTheMessage: "unable to receive the message", + unableToDeleteTheMessage: "unable to delete the message", + messageWasProbablySent: "message was probably sent, check the Sent folder to be sure", + errorSendingMessage: "error sending message", + imageAddedAsAnAttachment: "image added as an attachment", + unableToReadDirectory: "unable to read directory of people", + messageCouldNotBeSent: "message could to be sent", + incorrectPassword: "incorrect password", + // chats + chat: "chat", + chattingWith: "chatting with", + noMessages: "no messages", + stillLoading: "loading is still in progress", + directory: "directory", + select: "select", + mustSelectRecipient: "you have to select a recipient before chatting. Open directory on the left side by clicking on the top left addressbook button and select a recipient in order to start chatting with them", + recipientNotInDirectory: "recipient is not in directory.", + chatExternalInfo: "you have just received a chat. Chats are not supported by GimSIS, so you must reply by changing the subject to something else. Chat body: ", + // meals loginError: "login error", - loginToLopolis: "login to Lopolis", - loginToLopolisNote: "it seems like you're not currently logged in to eRestavracija, so this form has been presented to you. You have a different username and password combination used for applying and opting out of of menus. In order to use this feature, you have to log in with your Lopolis account.", - logInToLopolis: "log in to Lopolis", - logOutFromLopolis: "log out from Lopolis", - readOnly: "read only", - usage: "usage", - mealsUsageNote: "click on a date to open the collapsible menu with choices and click on a specific meal to select it. Reload the meals when you're done and check the entries.", - lunchesNote: "app was not tested with lunches in mind. Meals probably won't work with lunches and having a lunch subscription may even break its functionality.", - mealNotShownNote: "if a meal is not present in the meals collapsible field, this does not necessarily mean it does not exist. Meals that haven't been altered by you and are unchangable (read-only) are not shown for clarity.", - mealsContributeNote: "you are welcome to contribute to the LopolisAPI project and add features, such as checkouts.", - authenticationError: "authentication error", - lopolisAPIConnectionError: "LopolisAPI server connection error", - errorGettingMenus: "error getting menus", - errorUnexpectedResponse: "error: unexpected response", - requestForAuthenticationFailed: "request for authentication failed", - credentialsMatch: "credentials match", - errorSettingMeals: "error setting meals", - mealSet: "meal set! Reload meals to be sure", - selected: "selected", - // about - version: "version", - authors: "authors", - translatorsForThisLanguage: "translators for this language", - whatIsNew: "what's new", - whatsNew: "what's new", - reportABug: "report a bug", - sendASuggestion: "send a suggestion", - instagram: "instagram", - // changelog - changelog: "changelog", - // terms and conditions - termsOfUse: "terms of use", - termsOfUseDescription: "as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App", - termsOfUseHarass: "to abuse, harass, threaten, impersonate or intimidate any person", - termsOfUsePost: "to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person", - termsOfUseCommunicate: "to communicate with the App developers or other users in abusive or offensive manner", - termsOfUsePurpose: "for any purpose that is not permitted under the laws of the jurisdiction where you use the App", - termsOfUseExploit: "to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user", - termsOfUseSpam: "to create or transmit unwanted “spam” to any person or any URL", - termsOfUseModify: "you may also not reverse engineer, modify or redistribute the app without written consent from the developers", - terminationOfServices: "termination of services", - terminationOfServicesDescriptions: "the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons", - terminationOfServicesBreaching: "breaching the Terms of Service", - terminationOfServicesRequest: "receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App", - limitationOfLiability: "limitation of Liability", - limitationOfLiabilityContent: "the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.", - tosAreEffectiveAsOf: "the Terms of Service are effective as of", - // privacy policy - privacyImportant: "your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.", - privacyOnlyAskedWhen: "we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.", - privacyDataCollection: "we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.", - privacySharingData: "we don’t share any personally identifying information publicly or with third-parties, except when required to by law", - privacyExternalSites: "our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.", - privacyRefuse: "you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.", - privacyAcceptWithUse: "your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.", - privacyEffectiveAsOf: "this policy is effective as of", - // settings - language: "language", - selectLanguage: "select desired language", - languageSet: "language set, open another page for the changes to take effect", - theme: "theme", - themeLight: "light theme (default)", - themeDark: "dark theme", - themeNight: "night theme", - selectTheme: "select a theme", - triggerWarning: "the following switch enables additional settings, which some people may: disagree with, find annoying, be offended by them. By enabling the switch, you agree that you won't be triggered by any of the additional options and will not asociate any of the authors and/or their personal beliefs and opinions with additional options.", - triggerAgreement: "i agree with terms and conditions stated above", - triggerWarningSet: "additional settings toggled", - additionalOptions: "additional settings", - themeSet: "theme set, open another page for the changes to take effect", - errorReportingSet: "error reporting preference set", + loginToLopolis: "login to Lopolis", + loginToLopolisNote: "it seems like you're not currently logged in to eRestavracija, so this form has been presented to you. You have a different username and password combination used for applying and opting out of of menus. In order to use this feature, you have to log in with your Lopolis account.", + logInToLopolis: "log in to Lopolis", + logOutFromLopolis: "log out from Lopolis", + readOnly: "read only", + usage: "usage", + mealsUsageNote: "click on a date to open the collapsible menu with choices and click on a specific meal to select it. Reload the meals when you're done and check the entries.", + lunchesNote: "app was not tested with lunches in mind. Meals probably won't work with lunches and having a lunch subscription may even break its functionality.", + mealNotShownNote: "if a meal is not present in the meals collapsible field, this does not necessarily mean it does not exist. Meals that haven't been altered by you and are unchangable (read-only) are not shown for clarity.", + mealsContributeNote: "you are welcome to contribute to the LopolisAPI project and add features, such as checkouts.", + authenticationError: "authentication error", + lopolisAPIConnectionError: "LopolisAPI server connection error", + errorGettingMenus: "error getting menus", + errorUnexpectedResponse: "error: unexpected response", + requestForAuthenticationFailed: "request for authentication failed", + credentialsMatch: "credentials match", + errorSettingMeals: "error setting meals", + mealSet: "meal set! Reload meals to be sure", + selected: "selected", + // about + version: "version", + authors: "authors", + translatorsForThisLanguage: "translators for this language", + whatIsNew: "what's new", + whatsNew: "what's new", + reportABug: "report a bug", + sendASuggestion: "send a suggestion", + instagram: "instagram", + // changelog + changelog: "changelog", + // terms and conditions + termsOfUse: "terms of use", + termsOfUseDescription: "as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App", + termsOfUseHarass: "to abuse, harass, threaten, impersonate or intimidate any person", + termsOfUsePost: "to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person", + termsOfUseCommunicate: "to communicate with the App developers or other users in abusive or offensive manner", + termsOfUsePurpose: "for any purpose that is not permitted under the laws of the jurisdiction where you use the App", + termsOfUseExploit: "to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user", + termsOfUseSpam: "to create or transmit unwanted “spam” to any person or any URL", + termsOfUseModify: "you may also not reverse engineer, modify or redistribute the app without written consent from the developers", + terminationOfServices: "termination of services", + terminationOfServicesDescriptions: "the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons", + terminationOfServicesBreaching: "breaching the Terms of Service", + terminationOfServicesRequest: "receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App", + limitationOfLiability: "limitation of Liability", + limitationOfLiabilityContent: "the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.", + tosAreEffectiveAsOf: "the Terms of Service are effective as of", + // privacy policy + privacyImportant: "your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.", + privacyOnlyAskedWhen: "we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.", + privacyDataCollection: "we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.", + privacySharingData: "we don’t share any personally identifying information publicly or with third-parties, except when required to by law", + privacyExternalSites: "our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.", + privacyRefuse: "you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.", + privacyAcceptWithUse: "your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.", + privacyEffectiveAsOf: "this policy is effective as of", + // settings + language: "language", + selectLanguage: "select desired language", + languageSet: "language set, open another page for the changes to take effect", + theme: "theme", + themeLight: "light theme (default)", + themeDark: "dark theme", + themeNight: "night theme", + selectTheme: "select a theme", + triggerWarning: "the following switch enables additional settings, which some people may: disagree with, find annoying, be offended by them. By enabling the switch, you agree that you won't be triggered by any of the additional options and will not asociate any of the authors and/or their personal beliefs and opinions with additional options.", + triggerAgreement: "i agree with terms and conditions stated above", + triggerWarningSet: "additional settings toggled", + additionalOptions: "additional settings", + themeSet: "theme set, open another page for the changes to take effect", + errorReportingSet: "error reporting preference set", errorReporting: "error reporting", on: "on", off: "off", selectErrorReporting: "should error reports be submitted to the developers?", - // gsec - gsecErrNet: "GimSIS connection error", - gsecErrLogin: "GimSIS login error (bad password?), try logging out", - gsecErrOther: "GimSIS unknown error, try logging out", - // videoconferences - videoconferences: "GimB meet" - }, - sl: { - miscTranslationLanguage: "slovenščina", - miscTranslationAuthors: "Anton Luka Šijanec", - "": "", - // date - monday: "ponedeljek", - tuesday: "torek", - wednesday: "sreda", - thursday: "četrtek", - friday: "petek", - saturday: "sobota", - sunday: "nedelja", - am: "dop.", - pm: "pop.", - january: "januar", - february: "februar", - march: "marec", - april: "april", - may: "maj", - june: "junij", - july: "julij", - august: "avgust", - september: "september", - october: "oktober", - november: "november", - december: "december", - // login - username: "uporabniško ime", - password: "geslo", - signIn: "prijava", - bySigningInYouAgreeTo: "s prijavo se strinjate s", - theToS: "pogoji uporabe (v angleščini)", - and: "in", - thePrivacyPolicy: "politika zasebnosti (v angleščini)", - loginFailed: "prijava je spodletela", + // gsec + gsecErrNet: "GimSIS connection error", + gsecErrLogin: "GimSIS login error (bad password?), try logging out", + gsecErrOther: "GimSIS unknown error, try logging out", + // videoconferences + videoconferences: "GimB meet" + }, + sl: { + miscTranslationLanguage: "slovenščina", + miscTranslationAuthors: "Anton Luka Šijanec", + "": "", + // date + monday: "ponedeljek", + tuesday: "torek", + wednesday: "sreda", + thursday: "četrtek", + friday: "petek", + saturday: "sobota", + sunday: "nedelja", + am: "dop.", + pm: "pop.", + january: "januar", + february: "februar", + march: "marec", + april: "april", + may: "maj", + june: "junij", + july: "julij", + august: "avgust", + september: "september", + october: "oktober", + november: "november", + december: "december", + // login + username: "uporabniško ime", + password: "geslo", + signIn: "prijava", + bySigningInYouAgreeTo: "s prijavo se strinjate s", + theToS: "pogoji uporabe (v angleščini)", + and: "in", + thePrivacyPolicy: "politika zasebnosti (v angleščini)", + loginFailed: "prijava je spodletela", browserNotSupported: "BežiApp ne bo deloval na vaši napravi, če ne posodobite vašega Internetnega brskalnika", - // timetable - noPeriods: "ni ur v izbranem tednu", - // index - timetable: "urnik", - gradings: "ocenjevanja", - grades: "ocene", - teachers: "profesorji", - absences: "izostanki", - messaging: "sporočanje", - meals: "obroki", - about: "o", - logout: "odjava", - settings: "nastavitve", - // gradings - requestFailed: "zahteva spodletela", - noInternetConnection: "ni povezave s spletom", - // grades - temporary: "začasno", - useOnlyPermanentGrades: "uporabi le stalne ocene", - useOnlyPermanentGradesNote1: "če je označeno, bodo za izračun povprečja uporabljene le stalne ocene", - useOnlyPermanentGradesNote2: "če pa je polje neoznačeno, pa se ob izračunu povprečne ocene upoštevajo vse ocene", - type: "tip", - term: "rok", - teacher: "profesor", - // teachers - name: "ime", - schoolSubject: "predmet", - tpMeetings: "govorilne ure", - // absences - from: "od", - to: "do", - cancel: "preklic", - ok: "v redu", - noAbsences: "ni izostankov v izbranem časovnem obdobju", - lesson: "ura", - notProcessed: "ni obdelano", - authorizedAbsence: "opravičeno", - unauthorizedAbsence: "neopravičeno", - doesNotCount: "ne šteje", - // messaging - loadingMessages: "Nalagam sporočila...", - sendAMessage: "pošlji sporočilo", - recipient: "prejemnik", - messageSubject: "zadeva", - messageBody: "telo", - removeImages: "odstrani slike", - note: "opomba", - largeImagesNote: "GimB strežniki ne marajo velikih sporočil, zato lahko pošiljate le zelo majhne slike, v nasprotnem primeru sporočilo ne bo dostavljeno", - attachedImages: "pripete slike", - encryptMessage: "Šifriraj sporočilo", - passwordForE2EE: "geslo za šifriranje sporočila", - messages: "sporočila", - received: "prejeta", - sent: "poslana", - deleted: "izbrisana", - messageStorageUsed: "zasedenost shrambe sporočil v tej mapi", - maxMessagesNote: "v vsaki mapi imate lahko največ 120 sporočil. Starejša sporočila ne bodo prikazana. Redno brišite sporočila, da se izognete morebitnim težavam.", - loadMessageBody: "naloži telo sporočila", - thisMessageWasEncrypted: "to sporočilo je šifrirano", - enterPassword: "vnesite geslo", - decrypt: "dešifriraj", - nameDirectoryNotSet: "imenik ni nastavljen, pošiljanje ni mogoče", - errorFetchingMessages: "sporočil ni bilo mogoče prenesti", - unableToReceiveTheMessage: "sporočila ni bilo mogoče prenesti", - unableToDeleteTheMessage: "sporočila ni bilo mogoče izbrisati", - messageWasProbablySent: "sporočilo je bilo verjetno poslano, prepričajte se in preverite mapo s poslanimi sporočili", - errorSendingMessage: "sporočila ni bilo mogoče poslati", - imageAddedAsAnAttachment: "slika dodana kot priloga", - unableToReadDirectory: "imenika ni bilo mogoče prebrati", - messageCouldNotBeSent: "sporočila ni bilo mogoče poslati", - incorrectPassword: "nepravilno geslo", - // chats - chat: "klepet", - chattingWith: "klepet z osebo", - noMessages: "ni sporočil", - stillLoading: "nalaganje še poteka", - directory: "imenik", - select: "izberi", - mustSelectRecipient: "pred klepetom morate izbrati sogovornika. Odprite imenik (meni na levi strani) s pritiskom na gumb \"imenik\" zgoraj desno in izberite sogovornika.", - recipientNotInDirectory: "izbrane osebe ni v imeniku", - chatExternalInfo: "dobili ste kratko sporočilo v standardu, ki ga GimSIS ne podpira. Pri odgovarjanju spremenite zadevo. Vsebina sporočila: ", - // meals + // timetable + noPeriods: "ni ur v izbranem tednu", + // index + timetable: "urnik", + gradings: "ocenjevanja", + grades: "ocene", + teachers: "profesorji", + absences: "izostanki", + messaging: "sporočanje", + meals: "obroki", + about: "o", + logout: "odjava", + settings: "nastavitve", + // gradings + requestFailed: "zahteva spodletela", + noInternetConnection: "ni povezave s spletom", + // grades + temporary: "začasno", + useOnlyPermanentGrades: "uporabi le stalne ocene", + useOnlyPermanentGradesNote1: "če je označeno, bodo za izračun povprečja uporabljene le stalne ocene", + useOnlyPermanentGradesNote2: "če pa je polje neoznačeno, pa se ob izračunu povprečne ocene upoštevajo vse ocene", + type: "tip", + term: "rok", + teacher: "profesor", + // teachers + name: "ime", + schoolSubject: "predmet", + tpMeetings: "govorilne ure", + // absences + from: "od", + to: "do", + cancel: "preklic", + ok: "v redu", + noAbsences: "ni izostankov v izbranem časovnem obdobju", + lesson: "ura", + notProcessed: "ni obdelano", + authorizedAbsence: "opravičeno", + unauthorizedAbsence: "neopravičeno", + doesNotCount: "ne šteje", + // messaging + loadingMessages: "Nalagam sporočila...", + sendAMessage: "pošlji sporočilo", + recipient: "prejemnik", + messageSubject: "zadeva", + messageBody: "telo", + removeImages: "odstrani slike", + note: "opomba", + largeImagesNote: "GimB strežniki ne marajo velikih sporočil, zato lahko pošiljate le zelo majhne slike, v nasprotnem primeru sporočilo ne bo dostavljeno", + attachedImages: "pripete slike", + encryptMessage: "Šifriraj sporočilo", + passwordForE2EE: "geslo za šifriranje sporočila", + messages: "sporočila", + received: "prejeta", + sent: "poslana", + deleted: "izbrisana", + messageStorageUsed: "zasedenost shrambe sporočil v tej mapi", + maxMessagesNote: "v vsaki mapi imate lahko največ 120 sporočil. Starejša sporočila ne bodo prikazana. Redno brišite sporočila, da se izognete morebitnim težavam.", + loadMessageBody: "naloži telo sporočila", + thisMessageWasEncrypted: "to sporočilo je šifrirano", + enterPassword: "vnesite geslo", + decrypt: "dešifriraj", + nameDirectoryNotSet: "imenik ni nastavljen, pošiljanje ni mogoče", + errorFetchingMessages: "sporočil ni bilo mogoče prenesti", + unableToReceiveTheMessage: "sporočila ni bilo mogoče prenesti", + unableToDeleteTheMessage: "sporočila ni bilo mogoče izbrisati", + messageWasProbablySent: "sporočilo je bilo verjetno poslano, prepričajte se in preverite mapo s poslanimi sporočili", + errorSendingMessage: "sporočila ni bilo mogoče poslati", + imageAddedAsAnAttachment: "slika dodana kot priloga", + unableToReadDirectory: "imenika ni bilo mogoče prebrati", + messageCouldNotBeSent: "sporočila ni bilo mogoče poslati", + incorrectPassword: "nepravilno geslo", + // chats + chat: "klepet", + chattingWith: "klepet z osebo", + noMessages: "ni sporočil", + stillLoading: "nalaganje še poteka", + directory: "imenik", + select: "izberi", + mustSelectRecipient: "pred klepetom morate izbrati sogovornika. Odprite imenik (meni na levi strani) s pritiskom na gumb \"imenik\" zgoraj desno in izberite sogovornika.", + recipientNotInDirectory: "izbrane osebe ni v imeniku", + chatExternalInfo: "dobili ste kratko sporočilo v standardu, ki ga GimSIS ne podpira. Pri odgovarjanju spremenite zadevo. Vsebina sporočila: ", + // meals loginError: "napaka pri prijavi", - loginToLopolis: "prijava v Lopolis", - loginToLopolisNote: "izgleda, da niste prijavljeni v eRestavracijo, zato se vam je prikazal prijavni obrazec. Za uporavljanje s prehrano se uporablja druga kombinacija uporabniškega imena in gesla, zato se prijavite s svojimi Lopolis prijavnimi podatki za nadaljevanje.", - logInToLopolis: "prijava v Lopolis", - logOutFromLopolis: "odjava iz Lopolisa", - readOnly: "samo za branje", - usage: "uporaba", - mealsUsageNote: "kliknite na datum za prikaz menijev, nato pa si enega izberite s klikom na ime menija. Po nastavitvi menijev ponovno naložite menije in se prepričajte o pravilnih nastavitvah.", - lunchesNote: "aplikacija ni testirana za naročanje na koslila, zato verjetno to ne deluje. Če ste naročeni na kosila lahko naročanje na menije sploh ne deluje ali pa deluje narobe.", - mealNotShownNote: "če nek dan manjka med meniji, to verjetno pomeni, da ni več spremenljiv in zanj niste ročno spremenili menija", - mealsContributeNote: "vabimo vas k urejanju LopolisAPI programa za upravljanje z meniji.", - authenticationError: "napaka avtentikacije", - lopolisAPIConnectionError: "napaka povezave na LopolisAPI strežnik", - errorGettingMenus: "napaka branja menijev", - errorUnexpectedResponse: "napaka: nepričakovan odgovor", - requestForAuthenticationFailed: "zahteva za avtentikacijo ni uspela", - credentialsMatch: "prijavni podatki so pravilni", - errorSettingMeals: "napaka pri nastavljanju menijev", - mealSet: "obrok nastavljen! osvežite obroke in se prepričajte sami", - selected: "izbrano", - // about - version: "različica", - authors: "avtorji", - translatorsForThisLanguage: "prevajalci izbranega jezika", - whatIsNew: "kaj je novega", - whatsNew: "kaj je novega", - reportABug: "prijavite napako", - sendASuggestion: "pošljite pripombo/predlog/pohvalo/pritožbo", - instagram: "instagram", - // changelog - changelog: "dnevnik sprememb", - // terms and conditions - termsOfUse: "terms of use", - termsOfUseDescription: "as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App", - termsOfUseHarass: "to abuse, harass, threaten, impersonate or intimidate any person", - termsOfUsePost: "to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person", - termsOfUseCommunicate: "to communicate with the App developers or other users in abusive or offensive manner", - termsOfUsePurpose: "for any purpose that is not permitted under the laws of the jurisdiction where you use the App", - termsOfUseExploit: "to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user", - termsOfUseSpam: "to create or transmit unwanted “spam” to any person or any URL", - termsOfUseModify: "you may also not reverse engineer, modify or redistribute the app without written consent from the developers", - terminationOfServices: "termination of services", - terminationOfServicesDescriptions: "the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons", - terminationOfServicesBreaching: "breaching the Terms of Service", - terminationOfServicesRequest: "receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App", - limitationOfLiability: "limitation of Liability", - limitationOfLiabilityContent: "the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.", - tosAreEffectiveAsOf: "the Terms of Service are effective as of", - // privacy policy - privacyImportant: "your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.", - privacyOnlyAskedWhen: "we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.", - privacyDataCollection: "we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.", - privacySharingData: "we don’t share any personally identifying information publicly or with third-parties, except when required to by law", - privacyExternalSites: "our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.", - privacyRefuse: "you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.", - privacyAcceptWithUse: "your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.", - privacyEffectiveAsOf: "this policy is effective as of", - // settings + loginToLopolis: "prijava v Lopolis", + loginToLopolisNote: "izgleda, da niste prijavljeni v eRestavracijo, zato se vam je prikazal prijavni obrazec. Za uporavljanje s prehrano se uporablja druga kombinacija uporabniškega imena in gesla, zato se prijavite s svojimi Lopolis prijavnimi podatki za nadaljevanje.", + logInToLopolis: "prijava v Lopolis", + logOutFromLopolis: "odjava iz Lopolisa", + readOnly: "samo za branje", + usage: "uporaba", + mealsUsageNote: "kliknite na datum za prikaz menijev, nato pa si enega izberite s klikom na ime menija. Po nastavitvi menijev ponovno naložite menije in se prepričajte o pravilnih nastavitvah.", + lunchesNote: "aplikacija ni testirana za naročanje na koslila, zato verjetno to ne deluje. Če ste naročeni na kosila lahko naročanje na menije sploh ne deluje ali pa deluje narobe.", + mealNotShownNote: "če nek dan manjka med meniji, to verjetno pomeni, da ni več spremenljiv in zanj niste ročno spremenili menija", + mealsContributeNote: "vabimo vas k urejanju LopolisAPI programa za upravljanje z meniji.", + authenticationError: "napaka avtentikacije", + lopolisAPIConnectionError: "napaka povezave na LopolisAPI strežnik", + errorGettingMenus: "napaka branja menijev", + errorUnexpectedResponse: "napaka: nepričakovan odgovor", + requestForAuthenticationFailed: "zahteva za avtentikacijo ni uspela", + credentialsMatch: "prijavni podatki so pravilni", + errorSettingMeals: "napaka pri nastavljanju menijev", + mealSet: "obrok nastavljen! osvežite obroke in se prepričajte sami", + selected: "izbrano", + // about + version: "različica", + authors: "avtorji", + translatorsForThisLanguage: "prevajalci izbranega jezika", + whatIsNew: "kaj je novega", + whatsNew: "kaj je novega", + reportABug: "prijavite napako", + sendASuggestion: "pošljite pripombo/predlog/pohvalo/pritožbo", + instagram: "instagram", + // changelog + changelog: "dnevnik sprememb", + // terms and conditions + termsOfUse: "terms of use", + termsOfUseDescription: "as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App", + termsOfUseHarass: "to abuse, harass, threaten, impersonate or intimidate any person", + termsOfUsePost: "to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person", + termsOfUseCommunicate: "to communicate with the App developers or other users in abusive or offensive manner", + termsOfUsePurpose: "for any purpose that is not permitted under the laws of the jurisdiction where you use the App", + termsOfUseExploit: "to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user", + termsOfUseSpam: "to create or transmit unwanted “spam” to any person or any URL", + termsOfUseModify: "you may also not reverse engineer, modify or redistribute the app without written consent from the developers", + terminationOfServices: "termination of services", + terminationOfServicesDescriptions: "the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons", + terminationOfServicesBreaching: "breaching the Terms of Service", + terminationOfServicesRequest: "receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App", + limitationOfLiability: "limitation of Liability", + limitationOfLiabilityContent: "the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.", + tosAreEffectiveAsOf: "the Terms of Service are effective as of", + // privacy policy + privacyImportant: "your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.", + privacyOnlyAskedWhen: "we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.", + privacyDataCollection: "we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.", + privacySharingData: "we don’t share any personally identifying information publicly or with third-parties, except when required to by law", + privacyExternalSites: "our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.", + privacyRefuse: "you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.", + privacyAcceptWithUse: "your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.", + privacyEffectiveAsOf: "this policy is effective as of", + // settings language: "jezik", - selectLanguage: "izberite željen jezik", - languageSet: "jezik nastavljen, odprite neko drugo stran da se pokažejo spremembe", - 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", + selectLanguage: "izberite željen jezik", + languageSet: "jezik nastavljen, odprite neko drugo stran da se pokažejo spremembe", + 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", errorReporting: "pošiljanje napak", on: "vklopljeno", off: "izklopljeno", - selectErrorReporting: "ali naj so napake v aplikaciji posredovane razvijalcem?", - triggerWarning: "spodnji gumb omogoči dodatne možnosti, ki lahko razburijo/vznevoljijo nekatere uporabnike. Če omogočite stikalo se strinjate, da avtorjev in/ali njihovih osebnih prepričanj ne boste povezovali s katerokoli od dodatnih omogočenih možnosti.", - triggerAgreement: "strinjam se z zgoraj navedenimi pogoji", - triggerWarningSet: "spremenili ste stanje dodatnih nastavitev", - additionalOptions: "dodatne nastavitve", - // gsec - gsecErrNet: "napaka povezave na GimSIS", - gsecErrLogin: "prijava v GimSIS ni uspela (napačno geslo?), poskusite se odjaviti", - gsecErrOther: "neznana napaka GimSISa, poskusite se odjaviti", - // videoconferences - videoconferences: "GimB konference" - } + selectErrorReporting: "ali naj so napake v aplikaciji posredovane razvijalcem?", + triggerWarning: "spodnji gumb omogoči dodatne možnosti, ki lahko razburijo/vznevoljijo nekatere uporabnike. Če omogočite stikalo se strinjate, da avtorjev in/ali njihovih osebnih prepričanj ne boste povezovali s katerokoli od dodatnih omogočenih možnosti.", + triggerAgreement: "strinjam se z zgoraj navedenimi pogoji", + triggerWarningSet: "spremenili ste stanje dodatnih nastavitev", + additionalOptions: "dodatne nastavitve", + // gsec + gsecErrNet: "napaka povezave na GimSIS", + gsecErrLogin: "prijava v GimSIS ni uspela (napačno geslo?), poskusite se odjaviti", + gsecErrOther: "neznana napaka GimSISa, poskusite se odjaviti", + // videoconferences + videoconferences: "GimB konference" + } } diff --git a/assets/js/lib/themes.js b/assets/js/lib/themes.js index d2e99ce..c021e26 100644 --- a/assets/js/lib/themes.js +++ b/assets/js/lib/themes.js @@ -114,8 +114,8 @@ const THEME_COLOR_SCHEMES = { }, right: { "color-primary": "rgba(7, 0, 105, 1)", - "color-secondary": "rgba(206, 217, 0, 1)", - "color-accent": "rgba(0, 94, 156, 1)", + "color-secondary": "rgba(0, 94, 156, 1)", + "color-accent": "rgba(217, 214, 80, 1)", "color-primary-light": "rgba(195, 191, 255, 1)", "color-invalid": "rgba(192, 0, 0, 1)", "color-primary-transparent": "rgba(7, 0, 105, 0.3)", diff --git a/assets/js/messaging.js b/assets/js/messaging.js index 305b355..890da18 100644 --- a/assets/js/messaging.js +++ b/assets/js/messaging.js @@ -356,8 +356,8 @@ function displayData(messageType) { 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"> + <div class="card color-card"> + <div class="card-content general-text"> <span class="card-title"> ${filterXSS(element["zadeva"])} </span> diff --git a/assets/js/settings.js b/assets/js/settings.js index f9e3c79..2cc6029 100644 --- a/assets/js/settings.js +++ b/assets/js/settings.js @@ -1,66 +1,67 @@ // settings.js -- TODO async function setLanguage(langCode) { - localforage.setItem("chosenLang", langCode).then((value) => { - console.log("Language set: " + value); - UIAlert(D("languageSet"), "setLanguage(): languageSet"); - }); + localforage.setItem("chosenLang", langCode).then((value) => { + console.log("Language set: " + value); + UIAlert(D("languageSet"), "setLanguage(): languageSet"); + }); } async function setTheme(targetTheme) { - localforage.setItem("theme", targetTheme).then((value) => { - console.log("Theme set: " + value); - UIAlert(D("themeSet"), "setTheme(): themeSet"); - }); + localforage.setItem("theme", targetTheme).then((value) => { + console.log("Theme set: " + value); + UIAlert(D("themeSet"), "setTheme(): themeSet"); + }); } async function setErrorReporting(targetE) { - localforage.setItem("errorReporting", targetE).then((value) => { - console.log("ErrorReporing set: " + value); - UIAlert(D("errorReportingSet"), "setErrorReporting(): errorReportingSet"); - }); + localforage.setItem("errorReporting", targetE).then((value) => { + console.log("ErrorReporing set: " + value); + UIAlert(D("errorReportingSet"), "setErrorReporting(): errorReportingSet"); + }); } function shuffleArray(array) { - for (var i = array.length - 1; i > 0; i--) { - var j = Math.floor(Math.random() * (i + 1)); - var temp = array[i]; - array[i] = array[j]; - array[j] = temp; - } + for (var i = array.length - 1; i > 0; i--) { + var j = Math.floor(Math.random() * (i + 1)); + var temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } } function setUIAdditionalOptions(state) { - var SENSITIVE_THEMES = { - "left": "Left / leva", - "right": "Right / desna" - }; - if (state === true) { - var theme_keys = Object.keys(SENSITIVE_THEMES); - shuffleArray(theme_keys); - theme_keys.forEach((item) => { - var option_element = $(`<option value="${item}" id="option-${item}" data-theme="${item}">${SENSITIVE_THEMES[item]}</option>`); - $("#select-theme").append(option_element); - }); - } else { - Object.keys(SENSITIVE_THEMES).forEach((item) => { - $("#option-" + item).remove(); - }); - } - $("#select-theme").formSelect(); + var SENSITIVE_THEMES = { + "left": "Left / leva", + "right": "Right / desna" + }; + if (state === true) { + var theme_keys = Object.keys(SENSITIVE_THEMES); + shuffleArray(theme_keys); + theme_keys.forEach((item) => { + var option_element = $(`<option value="${item}" id="option-${item}" data-theme="${item}">${SENSITIVE_THEMES[item]}</option>`); + $("#select-theme").append(option_element); + }); + } else { + Object.keys(SENSITIVE_THEMES).forEach((item) => { + $("#option-" + item).remove(); + }); + } + var elems = document.querySelectorAll('#select-theme'); + M.FormSelect.init(elems, {}); } async function setAdditionalOptions(state) { - localforage.setItem("triggerWarningAccepted", state).then((value) => { - console.log("TriggerWarning set: " + value); - UIAlert(D("triggerWarningSet"), "setAdditionalOptions(): triggerWarningSet"); - setUIAdditionalOptions(value); - }); + localforage.setItem("triggerWarningAccepted", state).then((value) => { + console.log("TriggerWarning set: " + value); + UIAlert(D("triggerWarningSet"), "setAdditionalOptions(): triggerWarningSet"); + setUIAdditionalOptions(value); + }); } document.addEventListener("DOMContentLoaded", async () => { - // Setup checkbox handler + // Setup checkbox handler $("#triggered-checkbox").change(function() { if (this.checked) { setAdditionalOptions(true); @@ -69,53 +70,60 @@ document.addEventListener("DOMContentLoaded", async () => { } }); - $("#select-language").on("change", function() { - setLanguage($(this).find(":selected").val()); - }); + $("#select-language").on("change", function() { + setLanguage($(this).find(":selected").val()); + }); - $("#select-theme").on("change", function() { - setTheme($(this).find(":selected").val()); - }); + $("#select-theme").on("change", function() { + setTheme($(this).find(":selected").val()); + }); - $("#select-errorreporting").on("change", function() { - setErrorReporting($(this).find(":selected").val()); - }); + $("#select-errorreporting").on("change", function() { + setErrorReporting($(this).find(":selected").val()); + }); - localforage.getItem("chosenLang").then((value) => { - let selectedLanguage = value; + localforage.getItem("chosenLang").then((value) => { + let selectedLanguage = value; if(value == null || value.length < 1) { selectedLanguage = "sl"; } - $(`#option-${selectedLanguage}`).attr("selected", true); - }).catch(() => {}); + $(`#option-${selectedLanguage}`).attr("selected", true); + }).catch(() => {}); - localforage.getItem("theme").then((value) => { - let selectedTheme = value; + localforage.getItem("theme").then((value) => { + let selectedTheme = value; if(value == null || value.length < 1) { selectedTheme = "themeLight"; } - $(`#option-${selectedTheme}`).attr("selected", true); - }).catch(() => {}); + $(`#option-${selectedTheme}`).attr("selected", true); + }).catch(() => {}); - localforage.getItem("errorReporting").then((value) => { - let selectedE = value; + localforage.getItem("errorReporting").then((value) => { + let selectedE = value; if(value == null || value.length < 1) { selectedE = "on"; } - $(`#option-${selectedE}`).attr("selected", true); - }).catch(() => {}); - - // Setup side menu - const menus = document.querySelectorAll(".side-menu"); - M.Sidenav.init(menus, { edge: "right", draggable: true }); - - var elems = document.querySelectorAll(".theme-select"); - M.FormSelect.init(elems, {}); - - var elems = document.querySelectorAll(".errorreporting-select"); - M.FormSelect.init(elems, {}); - - // Setup language select dropdown - var elems = document.querySelectorAll(".lang-select"); - M.FormSelect.init(elems, {}); + $(`#option-${selectedE}`).attr("selected", true); + }).catch(() => {}); + + localforage.getItem("triggerWarningAccepted").then((value) => { + if (value === true) { + $("#triggered-checkbox").attr("checked", true); + setUIAdditionalOptions(true); + } + }).catch(() => {}); + + // Setup side menu + const menus = document.querySelectorAll(".side-menu"); + M.Sidenav.init(menus, { edge: "right", draggable: true }); + + var elems = document.querySelectorAll(".theme-select"); + M.FormSelect.init(elems, {}); + + var elems = document.querySelectorAll(".errorreporting-select"); + M.FormSelect.init(elems, {}); + + // Setup language select dropdown + var elems = document.querySelectorAll(".lang-select"); + M.FormSelect.init(elems, {}); }); diff --git a/assets/pages-src/settings.bvr b/assets/pages-src/settings.bvr index 46a9299..e3ebb9c 100644 --- a/assets/pages-src/settings.bvr +++ b/assets/pages-src/settings.bvr @@ -103,7 +103,7 @@ <h5 class="general-text"><x-su>additionalOptions</x-su></h5> </div> <div class="col s12"> - <p class="flow-text general-text"><x-du>triggerWarning</x-du></p> + <p class="general-text"><x-du>triggerWarning</x-du></p> </div> <div class="valign-wrapper col s12 m12"> <label> diff --git a/dist/css/styles.css b/dist/css/styles.css index 0c00378..4e6050b 100755 --- a/dist/css/styles.css +++ b/dist/css/styles.css @@ -47,6 +47,10 @@ body { background-color: var(--color-primary); } +.color-card { + color: var(--color-primary-light); +} + nav { background: var(--color-primary); border-bottom: 10px solid var(--color-accent); @@ -95,6 +99,10 @@ a { color: var(--color-accent); } +.card-action > a { + color: var(--color-accent) !important; +} + a.collection-item { color: var(--color-primary) !important; } @@ -109,11 +117,12 @@ a.collection-item { .datepicker-table td.is-selected { background-color: var(--color-primary); + color: var(--background-color) !important; } .datepicker-table td.is-selected.is-today { background-color: var(--color-primary); - color: var(--background-color); + color: var(--background-color) !important; } .datepicker-cancel { @@ -148,6 +157,10 @@ a.collection-item { background-color: var(--color-primary) !important; } +.determinate { + background-color: var(--color-primary) !important; +} + .no-select { -webkit-touch-callout: none; -webkit-user-select: none; diff --git a/dist/js/app.js b/dist/js/app.js index ea2e351..567524a 100755 --- a/dist/js/app.js +++ b/dist/js/app.js @@ -2,8 +2,8 @@ -const app_version = "1.0.14-beta"; -const previous_commit = "bf1bb2d36542cc2adf7b41dd347d3d77171cf1ce"; +const app_version = "1.0.13-beta"; +const previous_commit = "29b013b7591c0ee674bb8c2cf8cc660f67cdd9f7"; if ("serviceWorker" in navigator) { navigator.serviceWorker.register("/sw.js") diff --git a/dist/js/lang/bundle.js b/dist/js/lang/bundle.js index c375a9b..8270527 100644 --- a/dist/js/lang/bundle.js +++ b/dist/js/lang/bundle.js @@ -1,10 +1,513 @@ +// there's an DoS backdoor in BežiApp because of this (-:< +var chosenLang; +var dateString = { + day: (danv) => { + let dnevitedna = [S("sunday"), S("monday"), S("tuesday"), S("wednesday"), S("thursday"), S("friday"), S("saturday")]; + return dnevitedna[danv]; + }, + month: (mesl) => { + let mesecileta = [S("january"), S("february"), S("march"), S("april"), S("may"), S("june"), S("july"), S("august"), S("september"), S("october"), S("november"), S("december")]; + return mesecileta[mesl]; + }, + longFormatted: (dateObject) => { + return dateString.day(dateObject.getDay())+", "+(dateObject.getDate())+". "+dateString.month(dateObject.getMonth())+" "+dateObject.getFullYear(); + } +}; +async function refreshLangDOM() { + let promises_to_runn = [ + localforage.getItem("chosenLang").then( (value) => { + chosenLang = value; + }) + // localforage.getItem("chosenCapitalize").then( (value) => { // poor unused code + // chosenCapitalize = value; + // }) + ]; + await Promise.all(promises_to_runn); + // this could be done nicer. p. s.: lahko bi se uporablil x-s in x-S za razločitev med capitalize in !capitalize queryselectorall ni case sensitive za imena elementov + let stringContainerss = document.querySelectorAll("x-sl:not(.langFinished)"); + for (i = 0; i < stringContainerss.length; i++) { + stringContainerss[i].innerHTML = s(stringContainerss[i].innerHTML); + stringContainerss[i].classList.add("langFinished"); + stringContainerss[i].hidden = false; + } + let stringContainersd = document.querySelectorAll("x-dl:not(.langFinished)"); + for (i = 0; i < stringContainersd.length; i++) { + stringContainersd[i].innerHTML = d(stringContainersd[i].innerHTML); + stringContainersd[i].classList.add("langFinished"); + stringContainersd[i].hidden = false; + } + let stringContainersS = document.querySelectorAll("x-su:not(.langFinished)"); + for (i = 0; i < stringContainersS.length; i++) { + stringContainersS[i].innerHTML = S(stringContainersS[i].innerHTML); + stringContainersS[i].classList.add("langFinished"); + stringContainersS[i].hidden = false; + } + let stringContainersD = document.querySelectorAll("x-du:not(.langFinished)"); + for (i = 0; i < stringContainersD.length; i++) { + stringContainersD[i].innerHTML = D(stringContainersD[i].innerHTML); + stringContainersD[i].classList.add("langFinished"); + stringContainersD[i].hidden = false; + } +} +async function setLangConfigAndReload() { + let promises_to_run = [ + /* localforage.setItem("chosenCapitalize", true), */ // F for unused code + localforage.setItem("chosenLang", "en") + ]; + await Promise.all(promises_to_run); + window.location.reload(); +} +window.addEventListener("DOMContentLoaded", () => { + localforage.getItem("chosenLang").then( (value) => { + if(value == null) { + setLangConfigAndReload(); + } else { + chosenLang = value; + } + }); + refreshLangDOM(); +}); -var chosenLang;var dateString={day:(danv)=>{let dnevitedna=[S("sunday"),S("monday"),S("tuesday"),S("wednesday"),S("thursday"),S("friday"),S("saturday")];return dnevitedna[danv];},month:(mesl)=>{let mesecileta=[S("january"),S("february"),S("march"),S("april"),S("may"),S("june"),S("july"),S("august"),S("september"),S("october"),S("november"),S("december")];return mesecileta[mesl];},longFormatted:(dateObject)=>{return dateString.day(dateObject.getDay())+", "+(dateObject.getDate())+". "+dateString.month(dateObject.getMonth())+" "+dateObject.getFullYear();}};async function refreshLangDOM(){let promises_to_runn=[localforage.getItem("chosenLang").then((value)=>{chosenLang=value;})];await Promise.all(promises_to_runn);let stringContainerss=document.querySelectorAll("x-sl:not(.langFinished)");for(i=0;i<stringContainerss.length;i++){stringContainerss[i].innerHTML=s(stringContainerss[i].innerHTML);stringContainerss[i].classList.add("langFinished");stringContainerss[i].hidden=false;} -let stringContainersd=document.querySelectorAll("x-dl:not(.langFinished)");for(i=0;i<stringContainersd.length;i++){stringContainersd[i].innerHTML=d(stringContainersd[i].innerHTML);stringContainersd[i].classList.add("langFinished");stringContainersd[i].hidden=false;} -let stringContainersS=document.querySelectorAll("x-su:not(.langFinished)");for(i=0;i<stringContainersS.length;i++){stringContainersS[i].innerHTML=S(stringContainersS[i].innerHTML);stringContainersS[i].classList.add("langFinished");stringContainersS[i].hidden=false;} -let stringContainersD=document.querySelectorAll("x-du:not(.langFinished)");for(i=0;i<stringContainersD.length;i++){stringContainersD[i].innerHTML=D(stringContainersD[i].innerHTML);stringContainersD[i].classList.add("langFinished");stringContainersD[i].hidden=false;}} -async function setLangConfigAndReload(){let promises_to_run=[localforage.setItem("chosenLang","en")];await Promise.all(promises_to_run);window.location.reload();} -window.addEventListener("DOMContentLoaded",()=>{localforage.getItem("chosenLang").then((value)=>{if(value==null){setLangConfigAndReload();}else{chosenLang=value;}});refreshLangDOM();});const capitalize=(s)=>{if(typeof s!=='string')return'' -return s.charAt(0).toUpperCase()+s.slice(1)} -var s=function(whatString){return getLang.s(whatString);};var d=function(whatString){return getLang.d(whatString);};var S=function(whatString){return getLang.S(whatString);};var D=function(whatString){return getLang.D(whatString);};var getLang={s:function(whatString){return langstrings[chosenLang][whatString];},S:function(whatString){return capitalize(langstrings[chosenLang][whatString]);},d:function(whatString){if(langstrings[chosenLang][whatString].slice(-1)!="."){return langstrings[chosenLang][whatString]+".";}else{return langstrings[chosenLang][whatString];}},D:function(whatString){if(langstrings[chosenLang][whatString].slice(-1)!="."){return capitalize(langstrings[chosenLang][whatString]+".");}else{return capitalize(langstrings[chosenLang][whatString]);}},} -var langstrings={en:{miscTranslationLanguage:"English",miscTranslationAuthors:"Rok Štular","":"",monday:"monday",tuesday:"tuesday",wednesday:"wednesday",thursday:"thursday",friday:"friday",saturday:"saturday",sunday:"sunday",am:"am",pm:"pm",january:"january",february:"february",march:"march",april:"april",may:"may",june:"june",july:"july",august:"august",september:"september",october:"october",november:"november",december:"december",username:"username",password:"password",signIn:"sign in",bySigningInYouAgreeTo:"by signing in, you agree to",theToS:"the terms and conditions",and:"and",thePrivacyPolicy:"the privacy policy",loginFailed:"login failed",browserNotSupported:"bežiapp won't work on your device, unless you update your Internet browser",timetable:"timetable",gradings:"gradings",grades:"grades",teachers:"teachers",absences:"absences",messaging:"messaging",meals:"meals",about:"about",logout:"logout",settings:"settings",noPeriods:"no periods in selected week",requestFailed:"request failed",noInternetConnection:"no internet connection",temporary:"temporary",useOnlyPermanentGrades:"use only permanent grades",useOnlyPermanentGradesNote1:"if checked, only permanent grades will be used in the average grade calculation",useOnlyPermanentGradesNote2:"if left unchecked, the calculation will include every available grade",type:"type",term:"term",teacher:"teacher",name:"name",schoolSubject:"subject",tpMeetings:"TP meetings",from:"from",to:"to",cancel:"cancel",ok:"ok",noAbsences:"no absences in the chosen time period",lesson:"lesson",notProcessed:"not processed",authorizedAbsence:"authorized",unauthorizedAbsence:"unauthorized",doesNotCount:"does not count",loadingMessages:"Loading messages...",sendAMessage:"send a message",recipient:"recipient",messageSubject:"subject",messageBody:"message body",removeImages:"remove images",note:"note",largeImagesNote:"GimB servers don't like large messages, so only very small images may be attached or your message will not be delivered",attachedImages:"attached images",encryptMessage:"Encrypt message",passwordForE2EE:"password for encrypting the message",messages:"messages",received:"received",sent:"sent",deleted:"deleted",messageStorageUsed:"message storage used in this folder",maxMessagesNote:"you can only have 120 messages per message folder, older messages will not be shown. Remember to delete read and sent messages regulary to avoid any issues.",loadMessageBody:"load message body",thisMessageWasEncrypted:"this message was encrypted",enterPassword:"enter password",decrypt:"decrypt",nameDirectoryNotSet:"name directory not set, sending unavailable",errorFetchingMessages:"error fetching messages",unableToReceiveTheMessage:"unable to receive the message",unableToDeleteTheMessage:"unable to delete the message",messageWasProbablySent:"message was probably sent, check the Sent folder to be sure",errorSendingMessage:"error sending message",imageAddedAsAnAttachment:"image added as an attachment",unableToReadDirectory:"unable to read directory of people",messageCouldNotBeSent:"message could to be sent",incorrectPassword:"incorrect password",chat:"chat",chattingWith:"chatting with",noMessages:"no messages",stillLoading:"loading is still in progress",directory:"directory",select:"select",mustSelectRecipient:"you have to select a recipient before chatting. Open directory on the left side by clicking on the top left addressbook button and select a recipient in order to start chatting with them",recipientNotInDirectory:"recipient is not in directory.",chatExternalInfo:"you have just received a chat. Chats are not supported by GimSIS, so you must reply by changing the subject to something else. Chat body: ",loginError:"login error",loginToLopolis:"login to Lopolis",loginToLopolisNote:"it seems like you're not currently logged in to eRestavracija, so this form has been presented to you. You have a different username and password combination used for applying and opting out of of menus. In order to use this feature, you have to log in with your Lopolis account.",logInToLopolis:"log in to Lopolis",logOutFromLopolis:"log out from Lopolis",readOnly:"read only",usage:"usage",mealsUsageNote:"click on a date to open the collapsible menu with choices and click on a specific meal to select it. Reload the meals when you're done and check the entries.",lunchesNote:"app was not tested with lunches in mind. Meals probably won't work with lunches and having a lunch subscription may even break its functionality.",mealNotShownNote:"if a meal is not present in the meals collapsible field, this does not necessarily mean it does not exist. Meals that haven't been altered by you and are unchangable (read-only) are not shown for clarity.",mealsContributeNote:"you are welcome to contribute to the LopolisAPI project and add features, such as checkouts.",authenticationError:"authentication error",lopolisAPIConnectionError:"LopolisAPI server connection error",errorGettingMenus:"error getting menus",errorUnexpectedResponse:"error: unexpected response",requestForAuthenticationFailed:"request for authentication failed",credentialsMatch:"credentials match",errorSettingMeals:"error setting meals",mealSet:"meal set! Reload meals to be sure",selected:"selected",version:"version",authors:"authors",translatorsForThisLanguage:"translators for this language",whatIsNew:"what's new",whatsNew:"what's new",reportABug:"report a bug",sendASuggestion:"send a suggestion",instagram:"instagram",changelog:"changelog",termsOfUse:"terms of use",termsOfUseDescription:"as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App",termsOfUseHarass:"to abuse, harass, threaten, impersonate or intimidate any person",termsOfUsePost:"to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person",termsOfUseCommunicate:"to communicate with the App developers or other users in abusive or offensive manner",termsOfUsePurpose:"for any purpose that is not permitted under the laws of the jurisdiction where you use the App",termsOfUseExploit:"to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user",termsOfUseSpam:"to create or transmit unwanted “spam” to any person or any URL",termsOfUseModify:"you may also not reverse engineer, modify or redistribute the app without written consent from the developers",terminationOfServices:"termination of services",terminationOfServicesDescriptions:"the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons",terminationOfServicesBreaching:"breaching the Terms of Service",terminationOfServicesRequest:"receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App",limitationOfLiability:"limitation of Liability",limitationOfLiabilityContent:"the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.",tosAreEffectiveAsOf:"the Terms of Service are effective as of",privacyImportant:"your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.",privacyOnlyAskedWhen:"we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.",privacyDataCollection:"we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.",privacySharingData:"we don’t share any personally identifying information publicly or with third-parties, except when required to by law",privacyExternalSites:"our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.",privacyRefuse:"you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.",privacyAcceptWithUse:"your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.",privacyEffectiveAsOf:"this policy is effective as of",language:"language",selectLanguage:"select desired language",languageSet:"language set, open another page for the changes to take effect",theme:"theme",themeLight:"light theme (default)",themeDark:"dark theme",themeNight:"night theme",selectTheme:"select a theme",triggerWarning:"the following switch enables additional settings, which some people may: disagree with, find annoying, be offended by them. By enabling the switch, you agree that you won't be triggered by any of the additional options and will not asociate any of the authors and/or their personal beliefs and opinions with additional options.",triggerAgreement:"i agree with terms and conditions stated above",triggerWarningSet:"additional settings toggled",additionalOptions:"additional settings",themeSet:"theme set, open another page for the changes to take effect",errorReportingSet:"error reporting preference set",errorReporting:"error reporting",on:"on",off:"off",selectErrorReporting:"should error reports be submitted to the developers?",gsecErrNet:"GimSIS connection error",gsecErrLogin:"GimSIS login error (bad password?), try logging out",gsecErrOther:"GimSIS unknown error, try logging out",videoconferences:"GimB meet"},sl:{miscTranslationLanguage:"slovenščina",miscTranslationAuthors:"Anton Luka Šijanec","":"",monday:"ponedeljek",tuesday:"torek",wednesday:"sreda",thursday:"četrtek",friday:"petek",saturday:"sobota",sunday:"nedelja",am:"dop.",pm:"pop.",january:"januar",february:"februar",march:"marec",april:"april",may:"maj",june:"junij",july:"julij",august:"avgust",september:"september",october:"oktober",november:"november",december:"december",username:"uporabniško ime",password:"geslo",signIn:"prijava",bySigningInYouAgreeTo:"s prijavo se strinjate s",theToS:"pogoji uporabe (v angleščini)",and:"in",thePrivacyPolicy:"politika zasebnosti (v angleščini)",loginFailed:"prijava je spodletela",browserNotSupported:"BežiApp ne bo deloval na vaši napravi, če ne posodobite vašega Internetnega brskalnika",noPeriods:"ni ur v izbranem tednu",timetable:"urnik",gradings:"ocenjevanja",grades:"ocene",teachers:"profesorji",absences:"izostanki",messaging:"sporočanje",meals:"obroki",about:"o",logout:"odjava",settings:"nastavitve",requestFailed:"zahteva spodletela",noInternetConnection:"ni povezave s spletom",temporary:"začasno",useOnlyPermanentGrades:"uporabi le stalne ocene",useOnlyPermanentGradesNote1:"če je označeno, bodo za izračun povprečja uporabljene le stalne ocene",useOnlyPermanentGradesNote2:"če pa je polje neoznačeno, pa se ob izračunu povprečne ocene upoštevajo vse ocene",type:"tip",term:"rok",teacher:"profesor",name:"ime",schoolSubject:"predmet",tpMeetings:"govorilne ure",from:"od",to:"do",cancel:"preklic",ok:"v redu",noAbsences:"ni izostankov v izbranem časovnem obdobju",lesson:"ura",notProcessed:"ni obdelano",authorizedAbsence:"opravičeno",unauthorizedAbsence:"neopravičeno",doesNotCount:"ne šteje",loadingMessages:"Nalagam sporočila...",sendAMessage:"pošlji sporočilo",recipient:"prejemnik",messageSubject:"zadeva",messageBody:"telo",removeImages:"odstrani slike",note:"opomba",largeImagesNote:"GimB strežniki ne marajo velikih sporočil, zato lahko pošiljate le zelo majhne slike, v nasprotnem primeru sporočilo ne bo dostavljeno",attachedImages:"pripete slike",encryptMessage:"Šifriraj sporočilo",passwordForE2EE:"geslo za šifriranje sporočila",messages:"sporočila",received:"prejeta",sent:"poslana",deleted:"izbrisana",messageStorageUsed:"zasedenost shrambe sporočil v tej mapi",maxMessagesNote:"v vsaki mapi imate lahko največ 120 sporočil. Starejša sporočila ne bodo prikazana. Redno brišite sporočila, da se izognete morebitnim težavam.",loadMessageBody:"naloži telo sporočila",thisMessageWasEncrypted:"to sporočilo je šifrirano",enterPassword:"vnesite geslo",decrypt:"dešifriraj",nameDirectoryNotSet:"imenik ni nastavljen, pošiljanje ni mogoče",errorFetchingMessages:"sporočil ni bilo mogoče prenesti",unableToReceiveTheMessage:"sporočila ni bilo mogoče prenesti",unableToDeleteTheMessage:"sporočila ni bilo mogoče izbrisati",messageWasProbablySent:"sporočilo je bilo verjetno poslano, prepričajte se in preverite mapo s poslanimi sporočili",errorSendingMessage:"sporočila ni bilo mogoče poslati",imageAddedAsAnAttachment:"slika dodana kot priloga",unableToReadDirectory:"imenika ni bilo mogoče prebrati",messageCouldNotBeSent:"sporočila ni bilo mogoče poslati",incorrectPassword:"nepravilno geslo",chat:"klepet",chattingWith:"klepet z osebo",noMessages:"ni sporočil",stillLoading:"nalaganje še poteka",directory:"imenik",select:"izberi",mustSelectRecipient:"pred klepetom morate izbrati sogovornika. Odprite imenik (meni na levi strani) s pritiskom na gumb \"imenik\" zgoraj desno in izberite sogovornika.",recipientNotInDirectory:"izbrane osebe ni v imeniku",chatExternalInfo:"dobili ste kratko sporočilo v standardu, ki ga GimSIS ne podpira. Pri odgovarjanju spremenite zadevo. Vsebina sporočila: ",loginError:"napaka pri prijavi",loginToLopolis:"prijava v Lopolis",loginToLopolisNote:"izgleda, da niste prijavljeni v eRestavracijo, zato se vam je prikazal prijavni obrazec. Za uporavljanje s prehrano se uporablja druga kombinacija uporabniškega imena in gesla, zato se prijavite s svojimi Lopolis prijavnimi podatki za nadaljevanje.",logInToLopolis:"prijava v Lopolis",logOutFromLopolis:"odjava iz Lopolisa",readOnly:"samo za branje",usage:"uporaba",mealsUsageNote:"kliknite na datum za prikaz menijev, nato pa si enega izberite s klikom na ime menija. Po nastavitvi menijev ponovno naložite menije in se prepričajte o pravilnih nastavitvah.",lunchesNote:"aplikacija ni testirana za naročanje na koslila, zato verjetno to ne deluje. Če ste naročeni na kosila lahko naročanje na menije sploh ne deluje ali pa deluje narobe.",mealNotShownNote:"če nek dan manjka med meniji, to verjetno pomeni, da ni več spremenljiv in zanj niste ročno spremenili menija",mealsContributeNote:"vabimo vas k urejanju LopolisAPI programa za upravljanje z meniji.",authenticationError:"napaka avtentikacije",lopolisAPIConnectionError:"napaka povezave na LopolisAPI strežnik",errorGettingMenus:"napaka branja menijev",errorUnexpectedResponse:"napaka: nepričakovan odgovor",requestForAuthenticationFailed:"zahteva za avtentikacijo ni uspela",credentialsMatch:"prijavni podatki so pravilni",errorSettingMeals:"napaka pri nastavljanju menijev",mealSet:"obrok nastavljen! osvežite obroke in se prepričajte sami",selected:"izbrano",version:"različica",authors:"avtorji",translatorsForThisLanguage:"prevajalci izbranega jezika",whatIsNew:"kaj je novega",whatsNew:"kaj je novega",reportABug:"prijavite napako",sendASuggestion:"pošljite pripombo/predlog/pohvalo/pritožbo",instagram:"instagram",changelog:"dnevnik sprememb",termsOfUse:"terms of use",termsOfUseDescription:"as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App",termsOfUseHarass:"to abuse, harass, threaten, impersonate or intimidate any person",termsOfUsePost:"to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person",termsOfUseCommunicate:"to communicate with the App developers or other users in abusive or offensive manner",termsOfUsePurpose:"for any purpose that is not permitted under the laws of the jurisdiction where you use the App",termsOfUseExploit:"to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user",termsOfUseSpam:"to create or transmit unwanted “spam” to any person or any URL",termsOfUseModify:"you may also not reverse engineer, modify or redistribute the app without written consent from the developers",terminationOfServices:"termination of services",terminationOfServicesDescriptions:"the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons",terminationOfServicesBreaching:"breaching the Terms of Service",terminationOfServicesRequest:"receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App",limitationOfLiability:"limitation of Liability",limitationOfLiabilityContent:"the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.",tosAreEffectiveAsOf:"the Terms of Service are effective as of",privacyImportant:"your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.",privacyOnlyAskedWhen:"we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.",privacyDataCollection:"we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.",privacySharingData:"we don’t share any personally identifying information publicly or with third-parties, except when required to by law",privacyExternalSites:"our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.",privacyRefuse:"you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.",privacyAcceptWithUse:"your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.",privacyEffectiveAsOf:"this policy is effective as of",language:"jezik",selectLanguage:"izberite željen jezik",languageSet:"jezik nastavljen, odprite neko drugo stran da se pokažejo spremembe",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",errorReporting:"pošiljanje napak",on:"vklopljeno",off:"izklopljeno",selectErrorReporting:"ali naj so napake v aplikaciji posredovane razvijalcem?",triggerWarning:"spodnji gumb omogoči dodatne možnosti, ki lahko razburijo/vznevoljijo nekatere uporabnike. Če omogočite stikalo se strinjate, da avtorjev in/ali njihovih osebnih prepričanj ne boste povezovali s katerokoli od dodatnih omogočenih možnosti.",triggerAgreement:"strinjam se z zgoraj navedenimi pogoji",triggerWarningSet:"spremenili ste stanje dodatnih nastavitev",additionalOptions:"dodatne nastavitve",gsecErrNet:"napaka povezave na GimSIS",gsecErrLogin:"prijava v GimSIS ni uspela (napačno geslo?), poskusite se odjaviti",gsecErrOther:"neznana napaka GimSISa, poskusite se odjaviti",videoconferences:"GimB konference"}}
\ No newline at end of file + +const capitalize = (s) => { + if (typeof s !== 'string') return '' + return s.charAt(0).toUpperCase() + s.slice(1) +} +var s = function(whatString) { + return getLang.s(whatString); +}; +var d = function(whatString) { + return getLang.d(whatString); +}; +var S = function(whatString) { + return getLang.S(whatString); +}; +var D = function(whatString) { + return getLang.D(whatString); +}; +var getLang = { // language object + s: function(whatString) { // get string + return langstrings[chosenLang][whatString]; + }, + S: function(whatString) { // get capitalized string + return capitalize(langstrings[chosenLang][whatString]); + }, + d: function(whatString) { // add a dot and get string + if(langstrings[chosenLang][whatString].slice(-1) != ".") { + return langstrings[chosenLang][whatString]+"."; + } else { + return langstrings[chosenLang][whatString]; + } + }, + D: function(whatString) { // add a dot and get capitalized string + if(langstrings[chosenLang][whatString].slice(-1) != ".") { + return capitalize(langstrings[chosenLang][whatString]+"."); + } else { + return capitalize(langstrings[chosenLang][whatString]); + } + }, +} +var langstrings = { + en: { + miscTranslationLanguage: "English", + miscTranslationAuthors: "Rok Štular", + "": "", + // date + monday: "monday", + tuesday: "tuesday", + wednesday: "wednesday", + thursday: "thursday", + friday: "friday", + saturday: "saturday", + sunday: "sunday", + am: "am", + pm: "pm", + january: "january", + february: "february", + march: "march", + april: "april", + may: "may", + june: "june", + july: "july", + august: "august", + september: "september", + october: "october", + november: "november", + december: "december", + // login + username: "username", + password: "password", + signIn: "sign in", + bySigningInYouAgreeTo: "by signing in, you agree to", + theToS: "the terms and conditions", + and: "and", + thePrivacyPolicy: "the privacy policy", + loginFailed: "login failed", + browserNotSupported: "bežiapp won't work on your device, unless you update your Internet browser", + // index + timetable: "timetable", + gradings: "gradings", + grades: "grades", + teachers: "teachers", + absences: "absences", + messaging: "messaging", + meals: "meals", + about: "about", + logout: "logout", + settings: "settings", + // timetable + noPeriods: "no periods in selected week", + // gradings + requestFailed: "request failed", + noInternetConnection: "no internet connection", + // grades + temporary: "temporary", + useOnlyPermanentGrades: "use only permanent grades", + useOnlyPermanentGradesNote1: "if checked, only permanent grades will be used in the average grade calculation", + useOnlyPermanentGradesNote2: "if left unchecked, the calculation will include every available grade", + type: "type", + term: "term", + teacher: "teacher", + // teachers + name: "name", + schoolSubject: "subject", + tpMeetings: "TP meetings", + // absences + from: "from", + to: "to", + cancel: "cancel", + ok: "ok", + noAbsences: "no absences in the chosen time period", + lesson: "lesson", + notProcessed: "not processed", + authorizedAbsence: "authorized", + unauthorizedAbsence: "unauthorized", + doesNotCount: "does not count", + // messaging + loadingMessages: "Loading messages...", + sendAMessage: "send a message", + recipient: "recipient", + messageSubject: "subject", + messageBody: "message body", + removeImages: "remove images", + note: "note", + largeImagesNote: "GimB servers don't like large messages, so only very small images may be attached or your message will not be delivered", + attachedImages: "attached images", + encryptMessage: "Encrypt message", + passwordForE2EE: "password for encrypting the message", + messages: "messages", + received: "received", + sent: "sent", + deleted: "deleted", + messageStorageUsed: "message storage used in this folder", + maxMessagesNote: "you can only have 120 messages per message folder, older messages will not be shown. Remember to delete read and sent messages regulary to avoid any issues.", + loadMessageBody: "load message body", + thisMessageWasEncrypted: "this message was encrypted", + enterPassword: "enter password", + decrypt: "decrypt", + nameDirectoryNotSet: "name directory not set, sending unavailable", + errorFetchingMessages: "error fetching messages", + unableToReceiveTheMessage: "unable to receive the message", + unableToDeleteTheMessage: "unable to delete the message", + messageWasProbablySent: "message was probably sent, check the Sent folder to be sure", + errorSendingMessage: "error sending message", + imageAddedAsAnAttachment: "image added as an attachment", + unableToReadDirectory: "unable to read directory of people", + messageCouldNotBeSent: "message could to be sent", + incorrectPassword: "incorrect password", + // chats + chat: "chat", + chattingWith: "chatting with", + noMessages: "no messages", + stillLoading: "loading is still in progress", + directory: "directory", + select: "select", + mustSelectRecipient: "you have to select a recipient before chatting. Open directory on the left side by clicking on the top left addressbook button and select a recipient in order to start chatting with them", + recipientNotInDirectory: "recipient is not in directory.", + chatExternalInfo: "you have just received a chat. Chats are not supported by GimSIS, so you must reply by changing the subject to something else. Chat body: ", + // meals + loginError: "login error", + loginToLopolis: "login to Lopolis", + loginToLopolisNote: "it seems like you're not currently logged in to eRestavracija, so this form has been presented to you. You have a different username and password combination used for applying and opting out of of menus. In order to use this feature, you have to log in with your Lopolis account.", + logInToLopolis: "log in to Lopolis", + logOutFromLopolis: "log out from Lopolis", + readOnly: "read only", + usage: "usage", + mealsUsageNote: "click on a date to open the collapsible menu with choices and click on a specific meal to select it. Reload the meals when you're done and check the entries.", + lunchesNote: "app was not tested with lunches in mind. Meals probably won't work with lunches and having a lunch subscription may even break its functionality.", + mealNotShownNote: "if a meal is not present in the meals collapsible field, this does not necessarily mean it does not exist. Meals that haven't been altered by you and are unchangable (read-only) are not shown for clarity.", + mealsContributeNote: "you are welcome to contribute to the LopolisAPI project and add features, such as checkouts.", + authenticationError: "authentication error", + lopolisAPIConnectionError: "LopolisAPI server connection error", + errorGettingMenus: "error getting menus", + errorUnexpectedResponse: "error: unexpected response", + requestForAuthenticationFailed: "request for authentication failed", + credentialsMatch: "credentials match", + errorSettingMeals: "error setting meals", + mealSet: "meal set! Reload meals to be sure", + selected: "selected", + // about + version: "version", + authors: "authors", + translatorsForThisLanguage: "translators for this language", + whatIsNew: "what's new", + whatsNew: "what's new", + reportABug: "report a bug", + sendASuggestion: "send a suggestion", + instagram: "instagram", + // changelog + changelog: "changelog", + // terms and conditions + termsOfUse: "terms of use", + termsOfUseDescription: "as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App", + termsOfUseHarass: "to abuse, harass, threaten, impersonate or intimidate any person", + termsOfUsePost: "to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person", + termsOfUseCommunicate: "to communicate with the App developers or other users in abusive or offensive manner", + termsOfUsePurpose: "for any purpose that is not permitted under the laws of the jurisdiction where you use the App", + termsOfUseExploit: "to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user", + termsOfUseSpam: "to create or transmit unwanted “spam” to any person or any URL", + termsOfUseModify: "you may also not reverse engineer, modify or redistribute the app without written consent from the developers", + terminationOfServices: "termination of services", + terminationOfServicesDescriptions: "the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons", + terminationOfServicesBreaching: "breaching the Terms of Service", + terminationOfServicesRequest: "receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App", + limitationOfLiability: "limitation of Liability", + limitationOfLiabilityContent: "the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.", + tosAreEffectiveAsOf: "the Terms of Service are effective as of", + // privacy policy + privacyImportant: "your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.", + privacyOnlyAskedWhen: "we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.", + privacyDataCollection: "we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.", + privacySharingData: "we don’t share any personally identifying information publicly or with third-parties, except when required to by law", + privacyExternalSites: "our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.", + privacyRefuse: "you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.", + privacyAcceptWithUse: "your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.", + privacyEffectiveAsOf: "this policy is effective as of", + // settings + language: "language", + selectLanguage: "select desired language", + languageSet: "language set, open another page for the changes to take effect", + theme: "theme", + themeLight: "light theme (default)", + themeDark: "dark theme", + themeNight: "night theme", + selectTheme: "select a theme", + triggerWarning: "the following switch enables additional settings, which some people may: disagree with, find annoying, be offended by them. By enabling the switch, you agree that you won't be triggered by any of the additional options and will not asociate any of the authors and/or their personal beliefs and opinions with additional options.", + triggerAgreement: "i agree with terms and conditions stated above", + triggerWarningSet: "additional settings toggled", + additionalOptions: "additional settings", + themeSet: "theme set, open another page for the changes to take effect", + errorReportingSet: "error reporting preference set", + errorReporting: "error reporting", + on: "on", + off: "off", + selectErrorReporting: "should error reports be submitted to the developers?", + // gsec + gsecErrNet: "GimSIS connection error", + gsecErrLogin: "GimSIS login error (bad password?), try logging out", + gsecErrOther: "GimSIS unknown error, try logging out", + // videoconferences + videoconferences: "GimB meet" + }, + sl: { + miscTranslationLanguage: "slovenščina", + miscTranslationAuthors: "Anton Luka Šijanec", + "": "", + // date + monday: "ponedeljek", + tuesday: "torek", + wednesday: "sreda", + thursday: "četrtek", + friday: "petek", + saturday: "sobota", + sunday: "nedelja", + am: "dop.", + pm: "pop.", + january: "januar", + february: "februar", + march: "marec", + april: "april", + may: "maj", + june: "junij", + july: "julij", + august: "avgust", + september: "september", + october: "oktober", + november: "november", + december: "december", + // login + username: "uporabniško ime", + password: "geslo", + signIn: "prijava", + bySigningInYouAgreeTo: "s prijavo se strinjate s", + theToS: "pogoji uporabe (v angleščini)", + and: "in", + thePrivacyPolicy: "politika zasebnosti (v angleščini)", + loginFailed: "prijava je spodletela", + browserNotSupported: "BežiApp ne bo deloval na vaši napravi, če ne posodobite vašega Internetnega brskalnika", + // timetable + noPeriods: "ni ur v izbranem tednu", + // index + timetable: "urnik", + gradings: "ocenjevanja", + grades: "ocene", + teachers: "profesorji", + absences: "izostanki", + messaging: "sporočanje", + meals: "obroki", + about: "o", + logout: "odjava", + settings: "nastavitve", + // gradings + requestFailed: "zahteva spodletela", + noInternetConnection: "ni povezave s spletom", + // grades + temporary: "začasno", + useOnlyPermanentGrades: "uporabi le stalne ocene", + useOnlyPermanentGradesNote1: "če je označeno, bodo za izračun povprečja uporabljene le stalne ocene", + useOnlyPermanentGradesNote2: "če pa je polje neoznačeno, pa se ob izračunu povprečne ocene upoštevajo vse ocene", + type: "tip", + term: "rok", + teacher: "profesor", + // teachers + name: "ime", + schoolSubject: "predmet", + tpMeetings: "govorilne ure", + // absences + from: "od", + to: "do", + cancel: "preklic", + ok: "v redu", + noAbsences: "ni izostankov v izbranem časovnem obdobju", + lesson: "ura", + notProcessed: "ni obdelano", + authorizedAbsence: "opravičeno", + unauthorizedAbsence: "neopravičeno", + doesNotCount: "ne šteje", + // messaging + loadingMessages: "Nalagam sporočila...", + sendAMessage: "pošlji sporočilo", + recipient: "prejemnik", + messageSubject: "zadeva", + messageBody: "telo", + removeImages: "odstrani slike", + note: "opomba", + largeImagesNote: "GimB strežniki ne marajo velikih sporočil, zato lahko pošiljate le zelo majhne slike, v nasprotnem primeru sporočilo ne bo dostavljeno", + attachedImages: "pripete slike", + encryptMessage: "Šifriraj sporočilo", + passwordForE2EE: "geslo za šifriranje sporočila", + messages: "sporočila", + received: "prejeta", + sent: "poslana", + deleted: "izbrisana", + messageStorageUsed: "zasedenost shrambe sporočil v tej mapi", + maxMessagesNote: "v vsaki mapi imate lahko največ 120 sporočil. Starejša sporočila ne bodo prikazana. Redno brišite sporočila, da se izognete morebitnim težavam.", + loadMessageBody: "naloži telo sporočila", + thisMessageWasEncrypted: "to sporočilo je šifrirano", + enterPassword: "vnesite geslo", + decrypt: "dešifriraj", + nameDirectoryNotSet: "imenik ni nastavljen, pošiljanje ni mogoče", + errorFetchingMessages: "sporočil ni bilo mogoče prenesti", + unableToReceiveTheMessage: "sporočila ni bilo mogoče prenesti", + unableToDeleteTheMessage: "sporočila ni bilo mogoče izbrisati", + messageWasProbablySent: "sporočilo je bilo verjetno poslano, prepričajte se in preverite mapo s poslanimi sporočili", + errorSendingMessage: "sporočila ni bilo mogoče poslati", + imageAddedAsAnAttachment: "slika dodana kot priloga", + unableToReadDirectory: "imenika ni bilo mogoče prebrati", + messageCouldNotBeSent: "sporočila ni bilo mogoče poslati", + incorrectPassword: "nepravilno geslo", + // chats + chat: "klepet", + chattingWith: "klepet z osebo", + noMessages: "ni sporočil", + stillLoading: "nalaganje še poteka", + directory: "imenik", + select: "izberi", + mustSelectRecipient: "pred klepetom morate izbrati sogovornika. Odprite imenik (meni na levi strani) s pritiskom na gumb \"imenik\" zgoraj desno in izberite sogovornika.", + recipientNotInDirectory: "izbrane osebe ni v imeniku", + chatExternalInfo: "dobili ste kratko sporočilo v standardu, ki ga GimSIS ne podpira. Pri odgovarjanju spremenite zadevo. Vsebina sporočila: ", + // meals + loginError: "napaka pri prijavi", + loginToLopolis: "prijava v Lopolis", + loginToLopolisNote: "izgleda, da niste prijavljeni v eRestavracijo, zato se vam je prikazal prijavni obrazec. Za uporavljanje s prehrano se uporablja druga kombinacija uporabniškega imena in gesla, zato se prijavite s svojimi Lopolis prijavnimi podatki za nadaljevanje.", + logInToLopolis: "prijava v Lopolis", + logOutFromLopolis: "odjava iz Lopolisa", + readOnly: "samo za branje", + usage: "uporaba", + mealsUsageNote: "kliknite na datum za prikaz menijev, nato pa si enega izberite s klikom na ime menija. Po nastavitvi menijev ponovno naložite menije in se prepričajte o pravilnih nastavitvah.", + lunchesNote: "aplikacija ni testirana za naročanje na koslila, zato verjetno to ne deluje. Če ste naročeni na kosila lahko naročanje na menije sploh ne deluje ali pa deluje narobe.", + mealNotShownNote: "če nek dan manjka med meniji, to verjetno pomeni, da ni več spremenljiv in zanj niste ročno spremenili menija", + mealsContributeNote: "vabimo vas k urejanju LopolisAPI programa za upravljanje z meniji.", + authenticationError: "napaka avtentikacije", + lopolisAPIConnectionError: "napaka povezave na LopolisAPI strežnik", + errorGettingMenus: "napaka branja menijev", + errorUnexpectedResponse: "napaka: nepričakovan odgovor", + requestForAuthenticationFailed: "zahteva za avtentikacijo ni uspela", + credentialsMatch: "prijavni podatki so pravilni", + errorSettingMeals: "napaka pri nastavljanju menijev", + mealSet: "obrok nastavljen! osvežite obroke in se prepričajte sami", + selected: "izbrano", + // about + version: "različica", + authors: "avtorji", + translatorsForThisLanguage: "prevajalci izbranega jezika", + whatIsNew: "kaj je novega", + whatsNew: "kaj je novega", + reportABug: "prijavite napako", + sendASuggestion: "pošljite pripombo/predlog/pohvalo/pritožbo", + instagram: "instagram", + // changelog + changelog: "dnevnik sprememb", + // terms and conditions + termsOfUse: "terms of use", + termsOfUseDescription: "as a condition of use, you promise not to use the BežiApp (App or application) and its related infrastructure (API, hosting service) for any purpose that is unlawful or prohibited by these Terms, or any other purpose not reasonably intended by the authors of the App. By way of example, and not as a limitation, you agree not to use the App", + termsOfUseHarass: "to abuse, harass, threaten, impersonate or intimidate any person", + termsOfUsePost: "to post or transmit, or cause to be posted or transmitted, any Content that is libelous, defamatory, obscene, pornographic, abusive, offensive, profane or that infringes any copyright or other right of any person", + termsOfUseCommunicate: "to communicate with the App developers or other users in abusive or offensive manner", + termsOfUsePurpose: "for any purpose that is not permitted under the laws of the jurisdiction where you use the App", + termsOfUseExploit: "to post or transmit, or cause to be posted or transmitted, any Communication designed or intended to obtain password, account or private information of any App user", + termsOfUseSpam: "to create or transmit unwanted “spam” to any person or any URL", + termsOfUseModify: "you may also not reverse engineer, modify or redistribute the app without written consent from the developers", + terminationOfServices: "termination of services", + terminationOfServicesDescriptions: "the developers of the App may terminate your access to the App without any prior warning or notice for any of the following reasons", + terminationOfServicesBreaching: "breaching the Terms of Service", + terminationOfServicesRequest: "receiving a formal request from authorities of Gimnazija Bežigrad administration requesting termination of your access to the App", + limitationOfLiability: "limitation of Liability", + limitationOfLiabilityContent: "the developers of the App provide no warranty; You expressly acknowledge and agree that the use of the licensed application is at your sole risk. To the maximum extent permited by applicable law, the licensed application and any services performed of provided by the licensed application are provided “as is” and “as available”, with all faults and without warranty of any kind, and licensor hereby disclaims all warranties and conditions with respect to the licensed application and any services, either express, implied or statutory, including, but not limited to, the implied warranties and/or conditions of merchantability, of satisfactory quality, of fitness for a particular purpose, of accuracy, of quiet enjoyment, and of noninfringement of third-party rights. No oral or written information or advice given by licensor or its authorized representative shall create a warranty. Should the licensed application or services prove defective, you assume the entire cost of all necessary servicing, repair or correction. Some jurisdictions do not allow the exclusion of the implied warranties or limitations on applicable statutory rights of a customer, so the above exclusion may not apply to you.", + tosAreEffectiveAsOf: "the Terms of Service are effective as of", + // privacy policy + privacyImportant: "your privacy is important to us. It is the developers' policy to respect your privacy regarding any information we may collect from you through our app, BežiApp.", + privacyOnlyAskedWhen: "we only ask for personal information when we truly need it to provide a service to you. We collect it by fair and lawful means, with your knowledge and consent. We also let you know why we’re collecting it and how it will be used.", + privacyDataCollection: "we only retain collected information for as long as necessary to provide you with your requested service. What data we store, we’ll protect within commercially acceptable means to prevent loss and theft, as well as unauthorized access, disclosure, copying, use or modification.", + privacySharingData: "we don’t share any personally identifying information publicly or with third-parties, except when required to by law", + privacyExternalSites: "our app may link to external sites that are not operated by us. Please be aware that we have no control over the content and practices of these sites, and cannot accept responsibility or liability for their respective privacy policies.", + privacyRefuse: "you are free to refuse our request for your personal information, with the understanding that we may be unable to provide you with some of your desired services.", + privacyAcceptWithUse: "your continued use of our website will be regarded as acceptance of our practices around privacy and personal information. If you have any questions about how we handle user data and personal information, feel free to contact us.", + privacyEffectiveAsOf: "this policy is effective as of", + // settings + language: "jezik", + selectLanguage: "izberite željen jezik", + languageSet: "jezik nastavljen, odprite neko drugo stran da se pokažejo spremembe", + 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", + errorReporting: "pošiljanje napak", + on: "vklopljeno", + off: "izklopljeno", + selectErrorReporting: "ali naj so napake v aplikaciji posredovane razvijalcem?", + triggerWarning: "spodnji gumb omogoči dodatne možnosti, ki lahko razburijo/vznevoljijo nekatere uporabnike. Če omogočite stikalo se strinjate, da avtorjev in/ali njihovih osebnih prepričanj ne boste povezovali s katerokoli od dodatnih omogočenih možnosti.", + triggerAgreement: "strinjam se z zgoraj navedenimi pogoji", + triggerWarningSet: "spremenili ste stanje dodatnih nastavitev", + additionalOptions: "dodatne nastavitve", + // gsec + gsecErrNet: "napaka povezave na GimSIS", + gsecErrLogin: "prijava v GimSIS ni uspela (napačno geslo?), poskusite se odjaviti", + gsecErrOther: "neznana napaka GimSISa, poskusite se odjaviti", + // videoconferences + videoconferences: "GimB konference" + } +} diff --git a/dist/js/lib/themes.js b/dist/js/lib/themes.js index 8cc421b..bc5d485 100644 --- a/dist/js/lib/themes.js +++ b/dist/js/lib/themes.js @@ -1,4 +1,152 @@ -const THEME_COLOR_SCHEMES={light:{"color-primary":"rgba(0, 128, 83, 1)","color-secondary":"rgba(0, 77, 50, 1)","color-accent":"rgba(0, 156, 101, 1)","color-primary-light":"rgba(230, 250, 231, 1)","color-invalid":"rgba(192, 0, 0, 1)","color-primary-transparent":"rgba(0, 128, 83, 0.3)","background-color":"rgba(255, 255, 255, 1)","background-accent":"rgba(0, 156, 101, 0.2)","background-accent-1":"rgb(192, 219, 207, 1)","color-header-bold":"rgba(255, 255, 255, 1)","color-header-span":"rgba(255, 255, 255, 1)","color-text":"rgba(0, 0, 0, 1)","color-text-light":"rgba(97, 97, 97, 1)","color-label-text":"rgba(158, 158, 158, 1)","color-table-hover":"rgba(242, 242, 242, 0.5)","color-sidenav-background":"rgba(255, 255, 255, 1)","color-sidenav-text":"rgba(0, 0, 0, 0.87)","color-sidenav-header":"rgba(0, 0, 0, 0.54)","color-divider":"rgba(224, 224, 224, 1)","color-btn-flat":"rgba(52, 52, 52, 1)","color-btn-flat-disabled":"rgba(178, 178, 178, 1)"},dark:{"color-primary":"rgba(0, 128, 83, 1)","color-secondary":"rgba(0, 94, 61, 1)","color-accent":"rgba(20, 117, 83, 1)","color-primary-light":"rgba(6, 137, 9, 1)","color-invalid":"rgba(192, 0, 0, 1)","color-primary-transparent":"rgba(0, 128, 83, 0.3)","background-color":"rgba(31, 31, 31, 1)","background-accent":"rgba(0, 92, 44, 0.2)","background-accent-1":"rgb(26, 43, 32, 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(70, 70, 70, 0.5)","color-sidenav-background":"rgba(31, 31, 31, 1)","color-sidenav-text":"rgba(189, 189, 189, 1)","color-sidenav-header":"rgba(189, 189, 189, 0.54)","color-divider":"rgba(80, 80, 80, 1)","color-btn-flat":"rgba(178, 178, 178, 1)","color-btn-flat-disabled":"rgba(52, 52, 52, 1)"},night:{"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)","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(255, 255, 255, 1)","color-text-light":"rgba(200, 200, 200, 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(255, 255, 255, 1)","color-sidenav-header":"rgba(255, 255, 255, 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)"},left:{"color-primary":"rgba(173, 0, 0, 1)","color-secondary":"rgba(148, 15, 15, 1)","color-accent":"rgba(181, 42, 42, 1)","color-primary-light":"rgba(250, 230, 230, 1)","color-invalid":"rgba(120, 0, 108, 1)","color-primary-transparent":"rgba(173, 0, 0, 0.3)","background-color":"rgba(255, 255, 255, 1)","background-accent":"rgba(199, 38, 38, 0.2)","background-accent-1":"rgb(219, 192, 192, 1)","color-header-bold":"rgba(255, 255, 255, 1)","color-header-span":"rgba(255, 255, 255, 1)","color-text":"rgba(0, 0, 0, 1)","color-text-light":"rgba(97, 97, 97, 1)","color-label-text":"rgba(158, 158, 158, 1)","color-table-hover":"rgba(242, 242, 242, 0.5)","color-sidenav-background":"rgba(255, 255, 255, 1)","color-sidenav-text":"rgba(0, 0, 0, 0.87)","color-sidenav-header":"rgba(0, 0, 0, 0.54)","color-divider":"rgba(224, 224, 224, 1)","color-btn-flat":"rgba(52, 52, 52, 1)","color-btn-flat-disabled":"rgba(178, 178, 178, 1)"},right:{"color-primary":"rgba(7, 0, 105, 1)","color-secondary":"rgba(206, 217, 0, 1)","color-accent":"rgba(0, 94, 156, 1)","color-primary-light":"rgba(195, 191, 255, 1)","color-invalid":"rgba(192, 0, 0, 1)","color-primary-transparent":"rgba(7, 0, 105, 0.3)","background-color":"rgba(255, 255, 255, 1)","background-accent":"rgba(0, 60, 156, 0.2)","background-accent-1":"rgb(215, 219, 192, 1)","color-header-bold":"rgba(255, 255, 255, 1)","color-header-span":"rgba(255, 255, 255, 1)","color-text":"rgba(0, 0, 0, 1)","color-text-light":"rgba(97, 97, 97, 1)","color-label-text":"rgba(158, 158, 158, 1)","color-table-hover":"rgba(242, 242, 242, 0.5)","color-sidenav-background":"rgba(255, 255, 255, 1)","color-sidenav-text":"rgba(0, 0, 0, 0.87)","color-sidenav-header":"rgba(0, 0, 0, 0.54)","color-divider":"rgba(224, 224, 224, 1)","color-btn-flat":"rgba(52, 52, 52, 1)","color-btn-flat-disabled":"rgba(178, 178, 178, 1)"}} -function applyTheme(themeName){for(const[property,value]of Object.entries(THEME_COLOR_SCHEMES[themeName])){document.documentElement.style.setProperty(`--${property}`,value);}} -document.addEventListener("DOMContentLoaded",()=>{localforage.getItem("theme").then((selectedTheme)=>{if(selectedTheme==null){let isOsDarkTheme=window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches;applyTheme(isOsDarkTheme?"dark":"light");}else{applyTheme(selectedTheme);}});});
\ No newline at end of file + "background-color": "rgba(255, 255, 255, 1)", + "background-accent": "rgba(0, 156, 101, 0.2)", + "background-accent-1": "rgb(192, 219, 207, 1)", + + "color-header-bold": "rgba(255, 255, 255, 1)", + "color-header-span": "rgba(255, 255, 255, 1)", + + "color-text": "rgba(0, 0, 0, 1)", + "color-text-light": "rgba(97, 97, 97, 1)", + "color-label-text": "rgba(158, 158, 158, 1)", + "color-table-hover": "rgba(242, 242, 242, 0.5)", + + "color-sidenav-background": "rgba(255, 255, 255, 1)", + "color-sidenav-text": "rgba(0, 0, 0, 0.87)", + "color-sidenav-header": "rgba(0, 0, 0, 0.54)", + "color-divider": "rgba(224, 224, 224, 1)", + + "color-btn-flat": "rgba(52, 52, 52, 1)", + "color-btn-flat-disabled": "rgba(178, 178, 178, 1)" + + }, + dark: { + "color-primary": "rgba(0, 128, 83, 1)", + "color-secondary": "rgba(0, 94, 61, 1)", + "color-accent": "rgba(20, 117, 83, 1)", + "color-primary-light": "rgba(6, 137, 9, 1)", // it's not really light anymore, is it? + "color-invalid": "rgba(192, 0, 0, 1)", + "color-primary-transparent": "rgba(0, 128, 83, 0.3)", + + "background-color": "rgba(31, 31, 31, 1)", + "background-accent": "rgba(0, 92, 44, 0.2)", + "background-accent-1": "rgb(26, 43, 32, 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(70, 70, 70, 0.5)", + + "color-sidenav-background": "rgba(31, 31, 31, 1)", + "color-sidenav-text": "rgba(189, 189, 189, 1)", + "color-sidenav-header": "rgba(189, 189, 189, 0.54)", + "color-divider": "rgba(80, 80, 80, 1)", + + "color-btn-flat": "rgba(178, 178, 178, 1)", + "color-btn-flat-disabled": "rgba(52, 52, 52, 1)" + }, + night: { + "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(255, 255, 255, 1)", + "color-text-light": "rgba(200, 200, 200, 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(255, 255, 255, 1)", + "color-sidenav-header": "rgba(255, 255, 255, 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)" + }, + left: { + "color-primary": "rgba(173, 0, 0, 1)", + "color-secondary": "rgba(148, 15, 15, 1)", + "color-accent": "rgba(181, 42, 42, 1)", + "color-primary-light": "rgba(250, 230, 230, 1)", + "color-invalid": "rgba(120, 0, 108, 1)", + "color-primary-transparent": "rgba(173, 0, 0, 0.3)", + + "background-color": "rgba(255, 255, 255, 1)", + "background-accent": "rgba(199, 38, 38, 0.2)", + "background-accent-1": "rgb(219, 192, 192, 1)", + + "color-header-bold": "rgba(255, 255, 255, 1)", + "color-header-span": "rgba(255, 255, 255, 1)", + + "color-text": "rgba(0, 0, 0, 1)", + "color-text-light": "rgba(97, 97, 97, 1)", + "color-label-text": "rgba(158, 158, 158, 1)", + "color-table-hover": "rgba(242, 242, 242, 0.5)", + + "color-sidenav-background": "rgba(255, 255, 255, 1)", + "color-sidenav-text": "rgba(0, 0, 0, 0.87)", + "color-sidenav-header": "rgba(0, 0, 0, 0.54)", + "color-divider": "rgba(224, 224, 224, 1)", + + "color-btn-flat": "rgba(52, 52, 52, 1)", + "color-btn-flat-disabled": "rgba(178, 178, 178, 1)" + }, + right: { + "color-primary": "rgba(7, 0, 105, 1)", + "color-secondary": "rgba(0, 94, 156, 1)", + "color-accent": "rgba(217, 214, 80, 1)", + "color-primary-light": "rgba(195, 191, 255, 1)", + "color-invalid": "rgba(192, 0, 0, 1)", + "color-primary-transparent": "rgba(7, 0, 105, 0.3)", + + "background-color": "rgba(255, 255, 255, 1)", + "background-accent": "rgba(0, 60, 156, 0.2)", + "background-accent-1": "rgb(215, 219, 192, 1)", + + "color-header-bold": "rgba(255, 255, 255, 1)", + "color-header-span": "rgba(255, 255, 255, 1)", + + "color-text": "rgba(0, 0, 0, 1)", + "color-text-light": "rgba(97, 97, 97, 1)", + "color-label-text": "rgba(158, 158, 158, 1)", + "color-table-hover": "rgba(242, 242, 242, 0.5)", + + "color-sidenav-background": "rgba(255, 255, 255, 1)", + "color-sidenav-text": "rgba(0, 0, 0, 0.87)", + "color-sidenav-header": "rgba(0, 0, 0, 0.54)", + "color-divider": "rgba(224, 224, 224, 1)", + + "color-btn-flat": "rgba(52, 52, 52, 1)", + "color-btn-flat-disabled": "rgba(178, 178, 178, 1)" + } +} + +function applyTheme(themeName) { + for (const [property, value] of Object.entries(THEME_COLOR_SCHEMES[themeName])) { + document.documentElement.style.setProperty(`--${property}`, value); + } +} + +document.addEventListener("DOMContentLoaded", () => { + localforage.getItem("theme").then((selectedTheme) => { + if (selectedTheme == null) { + let isOsDarkTheme = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches; + applyTheme(isOsDarkTheme ? "dark" : "light"); + } else { + applyTheme(selectedTheme); + } + }); +}); diff --git a/dist/js/messaging.js b/dist/js/messaging.js index aa0223c..883ab64 100644 --- a/dist/js/messaging.js +++ b/dist/js/messaging.js @@ -1,140 +1,648 @@ -const API_ENDPOINT="https://gimb.tk/test.php";const DIRECTORY_URL="/directory.json";const ENCRYPTED_MESSAGE_REGEX=/<!-- ba-e2eemsg-(\d{4}) -->(\S+?)<!-- end-msg -->/;var directory=null;var messages={"0":[],"1":[],"2":[]} -var current_tab=0;async function checkLogin(){localforage.getItem("logged_in").then(function(value){if(value!==true){window.location.replace("/index.html");}}).catch(function(err){console.log(err);});} -function htmlEncode(value){return $("<textarea/>").text(value).html();} -function htmlDecode(value){return $("<textarea/>").html(value).text();} -async function loadDirectory(){$.ajax({url:DIRECTORY_URL,crossDomain:true,dataType:"json",cache:false,type:"GET",success:async function(data){let promises_to_run=[localforage.getItem("username").then((value)=>{username=value;}),localforage.getItem("password").then((value)=>{password=value;}),localforage.getItem("grades").then((value)=>{grades=value;})];await Promise.all(promises_to_run);var gsecdata;try{let gsecInstance=new gsec();await gsecInstance.login(username,password);gsecdata=await gsecInstance.fetchTeachersDirectory().catch((err)=>{gsecErrorHandlerUI(err);setLoading(false);});}catch(err){gsecErrorHandlerUI(err);setLoading(false);} -directory={...gsecdata,...data};console.log(directory);localforage.setItem("directory",directory);populateAutocomplete();},error:()=>{localforage.getItem("directory").then((stored_directory)=>{if(stored_directory===null){UIAlert(D("nameDirectoryNotSet"),"loadDirectory(): stored_directory === null");directory=null;document.getElementById("msg-send").disabled=true;}else{directory=stored_directory;populateAutocomplete();}});}});} -function populateAutocomplete(){let elems=document.querySelectorAll(".autocomplete-fullname");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 setLoading(state){if(state){$("#loading-bar").removeClass("hidden");}else{$("#loading-bar").addClass("hidden");}} -async function loadMessages(force_refresh=true,messageType=0){setLoading(true);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},dataType:"json",cache:false,type:"GET",success:(data)=>{if(data===null){UIAlert(D("requestFailed"));setLoading(false);}else{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);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===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);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===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"]));}} -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-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> - `);}});} -function getNumMessages(messageType=-1){if(messageType===-1){let sum=0;for(const[messageType,messageList]of Object.entries(messages)){sum+=messageList.length;} -return sum;}else{var what_to_return=messages[messageType].length;if(what_to_return==null) -return 0 -return what_to_return;}} -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:()=>{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");}}} -function setupEventListeners(){$("#msg-add-photo").click(()=>{let input=document.createElement("input");input.type="file";input.onchange=(e)=>{let file=e.target.files[0];let reader=new FileReader();reader.readAsDataURL(file);reader.onload=readerEvent=>{additionalstufftoaddtomessage+=`<br><img src="${readerEvent.target.result}" />`;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}" /> - `);} -UIAlert(D("imageAddedAsAnAttachment"));}} -input.click();});$("#full-name").on("blur",validateName);$("#refresh-icon").click(()=>{loadMessages(true,current_tab);});$("#encrypt-checkbox").change(function(){if(this.checked){$("#encryption-key-input").prop("hidden",false);}else{$("#encryption-key-input").prop("hidden",true);}});$("#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("/");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").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} -var additionalstufftoaddtomessage="";document.addEventListener("DOMContentLoaded",()=>{checkLogin();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();const tabs=document.querySelectorAll(".tabs");const tab_options={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);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();const menus=document.querySelectorAll(".side-menu");M.Sidenav.init(menus,{edge:"right",draggable:true});});
\ No newline at end of file +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": [] +} +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); + }); +} + +// -----------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(); +} + +function htmlDecode(value) { + return $("<textarea/>").html(value).text(); +} +// --------------------------------- + +// Try to fetch name:id directory +async function loadDirectory() { + $.ajax({ + url: DIRECTORY_URL, + crossDomain: true, + dataType: "json", + cache: false, + type: "GET", + success: async function (data) { + // If we were able to retrieve it, update the saved directory + let promises_to_run = [ + localforage.getItem("username").then((value) => { + username = value; + }), + localforage.getItem("password").then((value) => { + password = value; + }), + localforage.getItem("grades").then((value) => { + grades = value; + }) + ]; + await Promise.all(promises_to_run); + var gsecdata; + try { + let gsecInstance = new gsec(); + await gsecInstance.login(username, password); + gsecdata = await gsecInstance.fetchTeachersDirectory().catch( (err) => { + gsecErrorHandlerUI(err); + setLoading(false); + }); + } catch (err) { + gsecErrorHandlerUI(err); + setLoading(false); + } + directory = {...gsecdata, ...data }; + console.log(directory); + localforage.setItem("directory", directory); + // Populate autocomplete + populateAutocomplete(); + }, + error: () => { + // Otherwise, try to retrieve stored directory + localforage.getItem("directory").then((stored_directory) => { + if (stored_directory === null) { + // If unable, set directory to null (so other functions know that we don't have it) + UIAlert( D("nameDirectoryNotSet"), "loadDirectory(): stored_directory === null" ); + directory = null; + // Disable send button + document.getElementById("msg-send").disabled = true; + } else { + directory = stored_directory; + // Populate autocomplete + populateAutocomplete(); + } + }); + } + }); +} + +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(); +} + +// Function to toggle loading bar +function setLoading(state) { + 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); + } + }); +} + +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); + } + + }) + }); +} + + +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); + } + + }) + }); +} + +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"])); + } +} + +// 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 color-card"> + <div class="card-content general-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 +function getNumMessages(messageType = -1) { + if (messageType === -1) { + let sum = 0; + for (const [messageType, messageList] of Object.entries(messages)) { + sum += messageList.length; + } + return sum; + } else { + var what_to_return = messages[messageType].length; + if(what_to_return == null) + return 0 + return what_to_return; + } +} + +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); + } + }) + }); +} + +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"); + } + } +} + +// 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); + }); + }); +} + +function getUrlParameter(sParam) { + 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 }); +}); diff --git a/dist/js/settings.js b/dist/js/settings.js index a948380..a77b7ca 100644 --- a/dist/js/settings.js +++ b/dist/js/settings.js @@ -1,12 +1,128 @@ -async function setLanguage(langCode){localforage.setItem("chosenLang",langCode).then((value)=>{console.log("Language set: "+value);UIAlert(D("languageSet"),"setLanguage(): languageSet");});} -async function setTheme(targetTheme){localforage.setItem("theme",targetTheme).then((value)=>{console.log("Theme set: "+value);UIAlert(D("themeSet"),"setTheme(): themeSet");});} -async function setErrorReporting(targetE){localforage.setItem("errorReporting",targetE).then((value)=>{console.log("ErrorReporing set: "+value);UIAlert(D("errorReportingSet"),"setErrorReporting(): errorReportingSet");});} -function shuffleArray(array){for(var i=array.length-1;i>0;i--){var j=Math.floor(Math.random()*(i+1));var temp=array[i];array[i]=array[j];array[j]=temp;}} -function setUIAdditionalOptions(state){var SENSITIVE_THEMES={"left":"Left / leva","right":"Right / desna"};if(state===true){var theme_keys=Object.keys(SENSITIVE_THEMES);shuffleArray(theme_keys);theme_keys.forEach((item)=>{var option_element=$(`<option value="${item}" id="option-${item}" data-theme="${item}">${SENSITIVE_THEMES[item]}</option>`);$("#select-theme").append(option_element);});}else{Object.keys(SENSITIVE_THEMES).forEach((item)=>{$("#option-"+item).remove();});} -$("#select-theme").formSelect();} -async function setAdditionalOptions(state){localforage.setItem("triggerWarningAccepted",state).then((value)=>{console.log("TriggerWarning set: "+value);UIAlert(D("triggerWarningSet"),"setAdditionalOptions(): triggerWarningSet");setUIAdditionalOptions(value);});} -document.addEventListener("DOMContentLoaded",async()=>{$("#triggered-checkbox").change(function(){if(this.checked){setAdditionalOptions(true);}else{setAdditionalOptions(false);}});$("#select-language").on("change",function(){setLanguage($(this).find(":selected").val());});$("#select-theme").on("change",function(){setTheme($(this).find(":selected").val());});$("#select-errorreporting").on("change",function(){setErrorReporting($(this).find(":selected").val());});localforage.getItem("chosenLang").then((value)=>{let selectedLanguage=value;if(value==null||value.length<1){selectedLanguage="sl";} -$(`#option-${selectedLanguage}`).attr("selected",true);}).catch(()=>{});localforage.getItem("theme").then((value)=>{let selectedTheme=value;if(value==null||value.length<1){selectedTheme="themeLight";} -$(`#option-${selectedTheme}`).attr("selected",true);}).catch(()=>{});localforage.getItem("errorReporting").then((value)=>{let selectedE=value;if(value==null||value.length<1){selectedE="on";} -$(`#option-${selectedE}`).attr("selected",true);}).catch(()=>{});const menus=document.querySelectorAll(".side-menu");M.Sidenav.init(menus,{edge:"right",draggable:true});var elems=document.querySelectorAll(".theme-select");M.FormSelect.init(elems,{});var elems=document.querySelectorAll(".errorreporting-select");M.FormSelect.init(elems,{});var elems=document.querySelectorAll(".lang-select");M.FormSelect.init(elems,{});});
\ No newline at end of file +async function setLanguage(langCode) { + localforage.setItem("chosenLang", langCode).then((value) => { + console.log("Language set: " + value); + UIAlert(D("languageSet"), "setLanguage(): languageSet"); + }); +} + +async function setTheme(targetTheme) { + localforage.setItem("theme", targetTheme).then((value) => { + console.log("Theme set: " + value); + UIAlert(D("themeSet"), "setTheme(): themeSet"); + }); +} + +async function setErrorReporting(targetE) { + localforage.setItem("errorReporting", targetE).then((value) => { + console.log("ErrorReporing set: " + value); + UIAlert(D("errorReportingSet"), "setErrorReporting(): errorReportingSet"); + }); +} + +function shuffleArray(array) { + for (var i = array.length - 1; i > 0; i--) { + var j = Math.floor(Math.random() * (i + 1)); + var temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } +} + +function setUIAdditionalOptions(state) { + var SENSITIVE_THEMES = { + "left": "Left / leva", + "right": "Right / desna" + }; + if (state === true) { + var theme_keys = Object.keys(SENSITIVE_THEMES); + shuffleArray(theme_keys); + theme_keys.forEach((item) => { + var option_element = $(`<option value="${item}" id="option-${item}" data-theme="${item}">${SENSITIVE_THEMES[item]}</option>`); + $("#select-theme").append(option_element); + }); + } else { + Object.keys(SENSITIVE_THEMES).forEach((item) => { + $("#option-" + item).remove(); + }); + } + var elems = document.querySelectorAll('#select-theme'); + M.FormSelect.init(elems, {}); +} + +async function setAdditionalOptions(state) { + localforage.setItem("triggerWarningAccepted", state).then((value) => { + console.log("TriggerWarning set: " + value); + UIAlert(D("triggerWarningSet"), "setAdditionalOptions(): triggerWarningSet"); + setUIAdditionalOptions(value); + }); +} + +document.addEventListener("DOMContentLoaded", async () => { + + // Setup checkbox handler + $("#triggered-checkbox").change(function() { + if (this.checked) { + setAdditionalOptions(true); + } else { + setAdditionalOptions(false); + } + }); + + $("#select-language").on("change", function() { + setLanguage($(this).find(":selected").val()); + }); + + $("#select-theme").on("change", function() { + setTheme($(this).find(":selected").val()); + }); + + $("#select-errorreporting").on("change", function() { + setErrorReporting($(this).find(":selected").val()); + }); + + localforage.getItem("chosenLang").then((value) => { + let selectedLanguage = value; + if(value == null || value.length < 1) { + selectedLanguage = "sl"; + } + $(`#option-${selectedLanguage}`).attr("selected", true); + }).catch(() => {}); + + localforage.getItem("theme").then((value) => { + let selectedTheme = value; + if(value == null || value.length < 1) { + selectedTheme = "themeLight"; + } + $(`#option-${selectedTheme}`).attr("selected", true); + }).catch(() => {}); + + localforage.getItem("errorReporting").then((value) => { + let selectedE = value; + if(value == null || value.length < 1) { + selectedE = "on"; + } + $(`#option-${selectedE}`).attr("selected", true); + }).catch(() => {}); + + localforage.getItem("triggerWarningAccepted").then((value) => { + if (value === true) { + $("#triggered-checkbox").attr("checked", true); + setUIAdditionalOptions(true); + } + }).catch(() => {}); + + // Setup side menu + const menus = document.querySelectorAll(".side-menu"); + M.Sidenav.init(menus, { edge: "right", draggable: true }); + + var elems = document.querySelectorAll(".theme-select"); + M.FormSelect.init(elems, {}); + + var elems = document.querySelectorAll(".errorreporting-select"); + M.FormSelect.init(elems, {}); + + // Setup language select dropdown + var elems = document.querySelectorAll(".lang-select"); + M.FormSelect.init(elems, {}); +}); diff --git a/dist/pages/about.html b/dist/pages/about.html index 26bb7e8..2265153 100755 --- a/dist/pages/about.html +++ b/dist/pages/about.html @@ -142,7 +142,7 @@ <div class="row"> <p> <small> - ^HEAD bf1bb2d36542cc2adf7b41dd347d3d77171cf1ce + ^HEAD 29b013b7591c0ee674bb8c2cf8cc660f67cdd9f7 </small> </p> </div> diff --git a/dist/pages/settings.html b/dist/pages/settings.html index 73a7ead..5e96b77 100755 --- a/dist/pages/settings.html +++ b/dist/pages/settings.html @@ -123,7 +123,7 @@ <h5 class="general-text"><x-su>additionalOptions</x-su></h5> </div> <div class="col s12"> - <p class="flow-text general-text"><x-du>triggerWarning</x-du></p> + <p class="general-text"><x-du>triggerWarning</x-du></p> </div> <div class="valign-wrapper col s12 m12"> <label> @@ -3,8 +3,8 @@ // Change version to cause cache refresh -const static_cache_name = "site-static-1.0.14-beta-bf1bb2d"; -// commit before the latest is bf1bb2d36542cc2adf7b41dd347d3d77171cf1ce +const static_cache_name = "site-static-1.0.13-beta-29b013b"; +// commit before the latest is 29b013b7591c0ee674bb8c2cf8cc660f67cdd9f7 // Got them with find . -not -path '*/\.*' | sed "s/.*/\"&\",/" | grep -v sw.js // sw.js NE SME BITI CACHAN, ker vsebuje verzijo! |