Browse Source

v0.6.2 Follow and Unfollow contacts, Systray on Linux

master
LubuWest 4 months ago
parent
commit
baccd64303
  1. 6
      CHANGELOG.md
  2. 3
      README.md
  3. 6
      source-android/android/AndroidManifest.xml
  4. 101
      source-android/qml/friendiqa.qml
  5. 52
      source-linux/CMakeLists.txt
  6. 3
      source-linux/application.qrc
  7. 13
      source-linux/common/friendiqa.cpp
  8. 2
      source-linux/common/updatenews.cpp
  9. BIN
      source-linux/images/Friendica_monochrome.png
  10. BIN
      source-linux/images/Friendiqa.png
  11. 13
      source-linux/js/helper.js
  12. 1
      source-linux/js/layout.js
  13. 2
      source-linux/js/news.js
  14. 2
      source-linux/js/service.js
  15. 3
      source-linux/qml/calendarqml/CalendarTab.qml
  16. 3
      source-linux/qml/calendarqml/EventList.qml
  17. 13
      source-linux/qml/configqml/AccountPage.qml
  18. 2
      source-linux/qml/configqml/InfoBox.qml
  19. 7
      source-linux/qml/configqml/RegisterPage.qml
  20. 3
      source-linux/qml/configqml/SyncConfig.qml
  21. 7
      source-linux/qml/contactqml/FriendsListTab.qml
  22. 2
      source-linux/qml/contactqml/ProfileComponent.qml
  23. 85
      source-linux/qml/friendiqa.qml
  24. 5
      source-linux/qml/genericqml/ContactComponent.qml
  25. 2
      source-linux/qml/genericqml/DrawerAccountComponentContacts.qml
  26. 40
      source-linux/qml/newsqml/ContactPage.qml
  27. 67
      source-linux/qml/newsqml/NewsLink.qml
  28. 1
      source-linux/qml/newsqml/Newsitem.qml
  29. 9
      source-linux/qml/photoqml/PhotoTab.qml
  30. BIN
      source-linux/translations/friendiqa-de.qm
  31. 229
      source-linux/translations/friendiqa-de.ts
  32. BIN
      source-linux/translations/friendiqa-es.qm
  33. 224
      source-linux/translations/friendiqa-es.ts
  34. BIN
      source-linux/translations/friendiqa-hu.qm
  35. 224
      source-linux/translations/friendiqa-hu.ts
  36. BIN
      source-linux/translations/friendiqa-it.qm
  37. 224
      source-linux/translations/friendiqa-it.ts

6
CHANGELOG.md

@ -1,3 +1,9 @@
## v0.6.2
* Follow and Unfollow contacts (Friendica 2021.07 required)
* Linux: App stays in systemtray after close, syncs in background
## v0.6.1
* Add requestLegacyExternalStorage in AndroidManifest for attachment permissions
* Refresh timeline on start for Linux

3
README.md

@ -51,6 +51,7 @@ Currently supported:
* Tabs for own profiles, friends, other contacts and groups
* Show profile(s) of user and change profile picture
* List of all known contacts with locally downloaded pictures
* Follow or unfoolow contacts
* Show follow requests; approve, deny, ignore requests
* Additional information, last messages and other functionality shown in news tab
* Show public and private pictures of contact (screenscraping of contact's website, works only with certain theme)
@ -104,6 +105,8 @@ ToDo
# Other #
* on Linux: App stays in systemtray and syncs in background
ToDo
* Video tab
* Translation

6
source-android/android/AndroidManifest.xml

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.6.1" android:versionCode="27" android:installLocation="auto">
<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.6.2" android:versionCode="28" android:installLocation="auto">
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="29"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
@ -12,7 +12,7 @@
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<application android:hardwareAccelerated="false"
<application android:hardwareAccelerated="true"
android:name="org.qtproject.qt5.android.bindings.QtApplication"
android:label="Friendiqa"
android:extractNativeLibs="true"
@ -22,7 +22,7 @@
android:logo="@drawable/friendiqa">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:name="androidnative.friendiqa.FriendiqaActivity"
android:label="Friendiqa" android:screenOrientation="unspecified" android:launchMode="singleTask" android:taskAffinity="">
android:label="Friendiqa" android:screenOrientation="unspecified" android:launchMode="singleInstance" android:taskAffinity="">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>

101
source-android/qml/friendiqa.qml

@ -81,7 +81,7 @@ ApplicationWindow{
if(newContacts.length>0){// download contact images and update db
var contacturls=[];
var contactnames=[];
for (var link in newContacts){//print("new contact " +newContacts[link].screen_name);
for (var link in newContacts){
contacturls.push(newContacts[link].profile_image_url);
contactnames.push(newContacts[link].screen_name);
Service.updateContactInDB(login,db,newContacts[link].isFriend,newContacts[link])
@ -135,9 +135,7 @@ ApplicationWindow{
FontLoader{id: fontAwesome; source: "qrc:/images/fontawesome-webfont.ttf"}
//Keys.onReleased: {//print(event.key + "Backkey"+newstab.conversation.length+" "+root.depth)
onClosing: {
//if (event.key === osSettings.backKey) {
if (rootstack.currentIndex==0){
newstab.active=true;
if (newstab.newstabstatus!=globaloptions.newsViewType){
@ -164,74 +162,64 @@ ApplicationWindow{
Service.cleanNews(root.db,function(){
Service.cleanHashtags(root.db,function(){
Service.cleanContacts(root.login,root.db,function(){
Qt.quit()})
Qt.quit()
})
})})
close.accepted=true
}
}
else if (rootstack.currentIndex==2){fotoSignal("backButton")}
else {rootstack.currentIndex=0}
//event.accepted = true
//}
else if (rootstack.currentIndex==2){fotoSignal(login.username,"backButton");print("close rootstack currentindex==2");close.accepted=false}
else {rootstack.currentIndex=0;close.accepted=false}
}
footer:ToolBar{
//position: ToolBar.Footer
background: Rectangle{
anchors.fill: parent
color: "#EEEEEE"//"#F8F8F8"
}
//RowLayout{
// anchors.fill: parent
TabBar {
id: bar
width:parent.width
// Layout.fillWidth: true
//width: wideScreen?contentWidth:parent.width-10*mm
//x: 7*mm
onCurrentIndexChanged: rootstack.currentIndex=bar.currentIndex
TabButton {
text: "\uf03a"
font.pointSize: osSettings.bigFontSize
background:Rectangle{
anchors.fill: parent
color: "#EEEEEE"
}
TabBar {
id: bar
width:parent.width
onCurrentIndexChanged: rootstack.currentIndex=bar.currentIndex
TabButton {
text: "\uf03a"
font.pointSize: osSettings.bigFontSize
background:Rectangle{
anchors.fill: parent
color: "#EEEEEE"
}
TabButton {
text: "\uf0c0"
font.pointSize: osSettings.bigFontSize
background:Rectangle{
anchors.fill: parent
color: "#EEEEEE"
}
}
TabButton {
text: "\uf0c0"
font.pointSize: osSettings.bigFontSize
background:Rectangle{
anchors.fill: parent
color: "#EEEEEE"
}
TabButton {
text: "\uf03e"
font.pointSize: osSettings.bigFontSize
background:Rectangle{
anchors.fill: parent
color: "#EEEEEE"
}
}
TabButton {
text: "\uf03e"
font.pointSize: osSettings.bigFontSize
background:Rectangle{
anchors.fill: parent
color: "#EEEEEE"
}
TabButton {
text: "\uf073"
font.pointSize: osSettings.bigFontSize
background:Rectangle{
anchors.fill: parent
color: "#EEEEEE"
}
}
TabButton {
text: "\uf073"
font.pointSize: osSettings.bigFontSize
background:Rectangle{
anchors.fill: parent
color: "#EEEEEE"
}
}
// }
}
}
// states: State {
// name: "fullscreen";
// PropertyChanges { target: bar; height:0 }
@ -250,42 +238,32 @@ ApplicationWindow{
initialItem: StackLayout{
id:rootstack
width:rootstackView.width
height: rootstackView.height//-7*mm
//y:wideScreen?7*mm:0
height: rootstackView.height
currentIndex:bar.currentIndex
Loader{
id: newstab
// Layout.fillWidth:true
// Layout.fillHeight: true
property string newstabstatus
property var conversation:[]
source:(rootstack.currentIndex==0)? "qrc:/qml/newsqml/NewsTab.qml":""
}
Loader{
id: friendstab
// Layout.fillWidth:true
// Layout.fillHeight: true
source: (rootstack.currentIndex==1)?"qrc:/qml/contactqml/FriendsTab.qml":""
}
Loader{
id: fotostab
property string phototabstatus:"Images"
// Layout.fillWidth:true
// Layout.fillHeight: true
source: (rootstack.currentIndex==2)?"qrc:/qml/photoqml/PhotoTab.qml":""
}
Loader{
id: calendartab
property string calendartabstatus:"Events"
// Layout.fillWidth:true
// Layout.fillHeight: true
source: (rootstack.currentIndex==3)?"qrc:/qml/calendarqml/CalendarTab.qml":""
}
}
}
//}
Component.onCompleted: {
onLoginChanged(login);
globaloptions=Service.readGO(db);
@ -299,5 +277,4 @@ ApplicationWindow{
var LinuxSyncQml = component.createObject(root);
}
}
//}
}

52
source-linux/CMakeLists.txt

@ -1,3 +1,9 @@
# TEMPLATE = app
# TARGET = friendiqa
# CONFIG += release
# QT += qml quick gui widgets sql webview dbus webengine
cmake_minimum_required(VERSION 3.1.0)
project(friendiqa VERSION 0.6 LANGUAGES CXX)
@ -13,7 +19,9 @@ if(CMAKE_VERSION VERSION_LESS "3.7.0")
set(CMAKE_INCLUDE_CURRENT_DIR ON)
endif()
find_package(Qt5 COMPONENTS Widgets Quick Sql DBus WebView REQUIRED)
find_package(Qt5 COMPONENTS Widgets Quick Sql DBus WebView REQUIRED) #QuickWidgets
#Webview Webengine
set(MOC_SOURCES common/uploadableimage.h
common/xhr.h
@ -40,8 +48,50 @@ target_link_libraries(friendiqa Qt::Quick)
target_link_libraries(friendiqa Qt::Sql)
target_link_libraries(friendiqa Qt::WebView)
target_link_libraries(friendiqa Qt::DBus)
#target_link_libraries(friendiqa Qt::QuickWidgets)
# target_link_libraries(friendiqa Qt::Webengine)
# qt5_use_modules(friendiqa Core Widgets Quick Sql DBus)
install(TARGETS friendiqa DESTINATION bin)
#RESOURCES = application.qrc
# OTHER_FILES += qml/friendiqa.qml \
# translations/*.ts \
# qml/*.qml
# qml/newsqml/*.qml
# qml/contactqml/*.qml
# qml/photoqml/*.qml
# qml/configqml/*.qml
# js/*.js
#TRANSLATIONS += translations/friendiqa-de.ts \
# translations/friendiqa-es.ts \
# translations/friendiqa-it.ts
# HEADERS += \
# common/uploadableimage.h \
# common/xhr.h \
# common/filesystem.h \
# common/remoteauthasyncimageprovider.h \
# common/updatenews.h \
# common/alarm.h
#DISTFILES += \
# qml/calendarqml/*.qml \
# translations/*.ts \
# translations/*.qm \
# qml/*.qml \
# qml/newsqml/*.qml \
# qml/contactqml/*.qml \
# qml/photoqml/*.qml \
# qml/configqml/*.qml \
# js/*.js \
# target.path=/usr/bin
# desktop.path = /usr/share/applications
# desktop.files = images/de.ma-nic.Friendiqa.desktop
# icon.path = /usr/share/icons/hicolor/scalable/apps
# icon.files = images/Friendiqa.svg
# INSTALLS+=target desktop icon

3
source-linux/application.qrc

@ -12,7 +12,6 @@
<file>qml/newsqml/NewsImage.qml</file>
<file>qml/newsqml/NewsVideo.qml</file>
<file>qml/newsqml/ContactPage.qml</file>
<file>qml/newsqml/NewsLink.qml</file>
<file>qml/newsqml/NewsVideoLarge.qml</file>
<file>qml/newsqml/NewsYplayer.qml</file>
<file>qml/newsqml/SmileyDialog.qml</file>
@ -249,5 +248,7 @@
<file>qml/calendarqml/EventListItem.qml</file>
<file>translations/friendiqa-hu.qm</file>
<file>translations/friendiqa-hu.ts</file>
<file>images/Friendiqa.png</file>
<file>images/Friendica_monochrome.png</file>
</qresource>
</RCC>

13
source-linux/common/friendiqa.cpp

@ -44,6 +44,13 @@
//#include "AndroidNative/environment.h"
//#include "AndroidNative/debug.h"
//#include "AndroidNative/mediascannerconnection.h"
//#include <QQuickWidget>
#include <QSystemTrayIcon>
#include <QQmlContext>
// Declare a user-defined data type to work with an icon in QML
Q_DECLARE_METATYPE(QSystemTrayIcon::ActivationReason)
#ifdef Q_OS_ANDROID
@ -93,10 +100,16 @@ int main(int argc, char *argv[]) {
UPDATENEWS* updatenews = UPDATENEWS::instance();
view.rootContext()->setContextProperty("updatenews", updatenews);
qmlRegisterType<QSystemTrayIcon>("QSystemTrayIcon", 1, 0, "QSystemTrayIcon");
qRegisterMetaType<QSystemTrayIcon::ActivationReason>("ActivationReason");
view.rootContext()->setContextProperty("iconTray", QIcon(":/images/Friendica_monochrome.png"));
view.load(QUrl("qrc:/qml/friendiqa.qml"));
//view.show();
view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
return app.exec();
}
}

2
source-linux/common/updatenews.cpp

@ -181,7 +181,7 @@ void UPDATENEWS::timeline()
xhr.setParam("since_id",lastid);
}
}
xhr.setParam("count","50");
xhr.setParam("count","100");
xhr.get();
QObject::connect(&xhr,SIGNAL(success(QByteArray,QString)),this,SLOT(store(QByteArray,QString)));
QObject::connect(&xhr,SIGNAL(error(QString,QString,QString,int)),this,SLOT(showError(QString,QString,QString,int)));

BIN
source-linux/images/Friendica_monochrome.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 722 B

BIN
source-linux/images/Friendiqa.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

13
source-linux/js/helper.js

@ -180,6 +180,19 @@ var where = " AND "+ filter +" = '" + filtervalue+"'";
});
}
function updateData(database,table, username, key, value, callback,filter,filtervalue) { // reads and applies data from DB
if (filter){
var where = " AND "+ filter +" = '" + filtervalue+"'";
} else { var where="";}
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
if(!db) { return; }
db.transaction( function(tx) {
var rsArray=[];
var rs = tx.executeSql('UPDATE '+table+' SET '+key+' = '+value+' WHERE username="'+username+'"'+where);
callback();
});
}
function showMessage(header,message,rootwindow){//print(message);
var cleanmessage=message.replace(/"/g,"-");
if(cleanmessage.length>200){cleanmessage=cleanmessage.slice(0,200)+'...'}

1
source-linux/js/layout.js

@ -34,6 +34,7 @@ function showFriends(db) {
Service.requestFriends(login.url,login.user,login.password,displayFriends);
});
}
function displayFriends(obj){
for (var i=0; i<obj.length; i++){
//print(obj[i]);

2
source-linux/js/news.js

@ -334,7 +334,7 @@ function favorite(login,favorited,newsid,rootwindow){
}
function likerequest(login,database,verb,newsid,rootwindow){
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/"+verb+"?id="+newsid, "","POST",rootwindow,function (obj){print("like "+ obj);
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/"+verb+"?id="+newsid, "","POST",rootwindow,function (obj){
if (obj=='"ok"'){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {

2
source-linux/js/service.js

@ -394,7 +394,7 @@ function cleanNews(database,callback){
if (i!=0){var maxnewsa=maxnews/5}else{maxnewsa=maxnews}
var newscountrs = tx.executeSql('SELECT COUNT(*) from news WHERE messagetype='+i);
var newscount = 0;
if (newscountrs.rows.length>0){newscount=newscountrs.rows.item(0)["COUNT(*)"]};//print(i+"newscount "+newscount)
if (newscountrs.rows.length>0){newscount=newscountrs.rows.item(0)["COUNT(*)"]};//print(i+" "+maxnewsa+" newscount "+newscount)
if (newscount>maxnewsa){
var lastvalidtimers= tx.executeSql('SELECT DISTINCT created_at FROM news WHERE messagetype='+i+' ORDER BY created_at ASC LIMIT ' +(newscount-maxnewsa));
var lastvalidtime=lastvalidtimers.rows.item(newscount-maxnewsa-1).created_at;

3
source-linux/qml/calendarqml/CalendarTab.qml

@ -176,8 +176,7 @@ Rectangle {
snapMode: ListView.SnapOneItem
orientation: ListView.Horizontal
highlightRangeMode: ListView.StrictlyEnforceRange
// currentIndex: count
// onCurrentIndexChanged:{print("Index "+currentIndex)}
model: CalendarModel {id:calendarModel
from: new Date()
to: new Date(new Date().valueOf()+93312000000)

3
source-linux/qml/calendarqml/EventList.qml

@ -69,11 +69,10 @@ Rectangle{
id: eventModel
}
Component.onCompleted:{//print("daylist"+JSON.stringify(events) + dayint)
Component.onCompleted:{
var currentevents=events.filter(event=>(dayint>=event.startday)&&(dayint<=event.endday));
for (var i=0; i<currentevents.length;i++){
var liststate="";if(currentevents.length<2){liststate="large"};
//print(JSON.stringify(events[daylist[i]]));
eventModel.append({"event":currentevents[i],"eventstatus":liststate});
}
}

13
source-linux/qml/configqml/AccountPage.qml

@ -148,7 +148,6 @@ Page{
TextField {
id: password
x: root.fontFactor*osSettings.bigFontSize; y: 9*root.fontFactor*osSettings.bigFontSize; width: root.width-9*mm; //height: 5*mm;
//font.pixelSize:3*mm
font.pointSize: osSettings.systemFontSize
selectByMouse: true
echoMode: TextInput.Password
@ -218,9 +217,7 @@ Page{
else if (username.text==""){errormessage+=qsTr("No nickname given! ")}
else if (password.text=="") {errormessage+=qsTr("No password given! ")}
else if (imagestoredir=="") {errormessage+=qsTr("No image directory given!")}
//else if (imagestore.text=="") {errormessage+=qsTr("No image directory given!")}
//else if (maxNewsText.text=="") {errormessage+=qsTr("No maximum news number given!")}
else {errormessage=""}
if (errormessage=="") {
Helperjs.friendicaRequest(userconfig,"/api/account/verify_credentials?skip_status=true",root,function(obj){
@ -231,9 +228,8 @@ Page{
}
else{
if (users.length==0){Service.setDefaultOptions(db);}
//print("imagestore" + userconfig.imagestore + " path "+ filesystem.homePath+"/"+username.text)
if(userconfig.imagestore == filesystem.homePath+"/"+username.text+"/")
{//filesystem.Directory=filesystem.homePath;
{
filesystem.makePath(filesystem.homePath+"/"+username.text);
}
filesystem.Directory=imagestoredir //userconfig.imagestore;
@ -271,9 +267,7 @@ Page{
anchors.right: parent.right
anchors.rightMargin: 1*mm
MButton {
//x: parent.width/2+4*mm; y: mm;
width: 5*mm;
//height: 3*root.fontFactor*osSettings.bigFontSize
visible: users.length>0
text: "-"
font.pointSize: osSettings.bigFontSize
@ -303,8 +297,6 @@ Page{
}}
MButton {
//x: parent.width/2+10*mm; y: mm; //width: 5*mm; height: 8*mm;
//height: 3*root.fontFactor*osSettings.bigFontSize
width: 5*mm;
visible: users.length>0
text: "+"
@ -321,8 +313,6 @@ Page{
}
MButton {
//x: parent.width-12*mm; y: mm; //width: 5*mm; height: 8*mm;
//height: 3*root.fontFactor*osSettings.bigFontSize
width: 5*mm;
text: "?"
font.pointSize: osSettings.bigFontSize
@ -332,7 +322,6 @@ Page{
}
MButton{
id:closeButton
//height: 3*root.fontFactor*osSettings.bigFontSize
width: 5*mm;
visible: users.length>0
text: "\uf057"

2
source-linux/qml/configqml/InfoBox.qml

@ -44,7 +44,7 @@ Page{
width: root.width-mm
font.pointSize: osSettings.systemFontSize
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: "<b>Friendiqa v0.6.1 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
text: "<b>Friendiqa v0.6.2 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
"Website <a href='https://friendiqa.ma-nic.de'>https://friendiqa.ma-nic.de</a><br>"+
"Sourcecode: <a href='https://git.friendi.ca/LubuWest/Friendiqa'>https://git.friendi.ca/LubuWest/Friendiqa</a><br>"+
"Privacy Policy: <a href='https://git.friendi.ca/lubuwest/Friendiqa/src/branch/master/PrivacyPolicy.md'>http://git.friendi.ca/lubuwest/Friendiqa/src/branch/master/PrivacyPolicy.md</a><br>"+

7
source-linux/qml/configqml/RegisterPage.qml

@ -42,13 +42,6 @@ Rectangle{
height:parent.height-7*mm
width:parent.width
y:7*mm
// MouseArea {
// anchors.fill:parent;
// onClicked:{
// //print(url)
// }
// }
//onLoadingChanged: print(loadProgress)
}
Button{
id:closeButton

3
source-linux/qml/configqml/SyncConfig.qml

@ -69,7 +69,6 @@ Rectangle{
onTextChanged: {
Service.updateglobaloptions(root.db,"syncinterval",text);
if(osSettings.osType=="Android"){
//print("setalarm")
alarm.setAlarm(text);
} else if(osSettings.osType=="Linux" && text !=0){
root.updateSyncinterval(parseInt(text))
@ -89,10 +88,8 @@ Rectangle{
y:7*root.fontFactor*osSettings.bigFontSize
clip:true
Column{
//height: implicitHeight
width: parent.width
spacing:mm
//anchors.fill: parent
SyncComponent{adapter:"Timeline"}
SyncComponent{adapter:"Replies"}
SyncComponent{ adapter:"DirectMessages"}

7
source-linux/qml/contactqml/FriendsListTab.qml

@ -46,8 +46,8 @@ Item{
function showFriends(contact){
try {friendsModel.clear()} catch(e){print(e)};
Helperjs.readData(root.db,"friendshiprequests",login.username,function(friendrequestsobject){
for (var i=0;i<friendrequestsobject.length;i++){//print(Qt.atob(friendrequestsobject[i].note));
Helperjs.readData(db,"friendshiprequests",login.username,function(friendrequestsobject){
for (var i=0;i<friendrequestsobject.length;i++){
if (friendrequestsobject[i].note!=null){
friendrequestsobject[i].description=Qt.atob(friendrequestsobject[i].note);}
else{friendrequestsobject[i].description=""}
@ -60,7 +60,7 @@ Item{
friendsModel.append({"contact":friendrequestsobject[i],"contactType":qsTr("Friend Requests")});
}
});
Helperjs.readData(root.db,"contacts",login.username,function(friendsobject){
Helperjs.readData(db,"contacts",login.username,function(friendsobject){
for (var i=0;i<friendsobject.length;i++){
if(friendsobject[i].description!=""){
friendsobject[i].description=Qt.atob(friendsobject[i].description);}
@ -76,7 +76,6 @@ Item{
target:xhr
function onDownloaded(type,url,filename,i){
if(type=="contactlist"){
//print(url+" "+filename+" "+i)
friendsGridTab.currentContact=i+1;
if(friendsGridTab.currentContact==root.newContacts.length){
friendsGridTab.showFriends(root.login.username)

2
source-linux/qml/contactqml/ProfileComponent.qml

@ -54,7 +54,7 @@ Rectangle {
function buildProfiletext(pobject,callback){
var profileobject={};
var profiletext="";
for (var key in pobject){//print(key+obj[key])
for (var key in pobject){
if(pobject[key]!=""&&pobject[key]!=null&&key!="users"&&key!="profile_id"){
var keytext="";
switch(key){

85
source-linux/qml/friendiqa.qml

@ -34,10 +34,11 @@ import QtQuick.LocalStorage 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import QSystemTrayIcon 1.0
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/service.js" as Service
import "qrc:/qml/genericqml"
import "qrc:/qml/configqml"
ApplicationWindow{
id:root
@ -69,12 +70,11 @@ ApplicationWindow{
property var news:[]
property var newContacts:[]
property var contactposts:[]
//property string contactLoadType: ""
property bool imagePicking: false
function onLoginChanged(login){
if(login==""){rootstackView.push("qrc:/qml/configqml/AccountPage.qml")}
else{//rootstackView.push(rootstack)
else{
if (login.newsViewType!="" || login.newsViewType!=null){
newstab.newstabstatus=login.newsViewType;}
Newsjs.getCurrentContacts(login,db,function(contacts){
@ -97,7 +97,10 @@ ApplicationWindow{
xhr.setImagedir(login.imagestore);
xhr.getlist();
}
}
function showContact(contact){ //print(JSON.stringify(contact));
rootstackView.push("qrc:/qml/newsqml/ContactPage.qml",{"contact": contact})
}
Connections {
@ -108,6 +111,7 @@ ApplicationWindow{
}
}
}
Connections {
target: root
function onHeightChanged(appHeight) {
@ -117,12 +121,6 @@ ApplicationWindow{
}
}
function showContact(contact){ //print(JSON.stringify(contact));
rootstackView.push("qrc:/qml/newsqml/ContactPage.qml",{"contact": contact})
}
Connections{
target:xhr
function onDownloaded(type,url,filename,i){
@ -136,12 +134,9 @@ ApplicationWindow{
}
}
FontLoader{id: fontAwesome; source: "qrc:/images/fontawesome-webfont.ttf"}
//Keys.onReleased: {//print(event.key + "Backkey"+newstab.conversation.length+" "+root.depth)
onClosing: {
//if (event.key === osSettings.backKey) {
if (rootstack.currentIndex==0){
newstab.active=true;
if (newstab.newstabstatus!=globaloptions.newsViewType){
@ -168,15 +163,20 @@ ApplicationWindow{
Service.cleanNews(root.db,function(){
Service.cleanHashtags(root.db,function(){
Service.cleanContacts(root.login,root.db,function(){
Qt.quit()})
if (osSettings.osType=="Android"){
Qt.quit()}
else{
systemTray.show();
systemTray.showMessage("",qsTr("Background Sync\n Rightclick or Middleclick to Quit"),"",5000)
root.hide()
}
})
})})
close.accepted=true
}
}
else if (rootstack.currentIndex==2){fotoSignal("backButton")}
else {rootstack.currentIndex=0}
//event.accepted = true
//}
else if (rootstack.currentIndex==2){fotoSignal(login.username,"backButton");print("close rootstack currentindex==2");close.accepted=false}
else {rootstack.currentIndex=0;close.accepted=false}
}
@ -239,32 +239,17 @@ ApplicationWindow{
visible:!wideScreen
}
// states: State {
// name: "fullscreen";
// PropertyChanges { target: bar; height:0 }
// PropertyChanges { target: rootstack; height:parent.height }
// }
// transitions: Transition {
// PropertyAnimation { properties: "height";
// easing.type: Easing.InOutQuad
// duration: 1000
// }
// }
StackView{id:rootstackView
width:root.width
height: root.height
initialItem: StackLayout{
id:rootstack
width:rootstackView.width
height: rootstackView.height//-7*mm
//y:wideScreen?7*mm:0
height: rootstackView.height
currentIndex:bar.currentIndex
Loader{
id: newstab
Layout.fillWidth:true
Layout.fillHeight: true
property string newstabstatus
property var conversation:[]
@ -272,27 +257,44 @@ StackView{id:rootstackView
}
Loader{
id: friendstab
// Layout.fillWidth:true
// Layout.fillHeight: true
source: (rootstack.currentIndex==1)?"qrc:/qml/contactqml/FriendsTab.qml":""
}
Loader{
id: fotostab
property string phototabstatus:"Images"
// Layout.fillWidth:true
// Layout.fillHeight: true
source: (rootstack.currentIndex==2)?"qrc:/qml/photoqml/PhotoTab.qml":""
}
Loader{
id: calendartab
property string calendartabstatus:"Events"
// Layout.fillWidth:true
// Layout.fillHeight: true
source: (rootstack.currentIndex==3)?"qrc:/qml/calendarqml/CalendarTab.qml":""
}
}
}
//}
}
QSystemTrayIcon {
id: systemTray
visible: false
onActivated: {
if(reason === 3){
root.show();
bar.currentIndex=0;
root.globaloptions.hasOwnProperty("newsViewType")?newstab.newstabstatus=root.globaloptions.newsViewType:newstab.newstabstatus="Conversations";
newstypeSignal(newstab.newstabstatus)
systemTray.hide()
} else {
Qt.quit()
}
}
Component.onCompleted: {
icon = iconTray
toolTip = qsTr("Click to open Friendiqa")
hide()
}
}
Component.onCompleted: {
onLoginChanged(login);
globaloptions=Service.readGO(db);
@ -306,5 +308,4 @@ StackView{id:rootstackView
var LinuxSyncQml = component.createObject(root);
}
}
//}
}

5
source-linux/qml/genericqml/ContactComponent.qml

@ -86,7 +86,7 @@ Item {
id: descriptionlabel
width: Math.min(wrapper.width-4*root.fontFactor*osSettings.systemFontSize,contentWidth)//contentWidth+2*mm//wrapper.width-8*mm
height: 2*root.fontFactor*osSettings.systemFontSize//2.5*mm
text: contact.description
text: Qt.atob(contact.description)!=""?contact.description:""
elide:contentWidth>wrapper.width-4*root.fontFactor*osSettings.systemFontSize?Text.ElideRight:Text.ElideNone
color: "#303030"
font.pointSize: osSettings.systemFontSize
@ -96,9 +96,6 @@ Item {
anchors.fill: parent
onClicked:{
contactComponent.ListView.view.processContactSelection(contact)
// rootstack.currentIndex=0;
// bar.currentIndex=0;
// root.contactdetailsSignal(contact)
}
}
}

2
source-linux/qml/genericqml/DrawerAccountComponentContacts.qml

@ -57,7 +57,7 @@ Item {
y:2*root.fontFactor*osSettings.bigFontSize
width:parent.width
font.pointSize: osSettings.systemFontSize
font.bold: account.username==login.username && friendsTabView.currentIndex==0
font.bold: account.username==login.username && friendsTabView.currentIndex==0
text: " "+qsTr("Profile")
MouseArea{
anchors.fill:parent

40
source-linux/qml/newsqml/ContactPage.qml

@ -257,6 +257,42 @@ Page {
rootstackView.pop()
}
}
BlueButton{
id:followbutton
visible:(contact.isFriend==0)
height: 6*mm
//width: implicitContentWidth+2*mm//8*mm
text:qsTr("Follow")
onClicked:{
contactBusy.running=true;
Helperjs.friendicaPostRequest(login,"/api/v1/accounts/" + contact.id + "/follow",'',"POST",root,function(returnvalue){
Helperjs.updateData(db,"contacts",login.username,"isFriend",1,function(){},"id",contact.id)
root.friendsSignal(login.username);
rootstackView.pop()
// var username=login.username
//
});
}
}
BlueButton{
id:unfollowbutton
visible:(contact.isFriend==1)
height: 6*mm
//width: implicitContentWidth+2*mm//8*mm
text:qsTr("Unfollow")
onClicked:{
Helperjs.friendicaPostRequest(login,"/api/v1/accounts/" + contact.id + "/unfollow",'',"POST",root,function(returnvalue){
contactBusy.running=true;
Helperjs.updateData(db,"contacts",login.username,"isFriend",0,function(){},"id",contact.id)
root.friendsSignal(login.username);
rootstackView.pop()
});
}
}
}//Flow end
Label {
id: namelabel
@ -284,7 +320,7 @@ Page {
font.family: "Noto Sans"
textFormat:Text.RichText
wrapMode: Text.Wrap
text:"<b>"+qsTr("Description")+": </b> "+contact.description+"<br> <b>"+qsTr("Location")+":</b> "+contact.location+"<br> <b>"+qsTr("Posts")+":</b> "+contact.statuses_count+
text:"<b>"+qsTr("Description")+": </b> "+(Qt.atob(contact.description)!=""?contact.description:"")+"<br> <b>"+qsTr("Location")+":</b> "+contact.location+"<br> <b>"+qsTr("Posts")+":</b> "+contact.statuses_count+
"<br> <b>"+qsTr("URL")+":</b> <a href='"+ contact.url+"'>"+contact.url+"</a><br>"+
connectUrl+ "<b>"+qsTr("Created at")+":</b> "+createdAtDate.toLocaleString(Qt.locale())
onLinkActivated: {
@ -312,7 +348,7 @@ Page {
Connections{
target:root
function onContactpostsChanged(){
if (root.contactposts.length>0&&root.contactposts[0]!=null){profileimagesource=root.contactposts[0].user.profile_image_url_large}
if (root.contactposts.length>0&&root.contactposts[0]!=null){profileimagesource=root.contactposts[0].friendica_author.profile_image_url_large}
contactBusy.running=false;
contactModel.clear();
var currentTime= new Date();

67
source-linux/qml/newsqml/NewsLink.qml

@ -1,67 +0,0 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2020 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.9
import "qrc:/js/helper.js" as Helperjs
//import QtWebView 1.1
Rectangle{
color:"transparent"
width:newscolumn.width;
height:newscolumn.width/4*3
property string url:""//htmlview.text
Text{id:htmlview
textFormat:Text.RichText
}
// WebView {id:htmlview;
// anchors.fill: parent
// }
Component.onCompleted:{
// Helperjs.friendicaWebRequest(url,parent,function(document){
// print(document);
//// var metas = document.getElementsByTagName('meta'); //get all the meta tag elements
//// //iterate through them
//// for (i=0; i<metas.length; i++) {
//// if (metas[i].getAttribute("name") == "keywords") {
//// print(metas[i].getAttribute("content"));
//// }
//// else if (metas[i].getAttribute("name") == "description") {
//// console.log(metas[i].getAttribute("content"));
//// }
//// }
// //print(html);
// htmlview.text=""
// })
}
}

1
source-linux/qml/newsqml/Newsitem.qml

@ -133,7 +133,6 @@ Item {
}catch(e){" "}
}
}
//Component.onCompleted:print("Newsitemwidth "+newsitem.width+ " Indent "+newsitemobject.indent)
}
MouseArea{id: itemBody

9
source-linux/qml/photoqml/PhotoTab.qml

@ -55,7 +55,6 @@ StackView{
onNewimagesChanged:{
if(fotorectangle.newimages.length>0){
//print("newimages "+JSON.stringify(newimages));
var ownimagelist=[];
Helperjs.readField("album",root.db,"imageData",root.login.username,function(albums){
for (var i=0;i<fotorectangle.newimages.length;i++){
@ -106,12 +105,12 @@ StackView{
function showFotos(login,friend){
if(friend=="backButton"){
if (photoStack.depth>1){photoStack.pop()}
if(!albumgridview.currentItem){root.currentIndex=0}
if(albumgridview.currentItem.state=='fullscreen'){
if (photoStack.depth > 1){photoStack.pop()}
else if(albumgridview.currentItem==null){rootstack.currentIndex=0}
else if(albumgridview.currentItem.state=='fullscreen'){
albumgridview.currentItem.state = 'inGrid'}
else if (albumgridview.currentItem.state == 'inGrid'){albumgridview.currentItem.state=''}
else{root.currentIndex=0}
else{rootstack.currentIndex=0}
}
else{
try {photogroupModel.clear()}catch (e){print(e)}

BIN
source-linux/translations/friendiqa-de.qm

Binary file not shown.

229
source-linux/translations/friendiqa-de.ts

@ -5,8 +5,8 @@
<name>AccountPage</name>
<message>
<location filename="../qml/configqml/AccountPage.qml" line="60"/>
<location filename="../qml/configqml/AccountPage.qml" line="295"/>
<location filename="../qml/configqml/AccountPage.qml" line="317"/>
<location filename="../qml/configqml/AccountPage.qml" line="296"/>
<location filename="../qml/configqml/AccountPage.qml" line="319"/>
<source>User</source>
<translation>Name</translation>
</message>
@ -98,12 +98,12 @@
<context>
<name>CalendarTab</name>
<message>
<location filename="../qml/calendarqml/CalendarTab.qml" line="139"/>
<location filename="../qml/calendarqml/CalendarTab.qml" line="151"/>
<source>Events</source>
<translation>Termine</translation>
</message>
<message>
<location filename="../qml/calendarqml/CalendarTab.qml" line="144"/>
<location filename="../qml/calendarqml/CalendarTab.qml" line="156"/>
<source>Own Calendar</source>
<translation>Eigener Kalender</translation>
</message>
@ -111,35 +111,35 @@
<context>
<name>ConfigPage</name>
<message>
<location filename="../qml/configqml/ConfigPage.qml" line="61"/>
<location filename="../qml/configqml/ConfigPage.qml" line="62"/>
<source>News as</source>
<translation>Anzeige</translation>
</message>
<message>
<location filename="../qml/configqml/ConfigPage.qml" line="74"/>
<location filename="../qml/configqml/ConfigPage.qml" line="91"/>
<location filename="../qml/configqml/ConfigPage.qml" line="92"/>
<location filename="../qml/configqml/ConfigPage.qml" line="76"/>
<location filename="../qml/configqml/ConfigPage.qml" line="94"/>
<location filename="../qml/configqml/ConfigPage.qml" line="95"/>
<source>Conversations</source>
<translation>Unterhaltungen</translation>
</message>
<message>
<location filename="../qml/configqml/ConfigPage.qml" line="85"/>
<location filename="../qml/configqml/ConfigPage.qml" line="86"/>
<location filename="../qml/configqml/ConfigPage.qml" line="88"/>
<location filename="../qml/configqml/ConfigPage.qml" line="89"/>
<source>Timeline</source>
<translation>Chronologisch</translation>
</message>
<message>
<location filename="../qml/configqml/ConfigPage.qml" line="99"/>
<location filename="../qml/configqml/ConfigPage.qml" line="102"/>
<source>Max. News</source>
<translation>Max. Nachr.</translation>
</message>
<message>
<location filename="../qml/configqml/ConfigPage.qml" line="133"/>
<location filename="../qml/configqml/ConfigPage.qml" line="138"/>
<source>Hide #nsfw?</source>
<translation>#nsfw minimieren?</translation>
</message>
<message>
<location filename="../qml/configqml/ConfigPage.qml" line="52"/>
<location filename="../qml/configqml/ConfigPage.qml" line="53"/>
<source>Sync</source>
<translation>Autom. Aktualisierung</translation>
</message>
@ -389,52 +389,62 @@
<translation>Personen nehmen vielleicht teil.</translation>
</message>
<message>
<location filename="../qml/newsqml/ContactPage.qml" line="149"/>
<location filename="../qml/newsqml/ContactPage.qml" line="150"/>
<source>Connect</source>
<translation>Kontaktanfrage</translation>
</message>
<message>
<location filename="../qml/newsqml/ContactPage.qml" line="220"/>
<location filename="../qml/newsqml/ContactPage.qml" line="222"/>
<source>Approve</source>
<translation>Erlauben</translation>
</message>
<message>
<location filename="../qml/newsqml/ContactPage.qml" line="235"/>
<location filename="../qml/newsqml/ContactPage.qml" line="237"/>
<source>Reject</source>
<translation>Ablehnen</translation>
</message>
<message>
<location filename="../qml/newsqml/ContactPage.qml" line="249"/>
<location filename="../qml/newsqml/ContactPage.qml" line="251"/>
<source>Ignore</source>
<translation>Ignorieren</translation>
</message>
<message>
<location filename="../qml/newsqml/ContactPage.qml" line="285"/>