diff --git a/harbour-fernschreiber.pro b/harbour-fernschreiber.pro index e200e27..c7b972e 100644 --- a/harbour-fernschreiber.pro +++ b/harbour-fernschreiber.pro @@ -74,6 +74,7 @@ DISTFILES += qml/harbour-fernschreiber.qml \ qml/pages/ChatPage.qml \ qml/pages/ChatSelectionPage.qml \ qml/pages/CoverPage.qml \ + qml/pages/DebugPage.qml \ qml/pages/InitializationPage.qml \ qml/pages/NewChatPage.qml \ qml/pages/OverviewPage.qml \ diff --git a/qml/js/debug.js b/qml/js/debug.js index 011ccff..29f9db4 100644 --- a/qml/js/debug.js +++ b/qml/js/debug.js @@ -27,7 +27,11 @@ var timeEnd = enabled ? console.timeEnd : function(){}; var trace = enabled ? console.trace : function(){}; var count = enabled ? console.count : function(){}; var profile = enabled ? console.profile : function(){}; +var profileEnd = enabled ? console.profileEnd : function(){}; var exception = enabled ? console.exception : function(){}; +var warn = enabled ? console.warn: function(){}; +// Debug.error is always enabled. +var error = console.error; Fernschreiber.DebugLog.enabledChanged.connect(function() { enabled = Fernschreiber.DebugLog.enabled; @@ -39,9 +43,88 @@ Fernschreiber.DebugLog.enabledChanged.connect(function() { trace = console.trace; count = console.count; profile = console.profile; + profileEnd = console.profileEnd; exception = console.exception; } else { - log = assert = time = timeEnd = trace = count = profile = exception = function(){}; + log = assert = time = timeEnd = trace = count = profile = profileEnd = exception = warn = function(){}; } }); + +/** + * @function compareAndRepeat + * This function compares results of two functions for multiple sets of arguments and then repeats those calls to compare them with profiling. + * Testing showed that results are slightly skewed in favor of the secondaryProfileFunction, which (together with external factors) + * is almost compensated by running the calls often. + * + * @param {string} title - used for Debug output + * @param {function} profileFunction - function to compare + * @param {function} [secondaryProfileFunction] - secondary function to compare. Use falsy value to skip comparison. + * @param {Array.>} [functionArgumentsArray = []] - argument sets to run both functions with + * @param {number} [testCount = 10000] - times to run each function in addition to result comparison + * @param {Object} [testContext = null] - If the functions use `this` or otherwise depend on a Closure/Execution context, it can be set here. If they, for example, use properties of a QML `Item`, you can use that `Item` as `testContext`. + * + * @example + * // to compare the results of Debug.log("first", "second", "third") + * // and Debug.log("some value") + * // with the same calls of console.log and run 100 times each: + * Debug.compareAndRepeat("Debuglog", + * Debug.log, console.log, + * [["first", "second", "third"], ["some value"]], + * 100 + * ); + * +*/ + +function compareAndRepeat(title, profileFunction, secondaryProfileFunction, functionArgumentsArray, testCount, testContext) { + if(!enabled) { + log("Debugging disabled, compareAndRepeat ran uselessly:", title); + return; + } + var numberOfTests = testCount || 10000, + context = testContext || null, + args = functionArgumentsArray || [], + argumentIterator = args.length || 1, + results, + resultsComparison, + functionIterator = numberOfTests; + + if(secondaryProfileFunction) { + while(argumentIterator--) { + results = JSON.stringify(profileFunction.apply(context, args[argumentIterator] || null)); + resultsComparison = JSON.stringify(secondaryProfileFunction.apply(context, args[argumentIterator] || null)); + if(resultsComparison !== results) { + warn("\x1b[1m✘ Different return values!\x1b[0m", title) + warn("profileFunction result:", results); + warn("secondaryProfileFunction result:", resultsComparison); + return; + } + } + log("\x1b[1m✔ Comparison of", title, "return values successful!\x1b[0m") + } + log("Running", title, "with", args.length, "different argument sets", numberOfTests, "times each") + + if(secondaryProfileFunction) { + // "secondaryProfileFunction" + functionIterator = numberOfTests; + + while(functionIterator--) { + argumentIterator = args.length || 1; + while(argumentIterator--) { + secondaryProfileFunction.apply(context, args[argumentIterator] || null); + } + } + } + + // "profileFunction" + functionIterator = numberOfTests; + while(functionIterator--) { + argumentIterator = args.length || 1; + while(argumentIterator--) { + profileFunction.apply(context, args[argumentIterator] || null); + } + } + + log("Ran", title, args.length * numberOfTests, "times", secondaryProfileFunction ? "and compared results successfully" : ""); + +} diff --git a/qml/js/functions.js b/qml/js/functions.js index f33c172..0a88e16 100644 --- a/qml/js/functions.js +++ b/qml/js/functions.js @@ -29,89 +29,72 @@ function setGlobals(globals) { } function getUserName(userInformation) { - var firstName = typeof userInformation.first_name !== "undefined" ? userInformation.first_name : ""; - var lastName = typeof userInformation.last_name !== "undefined" ? userInformation.last_name : ""; - return (firstName + " " + lastName).trim(); + return ((userInformation.first_name || "") + " " + (userInformation.last_name || "")).trim(); } function getMessageText(message, simple, myself, ignoreEntities) { - if (message.content['@type'] === 'messageText') { + switch(message.content['@type']) { + case 'messageText': if (simple) { return message.content.text.text; } else { return enhanceMessageText(message.content.text, ignoreEntities); } - } - if (message.content['@type'] === 'messageSticker') { + case 'messageSticker': return simple ? qsTr("Sticker: %1").arg(message.content.sticker.emoji) : ""; - } - if (message.content['@type'] === 'messagePhoto') { + case 'messagePhoto': if (message.content.caption.text !== "") { return simple ? qsTr("Picture: %1").arg(message.content.caption.text) : enhanceMessageText(message.content.caption, ignoreEntities) } else { return simple ? (myself ? qsTr("sent a picture", "myself") : qsTr("sent a picture")) : ""; } - } - if (message.content['@type'] === 'messageVideo') { + case 'messageVideo': if (message.content.caption.text !== "") { return simple ? qsTr("Video: %1").arg(message.content.caption.text) : enhanceMessageText(message.content.caption, ignoreEntities) } else { return simple ? (myself ? qsTr("sent a video", "myself") : qsTr("sent a video")) : ""; } - } - if (message.content['@type'] === 'messageVideoNote') { + case 'messageVideoNote': return simple ? (myself ? qsTr("sent a video note", "myself") : qsTr("sent a video note")) : ""; - } - if (message.content['@type'] === 'messageAnimation') { + case 'messageAnimation': if (message.content.caption.text !== "") { return simple ? qsTr("Animation: %1").arg(message.content.caption.text) : enhanceMessageText(message.content.caption, ignoreEntities) } else { return simple ? (myself ? qsTr("sent an animation", "myself") : qsTr("sent an animation")) : ""; } - } - if (message.content['@type'] === 'messageAudio') { + case 'messageAudio': if (message.content.caption.text !== "") { return simple ? qsTr("Audio: %1").arg(message.content.caption.text) : enhanceMessageText(message.content.caption, ignoreEntities) } else { return simple ? (myself ? qsTr("sent an audio", "myself") : qsTr("sent an audio")) : ""; } - } - if (message.content['@type'] === 'messageVoiceNote') { + case 'messageVoiceNote': if (message.content.caption.text !== "") { return simple ? qsTr("Voice Note: %1").arg(message.content.caption.text) : enhanceMessageText(message.content.caption, ignoreEntities) } else { return simple ? (myself ? qsTr("sent a voice note", "myself") : qsTr("sent a voice note")) : ""; } - } - if (message.content['@type'] === 'messageDocument') { + case 'messageDocument': if (message.content.document.file_name !== "") { return simple ? qsTr("Document: %1").arg(message.content.document.file_name) : (message.content.document.file_name + ( message.content.caption.text !== "" ? ("
" + enhanceMessageText(message.content.caption, ignoreEntities) ) : "")).trim(); } else { return simple ? (myself ? qsTr("sent a document", "myself") : qsTr("sent a document")) : ""; } - } - if (message.content['@type'] === 'messageLocation') { + case 'messageLocation': return simple ? (myself ? qsTr("sent a location", "myself") : qsTr("sent a location")) : ""; - } - if (message.content['@type'] === 'messageVenue') { + case 'messageVenue': return simple ? (myself ? qsTr("sent a venue", "myself") : qsTr("sent a venue")) : ( "" + message.content.venue.title + ", " + message.content.venue.address ); - } - if (message.content['@type'] === 'messageContactRegistered') { + case 'messageContactRegistered': return myself ? qsTr("have registered with Telegram") : qsTr("has registered with Telegram"); - } - if (message.content['@type'] === 'messageChatJoinByLink') { + case 'messageChatJoinByLink': return myself ? qsTr("joined this chat", "myself") : qsTr("joined this chat"); - } - if (message.content['@type'] === 'messageChatAddMembers') { + case 'messageChatAddMembers': return myself ? qsTr("were added to this chat", "myself") : qsTr("was added to this chat"); - } - if (message.content['@type'] === 'messageChatDeleteMember') { + case 'messageChatDeleteMember': return myself ? qsTr("left this chat", "myself") : qsTr("left this chat"); - } - if (message.content['@type'] === 'messageChatChangeTitle') { + case 'messageChatChangeTitle': return myself ? qsTr("changed the chat title to %1", "myself").arg(message.content.title) : qsTr("changed the chat title to %1").arg(message.content.title); - } - if (message.content['@type'] === 'messagePoll') { + case 'messagePoll': if (message.content.poll.type['@type'] === "pollTypeQuiz") { if (message.content.poll.is_anonymous) { return simple ? (myself ? qsTr("sent an anonymous quiz", "myself") : qsTr("sent an anonymous quiz")) : ("" + qsTr("Anonymous Quiz") + ""); @@ -122,43 +105,33 @@ function getMessageText(message, simple, myself, ignoreEntities) { return simple ? (myself ? qsTr("sent an anonymous poll", "myself") : qsTr("sent an anonymous poll")) : ("" + qsTr("Anonymous Poll") + ""); } return simple ? (myself ? qsTr("sent a poll", "myself") : qsTr("sent a poll")) : ("" + qsTr("Poll") + ""); - } - if (message.content['@type'] === 'messageBasicGroupChatCreate' || message.content['@type'] === 'messageSupergroupChatCreate') { + case 'messageBasicGroupChatCreate': + case 'messageSupergroupChatCreate': return myself ? qsTr("created this group", "myself") : qsTr("created this group"); - } - if (message.content['@type'] === 'messageChatChangePhoto') { + case 'messageChatChangePhoto': return myself ? qsTr("changed the chat photo", "myself") : qsTr("changed the chat photo"); - } - if (message.content['@type'] === 'messageChatDeletePhoto') { + case 'messageChatDeletePhoto': return myself ? qsTr("deleted the chat photo", "myself") : qsTr("deleted the chat photo"); - } - if (message.content['@type'] === 'messageChatSetTtl') { + case 'messageChatSetTtl': return myself ? qsTr("changed the secret chat TTL setting", "myself; TTL = Time To Live") : qsTr("changed the secret chat TTL setting", "TTL = Time To Live"); - } - - if (message.content['@type'] === 'messageChatUpgradeFrom' || message.content['@type'] === 'messageChatUpgradeTo' ) { + case 'messageChatUpgradeFrom': + case 'messageChatUpgradeTo': return myself ? qsTr("upgraded this group to a supergroup", "myself") : qsTr("upgraded this group to a supergroup"); - } - if (message.content['@type'] === 'messageCustomServiceAction') { + case 'messageCustomServiceAction': return message.content.text; - } - if (message.content['@type'] === 'messagePinMessage') { + case 'messagePinMessage': return myself ? qsTr("changed the pinned message", "myself") : qsTr("changed the pinned message"); - } - if (message.content['@type'] === 'messageExpiredPhoto') { + case 'messageExpiredPhoto': return myself ? qsTr("sent a self-destructing photo that is expired", "myself") : qsTr("sent a self-destructing photo that is expired"); - } - if (message.content['@type'] === 'messageExpiredVideo') { + case 'messageExpiredVideo': return myself ? qsTr("sent a self-destructing video that is expired", "myself") : qsTr("sent a self-destructing video that is expired"); - } - if (message.content['@type'] === 'messageScreenshotTaken') { + case 'messageScreenshotTaken': return myself ? qsTr("created a screenshot in this chat", "myself") : qsTr("created a screenshot in this chat"); - } - if (message.content['@type'] === 'messageUnsupported') { + case 'messageUnsupported': return myself ? qsTr("sent an unsupported message", "myself") : qsTr("sent an unsupported message"); + default: + return myself ? qsTr("sent an unsupported message: %1", "myself; %1 is message type").arg(message.content['@type'].substring(7)) : qsTr("sent an unsupported message: %1", "%1 is message type").arg(message.content['@type'].substring(7)); } - - return myself ? qsTr("sent an unsupported message: %1", "myself; %1 is message type").arg(message.content['@type'].substring(7)) : qsTr("sent an unsupported message: %1", "%1 is message type").arg(message.content['@type'].substring(7)); } function getChatPartnerStatusText(statusType, was_online) { @@ -190,7 +163,6 @@ function getSecretChatStatus(secretChatDetails) { } function getChatMemberStatusText(statusType) { -// chatMemberStatusAdministrator, chatMemberStatusBanned, chatMemberStatusCreator, chatMemberStatusLeft, chatMemberStatusMember, and chatMemberStatusRestricted. switch(statusType) { case "chatMemberStatusAdministrator": return qsTr("Admin", "channel user role"); @@ -225,128 +197,135 @@ function getDateTimeTranslated(timestamp) { return new Date(timestamp * 1000).toLocaleString(); } -function MessageInsertion(offset, insertionString, removeLength) { - this.offset = offset; - this.insertionString = insertionString; - this.removeLength = removeLength; -} - -MessageInsertion.prototype.toString = function insertionToString() { - return "Offset: " + this.offset + ", Insertion String: " + this.insertionString + ", Remove Length: " + this.removeLength; -} - function handleHtmlEntity(messageText, messageInsertions, originalString, replacementString) { - var continueSearch = true; - var fromIndex = 0; - var nextIndex = 0; - while (continueSearch) { - nextIndex = messageText.indexOf(originalString, fromIndex); - if (nextIndex < 0) { - continueSearch = false; - } else { - messageInsertions.push(new MessageInsertion(nextIndex, replacementString, originalString.length)); - fromIndex = nextIndex + 1; - } + var nextIndex = -1; + while ((nextIndex = messageText.indexOf(originalString, nextIndex + 1)) > -1) { + messageInsertions.push({ offset: nextIndex, insertionString: replacementString, removeLength: originalString.length }); } } +var rawNewLineRegExp = /\r?\n/g; +var ampRegExp = /&/g; +var ltRegExp = //g; + function enhanceHtmlEntities(simpleText) { - - var messageInsertions = []; - var messageText = simpleText; - - handleHtmlEntity(messageText, messageInsertions, "&", "&"); - handleHtmlEntity(messageText, messageInsertions, "<", "<"); - handleHtmlEntity(messageText, messageInsertions, ">", ">"); - - messageInsertions.sort( function(a, b) { return (b.offset+b.removeLength) - (a.offset+a.removeLength) } ); - - for (var z = 0; z < messageInsertions.length; z++) { - messageText = messageText.substring(0, messageInsertions[z].offset) + messageInsertions[z].insertionString + messageText.substring(messageInsertions[z].offset + messageInsertions[z].removeLength); - } - - return messageText; - + return simpleText.replace(ampRegExp, "&").replace(ltRegExp, "<").replace(gtRegExp, ">");//.replace(rawNewLineRegExp, "
"); } +function messageInsertionSorter(a, b) { return (b.offset+b.removeLength) - (a.offset+a.removeLength) } + function enhanceMessageText(formattedText, ignoreEntities) { var messageInsertions = []; var messageText = formattedText.text; - + var entity; if (ignoreEntities) { return messageText; } + if(formattedText.entities.length === 0) { + return messageText.replace(ampRegExp, "&").replace(ltRegExp, "<").replace(gtRegExp, ">").replace(rawNewLineRegExp, "
"); + } + + for (var i = 0; i < formattedText.entities.length; i++) { + entity = formattedText.entities[i]; + if (entity['@type'] !== "textEntity") { + continue; + } + switch(entity.type['@type']) { + case "textEntityTypeBold": + messageInsertions.push( + { offset: entity.offset, insertionString: "", removeLength: 0 }, + { offset: (entity.offset + entity.length), insertionString: "", removeLength: 0 } + ); + break; + case "textEntityTypeUrl": + messageInsertions.push( + { offset: entity.offset, insertionString: "", removeLength: 0 }, + { offset: (entity.offset + entity.length), insertionString: "", removeLength: 0 } + ); + break; + case "textEntityTypeCode": + messageInsertions.push( + { offset: entity.offset, insertionString: "
", removeLength: 0 },
+                    { offset: (entity.offset + entity.length), insertionString: "
", removeLength: 0 } + ); + break; + case "textEntityTypeEmailAddress": + messageInsertions.push( + { offset: entity.offset, insertionString: "", removeLength: 0 }, + { offset: (entity.offset + entity.length), insertionString: "", removeLength: 0 } + ); + break; + case "textEntityTypeItalic": + messageInsertions.push( + { offset: entity.offset, insertionString: "", removeLength: 0 }, + { offset: (entity.offset + entity.length), insertionString: "", removeLength: 0 } + ); + break; + case "textEntityTypeMention": + messageInsertions.push( + { offset: entity.offset, insertionString: "", removeLength: 0 }, + { offset: (entity.offset + entity.length), insertionString: "", removeLength: 0 } + ); + break; + case "textEntityTypeMentionName": + messageInsertions.push( + { offset: entity.offset, insertionString: "", removeLength: 0 }, + { offset: (entity.offset + entity.length), insertionString: "", removeLength: 0 } + ); + break; + case "textEntityTypePhoneNumber": + messageInsertions.push( + { offset: entity.offset, insertionString: "", removeLength: 0 }, + { offset: (entity.offset + entity.length), insertionString: "", removeLength: 0 } + ); + break; + case "textEntityTypePre": + messageInsertions.push( + { offset: entity.offset, insertionString: "
", removeLength: 0 },
+                    { offset: (entity.offset + entity.length), insertionString: "
", removeLength: 0 } + ); + break; + case "textEntityTypePreCode": + messageInsertions.push( + { offset: entity.offset, insertionString: "
", removeLength: 0 },
+                    { offset: (entity.offset + entity.length), insertionString: "
", removeLength: 0 } + ); + break; + case "textEntityTypeTextUrl": + messageInsertions.push( + { offset: entity.offset, insertionString: "", removeLength: 0 }, + { offset: (entity.offset + entity.length), insertionString: "", removeLength: 0 } + ); + break; + case "textEntityTypeUnderline": + messageInsertions.push( + { offset: entity.offset, insertionString: "", removeLength: 0 }, + { offset: (entity.offset + entity.length), insertionString: "", removeLength: 0 } + ); + break; + } + } + + if(messageInsertions.length === 0) { + return messageText.replace(ampRegExp, "&").replace(ltRegExp, "<").replace(gtRegExp, ">").replace(rawNewLineRegExp, "
"); + } handleHtmlEntity(messageText, messageInsertions, "&", "&"); handleHtmlEntity(messageText, messageInsertions, "<", "<"); handleHtmlEntity(messageText, messageInsertions, ">", ">"); - - for (var i = 0; i < formattedText.entities.length; i++) { - if (formattedText.entities[i]['@type'] !== "textEntity") { - continue; - } - var entityType = formattedText.entities[i].type['@type']; - if (entityType === "textEntityTypeBold") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "", 0 )); - messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "", 0 )); - } - if (entityType === "textEntityTypeUrl") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "", 0 )); - messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "", 0 )); - } - if (entityType === "textEntityTypeCode") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "
", 0 ));
-            messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "
", 0 )); - } - if (entityType === "textEntityTypeEmailAddress") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "", 0 )); - messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "", 0 )); - } - if (entityType === "textEntityTypeItalic") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "", 0 )); - messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "", 0 )); - } - if (entityType === "textEntityTypeMention") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "", 0 )); - messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "", 0 )); - } - if (entityType === "textEntityTypeMentionName") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "", 0 )); - messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "", 0 )); - } - if (entityType === "textEntityTypePhoneNumber") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "", 0 )); - messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "", 0 )); - } - if (entityType === "textEntityTypePre") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "
", 0 ));
-            messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "
", 0 )); - } - if (entityType === "textEntityTypePreCode") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "
", 0 ));
-            messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "
", 0 )); - } - if (entityType === "textEntityTypeTextUrl") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "", 0 )); - messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "", 0 )); - } - if (entityType === "textEntityTypeUnderline") { - messageInsertions.push(new MessageInsertion(formattedText.entities[i].offset, "", 0 )); - messageInsertions.push(new MessageInsertion((formattedText.entities[i].offset + formattedText.entities[i].length), "", 0 )); - } - } - - messageInsertions.sort( function(a, b) { return (b.offset+b.removeLength) - (a.offset+a.removeLength) } ); + messageInsertions.sort(messageInsertionSorter); for (var z = 0; z < messageInsertions.length; z++) { - messageText = messageText.substring(0, messageInsertions[z].offset) + messageInsertions[z].insertionString + messageText.substring(messageInsertions[z].offset + messageInsertions[z].removeLength); + messageText = messageText.substring(0, messageInsertions[z].offset) + + messageInsertions[z].insertionString + + messageText.substring(messageInsertions[z].offset + messageInsertions[z].removeLength); } - messageText = messageText.replace(new RegExp("\r?\n", "g"), "
"); + messageText = messageText.replace(rawNewLineRegExp, "
"); return messageText; - } function handleLink(link) { @@ -401,6 +380,7 @@ function getVideoHeight(videoWidth, videoData) { return 1; } } + function replaceUrlsWithLinks(string) { return string.replace(/((\w+):\/\/[\w?=&.\/-;#~%-]+(?![\w\s?&.\/;#~%"=-]*>))/g, "$1"); } diff --git a/qml/pages/AboutPage.qml b/qml/pages/AboutPage.qml index f0080da..791f576 100644 --- a/qml/pages/AboutPage.qml +++ b/qml/pages/AboutPage.qml @@ -20,7 +20,6 @@ import QtQuick 2.6 import Sailfish.Silica 1.0 import "../components" import "../js/twemoji.js" as Emoji -import "../js/functions.js" as Functions Page { id: aboutPage diff --git a/qml/pages/DebugPage.qml b/qml/pages/DebugPage.qml new file mode 100644 index 0000000..b3e1b24 --- /dev/null +++ b/qml/pages/DebugPage.qml @@ -0,0 +1,95 @@ +/* + Copyright (C) 2020 Sebastian J. Wolf and other contributors + + This file is part of Fernschreiber. + + Fernschreiber is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Fernschreiber is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Fernschreiber. If not, see . +*/ +import QtQuick 2.6 +import Sailfish.Silica 1.0 +import "../components" +import "../js/twemoji.js" as Emoji +import "../js/functions.js" as Functions +import "../js/debug.js" as Debug + +Page { + id: debugPage + allowedOrientations: Orientation.All + + SilicaFlickable { + id: aboutContainer + contentHeight: column.height + anchors.fill: parent + + Column { + id: column + width: parent.width + spacing: Theme.paddingLarge + PageHeader { + title: "Debug Page" + description: "here be dragons" + + } + } + + VerticalScrollDecorator {} + } + + Timer { + id: profileTimer + interval: 1000 + property bool hasRun + property var cases: [] + onTriggered: { + if(cases.length === 0) { + return; + } + + if(!hasRun) { + hasRun = true; + Debug.profile(); + } + cases.pop()(); + + if(cases.length > 0) { + restart(); + } else { + Debug.profileEnd(); + } + } + } + + onStatusChanged: { + if (status === PageStatus.Active) { + // example runner for comparing function calls + +// profileTimer.cases.push(function(){ +// Debug.compareAndRepeat( +// "getUserName", +// Functions.getUserName, +// Functions.getUserName, +// [ +// [{first_name: "Test", last_name: "User"}], +// [{first_name: "Test", last_name: ""}], +// [{first_name: "Test"}], +// [{first_name: "", last_name: "User"}], +// [{last_name: "User"}] +// ], +// 800 +// ) +// }); +// profileTimer.start(); + } + } +} diff --git a/qml/pages/OverviewPage.qml b/qml/pages/OverviewPage.qml index 7006fa3..70ae2c7 100644 --- a/qml/pages/OverviewPage.qml +++ b/qml/pages/OverviewPage.qml @@ -190,6 +190,11 @@ Page { visible: !overviewPage.loading PullDownMenu { + MenuItem { + text: "Debug" + visible: Debug.enabled + onClicked: pageStack.push(Qt.resolvedUrl("../pages/DebugPage.qml")) + } MenuItem { text: qsTr("About Fernschreiber") onClicked: pageStack.push(Qt.resolvedUrl("../pages/AboutPage.qml"))