diff --git a/v0.002/Develop/source-android/android/AndroidManifest.xml b/v0.002/Develop/source-android/android/AndroidManifest.xml index acb0d5d..b1eb311 100644 --- a/v0.002/Develop/source-android/android/AndroidManifest.xml +++ b/v0.002/Develop/source-android/android/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/v0.002/Develop/source-android/android/res/drawable-ldpi/friendica32.png b/v0.002/Develop/source-android/android/res/drawable-ldpi/friendica32.png new file mode 100644 index 0000000..d77cd59 Binary files /dev/null and b/v0.002/Develop/source-android/android/res/drawable-ldpi/friendica32.png differ diff --git a/v0.002/Develop/source-android/application.qrc b/v0.002/Develop/source-android/application.qrc index 94f9b85..476ab64 100644 --- a/v0.002/Develop/source-android/application.qrc +++ b/v0.002/Develop/source-android/application.qrc @@ -3,7 +3,6 @@ js/layout.js js/photoworker.js js/service.js - qml/FriendComponent.qml qml/MessageSend.qml qml/Newsitem.qml qml/PhotoComponent.qml @@ -20,5 +19,7 @@ images/defaultcontact.jpg qml/InfoBox.qml qml/GroupComponent.qml + qml/ContactComponent.qml + qml/PermissionDialog.qml diff --git a/v0.002/Develop/source-android/common/friendiqa.cpp b/v0.002/Develop/source-android/common/friendiqa.cpp index 670f21a..de055f0 100644 --- a/v0.002/Develop/source-android/common/friendiqa.cpp +++ b/v0.002/Develop/source-android/common/friendiqa.cpp @@ -13,7 +13,7 @@ int main(int argc, char *argv[]) { view.rootContext()->setContextProperty("xhr", xhr); FILESYSTEM* filesystem = FILESYSTEM::instance(); view.rootContext()->setContextProperty("filesystem", filesystem); - view.setSource(QUrl("qrc:/qml/friendiqa.qml")); + view.setSource(QUrl("qrc:/qml/friendiqa.qml")); view.show(); view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit())); return app.exec(); diff --git a/v0.002/Develop/source-android/common/xhr.cpp b/v0.002/Develop/source-android/common/xhr.cpp index 6877135..3b75eb6 100644 --- a/v0.002/Develop/source-android/common/xhr.cpp +++ b/v0.002/Develop/source-android/common/xhr.cpp @@ -1,4 +1,4 @@ -#include "xhr.h" +#include "xhr.h" #include #include @@ -14,7 +14,7 @@ XHR *XHR::instance() XHR::XHR(QObject *parent) : QObject(parent) { - request.setSslConfiguration(QSslConfiguration::defaultConfiguration()); + // request.setSslConfiguration(QSslConfiguration::defaultConfiguration()); } void XHR::setUrl(QString url) @@ -32,6 +32,15 @@ void XHR::setLogin(QString login) emit loginChanged(); } } + +void XHR::setFilename(QString filename) +{ + if (filename!=m_filename) { + m_filename = filename; + emit filenameChanged(); + } +} + QString XHR::url() const { return m_url; @@ -42,6 +51,11 @@ QString XHR::login() const return m_login; } +QString XHR::filename() const +{ + return m_filename; +} + void XHR::setParam(QString name, QString value) { params.insert(name, value); @@ -58,6 +72,21 @@ void XHR::clearParams() params.clear(); } +void XHR::download() +{ + QUrl requrl(m_url); +// qDebug() << "start download of " << requrl; + request.setUrl(requrl); + reply = manager.get(request); +// qDebug() << "reply " << reply->header(QNetworkRequest::LocationHeader)<header(QNetworkRequest::LastModifiedHeader); +// qDebug() << "request " << request.url(); +// qDebug() << "error " << reply->error(); +// reply->ignoreSslErrors(); + connect(reply, &QNetworkReply::readyRead,this, &XHR::onRequestFinished); + connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError))); +} + void XHR::get() { QUrlQuery query; @@ -82,7 +111,7 @@ void XHR::get() connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError))); connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead); - + connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError); } void XHR::post() @@ -145,6 +174,22 @@ void XHR::onReplySuccess() reply->deleteLater(); } +void XHR::onRequestFinished() +{ + // Save the file here + QByteArray b = reply->readAll(); + QImage image = QImage::fromData(b); + if (image.isNull()){qDebug() << "Image empty"<downloaded(); + reply->deleteLater(); +} + void XHR::onReadyRead() { qDebug() << "."; diff --git a/v0.002/Develop/source-android/common/xhr.h b/v0.002/Develop/source-android/common/xhr.h index 3d61f25..dade20e 100644 --- a/v0.002/Develop/source-android/common/xhr.h +++ b/v0.002/Develop/source-android/common/xhr.h @@ -11,35 +11,43 @@ class XHR : public QObject Q_OBJECT Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) Q_PROPERTY(QString login READ login WRITE setLogin NOTIFY loginChanged) - + Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged) public: static XHR *instance(); explicit XHR(QObject *parent = 0); - void setUrl(QString url); - // void setLogin(QString login); + +// void setLogin(QString login); QString url() const; QString login() const; + QString filename() const; signals: void urlChanged(); void loginChanged(); + void filenameChanged(); + void downloaded(); void success(QString data); void error(QString data, int code); public slots: + void setUrl(QString url); void setLogin(QString login); + void setFilename(QString filename); void setParam(QString name, QString value); void setImageFileParam(QString name, QString url); void clearParams(); void post(); void get(); + void download(); private slots: void onReplyError(QNetworkReply::NetworkError code); void onReplySuccess(); + void onRequestFinished(); + //void onFileWritten(); void onReadyRead(); void onSSLError(const QList &errors); @@ -47,6 +55,7 @@ private: QByteArray buffer; QString m_url; QString m_login; + QString m_filename; QHash params; QHash files; diff --git a/v0.002/Develop/source-android/js/helper.js b/v0.002/Develop/source-android/js/helper.js index 8e8392c..e282d26 100644 --- a/v0.002/Develop/source-android/js/helper.js +++ b/v0.002/Develop/source-android/js/helper.js @@ -4,18 +4,19 @@ function friendicaRequest(login,api,rootwindow,callback) { var xhrequest= new XMLHttpRequest(); xhrequest.onreadystatechange = function() { - if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) { - } else if(xhrequest.readyState === XMLHttpRequest.DONE) { +// if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) { +// } else + if(xhrequest.readyState === XMLHttpRequest.DONE) { try{ if (xhrequest.responseText!=""){ callback(xhrequest.responseText) - }else{ - showMessage("Error",api+" NO RESPONSE",rootwindow) - callback(xhrequest.responseText) + }else{ + showMessage("Error",api+" NO RESPONSE",rootwindow); + callback(xhrequest.responseText) } } catch (e){ showMessage("Error", api+" "+e,rootwindow) -} + } } } xhrequest.open("GET", login.server+api,true,login.username,Qt.atob(login.password)); @@ -65,12 +66,15 @@ function readData(database,table,username,callback,filter,filtervalue) { // read if (filter){ var where = " AND "+ filter +" = '" + filtervalue+"'"; } else { var where="";} + if (username){ + var user = ' where username= "'+ username +'"'; + } else { var user='';} var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]); if(!db) { return; } db.transaction( function(tx) { -// print('select * from '+table'+where username= "'+username+'"'+'where); + //print('select * from '+table+user+where); var rsArray=[]; - var rs = tx.executeSql('select * from '+table+' where username= "'+username+'"'+where); + var rs = tx.executeSql('select * from '+table+user+where); for(var i = 0; i < rs.rows.length; i++) { rsArray.push(rs.rows.item(i)) } @@ -85,19 +89,20 @@ var where = " AND "+ filter +" = '" + filtervalue+"'"; var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]); if(!db) { return; } db.transaction( function(tx) { -// print('... read from database ' + field) - var rsArray=[]; - print('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC'); - var rs = tx.executeSql('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC'); - for(var i = 0; i < rs.rows.length; i++) { - rsArray.push(rs.rows.item(i)[field]) - } - callback(rsArray); + //print('... read from database ' + field) + var rsArray=[]; + //print('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC'); + var rs = tx.executeSql('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC'); + for(var i = 0; i < rs.rows.length; i++) { + rsArray.push(rs.rows.item(i)[field]) + } + callback(rsArray); }); } function showMessage(header,message,rootwindow){ - var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+message+'"}'; + var cleanmessage=message.replace(/"/g,"-"); + var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+cleanmessage+'"}'; var messageObject=Qt.createQmlObject(messageString,rootwindow,"messageOutput"); } diff --git a/v0.002/Develop/source-android/js/news.js b/v0.002/Develop/source-android/js/news.js index a7ed464..9d3c5b8 100644 --- a/v0.002/Develop/source-android/js/news.js +++ b/v0.002/Develop/source-android/js/news.js @@ -40,35 +40,66 @@ function getFriendsTimeline(login,database,contacts,rootwindow,callback){// retr var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" ORDER BY status_id DESC LIMIT 1'); // check for last news id try{parameter="&since_id="+result.rows.item(0).status_id;}catch(e){};}) var newContacts=[]; + //print(JSON.stringify("Contacts "+contacts)); Helperjs.friendicaRequest(login,"/api/statuses/friends_timeline"+parameter, rootwindow,function (obj){ var news=JSON.parse(obj); - for (var i=0;i0){ - print("Like Contact"+JSON.stringify(news[i].friendica_activities.like)); - for (var j=0;j0){ - print("DisLike Contact"+JSON.stringify(news[i].friendica_activities.dislike)); - for (var k=0;j0){ +// // print("Like Contact"+JSON.stringify(news[i].friendica_activities.like)); +// for (var j=0;j0){ +// //print("DisLike Contact"+JSON.stringify(news[i].friendica_activities.dislike)); +// for (var k=0;j0){ + // print("Like Contact"+JSON.stringify(news[i].friendica_activities.like)); + for (var j=0;j0){ + //print("DisLike Contact"+JSON.stringify(news[i].friendica_activities.dislike)); + for (var k=0;j 0 ) { diff --git a/v0.002/Develop/source-android/js/newsworker.js b/v0.002/Develop/source-android/js/newsworker.js index 8d5cc46..f08ba80 100644 --- a/v0.002/Develop/source-android/js/newsworker.js +++ b/v0.002/Develop/source-android/js/newsworker.js @@ -1,35 +1,50 @@ WorkerScript.onMessage = function(msg) { if(msg.appendnews!==true){ msg.model.clear()}; + for (var j=0;j0){ - if (msg.news[j].like.length==1){likeText= Qt.atob(msg.news[j].like[0].name)+" "+ qsTr("likes this.")} - else {likeText= msg.news[j].like.length+" "+ qsTr("like this.")} + if (msg.news[j]) { + var newsitemobject=msg.news[j]; + //print("Newsitem"+JSON.stringify(newsitemobject)); + if (newsitemobject.messagetype==2){ + newsitemobject.user={}; + newsitemobject.user.profile_image="qrc:/images/defaultcontact.jpg"; + newsitemobject.user.profile_image_url="qrc:/images/defaultcontact.jpg"; + newsitemobject.user.name=""; + } + var likeText="";var dislikeText="";var attendyesText="";var attendnoText="";var attendmaybeText=""; var self={}; + if (newsitemobject.messagetype==0){ + if (newsitemobject.like.length>0){ + if (newsitemobject.like.length==1){likeText= Qt.atob(newsitemobject.like[0].name)+" "+ qsTr("likes this.")} + else {likeText= newsitemobject.like.length+" "+ qsTr("like this.")} } - if (msg.news[j].dislike.length>0){ - if (msg.news[j].dislike.length==1){dislikeText= QT.atob(msg.news[j].dislike[0].name)+" "+ qsTr("doesn't like this.")} - else {dislikeText= msg.news[j].dislike.length+" "+ qsTr("don't like this.")} + if (newsitemobject.dislike.length>0){ + if (newsitemobject.dislike.length==1){dislikeText= QT.atob(newsitemobject.dislike[0].name)+" "+ qsTr("doesn't like this.")} + else {dislikeText= newsitemobject.dislike.length+" "+ qsTr("don't like this.")} } - if (msg.news[j].attendyes.length>0){ - if (msg.news[j].attendyes.length==1){attendyesText= Qt.atob(msg.news[j].attendyes[0].name)+" "+ qsTr("will attend.")} - else {attendyesText= msg.news[j].attendyes.length+" "+ qsTr("persons will attend.")} + if (newsitemobject.attendyes.length>0){ + if (newsitemobject.attendyes.length==1){attendyesText= Qt.atob(newsitemobject.attendyes[0].name)+" "+ qsTr("will attend.")} + else {attendyesText= newsitemobject.attendyes.length+" "+ qsTr("persons will attend.")} } - if (msg.news[j].attendno.length>0){ - if (msg.news[j].attendno.length==1){attendnoText= Qt.atob(msg.news[j].attendno[0].name)+" "+ qsTr("will not attend.")} - else {attendnoText= msg.news[j].attendno.length+" "+ qsTr("persons will not attend.")} + if (newsitemobject.attendno.length>0){ + if (newsitemobject.attendno.length==1){attendnoText= Qt.atob(newsitemobject.attendno[0].name)+" "+ qsTr("will not attend.")} + else {attendnoText= newsitemobject.attendno.length+" "+ qsTr("persons will not attend.")} } - if (msg.news[j].attendmaybe.length>0){ - if (msg.news[j].attendmaybe.length==1){attendmaybeText= Qt.atob(msg.news[j].attendmaybe[0].name)+" "+ qsTr("may attend.")} - else {attendmaybeText= msg.news[j].attendmaybe.length+" "+ qsTr("persons may attend.")} + if (newsitemobject.attendmaybe.length>0){ + if (newsitemobject.attendmaybe.length==1){attendmaybeText= Qt.atob(newsitemobject.attendmaybe[0].name)+" "+ qsTr("may attend.")} + else {attendmaybeText= newsitemobject.attendmaybe.length+" "+ qsTr("persons may attend.")} } + var friendica_activities_self=JSON.parse(newsitemobject.friendica_activities_self); + if (friendica_activities_self.indexOf(3)!=-1){self.attending=qsTr("yes")} + if (friendica_activities_self.indexOf(4)!=-1){self.attending=qsTr("no")} + if (friendica_activities_self.indexOf(5)!=-1){self.attending=qsTr("maybe")} + if (friendica_activities_self.indexOf(1)!=-1){self.liked=1} + if (friendica_activities_self.indexOf(2)!=-1){self.disliked=1} } - var friendica_activities={likeText:likeText,dislikeText:dislikeText,attendyesText:attendyesText,attendnoText:attendnoText,attendmaybeText:attendmaybeText} - var seconds=(msg.currentTime-newsitemobject.created_at)/1000; - var timestring=""; - if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");} + var friendica_activities={likeText:likeText,dislikeText:dislikeText,attendyesText:attendyesText,attendnoText:attendnoText,attendmaybeText:attendmaybeText,self:self} + //print(JSON.stringify(friendica_activities) ) ; + var seconds=(msg.currentTime-newsitemobject.created_at)/1000; + var timestring=""; + if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");} else if (seconds<90){timestring=Math.round(seconds/60)+" "+qsTr("minute") +" "+qsTr("ago");} else if (seconds<3600){timestring=Math.round(seconds/60)+" "+qsTr("minutes") +" "+qsTr("ago");} else if (seconds<5400){timestring=Math.round(seconds/3600)+" "+qsTr("hour") +" "+qsTr("ago");} @@ -40,7 +55,7 @@ WorkerScript.onMessage = function(msg) { else if (seconds<69984000){timestring=Math.round(seconds/3888000)+" "+qsTr("months") +" "+qsTr("ago");} else {timestring=Math.round(seconds/69984000)+" "+qsTr("years") +" "+qsTr("ago");} var data=({"newsitemobject": newsitemobject,"dateDiff":timestring,"friendica_activities":friendica_activities})} - // print("News:"+j+msg.news.length+JSON.stringify(data)); + //print("News:"+j+msg.news.length+JSON.stringify(data)); msg.model.append(data);} if (j==msg.news.length){ msg.model.sync() diff --git a/v0.002/Develop/source-android/js/service.js b/v0.002/Develop/source-android/js/service.js index ca70a64..3f3d4a1 100644 --- a/v0.002/Develop/source-android/js/service.js +++ b/v0.002/Develop/source-android/js/service.js @@ -24,13 +24,13 @@ function requestList(login,database,rootwindow,callback) { function dataRequest(login,photoID,database,rootwindow) { // check if image exist and call download function - Helperjs.friendicaRequest(login,"/api/friendica/photo?photo_id="+photoID, rootwindow, function (obj){ - try{ if(obj==""){currentImageNo=currentImageNo+1}else{ - var image = JSON.parse(obj); + Helperjs.friendicaRequest(login,"/api/friendica/photo?photo_id="+photoID, rootwindow, function (image){ + try{ if(image==""){currentImageNo=currentImageNo+1}else{ + var obj = JSON.parse(image); print('storeData() for ' + JSON.stringify(obj)); - try{sprite.destroy();}catch(e){} - if (obj["link"]["0"]){var source=obj["link"]["0"]} else {var source=obj["link"]["4"]}//source for profile picture or original size - print("Source"+obj["link"]["0"]+source) + // try{sprite.destroy();}catch(e){} +// if (obj["link"]["0"]){var source=obj["link"]["0"]} else {var source=obj["link"]["4"]}//source for profile picture or original size +// print("Source"+source); obj["source"]=source; var filename=obj.filename; if (filename==""){// check if file as any filename @@ -45,7 +45,7 @@ function dataRequest(login,photoID,database,rootwindow) { } print("obj.Filename: "+obj["filename"]+" filename: "+filename) } - saveImage(obj,login.imagestore,function(obj,sprite){ + saveImage(obj,login.imagestore+'albums/'+obj.album,function(obj,sprite){ //sprite.destroy(500); var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]); db.transaction( function(tx) { @@ -53,9 +53,9 @@ function dataRequest(login,photoID,database,rootwindow) { var result = tx.executeSql('SELECT * from imageData where id = "'+obj["id"]+'"'); if(result.rows.length === 1) {// use update print(obj["id"] +' exists, update it') - result = tx.executeSql('UPDATE imageData SET username ="' +login.username+ '",id="'+obj.id+'", created="'+obj.created+'", edited="'+obj.edited+'", profile="'+obj.profile+'", link="'+obj.source+'", filename="'+obj.filename+'",title="'+obj.title+'", desc="'+obj.desc+'", type="'+obj.type+'", width="'+obj.width+'", height="'+obj.height+'", album="'+obj.album+'", location="file://'+login.imagestore+'" where id="'+obj["id"]+'"'); + result = tx.executeSql('UPDATE imageData SET username ="' +login.username+ '",id="'+obj.id+'", created="'+obj.created+'", edited="'+obj.edited+'", profile="'+obj.profile+'", link="'+obj["link"]["4"]+'", filename="'+obj.filename+'",title="'+obj.title+'", desc="'+obj.desc+'", type="'+obj.type+'", width="'+obj.width+'", height="'+obj.height+'", album="'+obj.album+'", location="file://'+login.imagestore+'albums/'+obj.album+'/" where id="'+obj["id"]+'"'); } else {// use insert print('... does not exists, create it') - result = tx.executeSql('INSERT INTO imageData VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,obj.id,obj.created,obj.edited, obj.title, obj.desc, obj.album, obj.filename, obj.type, obj.height, obj.width,obj. profile,obj.source,'file://'+login.imagestore]); + result = tx.executeSql('INSERT INTO imageData VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,obj.id,obj.created,obj.edited, obj.title, obj.desc, obj.album, obj.filename, obj.type, obj.height, obj.width,obj. profile,obj["link"]["4"],'file://'+login.imagestore+'albums/'+obj.album+"/"]); print("Inserted");} })})}} catch (e){print("Data retrieval failure! "+ e+obj);} @@ -63,18 +63,17 @@ function dataRequest(login,photoID,database,rootwindow) { function saveImage(obj,storagedirectory,callback) { // create image component from base64 code and save it - print("Storing "+storagedirectory+obj.filename+obj.width+"x"+obj.height); + print("Storing "+storagedirectory+"/"+obj.filename+obj.width+"x"+obj.height); var maxSize=Math.max(fotostab.width,fotostab.height); var helpwidth=(obj.widthobj.height){ //landscape helpheight=helpwidth*obj.height/obj.width } else { //portrait helpwidth=helpheight*obj.width/obj.height } var component=Qt.createComponent("qrc:/qml/PhotoPlaceholder.qml"); - var sprite = component.createObject(fotostab, {"x":0,"y":0,"imageName":storagedirectory+obj.filename ,"width":helpwidth,"height":helpheight,"source": obj.source,"downloadtype":"picture"}); + var sprite = component.createObject(fotostab, {"x":0,"y":0,"imageName":storagedirectory+"/"+obj.filename ,"width":helpwidth,"height":helpheight,"source": obj["link"]["4"],"downloadtype":"picture"}); callback(obj,sprite) } @@ -141,8 +140,8 @@ function initDatabase(database) { // initialize the database object print('... create table') tx.executeSql('CREATE TABLE IF NOT EXISTS imageData(username TEXT,id INT, created TEXT,edited TEXT, title TEXT, desc TEXT, album TEXT,filename TEXT, type TEXT, height INT, width INT, profile INT, link TEXT,location TEXT)'); tx.executeSql('CREATE TABLE IF NOT EXISTS config(server TEXT, username TEXT, password TEXT, imagestore TEXT, maxnews INT, timerInterval INT, newsViewType TEXT,isActive INT)'); - tx.executeSql('CREATE TABLE IF NOT EXISTS news(username TEXT, messagetype INT, text TEXT, created_at INT, in_reply_to_status_id INT, source TEXT, status_id INT, in_reply_to_user_id INT, geo TEXT,favorited TEXT, uid INT, statusnet_html TEXT, statusnet_conversation_id TEXT,like TEXT, dislike TEXT, attendyes TEXT,attendno TEXT, attendmaybe TEXT)'); - tx.executeSql('CREATE TABLE IF NOT EXISTS contacts(username TEXT, id INT, name TEXT, screen_name TEXT, location TEXT,description TEXT, profile_image BLOB, url TEXT, protected TEXT, followers_count INT, friends_count INT, created_at TEXT, favourites_count TEXT, utc_offset TEXT, time_zone TEXT, statuses_count INT, following TEXT, verified TEXT, statusnet_blocking TEXT, notifications TEXT, statusnet_profile_url TEXT, cid INT, network TEXT, isFriend INT)'); + tx.executeSql('CREATE TABLE IF NOT EXISTS news(username TEXT, messagetype INT, text TEXT, created_at INT, in_reply_to_status_id INT, source TEXT, status_id INT, in_reply_to_user_id INT, geo TEXT,favorited TEXT, uid INT, statusnet_html TEXT, statusnet_conversation_id TEXT,friendica_activities TEXT, friendica_activities_self TEXT)'); + tx.executeSql('CREATE TABLE IF NOT EXISTS contacts(username TEXT, id INT, name TEXT, screen_name TEXT, location TEXT,profile_image_url TEXT, description TEXT, profile_image BLOB, url TEXT, protected TEXT, followers_count INT, friends_count INT, created_at INT, favourites_count TEXT, utc_offset TEXT, time_zone TEXT, statuses_count INT, following TEXT, verified TEXT, statusnet_blocking TEXT, notifications TEXT, statusnet_profile_url TEXT, cid INT, network TEXT, isFriend INT)'); tx.executeSql('CREATE TABLE IF NOT EXISTS groups(username TEXT, groupname TEXT, gid INT, members TEXT)'); })} diff --git a/v0.002/Develop/source-android/qml/BlueButton.qml b/v0.002/Develop/source-android/qml/BlueButton.qml new file mode 100644 index 0000000..e69de29 diff --git a/v0.002/Develop/source-android/qml/ConfigTab.qml b/v0.002/Develop/source-android/qml/ConfigTab.qml index 6cc9e8c..49afae9 100644 --- a/v0.002/Develop/source-android/qml/ConfigTab.qml +++ b/v0.002/Develop/source-android/qml/ConfigTab.qml @@ -187,7 +187,8 @@ onCurrentIndexChanged:{ if (errormessage=="") { filesystem.Directory=userconfig.imagestore; filesystem.makeDir("contacts"); - Service.storeConfig(db,userconfig); + filesystem.makeDir("albums"); + Service.storeConfig(db,userconfig); Service.readConfig(db,function(userconfig){Service.getServerConfig(userconfig,configBackground, function(obj){ var serverString=obj; var serverconfigObject=Qt.createQmlObject(serverString,configBackground,"serverconfigOutput"); @@ -236,13 +237,14 @@ onCurrentIndexChanged:{ } Component.onCompleted: { - try{Helperjs.readData(db,"config",root.login.username,function(users){ + try{print("get users"); + Helperjs.readData(db,"config","",function(users){ users.sort(function(obj1, obj2) { return obj1.isActive - obj2.isActive; }); for (var i=0; i"+qsTr("Description")+": "+Qt.atob(contact.description)+"
"+qsTr("Server Type")+": "+contact.location+"
"+qsTr("Posts")+": "+contact.statuses_count+ + "
"+qsTr("URL")+": "+linkUrl+"
"+ + qsTr("Created at")+": "+createdAtDate.toLocaleString(Qt.locale()) + onLinkActivated: { + Qt.openUrlExternally(link)} + } + } + + Row{ + anchors.top: namelabelflickable.bottom + anchors.topMargin: 2*mm + spacing:4 + + Button{ + id:photobutton + text:"Photos" + visible:contact.location=="Friendica"? 1:0 + onClicked:{contactComponent.state=""; + root.currentIndex=2; + fotostab.active=true; + root.fotoSignal(contact) ; + } + } + + Button{ + id:messagebutton + text:"Messages" + onClicked:{contactComponent.state=""; + root.currentIndex=0; + newstab.active=true; + root.messageSignal(contact.id) ; + } + } + + Button{ + id:dmbutton + visible: contact.following=="true"?true:false + text: "DM" + onClicked:{contactComponent.state=""; + root.currentIndex=0; + newstab.active=true; + root.directmessageSignal(contact.screen_name); + } + } + + Button{ + id: closeButton + text: "close" + onClicked:{contactComponent.state=""} + } + } + } +} +states: [ + State { + name: "large" + PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:friendsTabView.width-4*mm; text:Qt.atob(contact.name)+" (@"+contact.screen_name+")"} + PropertyChanges { target: contactComponent; z: 2 } + PropertyChanges { target: wrapper; width:friendsTabView.width-3*mm;height:friendsTabView.height-20*mm} + PropertyChanges { target: photoImage; width:15*mm;height:15*mm } + PropertyChanges { target:contactComponent.GridView.view;contentY:contactComponent.y;contentX:contactComponent.x;interactive:false} + PropertyChanges { target: detailsrectangle; opacity:1 } + } +] +} diff --git a/v0.002/Develop/source-android/qml/FriendsTab.qml b/v0.002/Develop/source-android/qml/FriendsTab.qml index 71b4b0b..65d2d2c 100644 --- a/v0.002/Develop/source-android/qml/FriendsTab.qml +++ b/v0.002/Develop/source-android/qml/FriendsTab.qml @@ -1,6 +1,7 @@ import QtQuick 2.0 import QtQuick.Dialogs 1.2 import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.4 import "qrc:/js/service.js" as Service import "qrc:/js/helper.js" as Helperjs import "qrc:/js/news.js" as Newsjs @@ -17,17 +18,35 @@ Rectangle { tabPosition: Qt.TopEdge x:mm y:mm - width: root.width-5*mm + width: root.width-2*mm height: root.height-10*mm currentIndex: 0 - signal friendsSignal(var username) + signal contactsSignal(var username) signal groupsSignal(var username) onCurrentIndexChanged:{ - if (currentIndex==0){friendsSignal(root.login.username)} + if (currentIndex==0){root.friendsSignal(root.login.username)} else if (currentIndex==1){contactsSignal(root.login.username)} else if (currentIndex==2){groupsSignal(root.login.username)} } + style: TabViewStyle { + frameOverlap: 1 + tab: Rectangle { + color: "white" + //border.color: "light grey" + implicitWidth: root.width/3-2*mm + implicitHeight: 4*mm + Text { id: text + anchors.centerIn: parent + text: styleData.title + color: "dark grey" + font.pixelSize:2.5*mm + font.bold: styleData.selected + } + } + frame: Rectangle { color: "light grey" } + tabsAlignment:Qt.AlignHCenter + } Tab{ title: qsTr("Friends") @@ -35,15 +54,16 @@ Rectangle { id: friendsGridTab function showFriends(username){ try {friendsModel.clear()} catch(e){print(e)}; - Helperjs.readData(db,"contacts",username,function(friends){ - for (var i=0;iFriendiqa v0.001
Licensed under GPL 3
"+ + text: "Friendiqa v0.002
Licensed under GPL 3
"+ "Sourcecode: https://github.com/LubuWest/Friendica
"+ "C++ code by Fabio
"+ "QML and Javascript code by Marco" diff --git a/v0.002/Develop/source-android/qml/MessageSend.qml b/v0.002/Develop/source-android/qml/MessageSend.qml index bdc7875..c89fea7 100644 --- a/v0.002/Develop/source-android/qml/MessageSend.qml +++ b/v0.002/Develop/source-android/qml/MessageSend.qml @@ -5,18 +5,22 @@ import QtQml 2.2 import QtQuick.Controls 1.3 import QtQuick.Dialogs 1.2 import QtQuick.LocalStorage 2.0 -//import "../qml" -import "qrc:/js/service.js" as Service +import "qrc:/js/helper.js" as Helperjs +import "qrc:/js/service.js" as Servicejs Item{ id:messageSend - property var login - property string parentId: "" - property string reply_to_user:"" - property string attachImageURL: ""; - property int directmessage: 0; - property var contacts: [] - // title: parentId !== "" ? qsTr("Reply to "+reply_to_user) : qsTr("New post") + property var login + property string parentId: "" + property string reply_to_user:"" + property string attachImageURL: ""; + property int directmessage: 0; + property var contacts: [] + property var groups: [] + property string contact_allow:"" + property string contact_deny:"" + property string group_allow:"" + property string group_deny:"" function statusUpdate(title,status,in_reply_to_status_id,attachImageURL) { xhr.url= login.server + "/api/statuses/update.xml"; @@ -46,7 +50,7 @@ Item{ Column { id:messageColumn spacing: 2 - + width: parent.width TextField { id: titleField width: parent.width @@ -59,8 +63,13 @@ Item{ width: parent.width height: 30*mm wrapMode: TextEdit.Wrap + textFormat: TextEdit.RichText } -CheckBox{ + + Row{ + + spacing: 2 + CheckBox{ id:dmCheckbox text:"DM" enabled: false @@ -70,18 +79,59 @@ CheckBox{ else if(dmCheckbox.checkedState==Qt.Unchecked){directmessage=0} } } + + Button{ + text:qsTr("Url") + onClicked: { + if(bodyField.selectedText==""){Helperjs.showMessage("Error","No text selected",messageSend)} + else{urlTextEdit.text=""; + urlRectangle.visible=true}} + } + Rectangle{ + id:urlRectangle + height:parent.height + width:37*mm + visible:false + TextField{ + id:urlTextEdit + width:30*mm + height:parent.height + } + Button{ + anchors.left:urlTextEdit.right + anchors.leftMargin:mm + text:qsTr("\u2713") + onClicked: { + var start = bodyField.selectionStart; + var end = bodyField.selectionEnd; + var text = bodyField.getText(start,end); + text = "" + text + ""; + bodyField.remove(start,end); + bodyField.insert(start,text); + urlRectangle.visible=false + } + } + } + } + + Row{ spacing:2 - Button { - id: cancelButton - text: qsTr("Cancel") - onClicked: {newsStack.pop()} - } - + Button{ + text:qsTr("Permissions") + onClicked: { + var component = Qt.createComponent("qrc:/qml/PermissionDialog.qml"); + var sprite = component.createObject(messageColumn); + if (sprite == null) { // Error Handling + console.log("Error creating object"); } + }} Button { id: attachButton text: qsTr("Attach") - onClicked: {imageAttachmentDialog.open()} + onClicked: { + try{imageAttachment.visible=false; + imageAttachment.opacity=0;imageAttachment.destroy()}catch(e){} + imageAttachmentDialog.open()} } Button{ id:contactButton @@ -90,43 +140,49 @@ CheckBox{ onClicked:{ var contactitems=""; for (var i=0;i0){ + print("Current image number"+currentImageNo) Service.dataRequest(root.login,newImages[currentImageNo].id,root.db,fotorectangle); newImagesProgress.visible=true //download first image }} + onCurrentImageNoChanged:{ if(currentImageNo0){// download first contact image and update db - print("newcontact"+JSON.stringify(newContacts[0])); +// print("newcontact"+JSON.stringify(newContacts)); updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])} } onCurrentContactChanged:{// download next contact image after photoplaceholder is finished saving and update db - print("Current contact"+JSON.stringify(newContacts[currentContact])); + //print("Current contact"+JSON.stringify(newContacts[currentContact])); if(currentContactjs/layout.js js/photoworker.js js/service.js - qml/FriendComponent.qml qml/MessageSend.qml qml/Newsitem.qml qml/PhotoComponent.qml @@ -20,5 +19,7 @@ images/defaultcontact.jpg qml/InfoBox.qml qml/GroupComponent.qml + qml/ContactComponent.qml + qml/PermissionDialog.qml diff --git a/v0.002/Develop/source-linux/common/friendiqa.cpp b/v0.002/Develop/source-linux/common/friendiqa.cpp index 670f21a..de055f0 100644 --- a/v0.002/Develop/source-linux/common/friendiqa.cpp +++ b/v0.002/Develop/source-linux/common/friendiqa.cpp @@ -13,7 +13,7 @@ int main(int argc, char *argv[]) { view.rootContext()->setContextProperty("xhr", xhr); FILESYSTEM* filesystem = FILESYSTEM::instance(); view.rootContext()->setContextProperty("filesystem", filesystem); - view.setSource(QUrl("qrc:/qml/friendiqa.qml")); + view.setSource(QUrl("qrc:/qml/friendiqa.qml")); view.show(); view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit())); return app.exec(); diff --git a/v0.002/Develop/source-linux/common/xhr.cpp b/v0.002/Develop/source-linux/common/xhr.cpp index 6877135..3b75eb6 100644 --- a/v0.002/Develop/source-linux/common/xhr.cpp +++ b/v0.002/Develop/source-linux/common/xhr.cpp @@ -1,4 +1,4 @@ -#include "xhr.h" +#include "xhr.h" #include #include @@ -14,7 +14,7 @@ XHR *XHR::instance() XHR::XHR(QObject *parent) : QObject(parent) { - request.setSslConfiguration(QSslConfiguration::defaultConfiguration()); + // request.setSslConfiguration(QSslConfiguration::defaultConfiguration()); } void XHR::setUrl(QString url) @@ -32,6 +32,15 @@ void XHR::setLogin(QString login) emit loginChanged(); } } + +void XHR::setFilename(QString filename) +{ + if (filename!=m_filename) { + m_filename = filename; + emit filenameChanged(); + } +} + QString XHR::url() const { return m_url; @@ -42,6 +51,11 @@ QString XHR::login() const return m_login; } +QString XHR::filename() const +{ + return m_filename; +} + void XHR::setParam(QString name, QString value) { params.insert(name, value); @@ -58,6 +72,21 @@ void XHR::clearParams() params.clear(); } +void XHR::download() +{ + QUrl requrl(m_url); +// qDebug() << "start download of " << requrl; + request.setUrl(requrl); + reply = manager.get(request); +// qDebug() << "reply " << reply->header(QNetworkRequest::LocationHeader)<header(QNetworkRequest::LastModifiedHeader); +// qDebug() << "request " << request.url(); +// qDebug() << "error " << reply->error(); +// reply->ignoreSslErrors(); + connect(reply, &QNetworkReply::readyRead,this, &XHR::onRequestFinished); + connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError); + connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError))); +} + void XHR::get() { QUrlQuery query; @@ -82,7 +111,7 @@ void XHR::get() connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError))); connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead); - + connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError); } void XHR::post() @@ -145,6 +174,22 @@ void XHR::onReplySuccess() reply->deleteLater(); } +void XHR::onRequestFinished() +{ + // Save the file here + QByteArray b = reply->readAll(); + QImage image = QImage::fromData(b); + if (image.isNull()){qDebug() << "Image empty"<downloaded(); + reply->deleteLater(); +} + void XHR::onReadyRead() { qDebug() << "."; diff --git a/v0.002/Develop/source-linux/common/xhr.h b/v0.002/Develop/source-linux/common/xhr.h index 3d61f25..dade20e 100644 --- a/v0.002/Develop/source-linux/common/xhr.h +++ b/v0.002/Develop/source-linux/common/xhr.h @@ -11,35 +11,43 @@ class XHR : public QObject Q_OBJECT Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged) Q_PROPERTY(QString login READ login WRITE setLogin NOTIFY loginChanged) - + Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged) public: static XHR *instance(); explicit XHR(QObject *parent = 0); - void setUrl(QString url); - // void setLogin(QString login); + +// void setLogin(QString login); QString url() const; QString login() const; + QString filename() const; signals: void urlChanged(); void loginChanged(); + void filenameChanged(); + void downloaded(); void success(QString data); void error(QString data, int code); public slots: + void setUrl(QString url); void setLogin(QString login); + void setFilename(QString filename); void setParam(QString name, QString value); void setImageFileParam(QString name, QString url); void clearParams(); void post(); void get(); + void download(); private slots: void onReplyError(QNetworkReply::NetworkError code); void onReplySuccess(); + void onRequestFinished(); + //void onFileWritten(); void onReadyRead(); void onSSLError(const QList &errors); @@ -47,6 +55,7 @@ private: QByteArray buffer; QString m_url; QString m_login; + QString m_filename; QHash params; QHash files; diff --git a/v0.002/Develop/source-linux/js/helper.js b/v0.002/Develop/source-linux/js/helper.js index 8e8392c..e282d26 100644 --- a/v0.002/Develop/source-linux/js/helper.js +++ b/v0.002/Develop/source-linux/js/helper.js @@ -4,18 +4,19 @@ function friendicaRequest(login,api,rootwindow,callback) { var xhrequest= new XMLHttpRequest(); xhrequest.onreadystatechange = function() { - if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) { - } else if(xhrequest.readyState === XMLHttpRequest.DONE) { +// if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) { +// } else + if(xhrequest.readyState === XMLHttpRequest.DONE) { try{ if (xhrequest.responseText!=""){ callback(xhrequest.responseText) - }else{ - showMessage("Error",api+" NO RESPONSE",rootwindow) - callback(xhrequest.responseText) + }else{ + showMessage("Error",api+" NO RESPONSE",rootwindow); + callback(xhrequest.responseText) } } catch (e){ showMessage("Error", api+" "+e,rootwindow) -} + } } } xhrequest.open("GET", login.server+api,true,login.username,Qt.atob(login.password)); @@ -65,12 +66,15 @@ function readData(database,table,username,callback,filter,filtervalue) { // read if (filter){ var where = " AND "+ filter +" = '" + filtervalue+"'"; } else { var where="";} + if (username){ + var user = ' where username= "'+ username +'"'; + } else { var user='';} var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]); if(!db) { return; } db.transaction( function(tx) { -// print('select * from '+table'+where username= "'+username+'"'+'where); + //print('select * from '+table+user+where); var rsArray=[]; - var rs = tx.executeSql('select * from '+table+' where username= "'+username+'"'+where); + var rs = tx.executeSql('select * from '+table+user+where); for(var i = 0; i < rs.rows.length; i++) { rsArray.push(rs.rows.item(i)) } @@ -85,19 +89,20 @@ var where = " AND "+ filter +" = '" + filtervalue+"'"; var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]); if(!db) { return; } db.transaction( function(tx) { -// print('... read from database ' + field) - var rsArray=[]; - print('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC'); - var rs = tx.executeSql('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC'); - for(var i = 0; i < rs.rows.length; i++) { - rsArray.push(rs.rows.item(i)[field]) - } - callback(rsArray); + //print('... read from database ' + field) + var rsArray=[]; + //print('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC'); + var rs = tx.executeSql('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC'); + for(var i = 0; i < rs.rows.length; i++) { + rsArray.push(rs.rows.item(i)[field]) + } + callback(rsArray); }); } function showMessage(header,message,rootwindow){ - var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+message+'"}'; + var cleanmessage=message.replace(/"/g,"-"); + var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+cleanmessage+'"}'; var messageObject=Qt.createQmlObject(messageString,rootwindow,"messageOutput"); } diff --git a/v0.002/Develop/source-linux/js/news.js b/v0.002/Develop/source-linux/js/news.js index a7ed464..9d3c5b8 100644 --- a/v0.002/Develop/source-linux/js/news.js +++ b/v0.002/Develop/source-linux/js/news.js @@ -40,35 +40,66 @@ function getFriendsTimeline(login,database,contacts,rootwindow,callback){// retr var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" ORDER BY status_id DESC LIMIT 1'); // check for last news id try{parameter="&since_id="+result.rows.item(0).status_id;}catch(e){};}) var newContacts=[]; + //print(JSON.stringify("Contacts "+contacts)); Helperjs.friendicaRequest(login,"/api/statuses/friends_timeline"+parameter, rootwindow,function (obj){ var news=JSON.parse(obj); - for (var i=0;i0){ - print("Like Contact"+JSON.stringify(news[i].friendica_activities.like)); - for (var j=0;j0){ - print("DisLike Contact"+JSON.stringify(news[i].friendica_activities.dislike)); - for (var k=0;j0){ +// // print("Like Contact"+JSON.stringify(news[i].friendica_activities.like)); +// for (var j=0;j0){ +// //print("DisLike Contact"+JSON.stringify(news[i].friendica_activities.dislike)); +// for (var k=0;j0){ + // print("Like Contact"+JSON.stringify(news[i].friendica_activities.like)); + for (var j=0;j0){ + //print("DisLike Contact"+JSON.stringify(news[i].friendica_activities.dislike)); + for (var k=0;j 0 ) { diff --git a/v0.002/Develop/source-linux/js/newsworker.js b/v0.002/Develop/source-linux/js/newsworker.js index 8d5cc46..f08ba80 100644 --- a/v0.002/Develop/source-linux/js/newsworker.js +++ b/v0.002/Develop/source-linux/js/newsworker.js @@ -1,35 +1,50 @@ WorkerScript.onMessage = function(msg) { if(msg.appendnews!==true){ msg.model.clear()}; + for (var j=0;j0){ - if (msg.news[j].like.length==1){likeText= Qt.atob(msg.news[j].like[0].name)+" "+ qsTr("likes this.")} - else {likeText= msg.news[j].like.length+" "+ qsTr("like this.")} + if (msg.news[j]) { + var newsitemobject=msg.news[j]; + //print("Newsitem"+JSON.stringify(newsitemobject)); + if (newsitemobject.messagetype==2){ + newsitemobject.user={}; + newsitemobject.user.profile_image="qrc:/images/defaultcontact.jpg"; + newsitemobject.user.profile_image_url="qrc:/images/defaultcontact.jpg"; + newsitemobject.user.name=""; + } + var likeText="";var dislikeText="";var attendyesText="";var attendnoText="";var attendmaybeText=""; var self={}; + if (newsitemobject.messagetype==0){ + if (newsitemobject.like.length>0){ + if (newsitemobject.like.length==1){likeText= Qt.atob(newsitemobject.like[0].name)+" "+ qsTr("likes this.")} + else {likeText= newsitemobject.like.length+" "+ qsTr("like this.")} } - if (msg.news[j].dislike.length>0){ - if (msg.news[j].dislike.length==1){dislikeText= QT.atob(msg.news[j].dislike[0].name)+" "+ qsTr("doesn't like this.")} - else {dislikeText= msg.news[j].dislike.length+" "+ qsTr("don't like this.")} + if (newsitemobject.dislike.length>0){ + if (newsitemobject.dislike.length==1){dislikeText= QT.atob(newsitemobject.dislike[0].name)+" "+ qsTr("doesn't like this.")} + else {dislikeText= newsitemobject.dislike.length+" "+ qsTr("don't like this.")} } - if (msg.news[j].attendyes.length>0){ - if (msg.news[j].attendyes.length==1){attendyesText= Qt.atob(msg.news[j].attendyes[0].name)+" "+ qsTr("will attend.")} - else {attendyesText= msg.news[j].attendyes.length+" "+ qsTr("persons will attend.")} + if (newsitemobject.attendyes.length>0){ + if (newsitemobject.attendyes.length==1){attendyesText= Qt.atob(newsitemobject.attendyes[0].name)+" "+ qsTr("will attend.")} + else {attendyesText= newsitemobject.attendyes.length+" "+ qsTr("persons will attend.")} } - if (msg.news[j].attendno.length>0){ - if (msg.news[j].attendno.length==1){attendnoText= Qt.atob(msg.news[j].attendno[0].name)+" "+ qsTr("will not attend.")} - else {attendnoText= msg.news[j].attendno.length+" "+ qsTr("persons will not attend.")} + if (newsitemobject.attendno.length>0){ + if (newsitemobject.attendno.length==1){attendnoText= Qt.atob(newsitemobject.attendno[0].name)+" "+ qsTr("will not attend.")} + else {attendnoText= newsitemobject.attendno.length+" "+ qsTr("persons will not attend.")} } - if (msg.news[j].attendmaybe.length>0){ - if (msg.news[j].attendmaybe.length==1){attendmaybeText= Qt.atob(msg.news[j].attendmaybe[0].name)+" "+ qsTr("may attend.")} - else {attendmaybeText= msg.news[j].attendmaybe.length+" "+ qsTr("persons may attend.")} + if (newsitemobject.attendmaybe.length>0){ + if (newsitemobject.attendmaybe.length==1){attendmaybeText= Qt.atob(newsitemobject.attendmaybe[0].name)+" "+ qsTr("may attend.")} + else {attendmaybeText= newsitemobject.attendmaybe.length+" "+ qsTr("persons may attend.")} } + var friendica_activities_self=JSON.parse(newsitemobject.friendica_activities_self); + if (friendica_activities_self.indexOf(3)!=-1){self.attending=qsTr("yes")} + if (friendica_activities_self.indexOf(4)!=-1){self.attending=qsTr("no")} + if (friendica_activities_self.indexOf(5)!=-1){self.attending=qsTr("maybe")} + if (friendica_activities_self.indexOf(1)!=-1){self.liked=1} + if (friendica_activities_self.indexOf(2)!=-1){self.disliked=1} } - var friendica_activities={likeText:likeText,dislikeText:dislikeText,attendyesText:attendyesText,attendnoText:attendnoText,attendmaybeText:attendmaybeText} - var seconds=(msg.currentTime-newsitemobject.created_at)/1000; - var timestring=""; - if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");} + var friendica_activities={likeText:likeText,dislikeText:dislikeText,attendyesText:attendyesText,attendnoText:attendnoText,attendmaybeText:attendmaybeText,self:self} + //print(JSON.stringify(friendica_activities) ) ; + var seconds=(msg.currentTime-newsitemobject.created_at)/1000; + var timestring=""; + if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");} else if (seconds<90){timestring=Math.round(seconds/60)+" "+qsTr("minute") +" "+qsTr("ago");} else if (seconds<3600){timestring=Math.round(seconds/60)+" "+qsTr("minutes") +" "+qsTr("ago");} else if (seconds<5400){timestring=Math.round(seconds/3600)+" "+qsTr("hour") +" "+qsTr("ago");} @@ -40,7 +55,7 @@ WorkerScript.onMessage = function(msg) { else if (seconds<69984000){timestring=Math.round(seconds/3888000)+" "+qsTr("months") +" "+qsTr("ago");} else {timestring=Math.round(seconds/69984000)+" "+qsTr("years") +" "+qsTr("ago");} var data=({"newsitemobject": newsitemobject,"dateDiff":timestring,"friendica_activities":friendica_activities})} - // print("News:"+j+msg.news.length+JSON.stringify(data)); + //print("News:"+j+msg.news.length+JSON.stringify(data)); msg.model.append(data);} if (j==msg.news.length){ msg.model.sync() diff --git a/v0.002/Develop/source-linux/js/service.js b/v0.002/Develop/source-linux/js/service.js index ca70a64..3f3d4a1 100644 --- a/v0.002/Develop/source-linux/js/service.js +++ b/v0.002/Develop/source-linux/js/service.js @@ -24,13 +24,13 @@ function requestList(login,database,rootwindow,callback) { function dataRequest(login,photoID,database,rootwindow) { // check if image exist and call download function - Helperjs.friendicaRequest(login,"/api/friendica/photo?photo_id="+photoID, rootwindow, function (obj){ - try{ if(obj==""){currentImageNo=currentImageNo+1}else{ - var image = JSON.parse(obj); + Helperjs.friendicaRequest(login,"/api/friendica/photo?photo_id="+photoID, rootwindow, function (image){ + try{ if(image==""){currentImageNo=currentImageNo+1}else{ + var obj = JSON.parse(image); print('storeData() for ' + JSON.stringify(obj)); - try{sprite.destroy();}catch(e){} - if (obj["link"]["0"]){var source=obj["link"]["0"]} else {var source=obj["link"]["4"]}//source for profile picture or original size - print("Source"+obj["link"]["0"]+source) + // try{sprite.destroy();}catch(e){} +// if (obj["link"]["0"]){var source=obj["link"]["0"]} else {var source=obj["link"]["4"]}//source for profile picture or original size +// print("Source"+source); obj["source"]=source; var filename=obj.filename; if (filename==""){// check if file as any filename @@ -45,7 +45,7 @@ function dataRequest(login,photoID,database,rootwindow) { } print("obj.Filename: "+obj["filename"]+" filename: "+filename) } - saveImage(obj,login.imagestore,function(obj,sprite){ + saveImage(obj,login.imagestore+'albums/'+obj.album,function(obj,sprite){ //sprite.destroy(500); var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]); db.transaction( function(tx) { @@ -53,9 +53,9 @@ function dataRequest(login,photoID,database,rootwindow) { var result = tx.executeSql('SELECT * from imageData where id = "'+obj["id"]+'"'); if(result.rows.length === 1) {// use update print(obj["id"] +' exists, update it') - result = tx.executeSql('UPDATE imageData SET username ="' +login.username+ '",id="'+obj.id+'", created="'+obj.created+'", edited="'+obj.edited+'", profile="'+obj.profile+'", link="'+obj.source+'", filename="'+obj.filename+'",title="'+obj.title+'", desc="'+obj.desc+'", type="'+obj.type+'", width="'+obj.width+'", height="'+obj.height+'", album="'+obj.album+'", location="file://'+login.imagestore+'" where id="'+obj["id"]+'"'); + result = tx.executeSql('UPDATE imageData SET username ="' +login.username+ '",id="'+obj.id+'", created="'+obj.created+'", edited="'+obj.edited+'", profile="'+obj.profile+'", link="'+obj["link"]["4"]+'", filename="'+obj.filename+'",title="'+obj.title+'", desc="'+obj.desc+'", type="'+obj.type+'", width="'+obj.width+'", height="'+obj.height+'", album="'+obj.album+'", location="file://'+login.imagestore+'albums/'+obj.album+'/" where id="'+obj["id"]+'"'); } else {// use insert print('... does not exists, create it') - result = tx.executeSql('INSERT INTO imageData VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,obj.id,obj.created,obj.edited, obj.title, obj.desc, obj.album, obj.filename, obj.type, obj.height, obj.width,obj. profile,obj.source,'file://'+login.imagestore]); + result = tx.executeSql('INSERT INTO imageData VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,obj.id,obj.created,obj.edited, obj.title, obj.desc, obj.album, obj.filename, obj.type, obj.height, obj.width,obj. profile,obj["link"]["4"],'file://'+login.imagestore+'albums/'+obj.album+"/"]); print("Inserted");} })})}} catch (e){print("Data retrieval failure! "+ e+obj);} @@ -63,18 +63,17 @@ function dataRequest(login,photoID,database,rootwindow) { function saveImage(obj,storagedirectory,callback) { // create image component from base64 code and save it - print("Storing "+storagedirectory+obj.filename+obj.width+"x"+obj.height); + print("Storing "+storagedirectory+"/"+obj.filename+obj.width+"x"+obj.height); var maxSize=Math.max(fotostab.width,fotostab.height); var helpwidth=(obj.widthobj.height){ //landscape helpheight=helpwidth*obj.height/obj.width } else { //portrait helpwidth=helpheight*obj.width/obj.height } var component=Qt.createComponent("qrc:/qml/PhotoPlaceholder.qml"); - var sprite = component.createObject(fotostab, {"x":0,"y":0,"imageName":storagedirectory+obj.filename ,"width":helpwidth,"height":helpheight,"source": obj.source,"downloadtype":"picture"}); + var sprite = component.createObject(fotostab, {"x":0,"y":0,"imageName":storagedirectory+"/"+obj.filename ,"width":helpwidth,"height":helpheight,"source": obj["link"]["4"],"downloadtype":"picture"}); callback(obj,sprite) } @@ -141,8 +140,8 @@ function initDatabase(database) { // initialize the database object print('... create table') tx.executeSql('CREATE TABLE IF NOT EXISTS imageData(username TEXT,id INT, created TEXT,edited TEXT, title TEXT, desc TEXT, album TEXT,filename TEXT, type TEXT, height INT, width INT, profile INT, link TEXT,location TEXT)'); tx.executeSql('CREATE TABLE IF NOT EXISTS config(server TEXT, username TEXT, password TEXT, imagestore TEXT, maxnews INT, timerInterval INT, newsViewType TEXT,isActive INT)'); - tx.executeSql('CREATE TABLE IF NOT EXISTS news(username TEXT, messagetype INT, text TEXT, created_at INT, in_reply_to_status_id INT, source TEXT, status_id INT, in_reply_to_user_id INT, geo TEXT,favorited TEXT, uid INT, statusnet_html TEXT, statusnet_conversation_id TEXT,like TEXT, dislike TEXT, attendyes TEXT,attendno TEXT, attendmaybe TEXT)'); - tx.executeSql('CREATE TABLE IF NOT EXISTS contacts(username TEXT, id INT, name TEXT, screen_name TEXT, location TEXT,description TEXT, profile_image BLOB, url TEXT, protected TEXT, followers_count INT, friends_count INT, created_at TEXT, favourites_count TEXT, utc_offset TEXT, time_zone TEXT, statuses_count INT, following TEXT, verified TEXT, statusnet_blocking TEXT, notifications TEXT, statusnet_profile_url TEXT, cid INT, network TEXT, isFriend INT)'); + tx.executeSql('CREATE TABLE IF NOT EXISTS news(username TEXT, messagetype INT, text TEXT, created_at INT, in_reply_to_status_id INT, source TEXT, status_id INT, in_reply_to_user_id INT, geo TEXT,favorited TEXT, uid INT, statusnet_html TEXT, statusnet_conversation_id TEXT,friendica_activities TEXT, friendica_activities_self TEXT)'); + tx.executeSql('CREATE TABLE IF NOT EXISTS contacts(username TEXT, id INT, name TEXT, screen_name TEXT, location TEXT,profile_image_url TEXT, description TEXT, profile_image BLOB, url TEXT, protected TEXT, followers_count INT, friends_count INT, created_at INT, favourites_count TEXT, utc_offset TEXT, time_zone TEXT, statuses_count INT, following TEXT, verified TEXT, statusnet_blocking TEXT, notifications TEXT, statusnet_profile_url TEXT, cid INT, network TEXT, isFriend INT)'); tx.executeSql('CREATE TABLE IF NOT EXISTS groups(username TEXT, groupname TEXT, gid INT, members TEXT)'); })} diff --git a/v0.002/Develop/source-linux/qml/BlueButton.qml b/v0.002/Develop/source-linux/qml/BlueButton.qml new file mode 100644 index 0000000..e69de29 diff --git a/v0.002/Develop/source-linux/qml/ConfigTab.qml b/v0.002/Develop/source-linux/qml/ConfigTab.qml index 6cc9e8c..49afae9 100644 --- a/v0.002/Develop/source-linux/qml/ConfigTab.qml +++ b/v0.002/Develop/source-linux/qml/ConfigTab.qml @@ -187,7 +187,8 @@ onCurrentIndexChanged:{ if (errormessage=="") { filesystem.Directory=userconfig.imagestore; filesystem.makeDir("contacts"); - Service.storeConfig(db,userconfig); + filesystem.makeDir("albums"); + Service.storeConfig(db,userconfig); Service.readConfig(db,function(userconfig){Service.getServerConfig(userconfig,configBackground, function(obj){ var serverString=obj; var serverconfigObject=Qt.createQmlObject(serverString,configBackground,"serverconfigOutput"); @@ -236,13 +237,14 @@ onCurrentIndexChanged:{ } Component.onCompleted: { - try{Helperjs.readData(db,"config",root.login.username,function(users){ + try{print("get users"); + Helperjs.readData(db,"config","",function(users){ users.sort(function(obj1, obj2) { return obj1.isActive - obj2.isActive; }); for (var i=0; i"+qsTr("Description")+": "+Qt.atob(contact.description)+"
"+qsTr("Server Type")+": "+contact.location+"
"+qsTr("Posts")+": "+contact.statuses_count+ + "
"+qsTr("URL")+": "+linkUrl+"
"+ + qsTr("Created at")+": "+createdAtDate.toLocaleString(Qt.locale()) + onLinkActivated: { + Qt.openUrlExternally(link)} + } + } + + Row{ + anchors.top: namelabelflickable.bottom + anchors.topMargin: 2*mm + spacing:4 + + Button{ + id:photobutton + text:"Photos" + visible:contact.location=="Friendica"? 1:0 + onClicked:{contactComponent.state=""; + root.currentIndex=2; + fotostab.active=true; + root.fotoSignal(contact) ; + } + } + + Button{ + id:messagebutton + text:"Messages" + onClicked:{contactComponent.state=""; + root.currentIndex=0; + newstab.active=true; + root.messageSignal(contact.id) ; + } + } + + Button{ + id:dmbutton + visible: contact.following=="true"?true:false + text: "DM" + onClicked:{contactComponent.state=""; + root.currentIndex=0; + newstab.active=true; + root.directmessageSignal(contact.screen_name); + } + } + + Button{ + id: closeButton + text: "close" + onClicked:{contactComponent.state=""} + } + } + } +} +states: [ + State { + name: "large" + PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:friendsTabView.width-4*mm; text:Qt.atob(contact.name)+" (@"+contact.screen_name+")"} + PropertyChanges { target: contactComponent; z: 2 } + PropertyChanges { target: wrapper; width:friendsTabView.width-3*mm;height:friendsTabView.height-20*mm} + PropertyChanges { target: photoImage; width:15*mm;height:15*mm } + PropertyChanges { target:contactComponent.GridView.view;contentY:contactComponent.y;contentX:contactComponent.x;interactive:false} + PropertyChanges { target: detailsrectangle; opacity:1 } + } +] +} diff --git a/v0.002/Develop/source-linux/qml/FriendsTab.qml b/v0.002/Develop/source-linux/qml/FriendsTab.qml index 71b4b0b..65d2d2c 100644 --- a/v0.002/Develop/source-linux/qml/FriendsTab.qml +++ b/v0.002/Develop/source-linux/qml/FriendsTab.qml @@ -1,6 +1,7 @@ import QtQuick 2.0 import QtQuick.Dialogs 1.2 import QtQuick.Controls 1.2 +import QtQuick.Controls.Styles 1.4 import "qrc:/js/service.js" as Service import "qrc:/js/helper.js" as Helperjs import "qrc:/js/news.js" as Newsjs @@ -17,17 +18,35 @@ Rectangle { tabPosition: Qt.TopEdge x:mm y:mm - width: root.width-5*mm + width: root.width-2*mm height: root.height-10*mm currentIndex: 0 - signal friendsSignal(var username) + signal contactsSignal(var username) signal groupsSignal(var username) onCurrentIndexChanged:{ - if (currentIndex==0){friendsSignal(root.login.username)} + if (currentIndex==0){root.friendsSignal(root.login.username)} else if (currentIndex==1){contactsSignal(root.login.username)} else if (currentIndex==2){groupsSignal(root.login.username)} } + style: TabViewStyle { + frameOverlap: 1 + tab: Rectangle { + color: "white" + //border.color: "light grey" + implicitWidth: root.width/3-2*mm + implicitHeight: 4*mm + Text { id: text + anchors.centerIn: parent + text: styleData.title + color: "dark grey" + font.pixelSize:2.5*mm + font.bold: styleData.selected + } + } + frame: Rectangle { color: "light grey" } + tabsAlignment:Qt.AlignHCenter + } Tab{ title: qsTr("Friends") @@ -35,15 +54,16 @@ Rectangle { id: friendsGridTab function showFriends(username){ try {friendsModel.clear()} catch(e){print(e)}; - Helperjs.readData(db,"contacts",username,function(friends){ - for (var i=0;iFriendiqa v0.001
Licensed under GPL 3
"+ + text: "Friendiqa v0.002
Licensed under GPL 3
"+ "Sourcecode: https://github.com/LubuWest/Friendica
"+ "C++ code by Fabio
"+ "QML and Javascript code by Marco" diff --git a/v0.002/Develop/source-linux/qml/MessageSend.qml b/v0.002/Develop/source-linux/qml/MessageSend.qml index bdc7875..c89fea7 100644 --- a/v0.002/Develop/source-linux/qml/MessageSend.qml +++ b/v0.002/Develop/source-linux/qml/MessageSend.qml @@ -5,18 +5,22 @@ import QtQml 2.2 import QtQuick.Controls 1.3 import QtQuick.Dialogs 1.2 import QtQuick.LocalStorage 2.0 -//import "../qml" -import "qrc:/js/service.js" as Service +import "qrc:/js/helper.js" as Helperjs +import "qrc:/js/service.js" as Servicejs Item{ id:messageSend - property var login - property string parentId: "" - property string reply_to_user:"" - property string attachImageURL: ""; - property int directmessage: 0; - property var contacts: [] - // title: parentId !== "" ? qsTr("Reply to "+reply_to_user) : qsTr("New post") + property var login + property string parentId: "" + property string reply_to_user:"" + property string attachImageURL: ""; + property int directmessage: 0; + property var contacts: [] + property var groups: [] + property string contact_allow:"" + property string contact_deny:"" + property string group_allow:"" + property string group_deny:"" function statusUpdate(title,status,in_reply_to_status_id,attachImageURL) { xhr.url= login.server + "/api/statuses/update.xml"; @@ -46,7 +50,7 @@ Item{ Column { id:messageColumn spacing: 2 - + width: parent.width TextField { id: titleField width: parent.width @@ -59,8 +63,13 @@ Item{ width: parent.width height: 30*mm wrapMode: TextEdit.Wrap + textFormat: TextEdit.RichText } -CheckBox{ + + Row{ + + spacing: 2 + CheckBox{ id:dmCheckbox text:"DM" enabled: false @@ -70,18 +79,59 @@ CheckBox{ else if(dmCheckbox.checkedState==Qt.Unchecked){directmessage=0} } } + + Button{ + text:qsTr("Url") + onClicked: { + if(bodyField.selectedText==""){Helperjs.showMessage("Error","No text selected",messageSend)} + else{urlTextEdit.text=""; + urlRectangle.visible=true}} + } + Rectangle{ + id:urlRectangle + height:parent.height + width:37*mm + visible:false + TextField{ + id:urlTextEdit + width:30*mm + height:parent.height + } + Button{ + anchors.left:urlTextEdit.right + anchors.leftMargin:mm + text:qsTr("\u2713") + onClicked: { + var start = bodyField.selectionStart; + var end = bodyField.selectionEnd; + var text = bodyField.getText(start,end); + text = "" + text + ""; + bodyField.remove(start,end); + bodyField.insert(start,text); + urlRectangle.visible=false + } + } + } + } + + Row{ spacing:2 - Button { - id: cancelButton - text: qsTr("Cancel") - onClicked: {newsStack.pop()} - } - + Button{ + text:qsTr("Permissions") + onClicked: { + var component = Qt.createComponent("qrc:/qml/PermissionDialog.qml"); + var sprite = component.createObject(messageColumn); + if (sprite == null) { // Error Handling + console.log("Error creating object"); } + }} Button { id: attachButton text: qsTr("Attach") - onClicked: {imageAttachmentDialog.open()} + onClicked: { + try{imageAttachment.visible=false; + imageAttachment.opacity=0;imageAttachment.destroy()}catch(e){} + imageAttachmentDialog.open()} } Button{ id:contactButton @@ -90,43 +140,49 @@ CheckBox{ onClicked:{ var contactitems=""; for (var i=0;i0){ + print("Current image number"+currentImageNo) Service.dataRequest(root.login,newImages[currentImageNo].id,root.db,fotorectangle); newImagesProgress.visible=true //download first image }} + onCurrentImageNoChanged:{ if(currentImageNo0){// download first contact image and update db - print("newcontact"+JSON.stringify(newContacts[0])); +// print("newcontact"+JSON.stringify(newContacts)); updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])} } onCurrentContactChanged:{// download next contact image after photoplaceholder is finished saving and update db - print("Current contact"+JSON.stringify(newContacts[currentContact])); + //print("Current contact"+JSON.stringify(newContacts[currentContact])); if(currentContact