Conf saving and Mastodon instance login
Worst login implementation in the history of worst logins implementation
This commit is contained in:
parent
e0b81bf291
commit
01ac966b35
12 changed files with 425 additions and 467 deletions
|
@ -18,7 +18,6 @@ SOURCES += src/harbour-tooter.cpp
|
||||||
|
|
||||||
OTHER_FILES += qml/harbour-tooter.qml \
|
OTHER_FILES += qml/harbour-tooter.qml \
|
||||||
qml/cover/CoverPage.qml \
|
qml/cover/CoverPage.qml \
|
||||||
qml/pages/FirstPage.qml \
|
|
||||||
qml/pages/SecondPage.qml \
|
qml/pages/SecondPage.qml \
|
||||||
rpm/harbour-tooter.changes.in \
|
rpm/harbour-tooter.changes.in \
|
||||||
rpm/harbour-tooter.spec \
|
rpm/harbour-tooter.spec \
|
||||||
|
@ -40,5 +39,7 @@ TRANSLATIONS += translations/harbour-tooter-de.ts
|
||||||
|
|
||||||
DISTFILES += \
|
DISTFILES += \
|
||||||
qml/lib/API.js \
|
qml/lib/API.js \
|
||||||
qml/pages/MyList.qml \
|
qml/pages/MainPage.qml \
|
||||||
qml/pages/Tweet.qml
|
qml/pages/LoginPage.qml \
|
||||||
|
qml/pages/JSONListModel.qml \
|
||||||
|
qml/lib/jsonpath.js
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE QtCreatorProject>
|
<!DOCTYPE QtCreatorProject>
|
||||||
<!-- Written by QtCreator 4.0.1, 2017-06-01T15:42:11. -->
|
<!-- Written by QtCreator 4.0.1, 2017-06-02T15:45:28. -->
|
||||||
<qtcreator>
|
<qtcreator>
|
||||||
<data>
|
<data>
|
||||||
<variable>EnvironmentId</variable>
|
<variable>EnvironmentId</variable>
|
||||||
|
@ -8,7 +8,7 @@
|
||||||
</data>
|
</data>
|
||||||
<data>
|
<data>
|
||||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||||
<value type="int">0</value>
|
<value type="int">1</value>
|
||||||
</data>
|
</data>
|
||||||
<data>
|
<data>
|
||||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||||
|
@ -768,7 +768,7 @@
|
||||||
<value type="QString" key="MerRunConfiguration.QmlLiveTargetWorkspace"></value>
|
<value type="QString" key="MerRunConfiguration.QmlLiveTargetWorkspace"></value>
|
||||||
<value type="int" key="PE.EnvironmentAspect.Base">1</value>
|
<value type="int" key="PE.EnvironmentAspect.Base">1</value>
|
||||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">harbour-tooter (on Mer Device)</value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">harbour-tooter (on Remote Device)</value>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRunConfiguration:harbour-tooter</value>
|
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QmakeProjectManager.MerRunConfiguration:harbour-tooter</value>
|
||||||
<value type="QString" key="Qt4ProjectManager.MaemoRunConfiguration.Arguments"></value>
|
<value type="QString" key="Qt4ProjectManager.MaemoRunConfiguration.Arguments"></value>
|
||||||
|
|
|
@ -45,12 +45,16 @@ ApplicationWindow
|
||||||
console.log('confLoaded');
|
console.log('confLoaded');
|
||||||
console.log(JSON.stringify(Logic.conf))
|
console.log(JSON.stringify(Logic.conf))
|
||||||
if (Logic.conf['instance']) {
|
if (Logic.conf['instance']) {
|
||||||
Logic.api = Logic.MastodonAPI({ instance: Logic.conf['instance'], api_user_token: "" });
|
Logic.api = new Logic.MastodonAPI({ instance: Logic.conf['instance'], api_user_token: "" });
|
||||||
}
|
}
|
||||||
if (Logic.conf['login']) {
|
if (Logic.conf['login']) {
|
||||||
Logic.api.setConfig("api_user_token", Logic.conf['api_user_token'])
|
Logic.api.setConfig("api_user_token", Logic.conf['api_user_token'])
|
||||||
|
pageStack.push(Qt.resolvedUrl("./pages/MainPage.qml"), {})
|
||||||
|
} else {
|
||||||
|
pageStack.push(Qt.resolvedUrl("./pages/LoginPage.qml"), {})
|
||||||
}
|
}
|
||||||
pageStack.push(Qt.resolvedUrl("./pages/FirstPage.qml"), {})
|
|
||||||
|
|
||||||
});
|
});
|
||||||
Logic.init()
|
Logic.init()
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,13 +57,19 @@ var init = function(){
|
||||||
};
|
};
|
||||||
|
|
||||||
function saveData() {
|
function saveData() {
|
||||||
|
console.log("SAVING CONF TO DB")
|
||||||
db.transaction(function(tx) {
|
db.transaction(function(tx) {
|
||||||
for (var key in conf) {
|
for (var key in conf) {
|
||||||
if (conf.hasOwnProperty(key)){
|
if (conf.hasOwnProperty(key)){
|
||||||
console.log(key + "\t>\t"+conf[key]);
|
console.log(key + "\t>\t"+conf[key]);
|
||||||
tx.executeSql('INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?) ', [key, JSON.stringify(conf[key])])
|
if (typeof conf[key] === "object" && conf[key] === null) {
|
||||||
|
tx.executeSql('DELETE FROM settings WHERE key=? ', [key])
|
||||||
|
} else {
|
||||||
|
tx.executeSql('INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?) ', [key, JSON.stringify(conf[key])])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
console.log("ENF OF SAVING")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,27 +274,34 @@ var MastodonAPI = function(config) {
|
||||||
if (typeof scopes !== "string") {
|
if (typeof scopes !== "string") {
|
||||||
scopes = scopes.join(" ");
|
scopes = scopes.join(" ");
|
||||||
}
|
}
|
||||||
$.ajax({
|
|
||||||
url: apiBase + "apps",
|
var http = new XMLHttpRequest()
|
||||||
type: "POST",
|
var url = apiBase + "apps";
|
||||||
data: {
|
var params = 'client_name=' + client_name + '&redirect_uris=' + redirect_uri + '&scopes=' + scopes + '&website=' + website;
|
||||||
client_name: client_name,
|
console.log(params)
|
||||||
redirect_uris: redirect_uri,
|
http.open("POST", url, true);
|
||||||
scopes: scopes,
|
|
||||||
website: website
|
// Send the proper header information along with the request
|
||||||
},
|
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||||
success: function (data, textStatus) {
|
|
||||||
console.log("Registered Application: " + data);
|
http.onreadystatechange = function() { // Call a function when the state changes.
|
||||||
callback(data);
|
if (http.readyState == 4) {
|
||||||
}
|
if (http.status == 200) {
|
||||||
});
|
console.log("Registered Application: " + http.response);
|
||||||
|
callback(http.response)
|
||||||
|
} else {
|
||||||
|
console.log("error: " + http.status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
http.send(params);
|
||||||
},
|
},
|
||||||
generateAuthLink: function (client_id, redirect_uri, responseType, scopes) {
|
generateAuthLink: function (client_id, redirect_uri, responseType, scopes) {
|
||||||
return config.instance + "/oauth/authorize?client_id=" + client_id + "&redirect_uri=" + redirect_uri +
|
return config.instance + "/oauth/authorize?client_id=" + client_id + "&redirect_uri=" + redirect_uri +
|
||||||
"&response_type=" + responseType + "&scope=" + scopes.join("+");
|
"&response_type=" + responseType + "&scope=" + scopes.join("+");
|
||||||
},
|
},
|
||||||
getAccessTokenFromAuthCode: function (client_id, client_secret, redirect_uri, code, callback) {
|
getAccessTokenFromAuthCode: function (client_id, client_secret, redirect_uri, code, callback) {
|
||||||
$.ajax({
|
/*$.ajax({
|
||||||
url: config.instance + "/oauth/token",
|
url: config.instance + "/oauth/token",
|
||||||
type: "POST",
|
type: "POST",
|
||||||
data: {
|
data: {
|
||||||
|
@ -302,7 +315,27 @@ var MastodonAPI = function(config) {
|
||||||
console.log("Got Token: " + data);
|
console.log("Got Token: " + data);
|
||||||
callback(data);
|
callback(data);
|
||||||
}
|
}
|
||||||
});
|
});*/
|
||||||
|
var http = new XMLHttpRequest()
|
||||||
|
var url = config.instance + "/oauth/token";
|
||||||
|
var params = 'client_id=' + client_id + '&client_secret=' + client_secret + '&redirect_uri=' + redirect_uri + '&grant_type=authorization_code&code=' + code;
|
||||||
|
console.log(params)
|
||||||
|
http.open("POST", url, true);
|
||||||
|
|
||||||
|
// Send the proper header information along with the request
|
||||||
|
http.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
|
||||||
|
|
||||||
|
http.onreadystatechange = function() { // Call a function when the state changes.
|
||||||
|
if (http.readyState == 4) {
|
||||||
|
if (http.status == 200) {
|
||||||
|
console.log("Got Token: " + http.response);
|
||||||
|
callback(http.response)
|
||||||
|
} else {
|
||||||
|
console.log("error: " + http.status)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
http.send(params);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
88
qml/lib/jsonpath.js
Normal file
88
qml/lib/jsonpath.js
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
/* JSONPath 0.8.5 - XPath for JSON
|
||||||
|
*
|
||||||
|
* Copyright (c) 2007 Stefan Goessner (goessner.net)
|
||||||
|
* Licensed under the MIT (MIT-LICENSE.txt) licence.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function jsonPath(obj, expr, arg) {
|
||||||
|
var P = {
|
||||||
|
resultType: arg && arg.resultType || "VALUE",
|
||||||
|
result: [],
|
||||||
|
normalize: function(expr) {
|
||||||
|
var subx = [];
|
||||||
|
return expr.replace(/[\['](\??\(.*?\))[\]']|\['(.*?)'\]/g, function($0,$1,$2){return "[#"+(subx.push($1||$2)-1)+"]";}) /* http://code.google.com/p/jsonpath/issues/detail?id=4 */
|
||||||
|
.replace(/'?\.'?|\['?/g, ";")
|
||||||
|
.replace(/;;;|;;/g, ";..;")
|
||||||
|
.replace(/;$|'?\]|'$/g, "")
|
||||||
|
.replace(/#([0-9]+)/g, function($0,$1){return subx[$1];});
|
||||||
|
},
|
||||||
|
asPath: function(path) {
|
||||||
|
var x = path.split(";"), p = "$";
|
||||||
|
for (var i=1,n=x.length; i<n; i++)
|
||||||
|
p += /^[0-9*]+$/.test(x[i]) ? ("["+x[i]+"]") : ("['"+x[i]+"']");
|
||||||
|
return p;
|
||||||
|
},
|
||||||
|
store: function(p, v) {
|
||||||
|
if (p) P.result[P.result.length] = P.resultType == "PATH" ? P.asPath(p) : v;
|
||||||
|
return !!p;
|
||||||
|
},
|
||||||
|
trace: function(expr, val, path) {
|
||||||
|
if (expr !== "") {
|
||||||
|
var x = expr.split(";"), loc = x.shift();
|
||||||
|
x = x.join(";");
|
||||||
|
if (val && val.hasOwnProperty(loc))
|
||||||
|
P.trace(x, val[loc], path + ";" + loc);
|
||||||
|
else if (loc === "*")
|
||||||
|
P.walk(loc, x, val, path, function(m,l,x,v,p) { P.trace(m+";"+x,v,p); });
|
||||||
|
else if (loc === "..") {
|
||||||
|
P.trace(x, val, path);
|
||||||
|
P.walk(loc, x, val, path, function(m,l,x,v,p) { typeof v[m] === "object" && P.trace("..;"+x,v[m],p+";"+m); });
|
||||||
|
}
|
||||||
|
else if (/^\(.*?\)$/.test(loc)) // [(expr)]
|
||||||
|
P.trace(P.eval(loc, val, path.substr(path.lastIndexOf(";")+1))+";"+x, val, path);
|
||||||
|
else if (/^\?\(.*?\)$/.test(loc)) // [?(expr)]
|
||||||
|
P.walk(loc, x, val, path, function(m,l,x,v,p) { if (P.eval(l.replace(/^\?\((.*?)\)$/,"$1"), v instanceof Array ? v[m] : v, m)) P.trace(m+";"+x,v,p); }); // issue 5 resolved
|
||||||
|
else if (/^(-?[0-9]*):(-?[0-9]*):?([0-9]*)$/.test(loc)) // [start:end:step] phyton slice syntax
|
||||||
|
P.slice(loc, x, val, path);
|
||||||
|
else if (/,/.test(loc)) { // [name1,name2,...]
|
||||||
|
for (var s=loc.split(/'?,'?/),i=0,n=s.length; i<n; i++)
|
||||||
|
P.trace(s[i]+";"+x, val, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
P.store(path, val);
|
||||||
|
},
|
||||||
|
walk: function(loc, expr, val, path, f) {
|
||||||
|
if (val instanceof Array) {
|
||||||
|
for (var i=0,n=val.length; i<n; i++)
|
||||||
|
if (i in val)
|
||||||
|
f(i,loc,expr,val,path);
|
||||||
|
}
|
||||||
|
else if (typeof val === "object") {
|
||||||
|
for (var m in val)
|
||||||
|
if (val.hasOwnProperty(m))
|
||||||
|
f(m,loc,expr,val,path);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
slice: function(loc, expr, val, path) {
|
||||||
|
if (val instanceof Array) {
|
||||||
|
var len=val.length, start=0, end=len, step=1;
|
||||||
|
loc.replace(/^(-?[0-9]*):(-?[0-9]*):?(-?[0-9]*)$/g, function($0,$1,$2,$3){start=parseInt($1||start);end=parseInt($2||end);step=parseInt($3||step);});
|
||||||
|
start = (start < 0) ? Math.max(0,start+len) : Math.min(len,start);
|
||||||
|
end = (end < 0) ? Math.max(0,end+len) : Math.min(len,end);
|
||||||
|
for (var i=start; i<end; i+=step)
|
||||||
|
P.trace(i+";"+expr, val, path);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
eval: function(x, _v, _vname) {
|
||||||
|
try { return $ && _v && eval(x.replace(/(^|[^\\])@/g, "$1_v").replace(/\\@/g, "@")); } // issue 7 : resolved ..
|
||||||
|
catch(e) { throw new SyntaxError("jsonPath: " + e.message + ": " + x.replace(/(^|[^\\])@/g, "$1_v").replace(/\\@/g, "@")); } // issue 7 : resolved ..
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var $ = obj;
|
||||||
|
if (expr && obj && (P.resultType == "VALUE" || P.resultType == "PATH")) {
|
||||||
|
P.trace(P.normalize(expr).replace(/^\$;?/,""), obj, "$"); // issue 6 resolved
|
||||||
|
return P.result.length ? P.result : false;
|
||||||
|
}
|
||||||
|
}
|
51
qml/pages/JSONListModel.qml
Normal file
51
qml/pages/JSONListModel.qml
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/* JSONListModel - a QML ListModel with JSON and JSONPath support
|
||||||
|
*
|
||||||
|
* Copyright (c) 2012 Romain Pokrzywka (KDAB) (romain@kdab.com)
|
||||||
|
* Licensed under the MIT licence (http://opensource.org/licenses/mit-license.php)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.0
|
||||||
|
import "../lib/jsonpath.js" as JSONPath
|
||||||
|
|
||||||
|
Item {
|
||||||
|
property string source: ""
|
||||||
|
property string json: ""
|
||||||
|
property string query: ""
|
||||||
|
|
||||||
|
property ListModel model : ListModel { id: jsonModel }
|
||||||
|
property alias count: jsonModel.count
|
||||||
|
|
||||||
|
onSourceChanged: {
|
||||||
|
var xhr = new XMLHttpRequest;
|
||||||
|
xhr.open("GET", source);
|
||||||
|
xhr.onreadystatechange = function() {
|
||||||
|
if (xhr.readyState == XMLHttpRequest.DONE)
|
||||||
|
json = xhr.responseText;
|
||||||
|
}
|
||||||
|
xhr.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
onJsonChanged: updateJSONModel()
|
||||||
|
onQueryChanged: updateJSONModel()
|
||||||
|
|
||||||
|
function updateJSONModel() {
|
||||||
|
jsonModel.clear();
|
||||||
|
|
||||||
|
if ( json === "" )
|
||||||
|
return;
|
||||||
|
|
||||||
|
var objectArray = parseJSONString(json, query);
|
||||||
|
for ( var key in objectArray ) {
|
||||||
|
var jo = objectArray[key];
|
||||||
|
jsonModel.append( jo );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseJSONString(jsonString, jsonPathQuery) {
|
||||||
|
var objectArray = JSON.parse(jsonString);
|
||||||
|
if ( jsonPathQuery !== "" )
|
||||||
|
objectArray = JSONPath.jsonPath(objectArray, jsonPathQuery);
|
||||||
|
|
||||||
|
return objectArray;
|
||||||
|
}
|
||||||
|
}
|
188
qml/pages/LoginPage.qml
Normal file
188
qml/pages/LoginPage.qml
Normal file
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
Copyright (C) 2013 Jolla Ltd.
|
||||||
|
Contact: Thomas Perl <thomas.perl@jollamobile.com>
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
You may use this file under the terms of BSD license as follows:
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
* Neither the name of the Jolla Ltd nor the
|
||||||
|
names of its contributors may be used to endorse or promote products
|
||||||
|
derived from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtWebKit 3.0
|
||||||
|
import Sailfish.Silica 1.0
|
||||||
|
import "../lib/API.js" as Logic
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Page {
|
||||||
|
id: loginPage
|
||||||
|
|
||||||
|
// The effective value will be restricted by ApplicationWindow.allowedOrientations
|
||||||
|
allowedOrientations: Orientation.All
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
SilicaFlickable {
|
||||||
|
anchors.fill: parent
|
||||||
|
contentHeight: column.height + Theme.paddingLarge
|
||||||
|
|
||||||
|
VerticalScrollDecorator {}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: column
|
||||||
|
width: parent.width
|
||||||
|
|
||||||
|
PageHeader { title: "Login" }
|
||||||
|
|
||||||
|
SectionHeader {
|
||||||
|
text: "Instance"
|
||||||
|
}
|
||||||
|
|
||||||
|
TextField {
|
||||||
|
id: instance
|
||||||
|
focus: true
|
||||||
|
label: "Enter the name mastodon instance"
|
||||||
|
placeholderText: label
|
||||||
|
text: "https://mastodon.social"
|
||||||
|
width: parent.width
|
||||||
|
EnterKey.iconSource: "image://theme/icon-m-enter-next"
|
||||||
|
EnterKey.onClicked: {
|
||||||
|
Logic.api = new Logic.MastodonAPI({ instance: instance.text, api_user_token: "" });
|
||||||
|
Logic.api.registerApplication("Tooter",
|
||||||
|
'http://localhost/harbour-tooter', // redirect uri, we will need this later on
|
||||||
|
["read", "write", "follow"], //scopes
|
||||||
|
"http://grave-design.com/harbour-tooter", //website on the login screen
|
||||||
|
function(data) {
|
||||||
|
|
||||||
|
console.log(data)
|
||||||
|
var conf = JSON.parse(data)
|
||||||
|
conf.instance = instance.text;
|
||||||
|
conf.login = false;
|
||||||
|
|
||||||
|
|
||||||
|
/*conf['login'] = false;
|
||||||
|
conf['mastodon_client_id'] = data['mastodon_client_id'];
|
||||||
|
conf['mastodon_client_secret'] = data['mastodon_client_secret'];
|
||||||
|
conf['mastodon_client_redirect_uri'] = data['mastodon_client_redirect_uri'];
|
||||||
|
delete Logic.conf;*/
|
||||||
|
Logic.conf = conf;
|
||||||
|
console.log(JSON.stringify(conf))
|
||||||
|
console.log(JSON.stringify(Logic.conf))
|
||||||
|
// we got our application
|
||||||
|
|
||||||
|
// our user to it!
|
||||||
|
var url = Logic.api.generateAuthLink(Logic.conf["client_id"],
|
||||||
|
Logic.conf["redirect_uri"],
|
||||||
|
"code", // oauth method
|
||||||
|
["read", "write", "follow"] //scopes
|
||||||
|
);
|
||||||
|
console.log(url)
|
||||||
|
webView.url = url
|
||||||
|
webView.visible = true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
leftMargin: Theme.paddingLarge
|
||||||
|
rightMargin: Theme.paddingLarge
|
||||||
|
}
|
||||||
|
|
||||||
|
width: parent.width
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
color: Theme.secondaryHighlightColor
|
||||||
|
font.pixelSize: Theme.fontSizeExtraSmall
|
||||||
|
text: "Mastodon is a free, open-source social network. A decentralized alternative to commercial platforms, it avoids the risks of a single company monopolizing your communication. Pick a server that you trust — whichever you choose, you can interact with everyone else. Anyone can run their own Mastodon instance and participate in the social network seamlessly."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
SilicaWebView {
|
||||||
|
id: webView
|
||||||
|
visible: false
|
||||||
|
anchors {
|
||||||
|
top: parent.top
|
||||||
|
left: parent.left
|
||||||
|
right: parent.right
|
||||||
|
bottom: parent.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
opacity: 0
|
||||||
|
onLoadingChanged: {
|
||||||
|
console.log(url)
|
||||||
|
if ((url+"").substr(0, 37) === 'http://localhost/harbour-tooter?code=') {
|
||||||
|
visible = false;
|
||||||
|
var authCode = (url+"").substr(37)
|
||||||
|
console.log(authCode)
|
||||||
|
|
||||||
|
Logic.api.getAccessTokenFromAuthCode(
|
||||||
|
Logic.conf["client_id"],
|
||||||
|
Logic.conf["client_secret"],
|
||||||
|
Logic.conf["redirect_uri"],
|
||||||
|
authCode,
|
||||||
|
function(data) {
|
||||||
|
// AAAND DATA CONTAINS OUR TOKEN!
|
||||||
|
console.log(data)
|
||||||
|
data = JSON.parse(data)
|
||||||
|
console.log(JSON.stringify(data))
|
||||||
|
console.log(JSON.stringify(data.access_token))
|
||||||
|
Logic.conf["api_user_token"] = data.access_token
|
||||||
|
Logic.conf["login"] = true;
|
||||||
|
Logic.api.setConfig("api_user_token", Logic.conf["api_user_token"])
|
||||||
|
pageStack.replace(Qt.resolvedUrl("MainPage.qml"), {})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
switch (loadRequest.status)
|
||||||
|
{
|
||||||
|
case WebView.LoadSucceededStatus:
|
||||||
|
opacity = 1
|
||||||
|
break
|
||||||
|
case WebView.LoadFailedStatus:
|
||||||
|
//opacity = 0
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
//opacity = 0
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FadeAnimation on opacity {}
|
||||||
|
PullDownMenu {
|
||||||
|
MenuItem {
|
||||||
|
text: "Reload"
|
||||||
|
onClicked: webView.reload()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ import "../lib/API.js" as Logic
|
||||||
|
|
||||||
|
|
||||||
Page {
|
Page {
|
||||||
id: page
|
id: mainPage
|
||||||
|
|
||||||
// The effective value will be restricted by ApplicationWindow.allowedOrientations
|
// The effective value will be restricted by ApplicationWindow.allowedOrientations
|
||||||
allowedOrientations: Orientation.All
|
allowedOrientations: Orientation.All
|
||||||
|
@ -43,16 +43,28 @@ Page {
|
||||||
SilicaFlickable {
|
SilicaFlickable {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
PageHeader {
|
||||||
|
title: "Tooter"
|
||||||
|
}
|
||||||
|
|
||||||
// PullDownMenu and PushUpMenu must be declared in SilicaFlickable, SilicaListView or SilicaGridView
|
// PullDownMenu and PushUpMenu must be declared in SilicaFlickable, SilicaListView or SilicaGridView
|
||||||
PullDownMenu {
|
PullDownMenu {
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: qsTrId("Set demo conf")
|
text: Logic.conf['login'] ? qsTrId("Logout"): qsTrId("Login")
|
||||||
onClicked: {
|
onClicked: {
|
||||||
Logic.conf['login'] = true
|
if (Logic.conf['login']) {
|
||||||
Logic.conf['instance'] = "https://mastodon.social";
|
Logic.conf['login'] = false
|
||||||
Logic.conf['api_user_token'] = '6d8cb23e3ebf3c7a97dd9adf204e47ad159f1a3d07dbbd0325e98981368d8c51';
|
Logic.conf['instance'] = null;
|
||||||
|
Logic.conf['api_user_token'] = null;
|
||||||
|
Logic.conf['dysko'] = null;
|
||||||
|
} else {
|
||||||
|
Logic.conf['login'] = true
|
||||||
|
Logic.conf['instance'] = "https://mastodon.social";
|
||||||
|
Logic.conf['api_user_token'] = '6d8cb23e3ebf3c7a97dd9adf204e47ad159f1a3d07dbbd0325e98981368d8c51';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MenuItem {
|
MenuItem {
|
||||||
text: qsTr("Show Page 2")
|
text: qsTr("Show Page 2")
|
||||||
onClicked: pageStack.push(Qt.resolvedUrl("SecondPage.qml"))
|
onClicked: pageStack.push(Qt.resolvedUrl("SecondPage.qml"))
|
||||||
|
@ -60,13 +72,7 @@ Page {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
MyList {
|
|
||||||
id: myList
|
|
||||||
anchors.fill: parent
|
|
||||||
model: ListModel {
|
|
||||||
id: model
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
|
@ -76,37 +82,8 @@ Page {
|
||||||
// data is the http response object
|
// data is the http response object
|
||||||
//sidenote: please do not actually execute this request, you could be bullied by your friends
|
//sidenote: please do not actually execute this request, you could be bullied by your friends
|
||||||
});*/
|
});*/
|
||||||
var tootParser = function(data){
|
|
||||||
console.log(data)
|
|
||||||
var ret = {};
|
|
||||||
ret.id = data.id
|
|
||||||
ret.content = data.content
|
|
||||||
ret.created_at = data.created_at
|
|
||||||
ret.in_reply_to_account_id = data.in_reply_to_account_id
|
|
||||||
ret.in_reply_to_id = data.in_reply_to_id
|
|
||||||
|
|
||||||
ret.user_id = data.account.id
|
/*Logic.api.get("timelines/home", [
|
||||||
ret.user_locked = data.account.locked
|
|
||||||
ret.username = data.account.username
|
|
||||||
ret.display_name = data.account.display_name
|
|
||||||
ret.avatar_static = data.account.avatar_static
|
|
||||||
|
|
||||||
|
|
||||||
ret.favourited = data.favourited ? true : false
|
|
||||||
ret.favourites_count = data.favourites_count ? data.favourites_count : 0
|
|
||||||
|
|
||||||
ret.reblog = data.reblog ? true : false
|
|
||||||
ret.reblogged = data.reblogged ? true : false
|
|
||||||
ret.reblogs_count = data.reblogs_count ? data.reblogs_count : false
|
|
||||||
|
|
||||||
ret.muted = data.muted ? true : false
|
|
||||||
ret.sensitive = data.sensitive ? true : false
|
|
||||||
ret.visibility = data.visibility ? data.visibility : false
|
|
||||||
ret.section = (new Date(ret.created_at)).toLocaleDateString()
|
|
||||||
console.log(ret)
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
Logic.api.get("timelines/home", [
|
|
||||||
//["since_id", 420],
|
//["since_id", 420],
|
||||||
//["max_id", 1337]
|
//["max_id", 1337]
|
||||||
], function(data) {
|
], function(data) {
|
||||||
|
@ -115,12 +92,11 @@ Page {
|
||||||
//model.append(data)
|
//model.append(data)
|
||||||
for (var i in data) {
|
for (var i in data) {
|
||||||
if (data.hasOwnProperty(i)) {
|
if (data.hasOwnProperty(i)) {
|
||||||
var toot = tootParser(data[i])
|
console.log(JSON.stringify(data[i]))
|
||||||
model.append(toot)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(model.count)
|
|
||||||
});
|
});*/
|
||||||
console.log(Logic.test)
|
console.log(Logic.test)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,177 +0,0 @@
|
||||||
import QtQuick 2.0
|
|
||||||
import Sailfish.Silica 1.0
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SilicaListView {
|
|
||||||
id: myList
|
|
||||||
property var locale: Qt.locale()
|
|
||||||
property bool loadStarted : false;
|
|
||||||
property int scrollOffset;
|
|
||||||
property string action: ""
|
|
||||||
property variant vars
|
|
||||||
property variant conf
|
|
||||||
|
|
||||||
signal notify (string what, int num)
|
|
||||||
onNotify: {
|
|
||||||
console.log(what + " - " + num)
|
|
||||||
}
|
|
||||||
|
|
||||||
signal openDrawer (bool setDrawer)
|
|
||||||
onOpenDrawer: {
|
|
||||||
//console.log("Open drawer: " + setDrawer)
|
|
||||||
}
|
|
||||||
signal send (string notice)
|
|
||||||
onSend: {
|
|
||||||
console.log("LIST send signal emitted with notice: " + notice)
|
|
||||||
}
|
|
||||||
BusyIndicator {
|
|
||||||
size: BusyIndicatorSize.Large
|
|
||||||
running: myList.model.count === 0 && !viewPlaceHolder.visible
|
|
||||||
anchors.centerIn: parent
|
|
||||||
}
|
|
||||||
|
|
||||||
WorkerScript {
|
|
||||||
id: worker
|
|
||||||
source: "../../lib/Worker.js"
|
|
||||||
onMessage: {
|
|
||||||
if (messageObject.error){
|
|
||||||
viewPlaceHolder.visible = true;
|
|
||||||
viewPlaceHolder.text = "Error"
|
|
||||||
viewPlaceHolder.hintText = messageObject.message
|
|
||||||
console.log(JSON.stringify(messageObject))
|
|
||||||
}
|
|
||||||
if (messageObject.notifyNewItems){
|
|
||||||
console.log(JSON.stringify(messageObject.notifyNewItems))
|
|
||||||
notify(action, messageObject.notifyNewItems)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Timer {
|
|
||||||
interval: 5*60*1000;
|
|
||||||
running: true;
|
|
||||||
repeat: true
|
|
||||||
onTriggered: loadData("prepend")
|
|
||||||
}
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
|
||||||
var msg = {
|
|
||||||
'bgAction' : action,
|
|
||||||
'params' : vars,
|
|
||||||
'model' : model,
|
|
||||||
'conf' : conf
|
|
||||||
};
|
|
||||||
worker.sendMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadData(mode){
|
|
||||||
var msg = {
|
|
||||||
'bgAction' : action,
|
|
||||||
'params' : vars,
|
|
||||||
'model' : model,
|
|
||||||
'mode' : mode,
|
|
||||||
'conf' : conf
|
|
||||||
};
|
|
||||||
worker.sendMessage(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
ViewPlaceholder {
|
|
||||||
id: viewPlaceHolder
|
|
||||||
enabled: model.count === 0
|
|
||||||
text: ""
|
|
||||||
hintText: ""
|
|
||||||
}
|
|
||||||
|
|
||||||
PullDownMenu {
|
|
||||||
MenuItem {
|
|
||||||
text: qsTr("Settings")
|
|
||||||
onClicked: pageStack.push(Qt.resolvedUrl("../Settings.qml"))
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
visible: action === 'statuses_userTimeline'
|
|
||||||
text: (following ? "Unfollow" : "Follow")
|
|
||||||
onClicked: {
|
|
||||||
var msg = { 'action': following ? "friendships_destroy" : "friendships_create", 'screen_name': username, 'conf' : conf
|
|
||||||
};
|
|
||||||
worker.sendMessage(msg);
|
|
||||||
following = !following
|
|
||||||
}
|
|
||||||
}
|
|
||||||
MenuItem {
|
|
||||||
text: qsTr("Load more")
|
|
||||||
onClicked: {
|
|
||||||
loadData("prepend")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
PushUpMenu {
|
|
||||||
MenuItem {
|
|
||||||
text: qsTr("Load more")
|
|
||||||
onClicked: {
|
|
||||||
loadData("append")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
anchors {
|
|
||||||
top: parent.top
|
|
||||||
bottom: parent.bottom
|
|
||||||
left: parent.left
|
|
||||||
right: parent.right
|
|
||||||
}
|
|
||||||
clip: true
|
|
||||||
section {
|
|
||||||
property: 'section'
|
|
||||||
criteria: ViewSection.FullString
|
|
||||||
delegate: SectionHeader {
|
|
||||||
text: {
|
|
||||||
var dat = Date.fromLocaleDateString(locale, section);
|
|
||||||
dat = Format.formatDate(dat, Formatter.TimepointRelativeCurrentDay)
|
|
||||||
if (dat === "00:00:00" || dat === "00:00") {
|
|
||||||
visible = false;
|
|
||||||
height = 0;
|
|
||||||
return " ";
|
|
||||||
}else {
|
|
||||||
return dat;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
delegate: Tweet {
|
|
||||||
onSend: {
|
|
||||||
myList.send(notice)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
add: Transition {
|
|
||||||
NumberAnimation { property: "opacity"; from: 0; to: 1.0; duration: 800 }
|
|
||||||
NumberAnimation { property: "x"; duration: 800; easing.type: Easing.InOutBack }
|
|
||||||
}
|
|
||||||
|
|
||||||
displaced: Transition {
|
|
||||||
NumberAnimation { properties: "x,y"; duration: 800; easing.type: Easing.InOutBack }
|
|
||||||
}
|
|
||||||
|
|
||||||
onCountChanged: {
|
|
||||||
contentY = scrollOffset
|
|
||||||
console.log("CountChanged!")
|
|
||||||
|
|
||||||
//last_id_MN
|
|
||||||
|
|
||||||
}
|
|
||||||
onContentYChanged: {
|
|
||||||
|
|
||||||
if (contentY > scrollOffset) {
|
|
||||||
openDrawer(false)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if (contentY < 100 && !loadStarted){
|
|
||||||
}
|
|
||||||
openDrawer(true)
|
|
||||||
}
|
|
||||||
scrollOffset = contentY
|
|
||||||
}
|
|
||||||
VerticalScrollDecorator {}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,192 +0,0 @@
|
||||||
import QtQuick 2.0
|
|
||||||
import Sailfish.Silica 1.0
|
|
||||||
import QtGraphicalEffects 1.0
|
|
||||||
|
|
||||||
BackgroundItem {
|
|
||||||
signal send (string notice)
|
|
||||||
|
|
||||||
id: delegate
|
|
||||||
//property string text: "0"
|
|
||||||
width: parent.width
|
|
||||||
signal navigateTo(string link)
|
|
||||||
height: lblText.paintedHeight + (lblText.text.length > 0 ? Theme.paddingLarge : 0 )+ lblName.paintedHeight + lblScreenName.paintedHeight + (reblog ? Theme.paddingLarge + iconRT.height : 0)
|
|
||||||
Image {
|
|
||||||
id: iconRT
|
|
||||||
y: Theme.paddingLarge
|
|
||||||
anchors {
|
|
||||||
right: avatar.right
|
|
||||||
}
|
|
||||||
visible: reblog
|
|
||||||
width: Theme.iconSizeExtraSmall
|
|
||||||
height: width
|
|
||||||
source: "image://theme/icon-s-retweet?" + (pressed ? Theme.primaryColor : Theme.secondaryColor)
|
|
||||||
}
|
|
||||||
Label {
|
|
||||||
id: lblRtByName
|
|
||||||
visible: reblog
|
|
||||||
anchors {
|
|
||||||
left: lblName.left
|
|
||||||
bottom: iconRT.bottom
|
|
||||||
}
|
|
||||||
text: 'retweeted by @' + retweetScreenName
|
|
||||||
font.pixelSize: Theme.fontSizeExtraSmall
|
|
||||||
color: Theme.secondaryColor
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: avatar
|
|
||||||
x: Theme.horizontalPageMargin
|
|
||||||
y: Theme.paddingLarge + (isRetweet ? iconRT.height+Theme.paddingMedium : 0)
|
|
||||||
asynchronous: true
|
|
||||||
width: Theme.iconSizeMedium
|
|
||||||
height: width
|
|
||||||
smooth: true
|
|
||||||
source: avatar_static
|
|
||||||
visible: true
|
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
pageStack.push(Qt.resolvedUrl("../Profile.qml"), {
|
|
||||||
"name": name,
|
|
||||||
"username": screenName,
|
|
||||||
"profileImage": profileImageUrl
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: lblName
|
|
||||||
anchors {
|
|
||||||
top: avatar.top
|
|
||||||
topMargin: 0
|
|
||||||
left: avatar.right
|
|
||||||
leftMargin: Theme.paddingMedium
|
|
||||||
}
|
|
||||||
text: username
|
|
||||||
font.weight: Font.Bold
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
Image {
|
|
||||||
id: iconVerified
|
|
||||||
y: Theme.paddingLarge
|
|
||||||
anchors {
|
|
||||||
left: lblName.right
|
|
||||||
leftMargin: Theme.paddingSmall
|
|
||||||
verticalCenter: lblName.verticalCenter
|
|
||||||
}
|
|
||||||
visible: isVerified
|
|
||||||
width: isVerified ? Theme.iconSizeExtraSmall*0.8 : 0
|
|
||||||
opacity: 0.8
|
|
||||||
height: width
|
|
||||||
source: "../../verified.svg"
|
|
||||||
}
|
|
||||||
ColorOverlay {
|
|
||||||
anchors.fill: iconVerified
|
|
||||||
source: iconVerified
|
|
||||||
color: (pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: lblScreenName
|
|
||||||
anchors {
|
|
||||||
left: iconVerified.right
|
|
||||||
right: lblDate.left
|
|
||||||
leftMargin: Theme.paddingMedium
|
|
||||||
baseline: lblName.baseline
|
|
||||||
}
|
|
||||||
truncationMode: TruncationMode.Fade
|
|
||||||
text: '@'+display_name
|
|
||||||
font.pixelSize: Theme.fontSizeExtraSmall
|
|
||||||
color: (pressed ? Theme.secondaryHighlightColor : Theme.secondaryColor)
|
|
||||||
}
|
|
||||||
Label {
|
|
||||||
function timestamp() {
|
|
||||||
var txt = Format.formatDate(created_at, Formatter.Timepoint)
|
|
||||||
var elapsed = Format.formatDate(created_at, Formatter.DurationElapsedShort)
|
|
||||||
return (elapsed ? elapsed : txt )
|
|
||||||
}
|
|
||||||
id: lblDate
|
|
||||||
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
|
|
||||||
text: Format.formatDate(created_at, new Date() - created_at < 60*60*1000 ? Formatter.DurationElapsedShort : Formatter.TimeValueTwentyFourHours)
|
|
||||||
font.pixelSize: Theme.fontSizeExtraSmall
|
|
||||||
horizontalAlignment: Text.AlignRight
|
|
||||||
anchors {
|
|
||||||
right: parent.right
|
|
||||||
baseline: lblName.baseline
|
|
||||||
rightMargin: Theme.paddingLarge
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Label {
|
|
||||||
id: lblText
|
|
||||||
anchors {
|
|
||||||
left: lblName.left
|
|
||||||
right: parent.right
|
|
||||||
top: lblScreenName.bottom
|
|
||||||
topMargin: Theme.paddingSmall
|
|
||||||
rightMargin: Theme.paddingLarge
|
|
||||||
}
|
|
||||||
height: content.length ? paintedHeight : 0
|
|
||||||
//text: (highlights.length > 0 ? Theme.highlightText(plainText, new RegExp(highlights, "igm"), Theme.highlightColor) : plainText)
|
|
||||||
//textFormat:Text.RichText
|
|
||||||
onLinkActivated: {
|
|
||||||
console.log(link)
|
|
||||||
if (link[0] === "@") {
|
|
||||||
pageStack.push(Qt.resolvedUrl("../Profile.qml"), {
|
|
||||||
"name": "",
|
|
||||||
"username": link.substring(1),
|
|
||||||
"profileImage": ""
|
|
||||||
})
|
|
||||||
} else if (link[0] === "#") {
|
|
||||||
|
|
||||||
pageStack.pop(pageStack.find(function(page) {
|
|
||||||
var check = page.isFirstPage === true;
|
|
||||||
if (check)
|
|
||||||
page.onLinkActivated(link)
|
|
||||||
return check;
|
|
||||||
}));
|
|
||||||
|
|
||||||
send(link)
|
|
||||||
} else {
|
|
||||||
pageStack.push(Qt.resolvedUrl("../Browser.qml"), {"href" : link})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
text: content
|
|
||||||
textFormat:Text.RichText
|
|
||||||
linkColor : Theme.highlightColor
|
|
||||||
wrapMode: Text.Wrap
|
|
||||||
font.pixelSize: Theme.fontSizeSmall
|
|
||||||
color: (pressed ? Theme.highlightColor : Theme.primaryColor)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*MediaBlock {
|
|
||||||
id: mediaImg
|
|
||||||
anchors {
|
|
||||||
left: lblName.left
|
|
||||||
right: parent.right
|
|
||||||
top: lblText.bottom
|
|
||||||
topMargin: Theme.paddingSmall
|
|
||||||
rightMargin: Theme.paddingLarge
|
|
||||||
}
|
|
||||||
model: (media ? media : '')
|
|
||||||
width: lblDate.x - lblName.x- Theme.paddingLarge
|
|
||||||
height: 100
|
|
||||||
}
|
|
||||||
onClicked: {
|
|
||||||
pageStack.push(Qt.resolvedUrl("../TweetDetails.qml"), {
|
|
||||||
"tweets": myList.model,
|
|
||||||
"screenName": screenName,
|
|
||||||
"selected": index
|
|
||||||
})
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,27 +3,20 @@
|
||||||
<TS version="2.1">
|
<TS version="2.1">
|
||||||
<context>
|
<context>
|
||||||
<name></name>
|
<name></name>
|
||||||
<message id="Set demo conf">
|
<message id="Logout">
|
||||||
|
<source></source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message id="Login">
|
||||||
<source></source>
|
<source></source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>FirstPage</name>
|
<name>MainPage</name>
|
||||||
<message>
|
<message>
|
||||||
<source>Show Page 2</source>
|
<source>Show Page 2</source>
|
||||||
<translation>Zur Seite 2</translation>
|
<translation type="unfinished">Zur Seite 2</translation>
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
|
||||||
<name>MyList</name>
|
|
||||||
<message>
|
|
||||||
<source>Settings</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Load more</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
|
|
|
@ -3,29 +3,22 @@
|
||||||
<TS version="2.1">
|
<TS version="2.1">
|
||||||
<context>
|
<context>
|
||||||
<name></name>
|
<name></name>
|
||||||
<message id="Set demo conf">
|
<message id="Logout">
|
||||||
|
<source></source>
|
||||||
|
<translation type="unfinished">Tooter</translation>
|
||||||
|
</message>
|
||||||
|
<message id="Login">
|
||||||
<source></source>
|
<source></source>
|
||||||
<translation type="unfinished">Tooter</translation>
|
<translation type="unfinished">Tooter</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>FirstPage</name>
|
<name>MainPage</name>
|
||||||
<message>
|
<message>
|
||||||
<source>Show Page 2</source>
|
<source>Show Page 2</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
<context>
|
|
||||||
<name>MyList</name>
|
|
||||||
<message>
|
|
||||||
<source>Settings</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<source>Load more</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
|
||||||
<context>
|
<context>
|
||||||
<name>SecondPage</name>
|
<name>SecondPage</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
Loading…
Reference in a new issue