This commit is contained in:
LubuWest 2019-06-25 20:59:10 +02:00
parent 63dfb9b197
commit d48847d183
135 changed files with 8879 additions and 3693 deletions

View file

@ -1,33 +1,68 @@
## v0.1##
## v0.5 ##
* Redesign due to QML Components 1 being deprecated in Qt 5.12: Slideview for News, left Drawer for Settings, message creation in listview header
* Android Notifications for News, DMs, Replies
* Global app config separated from account config
# News #
* Native Android image selector for new message
* Click on contacts shows contact details on news page
* Fix problem with news list after deletion of item
# Contacts #
* Clean contacts with no news
# Images #
* Upload pictures with description to album (permissions cannot be set due to API problems)
* Delete pictures or albums from client and server (long press on picture in overview)
* Fix problem when enlarging photo
# Translations #
* German, Spanish
## v0.4 ##
* Background sync for friends timeline (interval on config page must be > 0) for Android > 5
* Replies timeline
* Bugfix: App asks for storage permission on first start
## v0.1.1##
* FIX: Spanish translation
* FIX: Empty Newsview after deletion of first newsitem
## v0.3.4 ##
* Direct message creation from profile page works again
* Profile image upload works again
* Viewing private album pictures of contacts works again
* On first start servername from https://dir.friendica.social/servers/surprise selected
* Register button opens webview of registration page on server
## v0.3.3 ##
* Update for OpenSSL and At
* Experimental support for Peertube (links are expanded to video widget)
* Some Unicode emojis
* Redesign of contact details (click on contact opens in new stack and shows last news)
## v0.1.2#
* FIX: Include openssl v1.0.2m for SSL connections in Android v7 and above
## v0.3.2 ##
* For news containing url ending with mp3, mp4, avi, webm, ogg: media can be played in app
* Pictures can be renamed or moved to another album
* Bugfix: random crashes for conversations
* Bugfix: attach image to message works again
* Bugfix: check for nickname on Server has been removed due to API change
## v0.3.1 ##
* By popular demand: Conversations open in a new stack, like in Twidere
* Conversations open after (long) press on news, like in Twidere
* Image attachments are shown below text and can be enlarged, like in Twidere (solves issue #8)
* New messages are html, line breaks work (solves issue #7)
## v0.3 ##
* Fix for [issue 6](https://github.com/LubuWest/Friendiqa/issues/6)
* Refactoring of news part
* Search button for news
* Click on hashtag in newsitem starts search for news with that word
* Public timeline
* Timeline for selected group
* Small redesign of SendMessage page
## v0.2.2 ##
* Fix for [issue 5](https://github.com/LubuWest/Friendiqa/issues/5)
* Link to list of public server on Config Tab
* Small redesign of SendMessage page
* Intents for texts/urls (Send text or url from everywhere to create message)
## v0.2.1 ##
* Fix for [issue 4](https://github.com/LubuWest/Friendiqa/issues/4)
* Fix for Friendica [issue 4689](https://github.com/friendica/friendica/issues/4689)
* Long posts are automatically truncated
* Intents for pictures (Send one image from gallery: attach to message, send multiple images: upload to album)
## v0.2 ##
@ -53,57 +88,31 @@
# Translations #
* Italian thanks to Davide de Prisco
## v0.2.1 ##
* Fix for [issue 4](https://github.com/LubuWest/Friendiqa/issues/4)
* Fix for Friendica [issue 4689](https://github.com/friendica/friendica/issues/4689)
* Long posts are automatically truncated
* Intents for pictures (Send one image from gallery: attach to message, send multiple images: upload to album)
## v0.2.2 ##
* Fix for [issue 5](https://github.com/LubuWest/Friendiqa/issues/5)
* Link to list of public server on Config Tab
* Small redesign of SendMessage page
* Intents for texts/urls (Send text or url from everywhere to create message)
## v0.1.2##
* FIX: Include openssl v1.0.2m for SSL connections in Android v7 and above
## v0.3 ##
* Fix for [issue 6](https://github.com/LubuWest/Friendiqa/issues/6)
* Refactoring of news part
* Search button for news
* Click on hashtag in newsitem starts search for news with that word
* Public timeline
* Timeline for selected group
* Small redesign of SendMessage page
## v0.3.1 ##
* By popular demand: Conversations open in a new stack, like in Twidere
* Conversations open after (long) press on news, like in Twidere
* Image attachments are shown below text and can be enlarged, like in Twidere (solves issue #8)
* New messages are html, line breaks work (solves issue #7)
## v0.1.1##
* FIX: Spanish translation
* FIX: Empty Newsview after deletion of first newsitem
## v0.3.2 ##
* For news containing url ending with mp3, mp4, avi, webm, ogg: media can be played in app
* Pictures can be renamed or moved to another album
* Bugfix: random crashes for conversations
* Bugfix: attach image to message works again
* Bugfix: check for nickname on Server has been removed due to API change
## v0.1##
# News #
## v0.3.3 ##
* Update for OpenSSL and At
* Experimental support for Peertube (links are expanded to video widget)
* Some Unicode emojis
* Redesign of contact details (click on contact opens in new stack and shows last news)
* Native Android image selector for new message
* Click on contacts shows contact details on news page
* Fix problem with news list after deletion of item
## v0.3.4 ##
* Direct message creation from profile page works again
* Profile image upload works again
* Viewing private album pictures of contacts works again
* On first start servername from https://dir.friendica.social/servers/surprise selected
* Register button opens webview of registration page on server
# Contacts #
* Clean contacts with no news
## v0.4 ##
* Background sync for friends timeline (interval on config page must be > 0) for Android > 5
* Replies timeline
* Bugfix: App asks for storage permission on first start
# Images #
* Upload pictures with description to album (permissions cannot be set due to API problems)
* Delete pictures or albums from client and server (long press on picture in overview)
* Fix problem when enlarging photo
# Translations #
* German, Spanish

View file

@ -2,7 +2,7 @@
QML based client for the Friendica Social Network.
Tabs for news (incl. Direct Messages), friends, photos and events.
OS: currently Linux and Android (4.3 Jelly Bean).
OS: currently Linux and Android (4.3 Jelly Bean, 5.1 for background sync).
Source code is a QtCreator project.
## Screenshots ##
@ -18,9 +18,10 @@ QML based client for the Friendica Social Network.
# News #
Currently supported:
* Shows Posts from friends, selected group, replies, favorited messages, public timeline, Direct Messages and notifications
* Background sync with configurable interval of 15 min to 2h for active contact for friends timeline (Android 5 required)
* Search button for news
* Shows Posts from friends, replies, Direct Messages and notifications (in swipe view), selected group, replies, favorited messages, public timeline
* Background sync with configurable interval of 15 min to 2h for active contact for friends timeline, replies and DMs (Android 5.1 required)
* Android notifications for new items in friends timeline, replies and DMs
* Search for news
* Click on hashtag in newsitem starts search for news with that word
* Click on image shows image fullscreen
* For news containing urls ending with mp3, mp4, avi, webm, ogg or to a Peertube instance: media can be played in the app
@ -39,22 +40,19 @@ Currently supported:
* Native Android image dialog
ToDo:
* Videos and other binary data as attachment (sending)
* More than one attachment (currently not supported in API)
* Videos and other binary data as attachment (sending, not supported in API)
* More than one attachment
* Attachments for Direct messages (currently not supported in API)
# Friends #
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
* Additional information, last messages and other functionality shown in news tab
* Send direct message, if contact is following
* Show public and private (Friendica 3.6 required) pictures of contact (screenscraping of contact's website, works only with certain theme)
* Show public and private (Friendica 3.6 required) events of contact
* Show public and private pictures of contact (screenscraping of contact's website, works only with certain theme)
* Show public and private events of contact
* Show members of groups
* Open website of contact or connect page (for other contacts)
* Clean other contacts with no news
@ -81,8 +79,9 @@ ToDo:
# Events #
Currently supported:
* Download own public events
* Show public and private events of Friendica contacts (Friendica 3.6 server required)
* Show public and private events of Friendica contacts (Friendica >3.6 server required)
* List view of events of selected date
* Click on event to show details
@ -91,11 +90,12 @@ ToDo
* Create events (needs API)
# Config #
# Config/Accounts #
Currently supported:
* Multiple accounts
* Maximum news (deleted after use of Quit button)
* View mode for news (tree or timeline)
* Maximum news (deleted after use of Quit button)
* Sync home timeline, replies, DM, Notify yes/no
ToDo
* OAuth?

View file

@ -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.4" android:versionCode="12" android:installLocation="auto">
<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.5" android:versionCode="13" android:installLocation="auto">
<application android:hardwareAccelerated="true" android:vmSafeMode="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Friendiqa" android:icon="@drawable/friendiqa" android:logo="@drawable/friendiqa" android:theme="@android:style/Theme.Holo.Light">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="androidnative.friendiqa.FriendiqaActivity" android:label="Friendiqa" android:screenOrientation="unspecified" android:launchMode="singleInstance" android:taskAffinity="">
<intent-filter>
@ -79,8 +79,7 @@
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splash"/>
</service>
<service android:process=":qt" android:name="androidnative.friendiqa.FriendiqaStopService" android:permission="android.permission.BIND_JOB_SERVICE"
android:exported="true">
<service android:process=":qt" android:name="androidnative.friendiqa.FriendiqaStopService" android:permission="android.permission.BIND_JOB_SERVICE" android:exported="true">
<meta-data android:name="android.app.background_running" android:value="true"/>
</service>

View file

@ -26,6 +26,9 @@ dependencies {
compile 'com.android.support:support-v4:25.3.1'
}
dependencies {
compile 'com.android.support:support-compat:25.3.1'
}
android {
/*******************************************************

View file

@ -0,0 +1,4 @@
androidBuildToolsVersion=25.0.3
androidCompileSdkVersion=27
buildDir=.build
qt5AndroidDir=/home/pankraz/Qt/5.11.1/android_armv7/src/android/java

0
source-android/android/libcrypto.so Executable file → Normal file
View file

0
source-android/android/libssl.so Executable file → Normal file
View file

View file

@ -0,0 +1 @@
sdk.dir=/home/pankraz/android-sdk_alt

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 430 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 718 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

View file

@ -10,12 +10,18 @@ import android.content.Context;
import android.content.ComponentName;
import android.app.job.JobScheduler;
import android.app.job.JobInfo;
import android.app.PendingIntent;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationManagerCompat;
import org.qtproject.qt5.android.QtNative;
import androidnative.friendiqa.FriendiqaService;
import androidnative.friendiqa.FriendiqaStopService;
import androidnative.friendiqa.FriendiqaActivity;
import androidnative.AndroidNativeActivity;
import androidnative.AndroidNativeService;
import android.content.Intent;
import java.util.Map;
import org.qtproject.friendiqa.R;
public class Util {
@ -24,6 +30,7 @@ public class Util {
public static final String SET_TRANSLUCENT_STATUS_BAR = "androidnative.Util.setTranslucentStatusBar";
public static final String SET_FULL_SCREEN = "androidnative.Util.setFullScreen";
public static final String SET_SCHEDULE = "androidnative.Util.setSchedule";
public static final String SET_NOTIFICATION = "androidnative.Util.setNotification";
static {
@ -35,6 +42,8 @@ public class Util {
setFullScreen(message);
} else if (type.equals(SET_SCHEDULE)) {
setSchedule(message);
} else if (type.equals(SET_NOTIFICATION)) {
setNotification(message);
}
}
});
@ -98,11 +107,39 @@ public class Util {
}
static void setNotification(Map message) {
//Log.d(TAG,"setNotification");
Context context;
//Context appcontext;
context = QtNative.service().getApplicationContext();
//appcontext = QtNative.activity().getApplicationContext();
Intent intent = new Intent(context,FriendiqaActivity.class);
//intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
final String textTitle = (String) message.get("title");
final String textContent = (String) message.get("message");
final int notificationId = (int) message.get("id");
NotificationCompat.Builder builder = new NotificationCompat.Builder(context)
.setSmallIcon(R.drawable.friendiqanotification)
.setContentIntent(pendingIntent)
.setContentTitle(textTitle)
.setContentText(textContent)
.setStyle(new NotificationCompat.BigTextStyle()
.bigText(textContent))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
notificationManager.notify(notificationId, builder.build());
}
static void setSchedule(Map message) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
Log.d(TAG,"Friendiqa schedule Androidnative service");
//Log.d(TAG,"Friendiqa schedule Androidnative service");
final Integer value = (Integer) message.get("value");
//final Activity activity = QtNative.activity();
//final Service service = QtNative.service();
@ -126,7 +163,7 @@ public class Util {
jobScheduler.schedule(builder.build());
if (QtNative.service() != null){
Log.d(TAG,"Schedule Stopping Friendiqa Androidnative service");
//Log.d(TAG,"Schedule Stopping Friendiqa Androidnative service");
ComponentName componentStopper = new ComponentName(context, FriendiqaStopService.class);
JobInfo.Builder stopbuilder = new JobInfo.Builder(1, componentStopper)
.setMinimumLatency(50)

View file

@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/">
<file>qtquickcontrols2.conf</file>
<file>qml/friendiqa.qml</file>
<file>qml/newsqml/NewsTab.qml</file>
<file>qml/newsqml/Newsitem.qml</file>
@ -16,7 +17,7 @@
<file>qml/photoqml/PhotogroupComponent.qml</file>
<file>qml/photoqml/PhotoTab.qml</file>
<file>qml/configqml/InfoBox.qml</file>
<file>qml/configqml/ConfigTab.qml</file>
<file>qml/configqml/ConfigPage.qml</file>
<file>js/layout.js</file>
<file>js/photoworker.js</file>
<file>js/service.js</file>
@ -27,6 +28,7 @@
<file>images/fontawesome-webfont.ttf</file>
<file>images/folder-blue.png</file>
<file>qml/configqml/OSSettingsAndroid.qml</file>
<file>qml/genericqml/MButton.qml</file>
<file>qml/configqml/OSSettingsLinux.qml</file>
<file>qml/newsqml/SmileyDialog.qml</file>
<file>js/smiley.js</file>
@ -225,7 +227,9 @@
<file>qml/newsqml/ContactPage.qml</file>
<file>qml/newsqml/NewsLink.qml</file>
<file>qml/configqml/RegisterPage.qml</file>
<file>qml/newsqml/NewsYplayer.qml</file>
<file>js/yplayer.html</file>
<file>qml/configqml/AccountPage.qml</file>
<file>qml/newsqml/NewsStack.qml</file>
<file>qml/configqml/SyncConfig.qml</file>
<file>qml/configqml/SyncComponent.qml</file>
</qresource>
</RCC>

View file

@ -51,6 +51,7 @@ signals:
public slots:
void setAlarm(int time);
void notify(QString title, QString text, int id);
private:
int m_time;

View file

@ -29,8 +29,6 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//#include <QtAndroidExtras/QAndroidJniObject>
//#include <QtAndroidExtras/QAndroidJniEnvironment>
#include "alarm.h"
#include <QtCore/QDebug>
#include "AndroidNative/systemdispatcher.h"
@ -45,38 +43,20 @@ ALARM::ALARM(QObject *parent) : QObject(parent){}
void ALARM::setAlarm(int interval)
{
qDebug() << interval;
QVariantMap message;
message["value"] = interval;
AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setSchedule", message);
//AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.stopService", message);
// auto activity = QtAndroid::androidActivity();
// auto packageManager = activity.callObjectMethod("getPackageManager",
// "()Landroid/content/pm/PackageManager;");
// auto activityIntent = packageManager.callObjectMethod("getLaunchIntentForPackage",
// "(Ljava/lang/String;)Landroid/content/Intent;",
// activity.callObjectMethod("getPackageName",
// "()Ljava/lang/String;").object());
// auto pendingIntent = QAndroidJniObject::callStaticObjectMethod("android/app/PendingIntent", "getActivity",
// "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;",
// activity.object(), jint(0), activityIntent.object(),
// QAndroidJniObject::getStaticField<jint>("android/content/Intent",
// "FLAG_ACTIVITY_CLEAR_TOP"));
// auto alarmManager = activity.callObjectMethod("getSystemService",
// "(Ljava/lang/String;)Ljava/lang/Object;",
// QAndroidJniObject::getStaticObjectField("android/content/Context",
// "ALARM_SERVICE",
// "Ljava/lang/String;").object());
// alarmManager.callMethod<void>("set",
// "(IJLandroid/app/PendingIntent;)V",
// QAndroidJniObject::getStaticField<jint>("android/app/AlarmManager", "RTC"),
// jlong(QDateTime::currentMSecsSinceEpoch() + 100), pendingIntent.object());
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.stopService", message);
}
void ALARM::notify(QString title, QString text, int id)
{
//qDebug() << "notify "<< title << text;
QVariantMap message;
message["title"] = title;
message["message"] = text;
message["id"] = id;
AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setNotification", message);
}

View file

@ -0,0 +1,73 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 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/>.
//#include <QtAndroidExtras/QAndroidJniObject>
//#include <QtAndroidExtras/QAndroidJniEnvironment>
#include "alarm.h"
#include <QtCore/QDebug>
#include <QtDBus/QtDBus>
//#include "AndroidNative/systemdispatcher.h"
ALARM *ALARM::instance()
{
static ALARM alarm;
return &alarm;
}
ALARM::ALARM(QObject *parent) : QObject(parent){}
void ALARM::setAlarm(int interval)
{
qDebug() << interval;
QVariantMap message;
message["value"] = interval;
// AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
// AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setSchedule", message);
//AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.stopService", message);
}
void ALARM::notify(QString title, QString text, int id)
{
qDebug() << title << text;
QVariantMap message;
message["title"] = title;
message["message"] = text;
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusInterface dbus_iface("org.freedesktop.Notifications", "/org/freedesktop/Notifications",
"org.freedesktop.Notifications", bus);
QString appname="Friendiqa";
uint v=12321;
if (dbus_iface.isValid()){
dbus_iface.call("Notify",appname,v,"",title,text,"","",5000);
}
// AndroidNative::SystemDispatcher::instance()->dispatch("Notifier.notify", message);
}

View file

@ -32,17 +32,15 @@
#include <QApplication>
#include <QtQml/QQmlEngine>
#include <QAndroidService>
#include <QtAndroid>
#include <QtQuick>
#include "xhr.h"
#include "updatenews.h"
#include "filesystem.h"
#include "remoteauthasyncimageprovider.h"
#include "alarm.h"
#include "AndroidNative/systemdispatcher.h"
#include "AndroidNative/environment.h"
//#include "AndroidNative/environment.h"
//#include "AndroidNative/debug.h"
#include "AndroidNative/mediascannerconnection.h"
//#include "AndroidNative/mediascannerconnection.h"
#ifdef Q_OS_ANDROID
@ -66,13 +64,11 @@ int main(int argc, char *argv[]) {
UPDATENEWS* updatenews= UPDATENEWS::instance();
updatenews->setDatabase();
updatenews->login();
updatenews->timeline();
updatenews->startsync();
app.connect (updatenews,SIGNAL(quitapp()),&app,SLOT(quit()));
//QtAndroid::androidService().callMethod<void>("stopSelf");
return app.exec();
}
else{
QApplication app(argc, argv);
QQuickView view;
QTranslator qtTranslator;
@ -87,8 +83,8 @@ int main(int argc, char *argv[]) {
view.rootContext()->setContextProperty("filesystem", filesystem);
ALARM* alarm = ALARM::instance();
view.rootContext()->setContextProperty("alarm", alarm);
// UPDATENEWS* updatenews = UPDATENEWS::instance();
// view.rootContext()->setContextProperty("updatenews", updatenews);
UPDATENEWS* updatenews = UPDATENEWS::instance();
view.rootContext()->setContextProperty("updatenews", updatenews);
view.setSource(QUrl("qrc:/qml/friendiqa.qml"));
view.show();
view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));

View file

@ -100,47 +100,152 @@ void UPDATENEWS::login()
m_imagedir=query.value(3).toString();
xhr.setImagedir(m_imagedir);
QString isActive=query.value(7).toString();
m_updateInterval=query.value(5).toInt();
m_api="/api/statuses/friends_timeline";
xhr.setApi(m_api);
}
//m_updateInterval=query.value(5).toInt();
QSqlQuery syncquery("SELECT * FROM globaloptions",m_db);
// QSqlQuery delquery("DELETE FROM globaloptions WHERE k='sync_interval'",m_db);
// delquery.exec();
m_updateInterval=0;
syncindex=0;
synclist.clear();
//QSqlQuery syncquery("SELECT * FROM globaloptions WHERE k like 'sync_%' AND v=1",m_db);
while (syncquery.next()){
if (syncquery.value(0).toString()=="syncinterval"){
m_updateInterval=syncquery.value(1).toInt();
}
if (syncquery.value(0).toString().left(5)=="sync_" && syncquery.value(1).toInt()==1){
synclist.append(syncquery.value(0).toString());
//qDebug() << " sync " << syncquery.value(0).toString() << " " <<syncquery.value(1).toString();
}
if (syncquery.value(0).toString().left(7)=="notify_" && syncquery.value(1).toInt()==1){
notifylist.append(syncquery.value(0).toString());
//qDebug() << " notify " << syncquery.value(0).toString() << " " <<syncquery.value(1).toString();
}
}
// QSqlQuery notifyquery("SELECT * FROM globaloptions WHERE k like 'notify_%' AND v=1",m_db);
//qDebug() << "size " << notifyquery.size();
// while (notifyquery.next()){
// notifylist.append(syncquery.value(0).toString());
// qDebug() << " notify " << syncquery.value(0).toString();
//}
}
void UPDATENEWS::startsync()
{ //qDebug()<<"Friendiqa start syncing " <<synclist.length()<<" index "<<syncindex;
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)));
if (syncindex<synclist.length()){
if (synclist[syncindex]=="sync_Timeline"){
timeline();
} else if (synclist[syncindex]=="sync_Replies") {
replies();
} else if (synclist[syncindex]=="sync_DirectMessages") {
directmessages();
} else if (synclist[syncindex]=="sync_Notifications") {
notifications();
}
} else if (syncindex==synclist.length()) {
m_api="";
if(m_updateInterval!=0){
syncindex=0;
synclist.clear();
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
m_updateInterval=0;
}
}
}
void UPDATENEWS::timeline()
{
qDebug()<<"Friendiqa start timeline";
QSqlQuery query("SELECT status_id FROM news WHERE username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){query.first();};
QString lastid=query.value(0).toString();
m_api="/api/statuses/friends_timeline";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT status_id FROM news WHERE messagetype=0 AND username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
xhr.setParam("count","50");
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)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::replies()
{
m_api="/api/statuses/replies";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT status_id FROM news WHERE messagetype=3 AND username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
xhr.setParam("count","50");
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)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::directmessages()
{
m_api="/api/direct_messages/all";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT status_id FROM news WHERE messagetype=1 AND username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
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)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::notifications()
{
m_api="/api/friendica/notifications";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
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)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
//void UPDATENEWS::startservice(QString type,QVariantMap map)
//{
// qDebug ()<<"Friediqa start service "<<type;
// if (type=="androidnativeServiceStarted"){
// setDatabase();
// login();
// timeline();
// }
//}
void UPDATENEWS::store(QByteArray serverreply,QString apiname)
{
{ if (apiname!=m_api || xhr.downloadtype()!=""){} else {
QJsonDocument news;
qDebug()<<apiname << news;
//qDebug()<<apiname << serverreply;
QJsonParseError jsonerror;
news=QJsonDocument::fromJson(serverreply,&jsonerror);
if (news.isArray()){
for (int i=0; i < news.array().count();i++){
QJsonValue newsitem=news[i];
if (apiname=="/api/friendica/notifications"){
QSqlQuery testquery("SELECT status_id FROM news WHERE status_id=" + QString::number(newsitem["id"].toInt()) + " AND messagetype=2 AND username='"+ username +"'",m_db);
if (testquery.first()) {continue;}
}
QSqlQuery query(m_db);
query.prepare("INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,friendica_activities,friendica_activities_self,attachments,friendica_owner) " "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
query.bindValue(0,username);
@ -149,10 +254,10 @@ void UPDATENEWS::store(QByteArray serverreply,QString apiname)
QString sourcedate=newsitem["created_at"].toString();
QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
query.bindValue(3,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
if(newsitem["in_reply_to_status_id"]!=QJsonValue::Null){query.bindValue(4, newsitem["in_reply_to_status_id"].toInt());};
if(newsitem["in_reply_to_status_id"]!=QJsonValue::Null){query.bindValue(4, newsitem["in_reply_to_status_id"].toInt());}
query.bindValue(5,newsitem["source"]);
query.bindValue(6,newsitem["id"].toInt());
if(newsitem["in_reply_to_user_id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["in_reply_to_user_id"].toInt());};
if(newsitem["in_reply_to_user_id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["in_reply_to_user_id"].toInt());}
query.bindValue(8,newsitem["geo"]);
query.bindValue( 9, newsitem["favorited"].toInt());
query.bindValue(10, newsitem["user"]["id"].toInt());
@ -175,7 +280,7 @@ void UPDATENEWS::store(QByteArray serverreply,QString apiname)
for (int e = 0; e < newsitem["friendica_activities"]["attendmaybe"].toArray().count();e++){
attendmaybeArray.append(newsitem["friendica_activities"]["attendmaybe"][e]["url"].toString());
}
};
}
QJsonArray friendica_activities; friendica_activities={likeArray,dislikeArray,attendyesArray,attendnoArray,attendmaybeArray};
QJsonDocument activities; activities.setArray(friendica_activities);
query.bindValue(13,activities.toJson(QJsonDocument::Compact).toBase64());
@ -183,45 +288,114 @@ void UPDATENEWS::store(QByteArray serverreply,QString apiname)
if (newsitem["attachments"]!=QJsonValue::Undefined){
query.bindValue(15, QJsonDocument(newsitem["attachments"].toArray()).toJson(QJsonDocument::Compact).toBase64());
};
}else {
query.bindValue(15, "");
}
query.bindValue(16, newsitem["friendica_owner"]["url"]);
query.exec() ;
if (newsitem["friendica_author"]!=QJsonValue::Undefined){
query.bindValue(16, newsitem["friendica_author"]["url"]);
}else {
query.bindValue(16, newsitem["user"]["url"]);
}
if (apiname=="/api/statuses/replies"){
query.bindValue(1,"3");
}
if (apiname == "/api/direct_messages/all"){
query.bindValue(1,"1");
query.bindValue(5,"Friendica");
if(newsitem["recipient"]["id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["recipient"]["id"].toInt());}
query.bindValue(10, newsitem["sender_id"].toInt());
query.bindValue(11, newsitem["text"].toString().toUtf8().toBase64());
if(newsitem["friendica_parent_uri"]!=QJsonValue::Null){ query.bindValue(12,newsitem["friendica_parent_uri"]);}
query.bindValue(16, newsitem["sender"]["url"]);
}
if (apiname == "/api/friendica/notifications"){
query.bindValue(1,"2");
query.bindValue(3,QDateTime::fromString(newsitem["date"].toString(),"yyyy-MM-dd hh:mm:ss").toMSecsSinceEpoch());
query.bindValue(5,"Friendica");
QJsonObject cleancontact= findNotificationContact(newsitem["url"].toString());
query.bindValue(10, cleancontact["id"].toInt());
query.bindValue(11, newsitem["msg_html"].toString().toUtf8().toBase64());
if(newsitem["parent"]!=QJsonValue::Null){ query.bindValue(12,newsitem["parent"]);}
query.bindValue(16, newsitem["url"]);
}
if(!(query.exec())) {qDebug()<<query.lastError();}
// notifications
if (apiname=="/api/statuses/friends_timeline"){
if(notifylist.contains("notify_Timeline")){
alarm.notify("Home: "+ newsitem["user"]["name"].toString(),newsitem["text"].toString(),0);
}
}
if (apiname=="/api/statuses/replies"){
if(notifylist.contains("notify_Replies")){
alarm.notify("Replies: "+newsitem["user"]["name"].toString(),newsitem["text"].toString(),1);
}
}
if (apiname=="/api/direct_messages/all"){
if(notifylist.contains("notify_DirectMessages")){
alarm.notify("DirectMessage: "+newsitem["sender"]["name"].toString(),newsitem["text"].toString(),2);
}
}
if (apiname=="/api/friendica/notifications"){
if(notifylist.contains("notify_Notifications")){
alarm.notify("Notification: "+newsitem["name"].toString(),newsitem["text"].toString(),3);
}
}
}
QList<QJsonValue> newcontacts=findNewContacts(news);
//qDebug()<< "new contacts count " << newcontacts.size();
if (newcontacts.size()>0){
updateContacts(newcontacts);
startImagedownload();
} else {
if(m_updateInterval!=0){
syncindex+=1;
startsync();
}
}
}
else {
qDebug()<< "Friendiqa updatenews error";
qDebug()<< "Friendiqa updatenews error " << serverreply;
emit this->error(m_api,QTextCodec::codecForName("utf-8")->toUnicode(serverreply));
if(m_updateInterval!=0){
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
};
syncindex+=1;
startsync();
}
}
QList<QJsonValue> newcontacts=findNewContacts(news);
updateContacts(newcontacts);
startImagedownload();
connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index){
if (downloadtype=="contactlist"){
QSqlQuery testquery("SELECT profile_image FROM contacts WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
testquery.exec();
testquery.first();
//qDebug()<< "update imageurl for " <<imageurl << " from " <<testquery.value(0).toString() <<" to "<< filename <<" index " << index << " newcontactnames.length " <<newcontactnames.length();
QSqlQuery query("UPDATE contacts SET profile_image='"+ filename +"' WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
query.exec();
if (index==(newcontactnames.length()-1)){
newcontactnames.clear();
newcontactimagelinks.clear();
if(m_updateInterval!=0){
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
syncindex+=1;
startsync();
}
}
}
}
QJsonObject UPDATENEWS::findNotificationContact(QString contacturl){
QSqlQuery query("SELECT id,url FROM contacts WHERE url='"+contacturl+"' AND username='"+ username+"'",m_db);
query.first();
QJsonObject contact{
{"id", query.value(0).toInt()},
{"url", query.value(1).toString()}
};
}
}
return contact;
}
QList <QJsonValue> UPDATENEWS::findNewContacts(QJsonDocument news){
@ -231,46 +405,46 @@ QList <QJsonValue> UPDATENEWS::findNewContacts(QJsonDocument news){
imageurls.append(query.value(0).toString());
}
QList<QJsonValue> newcontacts;
qDebug()<<"updatenews findcontacts count "<<news.array().count();
//qDebug()<<"updatenews findcontacts news count "<<news.array().count();
for (int i=0; i<news.array().count();i++){
//main contacts
if(imageurls.contains(news[i]["user"]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["user"]["profile_image_url"].toString())){
if(imageurls.contains(news[i]["user"]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["user"]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["user"]);
newcontactimagelinks.append(news[i]["user"]["profile_image_url"].toString());
newcontactimagelinks.append(news[i]["user"]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["user"]["screen_name"].toString());
}
//like/dislike contacts
if (news[i].toObject().contains("friendica_activities") ){
for (int a=0; a < news[i]["friendica_activities"]["like"].toArray().count();a++){
if(imageurls.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString())){
if(imageurls.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["friendica_activities"]["like"][a]);
newcontactimagelinks.append(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString());
newcontactimagelinks.append(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["friendica_activities"][a]["screen_name"].toString());
}
}
for (int b=0; b < news[i]["friendica_activities"]["dislike"].toArray().count();b++){
if(imageurls.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString())){
if(imageurls.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["friendica_activities"]["dislike"][b]);
newcontactimagelinks.append(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString());
newcontactimagelinks.append(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["friendica_activities"][b]["screen_name"].toString());
}
}
}
//owner contacts
if (news[i].toObject().contains("friendica_owner") ){
if(imageurls.contains(news[i]["friendica_owner"]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_owner"]["profile_image_url"].toString())){
if (news[i].toObject().contains("friendica_author") ){
if(imageurls.contains(news[i]["friendica_author"]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["friendica_owner"]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["friendica_owner"]);
newcontactimagelinks.append(news[i]["friendica_owner"]["profile_image_url"].toString());
newcontactnames.append(news[i]["friendica_owner"]["screen_name"].toString());
newcontacts.append(news[i]["friendica_author"]);
newcontactimagelinks.append(news[i]["friendica_author"]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["friendica_author"]["screen_name"].toString());
}
}
}
@ -296,8 +470,8 @@ void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
query.bindValue(2, contact["screen_name"]);
query.bindValue(3, contact["location"]);
query.bindValue(4, currentTime);
query.bindValue(5, contact["profile_image_url"]);
if(contact["description"].isNull() ){query.bindValue(6,"");}else{query.bindValue(6, contact["description"].toString().toUtf8().toBase64());};
query.bindValue(5, contact["profile_image_url"].toString().section('?',0,0));
if(contact["description"].isNull() ){query.bindValue(6,"");}else{query.bindValue(6, contact["description"].toString().toUtf8().toBase64());}
query.bindValue(7,contact["protected"].toBool());
query.bindValue(8,contact["followers_count"].toInt());
query.bindValue(9,contact["friends_count"].toInt());
@ -317,7 +491,7 @@ void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
query.bindValue(21,contact["network"]);
qint64 timestamp=0;
QString timestamphelper=contact["profile_image_url"].toString();
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){};
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){}
query.bindValue(22,timestamp);
}
@ -334,8 +508,8 @@ void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
query.bindValue(3, contact["screen_name"]);
query.bindValue(4, contact["location"]);
query.bindValue(5, currentTime);
query.bindValue(6, contact["profile_image_url"]);
if(contact["description"].isNull() ){query.bindValue(7,"");}else{query.bindValue(7, contact["description"].toString().toUtf8().toBase64());};
query.bindValue(6, contact["profile_image_url"].toString().section('?',0,0));
if(contact["description"].isNull() ){query.bindValue(7,"");}else{query.bindValue(7, contact["description"].toString().toUtf8().toBase64());}
query.bindValue(8,"none");
query.bindValue(9, contact["url"].toString());
query.bindValue(10,contact["protected"].toBool());
@ -358,19 +532,12 @@ void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
query.bindValue(25, 0);
qint64 timestamp=0;
QString timestamphelper=contact["profile_image_url"].toString();
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){};
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){}
query.bindValue(26,timestamp);
}
query.exec() ;
}
emit this->success(m_api);
if ((contacts.count()==0) && (m_updateInterval!=0)){
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
};
}
QString UPDATENEWS::url() const
@ -380,6 +547,7 @@ QString UPDATENEWS::url() const
void UPDATENEWS::startImagedownload()
{
//qDebug() << "start image download";
xhr.setDownloadtype("contactlist");
xhr.setFilelist(newcontactimagelinks);
xhr.setContactlist(newcontactnames);
@ -389,11 +557,12 @@ void UPDATENEWS::startImagedownload()
void UPDATENEWS::showError(QString data, QString url,QString api, int code )
{
qDebug() << "showerror " << api << " data " << data;
emit this->error(api,data);
if (api!=m_api || xhr.downloadtype()!=""){} else{
if(m_updateInterval!=0){
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
};
syncindex+=1;
startsync();
}
}
}

View file

@ -37,7 +37,7 @@
#include <QSqlDatabase>
#include "xhr.h"
#include "alarm.h"
#include "AndroidNative/systemdispatcher.h"
//#include "AndroidNative/systemdispatcher.h"
class UPDATENEWS : public QObject
{
@ -64,6 +64,10 @@ public slots:
void setDatabase();
void login();
void timeline();
void replies();
void startsync();
void directmessages();
void notifications();
//void startservice(QString type,QVariantMap map);
void startImagedownload();
void updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index);
@ -76,8 +80,12 @@ private:
QString m_imagedir;
QString m_login;
QString username;
int syncindex;
QSqlDatabase m_db;
QList<QString> synclist;
QList <QString> notifylist;
QList<QJsonValue> findNewContacts(QJsonDocument news);
QJsonObject findNotificationContact(QString imagelink);
int m_updateInterval;
//void timeline();
//void store(QByteArray serverreply,QString apiname);

View file

@ -154,7 +154,7 @@ QString XHR::downloadtype() const
return m_downloadtype;
}
QString XHR::networktype() const
QString XHR::networktype()
{
return nc.bearerTypeFamily() + nc.bearerTypeName();
}
@ -184,7 +184,6 @@ void XHR::download()
request.setRawHeader("Authorization", headerData.toLocal8Bit());
}
request.setUrl(requrl);
//qDebug() << requrl;
reply = manager.get(request);
reply->ignoreSslErrors();
connect(reply, &QNetworkReply::readyRead,this, &XHR::onReadyRead);
@ -202,10 +201,11 @@ void XHR::get()
while(i.hasNext()) {
i.next();
query.addQueryItem(i.key(), i.value());
//qDebug()<<i.key() << " value "<< i.value();
}
QUrl requrl(m_url+m_api);
//qDebug() << requrl;
//qDebug() << "API "<< requrl<<m_api;
requrl.setQuery(query);
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
@ -229,7 +229,7 @@ void XHR::getlist()
else {
XHR::setUrl(m_filelist.at(dlindex));}
XHR::download();
} else {dlindex=0;}
} else {dlindex=0;m_downloadtype="";m_contactlist.clear();m_filelist.clear();}
}
@ -297,6 +297,7 @@ void XHR::onReplySuccess()
void XHR::onRequestFinished()
{
qDebug()<<"download requestFinished ";
// Save the file here
if (buffer.isNull()){qDebug() << "File empty"<<m_url; buffer.clear(); emit this->error(m_downloadtype,m_url,m_api,1);}
else if (m_downloadtype=="picturelist") {

View file

@ -49,7 +49,7 @@ class XHR : public QObject
Q_PROPERTY(QList<QString> contactlist READ contactlist WRITE setContactlist NOTIFY contactlistChanged)
Q_PROPERTY(QList<QString> filelist READ filelist WRITE setFilelist NOTIFY filelistChanged)
Q_PROPERTY(QString downloadtype READ downloadtype WRITE setDownloadtype NOTIFY downloadtypeChanged)
Q_PROPERTY(QString networktype READ networktype NOTIFY networktypeChanged)
Q_PROPERTY(QString networktype READ networktype() NOTIFY networktypeChanged)
public:
@ -65,7 +65,7 @@ public:
QList<QString> filelist() const;
QString imagedir() const;
QString downloadtype() const;
QString networktype() const;
QString networktype();
signals:
void urlChanged();
@ -98,6 +98,7 @@ public slots:
void get();
void getlist();
void download();
// void networktype();
private slots:

View file

@ -125,7 +125,8 @@ function friendicaRemoteAuthRequest(login,url,c_url,rootwindow,callback) {
function readData(database,table,username,callback,filter,filtervalue, sort) { // reads and applies data from DB
if (filter){
var where = " AND "+ filter +" = '" + filtervalue+"'";
if (username){var where = " AND "+ filter +" = '" + filtervalue+"'";} else{
var where = " WHERE "+ filter +" = '" + filtervalue+"'";}
} else { var where="";}
if (username){
var user = ' where username= "'+ username +'"';
@ -165,7 +166,7 @@ var where = " AND "+ filter +" = '" + filtervalue+"'";
});
}
function showMessage(header,message,rootwindow){print(message);
function showMessage(header,message,rootwindow){//print(message);
var cleanmessage=message.replace(/"/g,"-");
if(cleanmessage.length>200){cleanmessage=cleanmessage.slice(0,200)+'...'}
var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+cleanmessage+'"}';

View file

@ -36,7 +36,7 @@ function showFriends(db) {
}
function displayFriends(obj){
for (var i=0; i<obj.length; i++){
print(obj[i]);
//print(obj[i]);
if (obj[i]) {friendsModel.append({"friendName": obj[i]});
};

View file

@ -65,10 +65,15 @@ function requestGroups(login,database,rootwindow,callback){
});
})}
function listFriends(login,database,callback){
function listFriends(login,database,callback,filter){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var filtertext='';
try {filtertext=' AND screen_name like "' + filter+'%"'}catch(e){}
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from contacts WHERE username="'+login.username+'" AND isFriend>0'); // check for friends
//var result = tx.executeSql('SELECT * from contacts WHERE username="'+login.username+'" AND isFriend>0'+filtertext);
//print('SELECT * from contacts WHERE username="'+login.username+'"'+filtertext);
var result = tx.executeSql('SELECT * from contacts WHERE username="'+login.username+'" AND isFriend>0'+filtertext);
// check for friends
var contactlist=[];
for (var i=0;i<result.rows.length;i++){
contactlist.push(result.rows.item(i))
@ -88,13 +93,13 @@ function deleteGroup(login,database,rootwindow,group, callback){
});
}})}
function getLastNews(login,database){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var lastnewsid=0;
db.transaction( function(tx) {
function getLastNews(login,database,callback){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var lastnewsid=0;
db.transaction( function(tx) {
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" AND messagetype=0 ORDER BY status_id DESC LIMIT 1');
try{lastnewsid=result.rows.item(0).status_id;}catch(e){};
return lastnewsid
try{lastnewsid=result.rows.item(0).status_id;}catch(e){print(e)};
callback(lastnewsid)
})
}
@ -163,11 +168,11 @@ function findNewContacts(news,contacts){
}
}
if(news[i].hasOwnProperty('friendica_owner')){
var owner_url=news[i].friendica_owner.url;
if(news[i].hasOwnProperty('friendica_author')){
var owner_url=news[i].friendica_author.url;
if(contacts.indexOf(owner_url)==-1 && !(inArray(newContacts,"url",owner_url))){
news[i].friendica_owner.isFriend=0;
newContacts.push(news[i].friendica_owner);
news[i].friendica_author.isFriend=0;
newContacts.push(news[i].friendica_author);
}
}
}
@ -178,7 +183,7 @@ function storeNews(login,database,news,rootwindow){
// save news after contacts download, call next function
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
for (var i=0;i<news.length;i++){
//print('store news data for ' + news[i].id+JSON.stringify(news[i].friendica_activities));
//print('store news data for ' + news[i].id+JSON.stringify(news[i].friendica_author));
//var ausdruck=news[i];
var likearray=[];var dislikearray=[];var attendyesarray=[];var attendnoarray=[];var attendmaybearray=[];
if(news[i].hasOwnProperty('friendica_activities')){
@ -191,12 +196,12 @@ function storeNews(login,database,news,rootwindow){
var friendica_activities=[likearray,dislikearray,attendyesarray,attendnoarray,attendmaybearray]
var attachments="";if (news[i].attachments){attachments=Qt.btoa(JSON.stringify(news[i].attachments))}
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where username="'+login.username+'" AND status_id = "'+news[i].id+'" AND messagetype=0'); // check for news id
var result = tx.executeSql('SELECT * from news where username="'+login.username+'" AND status_id = "'+news[i].id+'" AND messagetype='+news[i].messagetype); // check for news id
if(result.rows.length === 1) {// use update
//print(news[i].id +' news exists, update it'+'UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", created_at="'+Date.parse(cleanDate(news[i].created_at))+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",friendica_activities="'+Qt.btoa(JSON.stringify(friendica_activities))+'",attachments="'+attachments+'",friendica_owner="'+news[i].friendica_owner.url+'" where username="'+login.username+'" AND status_id="'+news[i].status_id+'" AND messagetype=0')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", created_at="'+news[i].created_at+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",friendica_activities="'+Qt.btoa(JSON.stringify(friendica_activities))+'",attachments="'+attachments+'",friendica_owner="'+news[i].friendica_owner.url+'" where username="'+login.username+'" AND status_id="'+news[i].status_id+'" AND messagetype=0');
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype='+news[i].messagetype+', text="'+Qt.btoa(news[i].text)+'", created_at="'+news[i].created_at+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",friendica_activities="'+Qt.btoa(JSON.stringify(friendica_activities))+'",attachments="'+attachments+'",friendica_owner="'+news[i].friendica_author.url+'" where username="'+login.username+'" AND status_id="'+news[i].status_id+'" AND messagetype=0');
} else {// use insert
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,friendica_activities,friendica_activities_self,attachments,friendica_owner) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,0,Qt.btoa(news[i].text),news[i].created_at, news[i].in_reply_to_status_id, news[i].source, news[i].id,news[i].in_reply_to_user_id,news[i].geo,news[i].favorited, news[i].user.id,Qt.btoa(news[i].statusnet_html),news[i].statusnet_conversation_id, Qt.btoa(JSON.stringify(friendica_activities)),"[]",attachments,news[i].friendica_owner.url])}})
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,friendica_activities,friendica_activities_self,attachments,friendica_owner) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,news[i].messagetype,Qt.btoa(news[i].text),news[i].created_at, news[i].in_reply_to_status_id, news[i].source, news[i].id,news[i].in_reply_to_user_id,news[i].geo,news[i].favorited, news[i].user.id,Qt.btoa(news[i].statusnet_html),news[i].statusnet_conversation_id, Qt.btoa(JSON.stringify(friendica_activities)),"[]",attachments,news[i].friendica_author.url])}})
}
// getDirectMessage(login,database,rootwindow,callback)
}
@ -260,35 +265,41 @@ function getActivitiesUserData(allcontacts,userUrlArray){//print(JSON.stringify(
return helpArray
}
function newsfromdb(database,user,callback,contact,stop_time){
function newsfromdb(database,login,messagetype,callback,contact,stop_time){
// return news before stop_time (used by More button), in brackets of 20 entries, or by specified contact
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" AND messagetype=0 ORDER BY status_id DESC LIMIT 1');
try{var lastid=result.rows.item(0).status_id;}catch(e){var lastid=0};
if (!stop_time){var stop="";
try{var rs = tx.executeSql('select created_at from news WHERE username="'+user+'" ORDER BY created_at DESC LIMIT 1');
try{var rs = tx.executeSql('select created_at from news WHERE username="'+login.username+'" AND messagetype="'+messagetype+'" ORDER BY created_at DESC LIMIT 1');
stop="<="+rs.rows.item(0).created_at}catch(e){stop="<99999999999999"}}
else{var stop="<"+stop_time}
var contactfilter="";if(contact){contactfilter=" AND (uid='"+contact+"' OR friendica_owner='"+contact+"')"}
//print('select * from news WHERE username="'+username+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
var newsrs=tx.executeSql('select * from news WHERE username="'+user+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
var newsrs=tx.executeSql('select * from news WHERE username="'+login.username+'" AND messagetype="'+messagetype+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
var newsArray=[];
var allcontacts=getAllContacts(database,user);
var allcontacts=getAllContacts(database,login.username);
for(var i = 0; i < newsrs.rows.length; i++) {
newsArray.push(newsrs.rows.item(i));
newsArray[i].statusnet_html=Qt.atob(newsArray[i].statusnet_html);
newsArray[i].text=Qt.atob(newsArray[i].text);
newsArray[i].id=newsArray[i].status_id;
newsArray[i]=fetchUsersForNews(database,user,newsArray[i],allcontacts);
if (newsArray[i].attachments!==null){newsArray[i].attachments=JSON.parse(Qt.atob(newsArray[i].attachments))};
newsArray[i].friendica_author=newsArray[i].friendica_owner
newsArray[i]=fetchUsersForNews(database,login.username,newsArray[i],allcontacts);
if (newsArray[i].attachments!="" && newsArray[i].attachments!==null){newsArray[i].attachments=JSON.parse(Qt.atob(newsArray[i].attachments))};
}
callback(newsArray)});
callback(newsArray,lastid)});
}
function fetchUsersForNews(database,username,news,allcontacts){//print(JSON.stringify(news))
function fetchUsersForNews(database,username,news,allcontacts){//print("fetchusers "+JSON.stringify(news))
news.user=objFromArray(allcontacts,"id",news.uid);
if(news.in_reply_to_user_id){news.reply_user=objFromArray(allcontacts,"id",news.in_reply_to_user_id)}
//news.friendica_owner_object=objFromArray(allcontacts,"url",news.friendica_owner);
news.friendica_owner=objFromArray(allcontacts,"url",news.friendica_owner);
news.friendica_author=objFromArray(allcontacts,"url",news.friendica_author);
if (news.messagetype==0){
var friendicaArray=JSON.parse(Qt.atob(news.friendica_activities));
delete news.friendica_activities;
@ -413,7 +424,7 @@ function conversationfromdb(database,user,conversationId,callback){
newsArray[i].text=Qt.atob(newsArray[i].text);
newsArray[i].id=newsArray[i].status_id;
newsArray[i]=fetchUsersForNews(database,user,newsArray[i],allcontacts);
if (newsArray[i].attachments!==null){newsArray[i].attachments=JSON.parse(Qt.atob(newsArray[i].attachments))};
if (helpernews.attachments!="" && newsArray[i].attachments!==null){newsArray[i].attachments=JSON.parse(Qt.atob(newsArray[i].attachments))};
}
callback(newsArray)})
}
@ -443,32 +454,36 @@ function requestFavorites(login,database,contacts,rootwindow,callback){
// callback(newsArray);
// }})}
function chatsfromdb(database,user,callback,stop_time){
function chatsfromdb(database,login,messagetype,callback,stop_time){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
if (!stop_time){var stop="";
try{var rs = tx.executeSql('select created_at from news WHERE username="'+username+'" ORDER BY created_at DESC LIMIT 1');
try{var rs = tx.executeSql('select created_at from news WHERE username="'+login.username+'" AND messagetype="'+messagetype+'" ORDER BY created_at DESC LIMIT 1');
stop="<="+rs.rows.item(0).created_at}catch(e){stop="<99999999999999"}}
else{var stop="<"+stop_time}
var conversationsrs=tx.executeSql('select DISTINCT statusnet_conversation_id from news WHERE username="'+user+'" AND created_at'+stop+' ORDER BY created_at DESC LIMIT 20'); //+' ORDER BY created_at DESC LIMIT 20');
var conversationsrs=tx.executeSql('select DISTINCT statusnet_conversation_id from news WHERE username="'+login.username+'" AND created_at'+stop+' AND messagetype="'+messagetype+'" ORDER BY created_at DESC LIMIT 20'); //+' ORDER BY created_at DESC LIMIT 20');
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" AND messagetype=0 ORDER BY status_id DESC LIMIT 1');
try{var lastid=result.rows.item(0).status_id;}catch(e){var lastid=0};
var conversations=[];
for(var i = 0; i < conversationsrs.rows.length; i++) {
conversations.push(conversationsrs.rows.item(i).statusnet_conversation_id);
}
var newsArray=[];
var allcontacts=getAllContacts(database,user);
var allcontacts=getAllContacts(database,login.username);
for(var j = 0; j< conversations.length; j++) {
var newsrs=tx.executeSql('select * from news WHERE username="'+user+'" AND statusnet_conversation_id="'+conversations[j] +'" ORDER BY created_at ASC');
var newsrs=tx.executeSql('select * from news WHERE username="'+login.username+'" AND statusnet_conversation_id="'+conversations[j] +'" AND messagetype="'+messagetype+'" ORDER BY created_at ASC');
var helpernews=newsrs.rows.item(0);
helpernews.newscount=newsrs.rows.length;
helpernews=fetchUsersForNews(database,user,helpernews,allcontacts);
helpernews=fetchUsersForNews(database,login.username,helpernews,allcontacts);
helpernews.statusnet_html=Qt.atob(helpernews.statusnet_html);
helpernews.text=Qt.atob(helpernews.text);
helpernews.id=helpernews.status_id;
if (helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
if (helpernews.attachments!="" && helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
newsArray.push(helpernews);
}
callback(newsArray);
callback(newsArray,lastid);
})}
@ -495,7 +510,7 @@ function allchatsfromdb(database,user,callback){
helpernews.statusnet_html=Qt.atob(helpernews.statusnet_html);
helpernews.text=Qt.atob(helpernews.text);
helpernews.id=helpernews.status_id;
if (helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
if (helpernews.attachments!="" && helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
newsArray.push(helpernews);
countArray.push(newsrs.rows.length)
}
@ -520,7 +535,7 @@ function oldchatfromdb(database,user,conversationId,lastpost,allcontacts,callbac
helpernews.statusnet_html=Qt.atob(helpernews.statusnet_html);
helpernews.text=Qt.atob(helpernews.text);
helpernews.id=helpernews.status_id;
if (helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
if (helpernews.attachments!="" && helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
callback(helpernews,newscount);}
// var conversationobject={news:helpernews,newscount:newscount};
// return conversationobject;

View file

@ -53,9 +53,12 @@ else{
// newsitemobject.user.profile_image_url="";
// newsitemobject.user.name="";
// }
var forumname="";try{if (newsitemobject.messagetype==0&&newsitemobject.hasOwnProperty('friendica_owner')&&((newsitemobject.friendica_owner.url)!=(newsitemobject.user.url))){
//print(newsitemobject.friendica_owner+" Friendica Owner "+JSON.stringify(newsitemobject));
forumname=" via "+newsitemobject.friendica_owner.name
var forumname="";
try{if (newsitemobject.messagetype==0&&newsitemobject.hasOwnProperty('friendica_author')&&
((newsitemobject.friendica_author.url)!=(newsitemobject.user.url))&&((newsitemobject.friendica_author.url)!=null)){
print(" Friendica Author "+JSON.stringify(newsitemobject.friendica_author));
forumname=" via "+newsitemobject.user.name;
newsitemobject.user=newsitemobject.friendica_author;
}}catch(e){print("forum name "+e)}
var likeText="";var dislikeText="";var attendyesText="";var attendnoText="";var attendmaybeText=""; var self={};
try{if (newsitemobject.messagetype==0&&newsitemobject.hasOwnProperty('friendica_activities')){
@ -166,7 +169,6 @@ else{
// }
newsitemobject.attachmentList=attachmentList;
var seconds=(msg.currentTime-newsitemobject.created_at)/1000;
var timestring="";
if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");}

View file

@ -38,7 +38,7 @@
function initDatabase(database) { // initialize the database object
var db =Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('initDatabase()'+database[0]+database[1]+database[2]+database[3])
//print('initDatabase()'+database[0]+database[1]+database[2]+database[3])
db.transaction( function(tx) {
//var version=tx.executeSql('PRAGMA user_version');print(JSON.stringify(version.rows.item(0)))
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)');
@ -194,13 +194,11 @@ function storeConfig(database,obj) { // stores config to DB
//print(JSON.stringify(obj));
var result = tx.executeSql('SELECT * from config WHERE username="'+obj.username+'"');
if(result.rows.length === 1) {// use update
var result2 = tx.executeSql('UPDATE config SET server="'+obj.server+'",password="'+obj.password+'", imagestore="'+obj.imagestore+'", maxnews='+obj.maxnews+', timerInterval='+obj.interval+', newsViewType="'+obj.newsViewType+'", isActive=0 WHERE username="'+obj.username +'"');
var result2 = tx.executeSql('UPDATE config SET server="'+obj.server+'",password="'+obj.password+'", imagestore="'+obj.imagestore+'", maxnews=0, timerInterval=0, newsViewType="'+obj.newsViewType+'", isActive=0 WHERE username="'+obj.username +'"');
var result3 = tx.executeSql('UPDATE config SET isActive=1 WHERE username !="'+obj.username +'"');
var result4 = tx.executeSql('UPDATE config SET maxnews='+obj.maxnews);
} else {// use insert print('... does not exists, create it')
var result2 = tx.executeSql('INSERT INTO config VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)', [obj.server, obj.username, obj.password, obj.imagestore, obj.maxnews, obj.interval,obj.newsViewType,0,"[[],[],[],[]]",0,"","",""]);
var result2 = tx.executeSql('INSERT INTO config VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)', [obj.server, obj.username, obj.password, obj.imagestore, 0, 0,obj.newsViewType,0,"[[],[],[],[]]",0,"","",""]);
var result3 = tx.executeSql('UPDATE config SET isActive=1 WHERE username !="'+obj.username +'"');
var result4 = tx.executeSql('UPDATE config SET maxnews='+obj.maxnews);
}
})}
@ -283,7 +281,7 @@ function readConfig(database,callback,filter,filtervalue) { // reads config
for(var i = 0; i < rs.rows.length; i++) {
rsArray.push(rs.rows.item(i))
}
var rsObject={server:rsArray[0].server,username:rsArray[0].username, password:rsArray[0].password,imagestore:rsArray[0].imagestore,maxnews:rsArray[0].maxnews,isActive:rsArray[0].isActive,timerInterval:rsArray[0].timerInterval, newsViewType:rsArray[0].newsViewType,permissions:JSON.parse(rsArray[0].permissions),maxContactAge:rsArray[0].maxContactAge,APIVersion:rsArray[0].APIVersion,addons:rsArray[0].addons};
var rsObject={server:rsArray[0].server,username:rsArray[0].username, password:rsArray[0].password,imagestore:rsArray[0].imagestore,isActive:rsArray[0].isActive, newsViewType:rsArray[0].newsViewType,permissions:JSON.parse(rsArray[0].permissions),maxContactAge:rsArray[0].maxContactAge,APIVersion:rsArray[0].APIVersion,addons:rsArray[0].addons};
} else {var rsObject=""}
callback(rsObject)}}
)
@ -318,6 +316,7 @@ function updateglobaloptions(database,key,value){
result = tx.executeSql('INSERT INTO globaloptions (k,v) VALUES (?,?)', [key,value])
}
})
root.globaloptions[key]=value;
}
function deleteConfig(database,userobj,callback) { // delete user data from DB
@ -338,8 +337,9 @@ function deleteConfig(database,userobj,callback) { // delete user data from DB
function cleanNews(database,callback){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
var maxnewsrs = tx.executeSql("SELECT DISTINCT maxnews FROM config");
var maxnews=maxnewsrs.rows.item(0).maxnews;
//var maxnewsrs = tx.executeSql("SELECT DISTINCT maxnews FROM config");
var maxnewsrs = tx.executeSql("SELECT v FROM globaloptions WHERE k='max_news'");
var maxnews=1000; if(maxnewsrs.rows.length>0){ maxnews=maxnewsrs.rows.item(0).v};
var newscountrs = tx.executeSql('SELECT COUNT(*) from news');
var newscount = newscountrs.rows.item(0)["COUNT(*)"];//print("newscount "+newscount)
if (newscount>maxnews){
@ -384,6 +384,7 @@ function updateContactInDB(login,database,isFriend,contact){// for newstab and f
}
function processNews(api,data){
//print(api + data);
try{var newslist=JSON.parse(data)} catch(e){newsBusy.running=false;};
if (data==""){}
else if (typeof(newslist)=='undefined'){
@ -393,6 +394,7 @@ function processNews(api,data){
Helperjs.showMessage(qsTr("JSON status Error"),"API:\n" +login.server+api+"\n Return: \n"+data,root)
}
else if (!(Array.isArray(newslist))){
//print("processNews not array"+newslist+JSON.stringify(newslist));
replytimer.restart()
}
else {
@ -407,6 +409,8 @@ function processNews(api,data){
newslist[n].uid=newslist[n].sender.id;
newslist[n].statusnet_conversation_id=newslist[n].friendica_parent_uri;
newslist[n].user=cleanUser(newslist[n].sender);
newslist[n].friendica_owner=newslist[n].user;
newslist[n].friendica_author=newslist[n].user;
newslist[n].statusnet_html=newslist[n].text;
}}
else if (api=="/api/friendica/notifications"){
@ -418,6 +422,8 @@ function processNews(api,data){
newslist[n].user={"profile_image_url": newslist[n].photo,"name": newslist[n].name," url":newslist[n].url, "created_at":newslist[n].date};
newslist[n].user=cleanUser(newslist[n].user);
}
newslist[n].friendica_author=newslist[n].user;
newslist[n].friendica_owner=newslist[n].user;
newslist[n].statusnet_html=newslist[n].msg_html;
newslist[n].text=newslist[n].msg;
}
@ -427,8 +433,9 @@ function processNews(api,data){
var commentCount=[];
for (var n in newslist){
newslist[n].created_at=Date.parse(Newsjs.cleanDate(newslist[n].created_at));
newslist[n].messagetype=0;
newslist[n].user=cleanUser(newslist[n].user)
if (api=="/api/statuses/replies"){newslist[n].messagetype=3}else{newslist[n].messagetype=0;}
newslist[n].friendica_author=cleanUser(newslist[n].friendica_author);
newslist[n].user=cleanUser(newslist[n].user);
if(newslist[n].in_reply_to_user_id){newslist[n].reply_user=Newsjs.objFromArray(allcontacts,"id",newslist[n].in_reply_to_user_id)}
//print (JSON.stringify(newslist[n].user))
if(newslist[n].hasOwnProperty('friendica_activities')){
@ -448,8 +455,8 @@ function processNews(api,data){
newslist[n].friendica_activities.attendmaybe[r]=cleanUser(newslist[n].friendica_activities.attendmaybe[r]);
}
}
if(!(newslist[n].hasOwnProperty('friendica_owner'))){
newslist[n].friendica_owner=newslist[n].user
if(!(newslist[n].hasOwnProperty('friendica_author'))){
newslist[n].friendica_author=newslist[n].user
}
var conversationindex=conversationIds.indexOf(newslist[n].statusnet_conversation_id);
@ -488,11 +495,13 @@ function processNews(api,data){
else if (api=="/api/statuses/user_timeline"){
newstab.contactposts=newslist
}
else if (newstab.newstabstatus==="Conversations"){
showNews(chatlist);root.news=newslist}
else {showNews(newslist);root.news=newslist};
else if ((api!="/api/direct_messages/all")&&(api!="/api/friendica/notifications")&&(newstab.newstabstatus==="Conversations")){
showNews(chatlist);root.news=newslist
}
else {
showNews(newslist);root.news=newslist};
var newstabarray=["Conversations","Favorites","Timeline","DirectMessage"];
var newstabarray=["Conversations","Favorites","Timeline","DirectMessage","Replies"];
if (newstabarray.indexOf(newstab.newstabstatus)>-1){contacttimer.start()}
}
@ -509,26 +518,28 @@ function cleanUser(user){
}
function updateView(viewtype){
newsBusy.running=true;
//messageSend.state="";
//newsBusy.running=true;
//downloadNotice.text="xhr start "+Date.now()
switch(viewtype){
case "Conversations":
var lastnews=Newsjs.getLastNews(login,db);
Newsjs.getLastNews(login,db,function(lastnews){
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/statuses/friends_timeline");
xhr.clearParams();
xhr.setParam("since_id",lastnews);
xhr.setParam("count",50)
xhr.setParam("count",50)});
break;
case "Timeline":
var lastnews=Newsjs.getLastNews(login,db);
var lastnews=Newsjs.getLastNews(login,db,function(lastnews){
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/statuses/friends_timeline");
xhr.clearParams();
xhr.setParam("since_id",lastnews);
xhr.setParam("count",50)
});
break;
case "Search":
xhr.setLogin(login.username+":"+Qt.atob(login.password));
@ -566,7 +577,7 @@ function updateView(viewtype){
xhr.clearParams();
break;
default:
var lastnews=Newsjs.getLastNews(login,db);
Newsjs.getLastNews(login,db,function(lastnews){
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/statuses/friends_timeline");
@ -574,6 +585,7 @@ function updateView(viewtype){
xhr.setParam("since_id",lastnews);
xhr.setParam("count",50)
newstab.newstabstatus="Conversations";
});
}
xhr.get();

View file

@ -29,8 +29,8 @@
// 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.0
import QtQuick.Controls 1.4
import QtQuick 2.11
//import QtQuick.Controls 2.4
Item {
id: calendarDay

View file

@ -30,10 +30,10 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 2.3
import QtQuick.Controls 2.4
import QtQml 2.2
import Qt.labs.calendar 1.0
import QtQuick.Controls 1.2 as Oldcontrol
//import QtQuick.Controls 1.2 as Oldcontrol
import QtQuick.Layouts 1.3
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
@ -42,9 +42,10 @@ import "qrc:/qml/genericqml"
Rectangle {
id:calendarrectangle
y:1
width:root.width-mm
height:root.height-5*mm
// y:1
// width:root.width-mm
// height:root.height-5*mm
anchors.fill: parent
color: '#fff'
property date currentTime: new Date()
property int offsetTime: currentTime.getTimezoneOffset() * 60 * 1000
@ -83,30 +84,35 @@ Rectangle {
}
BlueButton{
MButton{
id: updateEvents
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right:calendartabstatusButton.left
anchors.rightMargin:mm
height: 6*mm
width: 8*mm
text:"\uf021"
onClicked: {
Service.getEvents(db,login, calendartab,function(){
showEvents("")
})}}
BlueButton{
MButton{
id: calendartabstatusButton
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right: parent.right
anchors.rightMargin:2*mm
height: 6*mm
width: Math.max(10*mm,implicitWidth)
text: calendartab.calendartabstatus=="Events"?qsTr("Events"):calendartabstatus
Oldcontrol.Menu {
Menu {
id:calendartabmenu
Oldcontrol.MenuItem {
width: 40*mm
MenuItem {
text: qsTr("Own Calendar")
font.pixelSize: 3*mm
onTriggered: {
calendartab.calendartabstatus="Events";
// calendartabstatusButton.text=qsTr("own Calendar");
@ -146,6 +152,7 @@ Rectangle {
DayOfWeekRow{
locale: monthgrid.locale
Layout.fillWidth: true
font.pixelSize: 3*mm
}
MonthGrid {

View file

@ -30,7 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls 2.4
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
@ -45,12 +45,14 @@ Rectangle{
y:mm
property var daylist:[]
BlueButton{
MButton{
id:closeButton
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
height: 6*mm
width: 8*mm
text: "\uf057"
onClicked:{eventList.destroy()}
}

View file

@ -0,0 +1,463 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 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.7
import QtQuick.Dialogs 1.2
import QtQuick.Controls 2.4
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/configqml"
import "qrc:/qml/genericqml"
Page{
id:accountPage
width: root.width
height: root.height
property var users:[]
property var userdata: ({})
function setServericon(server){
try {Helperjs.friendicaWebRequest(server+"/api/statusnet/config",accountPage, function (obj){
var serverdata = JSON.parse(obj);
servericon.visible=true;
servericon.source=serverdata.site.logo})} catch(e){print(e)}
}
Button{
id:userButton
height: 8*mm
text:qsTr("User")
font.pixelSize: 3*mm
x: mm
y: mm
width: root.width/2
onClicked:{
var useritems="";
for (var i=0;i<accountPage.users.length;i++){
useritems=useritems+"MenuItem{font.pixelSize: 3*mm; text:'"+accountPage.users[i].username+
"'; onTriggered: {Service.readConfig(db,function(obj){
userButton.text=obj.username;
servername.text=obj.server;
accountPage.setServericon(obj.server);
username.text= obj.username;
password.text=Qt.atob(obj.password);
imagestore.text=obj.imagestore;
newsTypeField.text=obj.newsViewType;
if( obj.isActive==0){userButton.font.bold='true'} else {userButton.font.bold='false'}
},'username','"+ accountPage.users[i].username+"')}}"
}
var menuString="import QtQuick.Controls 2.4;import 'qrc:/js/service.js' as Service; Menu {"+useritems+"}";
var userlistObject=Qt.createQmlObject(menuString,accountPage,"usermenuOutput")
userlistObject.popup() }
}
Text {
text: qsTr("Server")
font.pixelSize:3*mm
x: 4*mm; y: 10*mm
}
Text {
text: qsTr("Nickname")
font.pixelSize:3*mm
x: 4*mm; y: 20*mm
}
Text {
text: qsTr("Password")
font.pixelSize:3*mm
x: 4*mm; y: 30*mm
}
Text {
text: qsTr("Image dir.")
font.pixelSize:3*mm
x: 4*mm; y: 40*mm
}
// Text {
// text: qsTr("Max. News")
// font.pixelSize:3*mm
// x: 4*mm; y: 50*mm
// }
Text {
text: qsTr("News as")
font.pixelSize:3*mm
x: 4*mm; y: 50*mm
}
// Text {
// text: qsTr("Show Website")
// x: 4*mm; y:80*mm; width: 20*mm
// }
Image{
id:servericon
x:4*mm;y:13.5*mm
width:5*mm; height: 5*mm
visible: false
source:""
MouseArea{
anchors.fill:parent
onClicked:{
Service.showServerConfig(servername.text, accountPage, function(configString){
var serverconfigObject=Qt.createQmlObject(configString,accountPage,"serverconfigOutput");})
}
}
}
Button{
id:serverSearchButton
text:"\uf002"
font.pixelSize: 3*mm
x:4*mm
y:13.5*mm
width: 5*mm; height:5*mm
visible: servericon.visible?false:true
onClicked:{Qt.openUrlExternally(Qt.resolvedUrl("https://dir.friendica.social/servers"))}
}
Rectangle{color: "light grey"; x: 10*mm; y: 13.5*mm; width: root.width-12*mm; height: 5*mm;}
Flickable {
id: servernameFlickable
x: 10*mm; y: 13.5*mm; width: root.width-12*mm; height: 5*mm;
contentWidth: servername.paintedWidth
contentHeight: servername.paintedHeight
clip: true
TextEdit {
id: servername
width: servernameFlickable.width
height: servernameFlickable.height
focus: true
font.pixelSize:3*mm
text:"https://"
onEditingFinished:{
if((servername.text).substring(0,11) =="https://http"){
serverstring.text= (serverstring.text).substring(8)
}
accountPage.setServericon(servername.text)
}
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,servernameFlickable)
}
}
Rectangle{
color: "light grey"
x: 4*mm; y: 23.5*mm; width: root.width-14*mm; height: 5*mm;
TextInput {
id: username
anchors.fill: parent
font.pixelSize:3*mm
selectByMouse: true
onEditingFinished:{
if (username.text.indexOf('@')>-1){
Helperjs.showMessage(qsTr("Error"),qsTr("Nicknames containing @ symbol currently not supported"),accountPage)
}
}
}
}
Button {
x: root.width-9*mm; y: 23.5*mm; width:5*mm; height:5*mm
text: "\uf234"
font.pixelSize: 3*mm
onClicked: {
configStack.push({item:"qrc:/qml/configqml/RegisterPage.qml",properties:{url:servername.text+"/register?nickname="+username.getText(0,username.length)}})
}
}
Rectangle{
color: "light grey"
x: 4*mm; y: 33.5*mm; width: root.width-6*mm; height: 5*mm;
TextInput {
id: password
anchors.fill: parent
font.pixelSize:3*mm
selectByMouse: true
echoMode: TextInput.PasswordEchoOnEdit
}
}
Rectangle{color: "light grey"; x: 4*mm; y: 43.5*mm; width: root.width-14*mm; height: 5*mm;}
Flickable {
id: imagestoreFlickable
x: 4*mm; y: 43.5*mm; width: root.width-14*mm; height: 5*mm;
clip: true
TextInput {
id: imagestore
width: imagestoreFlickable.width
height: imagestoreFlickable.height
font.pixelSize:3*mm
wrapMode: TextEdit.NoWrap
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
}
}
FileDialog {
id: imagestoreDialog
title: "Please choose a directory"
folder: shortcuts.pictures
selectFolder: true
onAccepted: {
var imagestoreString=imagestoreDialog.folder.toString();
imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
imagestore.text=imagestoreString
}
}
Button {
x: root.width-9*mm; y: 43.5*mm; width: 5*mm; height: 5*mm;
text: "..."
font.pixelSize: 3*mm
onClicked:
{imagestoreDialog.open()}
}
// Slider{ id: maxNews
// x:19*mm; y: 53.5*mm;width: root.width/2;height:5*mm
// from: 0;to:2000; stepSize: 100
// }
// Rectangle{color: "light grey"; x: 4*mm; y: 53.5*mm; width: 9*mm; height: 5*mm;
// TextEdit{id:maxNewsText;
// anchors.fill: parent
// font.pixelSize:3*mm
// verticalAlignment:TextEdit.AlignRight
// text:maxNews.value
// focus: true
// selectByMouse: true
// }
// }
Rectangle{
x: 4*mm; y: 53.5*mm; width: newsTypeField.contentWidth+2*mm; height: 5*mm;
color:"light grey"
Text{
id: newsTypeField
anchors.fill: parent
font.pixelSize:3*mm
text:"Conversations"
}
MouseArea{
anchors.fill:parent
onClicked:newstypemenu.popup()
}
}
BusyIndicator{
id: accountBusy
anchors.horizontalCenter: parent.horizontalCenter
y: 63.5*mm
width:10*mm
height: 10*mm
running: false
}
// CheckBox{
// id:showwebsiteCheckbox
// x:35*mm;y:80*mm
// onClicked:{
// if (checked==true){
// Service.updateglobaloptions(root.db,"showWebsiteForLinks","true")
// root.globaloptions.showWebsiteForLinks="true"
// }
// else {
// Service.updateglobaloptions(root.db,"showWebsiteForLinks","false")
// root.globaloptions.showWebsiteForLinks="false"
// }
// }
// }
Button {
x: 4*mm; y: 63.5*mm
height: 8*mm
text: qsTr("Confirm")
font.pixelSize: 3*mm
onClicked:{
accountBusy.running=true;
var userconfig={server: servername.text, username: username.text, password:Qt.btoa(password.text), imagestore:imagestore.text, maxnews:"",interval: "",newsViewType:newsTypeField.text};
var errormessage="";
if (servername.text==""){errormessage=qsTr("No server given! ")}
else if (username.text==""){errormessage+=qsTr("No nickname given! ")}
else if (password.text=="") {errormessage+=qsTr("No password 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){
accountBusy.running=false;
var credentials=JSON.parse(obj);
if (credentials.hasOwnProperty('status')){
Helperjs.showMessage(qsTr("Error"),qsTr("Wrong password!"),root)
}
else{
filesystem.Directory=userconfig.imagestore;
filesystem.makeDir("contacts");
filesystem.makeDir("albums");
Service.storeConfig(db,userconfig);
Service.readConfig(db,function(userconfig){
Helperjs.readData(db,"config","",function(storedUsers){
storedUsers.sort(function(obj1, obj2) {
return obj1.isActive - obj2.isActive;
});
accountPage.users=storedUsers});
//reset values
root.login=userconfig;
root.news=[];
},"isActive",0);
//Service.requestProfile(userconfig,db,root,function(nc){root.newContacts=nc});
Helperjs.showMessage(qsTr("Success"),qsTr("Name")+": "+credentials.name+"\nScreen Name: "+credentials.screen_name,root)
}
});
}
else {Helperjs.showMessage(qsTr("Error"), errormessage,root)}
}}
Button {
x: parent.width/2+2*mm; y: mm; width: 5*mm; height: 8*mm;
text: "-"
font.pixelSize: 3*mm
onClicked:{
var userconfig={server: servername.text, username: username.text, password: Qt.btoa(password.text)};
Service.deleteConfig(db,userconfig,function(){
filesystem.Directory=imagestore.text+"contacts";
filesystem.rmDir();
filesystem.Directory=imagestore.text+"albums";
filesystem.rmDir();
servername.text="https://";
servericon.visible=false;
servericon.source="";
username.text="";
password.text="";
imagestore.text="";
//maxNews.value=0;
newsTypeField.text="Conversations";
//messageIntervalSlider.value=30;
userButton.text=qsTr("User");
Helperjs.readData(db,"config","",function(storedUsers){
storedUsers.sort(function(obj1, obj2) {
return obj1.isActive - obj2.isActive;
})
accountPage.users=storedUsers;})
})
}}
Button {
x: parent.width/2+8*mm; y: mm; width: 5*mm; height: 8*mm;
text: "+"
font.pixelSize: 3*mm
onClicked:{
servername.text="https://"
servericon.visible=false;
servericon.source="";
username.text=""
password.text=""
imagestore.text=""
//maxNews.value=0
newsTypeField.text="Conversations"
//messageIntervalSlider.value=30
userButton.text=qsTr("User")
}
}
Button {
x: parent.width/2+14*mm; y: mm; width: 5*mm; height: 8*mm;
text: "?"
font.pixelSize: 3*mm
onClicked:{
root.push("qrc:/qml/configqml/InfoBox.qml");
}
}
Button{
id:closeButton
height: 8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
font.pixelSize: 3*mm
onClicked:{root.pop()}
}
Menu {
id:newstypemenu
MenuItem {
font.pixelSize: 3*mm
text: qsTr("Timeline")
onTriggered: {newsTypeField.text="Timeline"}
}
MenuItem {
font.pixelSize: 3*mm
text: qsTr("Conversations")
onTriggered: {newsTypeField.text="Conversations"}
}
}
Component.onCompleted: {
try{Helperjs.readData(db,"config","",function(storedUsers){
storedUsers.sort(function(obj1, obj2) {
return obj1.isActive - obj2.isActive;
})
accountPage.users=storedUsers;
Service.readConfig(db,function(obj){
userButton.text=obj.username;
servername.text=obj.server;
accountPage.setServericon(obj.server);
username.text= obj.username;
password.text=Qt.atob(obj.password);
imagestore.text=obj.imagestore;
//maxNews.value=obj.maxnews;
newsTypeField.text=obj.newsViewType;
//messageIntervalSlider.value=obj.timerInterval;
if( obj.isActive==0){userButton.font.bold='true'} else {userButton.font.bold='false'}
},"isActive",0)
})
// Service.readGlobaloptions(db,function(go){
// if (root.globaloptions.showWebsiteForLinks!="false"){showwebsiteCheckbox.checked=true}
// })
}
catch (e){print(e)
// Helperjs.friendicaWebRequest("https://dir.friendica.social/servers/surprise",accountPage,function(html){
// print(html);
// var bpos=html.indexOf("base ");
// var baseurl=html.substring(html.indexOf("http",bpos),html.indexOf('"',html.indexOf("http",bpos)));
// servername.text=baseurl
// })
}
}
}

View file

@ -0,0 +1,227 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 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.11
import QtQuick.Dialogs 1.2
import QtQuick.Controls 2.4
import "qrc:/js/service.js" as Service
//import "qrc:/js/layout.js" as Layoutjs
//import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/configqml"
import "qrc:/qml/genericqml"
Page{
//anchors.fill: parent
width:root.width
height:root.height
//contentHeight: configBackground.height
//boundsBehavior: Flickable.StopAtBounds
// Rectangle{
// id:configBackground
// color: "white"
// anchors.fill: parent
// width:parent.width
// height:Math.max(90*mm,root.height-12*mm)
// property var users:[]
// property bool registeredUser: true
// property var userdata: ({})
// Text {
// text: qsTr("Image dir.")
// //text: qsTr("Max. News")
// font.pixelSize:3*mm
// x: 4*mm; y: 10*mm
// }
Text {
text: qsTr("Max. News")
//text: qsTr("News as")
font.pixelSize:3*mm
x: 4*mm; y:10*mm
}
// Text {
// text: qsTr("Show Website")
// x: 4*mm; y: 40*mm; width: 20*mm
// }
// Rectangle{color: "light grey"; x: 4*mm; y: 13.5*mm; width: root.width-14*mm; height: 5*mm;}
// Flickable {
// id: imagestoreFlickable
// x: 4*mm; y: 13.5*mm; width: root.width-14*mm; height: 5*mm;
// clip: true
// TextInput {
// id: imagestore
// width: imagestoreFlickable.width
// height: imagestoreFlickable.height
// font.pixelSize:3*mm
// wrapMode: TextEdit.NoWrap
// onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
// }
// }
// FileDialog {
// id: imagestoreDialog
// title: "Please choose a directory"
// folder: shortcuts.pictures
// selectFolder: true
// onAccepted: {
// var imagestoreString=imagestoreDialog.folder.toString();
// imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
// imagestore.text=imagestoreString
// }
// }
// Button {
// x: root.width-9*mm; y: 13.5*mm; width: 7*mm; height: 8*mm;
// text: "..."
// onClicked:
// {imagestoreDialog.open()}
// }
Slider{ id: maxNews
x:19*mm; y: 13.5*mm;width: root.width/2;height:5*mm
from: 0;to:2000; stepSize: 100
value: root.globaloptions.hasOwnProperty("max_news")?root.globaloptions.max_news:1000
}
Rectangle{color: "light grey"; x: 4*mm; y: 13.5*mm; width: 9*mm; height: 5*mm;
radius: 0.5*mm
TextEdit{id:maxNewsText;
anchors.fill: parent
font.pixelSize:3*mm
verticalAlignment:TextEdit.AlignRight
text:maxNews.value
focus: true
selectByMouse: true
onTextChanged: {
Service.updateglobaloptions(root.db,"max_news",text);
}
}
}
Rectangle{
x: 4*mm; y:23.5*mm; width: parent.width - 14*mm; height: 5*mm;
color:"light grey"
radius: 0.5*mm
Text{
anchors.fill: parent
font.pixelSize:3*mm
text:qsTr("Sync")
}
MouseArea{
anchors.fill:parent
onClicked:root.push("qrc:qml/configqml/SyncConfig.qml");
}
}
// Slider{ id: messageIntervalSlider
// x:22*mm; y: 73.5*mm;width: root.width/2;height:5*mm
// from: 0;to:120; stepSize: 15
// }
// Rectangle{
// x: 4*mm; y: 73.5*mm; width: 9*mm; height: 5*mm;
// TextEdit{
// id: messageIntervalField
// anchors.fill: parent
// font.pixelSize:3*mm
// verticalAlignment:TextEdit.AlignRight
// text:messageIntervalSlider.value
// focus: true
// selectByMouse: true
// }
// }
// Text{x: 14*mm; y: 73.5*mm; width: 5*mm; height: 5*mm;
// font.pixelSize:3*mm
// text:qsTr("Min.")
// }
// CheckBox{
// id:showwebsiteCheckbox
// x:35*mm;y:80*mm
// onClicked:{
// if (checked==true){
// Service.updateglobaloptions(root.db,"showWebsiteForLinks","true")
// root.globaloptions.showWebsiteForLinks="true"
// }
// else {
// Service.updateglobaloptions(root.db,"showWebsiteForLinks","false")
// root.globaloptions.showWebsiteForLinks="false"
// }
// }
// }
MButton {
anchors.right: closeButton.left; anchors.rightMargin: mm;
anchors.top: parent.top
anchors.topMargin: 1*mm
width: 8*mm; height: 6*mm;
text: "?"
font.pixelSize: 3*mm
onClicked:{
root.push("qrc:/qml/configqml/InfoBox.qml");
}
}
MButton{
id:closeButton
height: 6*mm
width :8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
font.pixelSize: 3*mm
onClicked:{root.pop()}
}
// Menu {
// id:newstypemenu
// MenuItem {
// text: qsTr("Timeline")
// onTriggered: {newsTypeField.text="Timeline"}
// }
// MenuItem {
// text: qsTr("Conversations")
// onTriggered: {newsTypeField.text="Conversations"}
// }
// }
// Component.onCompleted: {
// Service.readGlobaloptions(db,function(go){
// if(go.hasOwnProperty("max_news")){maxNews.value=go.max_news}else{maxNews.value=1000}
// //if (root.globaloptions.showWebsiteForLinks!="false"){showwebsiteCheckbox.checked=true}
// })
// }
}

View file

@ -30,7 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls 2.4
import "qrc:/qml/genericqml"
Rectangle{
@ -41,11 +41,12 @@ Rectangle{
anchors.top:closeButton.bottom
anchors.topMargin: mm
textFormat: Text.RichText
width: parent.width
width: root.width-mm
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: "<b>Friendiqa v0.4 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
text: "<b>Friendiqa v0.5 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
"Profile <a href='https://freunde.ma-nic.de/profile/friendiqa'>https://freunde.ma-nic.de/profile/friendiqa</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>"+
"Most of C++ code by <a href='https://kirgroup.com/profile/fabrixxm'>Fabio</a><br>"+
"QML and Javascript code by <a href='https://freunde.ma-nic.de/profile/marco'>Marco</a><br>"+
"Qt Framework <a href='https://www.qt.io'>www.qt.io</a><br>"+
@ -56,13 +57,16 @@ Rectangle{
onLinkActivated:{
Qt.openUrlExternally(link)}
}
BlueButton{
Button{
id:closeButton
height: 6*mm
width: 8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
onClicked:{configStack.pop()}
font.pixelSize: 3*mm
onClicked:{root.pop()}
}
}

View file

@ -34,7 +34,7 @@ QtObject{
property real appWidth: 500
property real appHeight: 500
property int backKey: Qt.Key_Escape
property string osType: "Android"
property string osType: "Linux"
//property string attachImageDir:filesystem.homePath+"/Pictures/"
property string imagePickQml: "ImagePickerLinux"
}

View file

@ -30,6 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.9
import QtQuick.Controls 2.5
import QtWebView 1.1
import "qrc:/qml/genericqml"
@ -45,17 +46,21 @@ Rectangle{
width:parent.width
y:7*mm
MouseArea {anchors.fill:parent;
onClicked:{print(url)}
onClicked:{
//print(url)
}
onLoadingChanged: print(loadProgress)
}
BlueButton{
//onLoadingChanged: print(loadProgress)
}
Button{
id:closeButton
height:8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
font.pixelSize: 3*mm
onClicked:{configStack.pop()}
}
}

View file

@ -0,0 +1,87 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 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.11
import QtQuick.Controls 2.4
import "qrc:/qml/configqml"
import "qrc:/js/service.js" as Service
Rectangle{
color: "#EEEEEE" //Material.Grey
property string adapter: ""
width: parent.width
height: 12*mm
Label{
x: mm
y: 0.5*mm
font.pixelSize:3*mm
text: qsTr(adapter)
}
CheckBox{
id: syncCheckbox
x: mm
y: 5*mm
width:20*mm
checked:(globaloptions["sync_"+adapter]==1)?true:false
//style: CheckBoxStyle {
text: qsTr("sync")
font.pixelSize:3*mm
onClicked: {
toggle();
if(syncCheckbox.checked==true){
Service.updateglobaloptions(root.db,"sync_"+adapter,0);syncCheckbox.checked=false;
}
else{
Service.updateglobaloptions(root.db,"sync_"+adapter,1);syncCheckbox.checked=true;
}
}
}
CheckBox{
id: notifyCheckbox
x:25*mm
y: 5*mm
width:25*mm
enabled: adapter!="Notifications"
checked:(globaloptions["notify_"+adapter]==1)?true:false
text: qsTr("notify")
font.pixelSize:3*mm
onClicked: {
toggle();
if(notifyCheckbox.checked==true){
Service.updateglobaloptions(root.db,"notify_"+adapter,0);notifyCheckbox.checked=false;
}
else{
Service.updateglobaloptions(root.db,"notify_"+adapter,1);notifyCheckbox.checked=true;
}
}
}
}

View file

@ -0,0 +1,101 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 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.11
import QtQuick.Controls 2.4
import "qrc:/qml/configqml"
import "qrc:/js/service.js" as Service
Rectangle{
color:"white"
width:root.width
height:root.height
Text {
text: qsTr("Sync Interval (0=None)")
font.pixelSize:3*mm
//visible: false
x: 4*mm; y: 10*mm; //width:35*mm;wrapMode: Text.Wrap
}
Slider{ id: messageIntervalSlider
x:22*mm; y: 13.5*mm;width: root.width/2;height:5*mm
value: globaloptions.syncinterval
from: 0;to:120; stepSize: 15
}
Rectangle{
x: 4*mm; y: 13.5*mm; width: 9*mm; height: 5*mm;
TextEdit{
id: messageIntervalField
anchors.fill: parent
font.pixelSize:3*mm
verticalAlignment:TextEdit.AlignRight
text:messageIntervalSlider.value
focus: true
selectByMouse: true
onTextChanged: {
Service.updateglobaloptions(root.db,"syncinterval",text);
if(osSettings.osType=="Android" && text !=0){
alarm.setAlarm(text);
} else if(osSettings.osType=="Linux" && text !=0){
}
}
}
}
Text{x: 14*mm; y: 13.5*mm; width: 5*mm; height: 5*mm;
font.pixelSize:3*mm
text:qsTr("Min.")
}
Column{
y:22*mm
width: parent.width
spacing:mm
//anchors.fill: parent
SyncComponent{adapter:"Timeline"}
SyncComponent{adapter:"Replies"}
SyncComponent{ adapter:"DirectMessages"}
SyncComponent{ adapter:"Notifications"}
}
Button{
id:closeButton
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
height: 6*mm
width: 8*mm
text: "\uf057"
font.pixelSize: 3*mm
onClicked:{root.pop()}
}
}

View file

@ -30,7 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Controls 2.4
import "qrc:/qml/genericqml"
Item {
@ -83,7 +83,8 @@ Item {
MouseArea{
anchors.fill: parent
onClicked:{
root.currentIndex=0;
rootstack.currentIndex=0;
bar.currentIndex=0;
root.contactdetailsSignal(contact)
}
}

View file

@ -30,7 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Controls 2.4
import "qrc:/qml/genericqml"
Item {
@ -78,7 +78,7 @@ Rectangle{
ScrollView{
horizontalScrollBarPolicy:Qt.ScrollBarAlwaysOff
frameVisible: true
//frameVisible: true
id:namelabelflickable
width: root.width-10*mm
height:root.height-50*mm
@ -105,8 +105,10 @@ Rectangle{
x: mm
spacing:4
BlueButton{
MButton{
id:photobutton
height: 6*mm
width: 8*mm
text: "\uf03e" // "Photos"
visible:(contact.network=="dfrn")
onClicked:{
@ -118,8 +120,10 @@ Rectangle{
}
}
BlueButton{
MButton{
id:messagebutton
height: 6*mm
width: 8*mm
text: "\uf0e6" //"Messages"
onClicked:{
root.currentIndex=0;
@ -129,23 +133,26 @@ Rectangle{
}
}
BlueButton{
MButton{
id:dmbutton
visible: (contact.following=="true")
height: 6*mm
width: 8*mm
text: "\uf040" //"DM"
onClicked:{
root.currentIndex=0;
//newstab.active=true;
root.directmessageSignal(contact.screen_name);
contactLargeComponent.destroy();
}
}
BlueButton{
Button{
id:eventbutton
visible:(contact.network=="dfrn")
text:"\uf073"
height: 6*mm
width: 8*mm
text:"\uf073" //Events
onClicked:{
root.currentIndex=3;
calendartab.active=true;
@ -155,8 +162,10 @@ Rectangle{
}
}
BlueButton{
Button{
id: closeButton
height: 6*mm
width: 8*mm
text: "\uf057" //"close"
onClicked:{contactLargeComponent.destroy();
}

View file

@ -31,6 +31,7 @@
// List of people
import QtQuick 2.0
import QtQuick.Controls 2.5
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
@ -109,13 +110,15 @@ Rectangle {
}
}
BlueButton {
MButton {
id: closeButton
height:6* mm
width: 8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
color:"white"
//color:"white"
text: "\uf057"
onClicked: {
groupModelAppend(contacts,function(){

View file

@ -29,9 +29,10 @@
// 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.0
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick 2.11
import QtQuick.Controls 2.4
//import QtQuick.Controls.Styles 1.4
import QtQuick.Layouts 1.11
import QtQuick.LocalStorage 2.0
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/news.js" as Newsjs
@ -69,14 +70,37 @@ Rectangle {
callback(profile)
}
TabView{
id:friendsTabView
tabPosition: Qt.TopEdge
x:mm
y:mm
width: root.width-2*mm
height: root.height-10*mm
TabBar {
id: friendsbar
width: parent.width
height: 9*mm
position:TabBar.Header
currentIndex: 1
TabButton {
text: qsTr("Me")
font.pixelSize: 2*mm
}
TabButton {
text: qsTr("Friends")
font.pixelSize: 2*mm
}
TabButton {
text: qsTr("Contacts")
font.pixelSize: 2*mm
}
TabButton {
text: qsTr("Groups")
font.pixelSize: 2*mm
}
}
StackLayout{
id:friendsTabView
//anchors.fill: parent
x:mm
y:10*mm
width: parent.width-2*mm
height: parent.height-10*mm
currentIndex: friendsbar.currentIndex
signal contactsSignal(var contact)
signal groupsSignal(var username)
onCurrentIndexChanged:{
@ -88,27 +112,28 @@ Rectangle {
}
else if (currentIndex==3){groupsSignal(root.login.username)}
}
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {
color: "white"
implicitWidth: root.width/4-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
}
// style: TabViewStyle {
// frameOverlap: 1
// tab: Rectangle {
// color: "white"
// implicitWidth: root.width/4-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{
Item{
id:profileGridTab
title: qsTr("Me")
Layout.fillWidth:true
Layout.fillHeight: true
Component.onCompleted:{
showProfile(function(profile){
var component = Qt.createComponent("qrc:/qml/contactqml/ProfileComponent.qml");
@ -117,11 +142,11 @@ Rectangle {
}
}
Tab{
title: qsTr("Friends")
Rectangle{
Item{
id: friendsGridTab
property int currentContact:0
Layout.fillWidth:true
Layout.fillHeight: true
property int currentContact: 0
function showFriends(contact){
try {friendsModel.clear()} catch(e){print(e)};
Helperjs.readData(root.db,"contacts",login.username,function(friendsobject){
@ -140,17 +165,21 @@ Rectangle {
onDownloaded:{
if(type=="contactlist"){
//print(url+" "+filename+" "+i)
currentContact=i+1;
if(currentContact==root.newContacts.length){showFriends(root.login.username)}
friendsGridTab.currentContact=i+1;
if(friendsGridTab.currentContact==root.newContacts.length){
friendsGridTab.showFriends(root.login.username)
}
}
}
BlueButton {
}
MButton {
id: updateFriendsButton
text: "\uf021"
anchors.top: parent.top
anchors.topMargin: mm
anchors.right: parent.right
height: 6*mm
width: 8*mm
onClicked: {
try {friendsModel.clear()} catch(e){print(e)};
//root.contactLoadType="friends";
@ -167,8 +196,8 @@ Rectangle {
anchors.top: parent.top
anchors.right:updateFriendsButton.left
anchors.rightMargin:mm
visible: (currentContact!=(root.newContacts.length))?true:false
value: currentContact/root.newContacts.length
visible: (friendsGridTab.currentContact!=(root.newContacts.length))?true:false
value: friendsGridTab.currentContact/root.newContacts.length
}
//GridView {
@ -196,13 +225,11 @@ Rectangle {
root.newContacts=[]
}
}
}
Tab{
title: qsTr("Contacts")
Rectangle{
Item{
id: contactsGridTab
Layout.fillWidth:true
Layout.fillHeight: true
function showContacts(contact){
try {contactsModel.clear()} catch(e){print(e)};
Helperjs.readData(db, "contacts",root.login.username,function(contactsobject){
@ -213,12 +240,14 @@ Rectangle {
}
},"isFriend",0,"screen_name ASC");
}
BlueButton {
MButton {
id: cleanButton
text: "\uf021"
anchors.top: parent.top
anchors.topMargin: mm
anchors.right: parent.right
height: 6*mm
width: 8*mm
onClicked: {
Service.cleanContacts(root.login,root.db,function(){
try {contactsModel.clear()} catch(e){print(e)};
@ -252,11 +281,13 @@ Rectangle {
friendsTabView.contactsSignal.connect(showContacts);
}
}
}
Tab{
title: qsTr("Groups")
Rectangle{
Item{
id: groupsGridTab
Layout.fillWidth:true
Layout.fillHeight: true
function showGroups(username){
try {groupsModel.clear()} catch(e){print(e)};
Helperjs.readData(db, "groups",root.login.username,function(groupsobject){
@ -289,16 +320,18 @@ Rectangle {
showGroups(root.login.username)});
}
}
BlueButton {
MButton {
id: updateGroupsButton
text: "\uf021"
anchors.top: parent.top
anchors.topMargin: mm
anchors.right: parent.right
anchors.rightMargin: mm
height: 6*mm
width: 8*mm
onClicked: {
Newsjs.requestGroups(root.login,root.db,root,function(){
showGroups(root.login.username)})}
groupsGridTab.showGroups(root.login.username)})}
}
// BlueButton {
// id: newGroupButton
@ -351,9 +384,9 @@ Rectangle {
friendsTabView.groupsSignal.connect(showGroups);
}
}
}
}
}
Component.onCompleted: {
root.contactdetailsSignal.connect(showContactdetails);
//root.contactdetailsSignal.connect(showContactdetails);
}
}

View file

@ -29,7 +29,8 @@
// 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.0
import QtQuick 2.11
import QtQuick.Controls 2.4
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/news.js" as Newsjs
import "qrc:/qml/genericqml"
@ -76,15 +77,34 @@ Item {
}
}
BlueButton{
MButton{
id: closeButton
visible: false
width: 8*mm
height: 6*mm
anchors.left: infobutton.right
anchors.margins: mm
anchors.top: parent.top
text: "\uf057"
font.pixelSize: 3*mm
onClicked:{groupComponent.state="";
if (group.new){groupsModel.remove(index)}
}
}
MButton{
id:infobutton
width: 5*mm
height: 5*mm
color:"transparent"
width: 4*mm
height: 6*mm
//color:"transparent"
text:"?"
font.pixelSize: 3*mm
anchors.left: photoImage.right
anchors.leftMargin: 3
anchors.topMargin: 3
anchors.leftMargin: mm
anchors.topMargin: mm
anchors.top: parent.top
onClicked:{
//if(group.new){
@ -109,7 +129,7 @@ Item {
Rectangle{
id: detailsrectangle
anchors.top: namelabelRect.bottom
anchors.topMargin: 2*mm
anchors.topMargin: mm
opacity: 0
Component {
@ -165,7 +185,7 @@ Item {
x:1
//anchors.top: parent.top
width: root.width-10*mm
height:groupsView.height -31*mm
height:groupsView.height - 24*mm
clip: true
spacing: 2
model: groupModel
@ -178,12 +198,7 @@ Item {
anchors.top: groupListView.bottom
anchors.topMargin: mm
spacing: mm
BlueButton{
id: closeButton
text: "\uf057"
onClicked:{groupComponent.state="";
if (group.new){groupsModel.remove(index)}
}
}
// BlueButton{
@ -232,7 +247,7 @@ Item {
// groupsModel.remove(index)})
// }
// }
}
}
Component.onCompleted:{if(group.new){groupComponent.state="large"}}
}
@ -242,11 +257,13 @@ Item {
name: "large"
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:groupsView.width; readOnly:false}
PropertyChanges { target: namelabelRect; height: 4.5*mm}
PropertyChanges { target: closeButton; visible: true}
PropertyChanges { target: groupComponent; z: 2 }
PropertyChanges { target: wrapper; width:groupsView.width;height:groupsView.height -2*mm-1}
PropertyChanges { target: photoImage; width:15*mm;height:15*mm }
PropertyChanges { target:groupComponent.GridView.view ;contentY:groupComponent.y;contentX:groupComponent.x;interactive:false}
PropertyChanges { target: detailsrectangle; opacity:1 }
PropertyChanges { target: infobutton; visible: false}
}
]
}

View file

@ -30,13 +30,14 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Controls 2.4
import "qrc:/qml/genericqml"
import "qrc:/js/service.js" as Service
Rectangle {
width:root.width-2*mm
height:root.height-14*mm
// width:parent.width-2*mm
// height:parent.height-14*mm
anchors.fill:parent
color:"white"
property var profile:({})
property var attachImageURLs:[]
@ -102,12 +103,15 @@ Rectangle {
callback(profiletext)
}
BlueButton {
MButton {
id: update
height: 6*mm
width: 8*mm
anchors.top: parent.top
anchors.topMargin: mm
anchors.right: parent.right
text: "\uf021"
font.pixelSize: 3*mm
onClicked: {
Service.requestProfile(root.login,root.db,root,function(nc){
root.newContacts=nc;
@ -132,8 +136,9 @@ Rectangle {
Image {
id: photoImage
x:mm
y:mm
anchors.top: parent.top
anchors.topMargin: mm
anchors.left: parent.left
width: 15*mm
height:15*mm
source: "file://"+profile.friendica_owner.profile_image
@ -170,11 +175,13 @@ Rectangle {
font.pixelSize: 4*mm
}
BlueButton{
MButton{
id:updatebutton
height: 5*mm
height: 6*mm
width:8*mm
visible: "file://"+profile.friendica_owner.profile_image!= photoImage.source
text:qsTr("Update")
font.pixelSize: 3*mm
anchors.left: photoImage.right
anchors.leftMargin: 0.5*mm
anchors.topMargin: mm
@ -184,7 +191,7 @@ Rectangle {
Label {
id: namelabel
x: mm
width: root.width-6*mm
width: parent.width-6*mm
height: 3*mm
text:(Qt.atob(profile.friendica_owner.name))+" (@"+profile.friendica_owner.screen_name+")"
elide:Text.ElideRight
@ -230,7 +237,7 @@ Rectangle {
font.pixelSize: 3*mm
textFormat:Text.RichText
wrapMode: Text.Wrap
text:"<b>"+qsTr("Description")+": </b> "+(profile.friendica_owner.description)+"<br> <b>"+qsTr("Location")+":</b> "+profile.friendica_owner.location+"<br> <b>"+qsTr("Posts")+":</b> "+profile.friendica_owner.statuses_count+
text:"<b>"+qsTr("Description")+": </b> "+(Qt.atob(profile.friendica_owner.description))+"<br> <b>"+qsTr("Location")+":</b> "+profile.friendica_owner.location+"<br> <b>"+qsTr("Posts")+":</b> "+profile.friendica_owner.statuses_count+
"<br> <b>"+qsTr("URL")+":</b> <a href='"+ profile.friendica_owner.url+"'>"+profile.friendica_owner.url+"</a><br>"+
"<b>"+qsTr("Created at")+":</b> "+createdAtDate.toLocaleString(Qt.locale())
onLinkActivated: {
@ -238,32 +245,32 @@ Rectangle {
}
}
Rectangle{
id: detailsrectangle
anchors.top: namelabel.bottom
anchors.topMargin: 2*mm
// Rectangle{
// id: detailsrectangle
ScrollView{
horizontalScrollBarPolicy:Qt.ScrollBarAlwaysOff
frameVisible: true
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
id:namelabelflickable
width: root.width-10*mm
height:root.height-36*mm//friendsTabView.height-45*mm
anchors.top: namelabel.bottom
anchors.topMargin: 2*mm
width: parent.width-mm
height:parent.height-22*mm//friendsTabView.height-45*mm
x: mm
clip:true
ListView {
id: profileView
header:textcomponent
width:root.width-10*mm
height: root.height
clip: true
// width:parent.width
// height: root.height
// clip: true
spacing: 0
model: profileModel
delegate: profileItem
}
}
}
// }
Component.onCompleted: {
profile.profiles.sort(function(obj1, obj2) {

View file

@ -32,37 +32,27 @@
import QtQuick 2.5
import QtQuick.LocalStorage 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
//import QtQuick.Controls 2.3
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/service.js" as Service
import "qrc:/qml/genericqml"
import "qrc:/qml/newsqml"
import "qrc:/qml/contactqml"
import "qrc:/qml/photoqml"
import "qrc:/qml/calendarqml"
import "qrc:/qml/configqml"
TabView{
StackView{
id:root
property QtObject osSettings: {var tmp=Qt.createComponent("qrc:/qml/configqml/OSSettingsAndroid.qml");return tmp.createObject(root)}
//IntentReceiver{}
tabPosition: Qt.BottomEdge
width: osSettings.appWidth
height:osSettings.appHeight
focus:true
property var db: ["Friendiqa", "1.0", "Stores Friendica data", 100000000]
property var login: Service.readActiveConfig(db)
property var globaloptions: ({}) //Service.readGlobaloptions(db)
property var contactlist: []
property real mm: Screen.pixelDensity
property real mm: osSettings.osType=="Android"?Screen.pixelDensity:Screen.pixelDensity*1.5
signal messageSignal(var friend)
signal fotoSignal(var username, var friend)
signal directmessageSignal(var friend)
signal newsSignal(var news)
signal newstypeSignal(var type)
signal friendsSignal(var username)
signal contactdetailsSignal(var contact)
signal eventSignal(var contact)
@ -75,8 +65,8 @@ TabView{
property bool imagePicking: false
onLoginChanged:{
if(login==""){root.currentIndex=4}
else{
if(login==""){root.push("qrc:/qml/configqml/AccountPage.qml")}
else{root.push(rootStackItem)
newstab.newstabstatus=login.newsViewType;
Newsjs.getCurrentContacts(login,db,function(contacts){
contactlist=contacts})}
@ -121,7 +111,7 @@ TabView{
newstab.active=true;
if (newstab.newstabstatus!=login.newsViewType){
newstab.newstabstatus=login.newsViewType;
if(login.newsViewType=="Timeline"){Newsjs.newsfromdb(db,login.username,function(dbnews){
if(login.newsViewType=="Timeline"){Newsjs.newsfromdb(db,login.username,0,function(dbnews){
newsSignal(dbnews)
})}
else{
@ -140,64 +130,273 @@ TabView{
event.accepted = true
}}
Drawer{
id: leftDrawer
width: 0.66* root.width
height: root.height
edge: Qt.LeftEdge
position: 1.0
Column{
x:mm
width:parent.width-mm
Label{
text: login.hasOwnProperty("username")?login.username:""
font.pixelSize: 4*mm
width: parent.width
height: 6*mm
}
// Label{
// text:login.hasOwnProperty("server")?"@"+login.server:""
// font.pixelSize: 5*mm
// width: parent.width
// }
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {
color: styleData.selected?"sky blue":"light blue"
//border.color: "light grey"
implicitWidth: root.width/5
implicitHeight: 5*mm
Text { id: text
anchors.centerIn: parent
text: styleData.title
color: "black"
font.family: fontAwesome.name
Label{
text: "\uf021 " + qsTr("Refresh")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked:{
leftDrawer.close();
newstypeSignal("refresh")
// updatenews.setDatabase();
// updatenews.login();
// updatenews.startsync();
}
}
}
Label{
text: "\uf1da " + qsTr("Timeline")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked:{
leftDrawer.close();
newstypeSignal("timeline")
}
}
}
Label{
text: "\uf086 " + qsTr("Conversations")
width: parent.width
font.pixelSize: 4*mm
MouseArea{
anchors.fill: parent
onClicked:{
leftDrawer.close();
newstypeSignal("conversation")
}
}
}
Label{
text: "\uf005 " + qsTr("Favorites")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked:{
leftDrawer.close();
newstypeSignal("favorites")
}
}
}
Label{
text: "\uf0ec " + qsTr("Replies")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked:{
leftDrawer.close();
newstypeSignal("replies")
}
}
}
Label{
text: "\uf0ac " + qsTr("Public Timeline")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked:{
leftDrawer.close();
newstypeSignal("publictimeline")
}
}
}
Label{
text: "\uf0c0 " + qsTr("Group news")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked:{
leftDrawer.close();
newstypeSignal("groupnews")
}
}
}
Label{
text: "\uf002 " + qsTr("Search")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked:{
leftDrawer.close();
newstypeSignal("search")
}
}
}
Label{
text: "\uf085 "+ qsTr("Settings")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked: {root.push("qrc:qml/configqml/ConfigPage.qml");
leftDrawer.close()
}
}
}
Label{
text: "\uf2bb " + qsTr("Accounts")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked: {root.push("qrc:qml/configqml/AccountPage.qml");
leftDrawer.close()
}
}
}
Label{
text: "\uf08b " +qsTr("Quit")
font.pixelSize: 4*mm
width: parent.width
MouseArea{
anchors.fill: parent
onClicked:{
Service.cleanNews(root.db,function(){
Service.cleanContacts(root.login,root.db,function(){
Qt.quit()})
})
}
}
}
}
}
Item{
id:rootStackItem
//anchors.fill:parent
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
}
}
TabBar {
id: bar
width: parent.width
height: 7*mm
position:TabBar.Footer
anchors.top: rootstack.bottom
onCurrentIndexChanged: rootstack.currentIndex=bar.currentIndex
TabButton {
text: "\uf03a"
font.pixelSize: 3*mm
height: 6*mm
}
TabButton {
text: "\uf0c0"
font.pixelSize: 3*mm
height: 6*mm
}
frame: Rectangle { color: "light grey" }
tabsAlignment:Qt.AlignHCenter
TabButton {
text: "\uf03e"
font.pixelSize: 3*mm
height: 6*mm
}
Tab{
title: "\uf03a"
TabButton {
text: "\uf073"
font.pixelSize: 3*mm
height: 6*mm
}
}
StackLayout{
id:rootstack
width:parent.width
height: parent.height-7*mm
currentIndex:bar.currentIndex
Loader{
id: newstab
Layout.fillWidth:true
Layout.fillHeight: true
property string newstabstatus
property var conversation:[]
property var contactposts:[]
source:(root.currentIndex==0)? "qrc:/qml/newsqml/NewsTab.qml":""
source:(rootstack.currentIndex==0)? "qrc:/qml/newsqml/NewsTab.qml":""
}
Tab{
title: "\uf0c0"
Loader{
id: friendstab
source: (root.currentIndex==1)?"qrc:/qml/contactqml/FriendsTab.qml":""
Layout.fillWidth:true
Layout.fillHeight: true
source: (rootstack.currentIndex==1)?"qrc:/qml/contactqml/FriendsTab.qml":""
}
Tab{
title: "\uf03e"
Loader{
id: fotostab
property string phototabstatus:"Images"
source: (root.currentIndex==2)?"qrc:/qml/photoqml/PhotoTab.qml":""
Layout.fillWidth:true
Layout.fillHeight: true
source: (rootstack.currentIndex==2)?"qrc:/qml/photoqml/PhotoTab.qml":""
}
Tab{
title: "\uf073"
Loader{
id: calendartab
property string calendartabstatus:"Events"
source: (root.currentIndex==3)?"qrc:/qml/calendarqml/CalendarTab.qml":""
Layout.fillWidth:true
Layout.fillHeight: true
source: (rootstack.currentIndex==3)?"qrc:/qml/calendarqml/CalendarTab.qml":""
}
Tab{
title:"\uf085"
id: configtab
source: (root.currentIndex==4)?"qrc:/qml/configqml/ConfigTab.qml":""
}
Component.onCompleted: {
Service.readGlobaloptions(db,function(go){globaloptions=go})
//print(xhr.networktype);
//print(xhr.networktype());
if(osSettings.osType=="Android"){
var component = Qt.createComponent("qrc:/qml/genericqml/IntentReceiver.qml");
var IntentReceiverQml = component.createObject(root);
} else if (osSettings.osType=="Linux"){
var component = Qt.createComponent("qrc:/qml/genericqml/LinuxSync.qml");
var LinuxSyncQml = component.createObject(root);
}
}
}
}

View file

@ -64,7 +64,7 @@ Rectangle{
states: [
State { name: "Pressed"
PropertyChanges { target: blueButton; color: "sky blue"} }
PropertyChanges { target: blueButton; color: "white"} }
]
transitions: [
Transition { to:"*"

View file

@ -38,7 +38,7 @@ Item {
Connections {
target: SystemDispatcher
onDispatched: {
if (type === m_CHOSEN_MESSAGE) {
if ((type === m_CHOSEN_MESSAGE) && (root.imagePicking==true)) {
var h=[];
for (var n in message.imageUrls){
h.push("file://"+ decodeURIComponent(message.imageUrls[n]).substring(5))

View file

@ -30,7 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls 2.4
import Qt.labs.folderlistmodel 2.1
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
@ -60,8 +60,9 @@ Rectangle{
wrapMode: Text.Wrap
text: directory
}
BlueButton{
Button{
id:closeButton
height: 8*mm
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right: parent.right

View file

@ -23,14 +23,14 @@ Item {
}
imageUrls=h;
if(imageUrls.length==1){
root.currentIndex=0;newstab.active=true;
rootstack.currentIndex=0;newstab.active=true;
root.uploadSignal(imageUrls)
} else{
root.currentIndex=2;fotostab.active=true;
rootstack.currentIndex=2;fotostab.active=true;
root.uploadSignal(imageUrls)
}
} else if (type==m_TEXT_MESSAGE){
root.currentIndex=0;newstab.active=true;
rootstack.currentIndex=0;newstab.active=true;
root.sendtextSignal(message)
}
}
@ -38,9 +38,8 @@ Item {
Component.onCompleted: {
SystemDispatcher.setInitialized();
print("timer " + login.timerInterval)
if (login.timerInterval !=0){
alarm.setAlarm(login.timerInterval);
if (root.globaloptions.hasOwnProperty("syncinterval") && root.globaloptions.syncinterval !=null && root.globaloptions.syncinterval !=0){
alarm.setAlarm(root.globaloptions.syncinterval);
}
}
}

View file

@ -0,0 +1,22 @@
import QtQuick 2.4
Item {
Timer{
id:syncTimer
repeat: true
onTriggered: {
updatenews.setDatabase();
updatenews.login();
updatenews.startsync();
}
}
Component.onCompleted: {
if (root.globaloptions.hasOwnProperty("syncinterval") && root.globaloptions.syncinterval !=null && root.globaloptions.syncinterval !=0){
syncTimer.interval=root.globaloptions.syncinterval*60000;
syncTimer.start()
}
}
}

View file

@ -0,0 +1,39 @@
// This file is part of Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 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.Controls 2.4
Button{
id: mButton
width: Math.max(text.width+2*mm,8*mm)
height: 6*mm
//color: Material.grey
font.pixelSize: 3*mm
}

View file

@ -29,7 +29,7 @@
// 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.0
import QtQuick 2.11
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
@ -178,7 +178,7 @@ Rectangle{
else {groupstatus="neutral"} }
}
}
BlueButton{
MButton{
x:0.5*mm
anchors.bottom: parent.bottom
anchors.bottomMargin:1
@ -190,7 +190,7 @@ Rectangle{
Service.savePermissions(db,perms)
}
}
BlueButton{
MButton{
x:contactView.width+2*mm
anchors.bottom: parent.bottom
anchors.bottomMargin:1

View file

@ -54,7 +54,7 @@ Rectangle {
anchors.top:parent.top
anchors.topMargin: 0.5*mm
width:parent.width-2*mm
height: 7*mm //Math.max( searchText.contentHeight,5*mm)
height: 4*mm //Math.max( searchText.contentHeight,5*mm)
TextInput {
id: searchText

View file

@ -31,7 +31,7 @@
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls 2.4
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
@ -43,7 +43,7 @@ Rectangle {
ListView {
id: contactView
x:mm
y:8*mm
y:9*mm
width: contactList.width-4*mm
height:contactList.height-10*mm
clip: true
@ -90,35 +90,48 @@ Rectangle {
y: mm
spacing:4
BlueButton{
MButton{
id:photobutton
height: 6*mm
width: 8*mm
text: "\uf03e" // "Photos"
//font.pixelSize: 3*mm
visible:(contact.network=="dfrn")
onClicked:{print(createdAtDate + " contact.created_at"+contact.created_at)
onClicked:{
rootstack.currentIndex=2;
bar.currentIndex=2;
fotostab.phototabstatus="Contact";
currentIndex=2;
fotostab.active=true;
//fotostab.active=true;
fotoSignal(root.login,contact) ;
newsStack.pop();
}
}
BlueButton{
MButton{
id:dmbutton
height: 6*mm
width: 8*mm
visible: (contact.following=="true")
text: "\uf040" //"DM"
//font.pixelSize: 3*mm
onClicked:{
currentIndex=0;
directmessageSignal(contact.screen_name)
rootstack.currentIndex=0;
newsSwipeview.currentIndex=2;
directmessageSignal(contact)
}
}
BlueButton{
MButton{
id:eventbutton
visible:(contact.network=="dfrn")
height: 6*mm
width: 8*mm
text:"\uf073"
//font.pixelSize: 3*mm
onClicked:{
currentIndex=3;
rootstack.currentIndex=3;
bar.currentIndex=3;
calendartab.calendartabstatus="Friend"
eventSignal(contact);
newsStack.pop()
@ -179,14 +192,16 @@ Rectangle {
source: "qrc:/js/newsworker.js"
}
BlueButton {
MButton {
id: closeButton
width:10*mm
height: 6*mm
width: 8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
//font.pixelSize: 3*mm
onClicked: {
newsStack.pop()
}

View file

@ -31,9 +31,10 @@
// ConversationView with button
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls 2.4
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
import "qrc:/qml/newsqml"
Rectangle {
id:conversationList
@ -56,7 +57,7 @@ Rectangle {
height:conversationList.height-10*mm
clip: true
spacing: 0
footer: footerReply
footer: MessageSend{conversation:true}//footerReply
model: conversationModel
delegate: Newsitem{}
}
@ -89,68 +90,70 @@ Rectangle {
}
}
Component { id:footerReply
Rectangle{
border.color: "#EEEEEE"
border.width: 1
color:"lightgrey"
width:conversationView.width
height:Math.max(replyText.contentHeight+2*mm,6*mm)
Rectangle{
color: "white"
radius:0.5*mm
anchors.left: parent.left
anchors.leftMargin:mm
anchors.top:parent.top
anchors.topMargin: 0.5*mm
width:parent.width-12*mm
height:Math.max( replyText.contentHeight,5*mm)
// Component { id:footerReply
// Rectangle{
// border.color: "#EEEEEE"
// border.width: 1
// color:"lightgrey"
// width:conversationView.width
// height:Math.max(replyText.contentHeight+2*mm,6*mm)
// Rectangle{
// color: "white"
// radius:0.5*mm
// anchors.left: parent.left
// anchors.leftMargin:mm
// anchors.top:parent.top
// anchors.topMargin: 0.5*mm
// width:parent.width-12*mm
// height:Math.max( replyText.contentHeight,5*mm)
TextInput {
id: replyText
font.pixelSize: 3*mm
wrapMode: Text.Wrap
anchors.fill: parent
selectByMouse: true
onHeightChanged: conversationView.contentY+=4.5*mm
}
}
// TextInput {
// id: replyText
// font.pixelSize: 3*mm
// wrapMode: Text.Wrap
// anchors.fill: parent
// selectByMouse: true
// onHeightChanged: conversationView.contentY+=4.5*mm
// }
// }
BlueButton {
id: sendButton
text: "\uf1d9"
anchors.right: parent.right
anchors.rightMargin:mm
anchors.top:parent.top
anchors.topMargin: 0.5*mm
color:"white"
onClicked: { try{
var body=replyText.getText(0,replyText.length);
newsBusy.running=true;
replyText.text=""
xhr.clearParams();
xhr.setLogin(login.username+":"+Qt.atob(login.password));
if (conversationModel.get(0).newsitemobject.messagetype==0){
// Button {
// id: sendButton
// height: 8*mm
// width:8*mm
// text: "\uf1d9"
// anchors.right: parent.right
// anchors.rightMargin:mm
// anchors.top:parent.top
// anchors.topMargin: 0.5*mm
// //color:"white"
// onClicked: { try{
// var body=replyText.getText(0,replyText.length);
// newsBusy.running=true;
// replyText.text=""
// xhr.clearParams();
// xhr.setLogin(login.username+":"+Qt.atob(login.password));
// if (conversationModel.get(0).newsitemobject.messagetype==0){
//xhr.url= login.server + "/api/statuses/update.json";
xhr.setUrl(login.server);
xhr.setApi("/api/statuses/update");
xhr.setParam("source", "Friendiqa");
xhr.setParam("status", body);
xhr.setParam("in_reply_to_status_id", conversationModel.get(conversationModel.count-1).newsitemobject.id)}
else {//xhr.url= login.server + "/api/direct_messages/new.json";
xhr.setUrl(login.server);
xhr.setApi("/api/direct_messages/new");
xhr.setParam("text", body);
xhr.setParam("screen_name",conversationModel.get(conversationModel.count-1).newsitemobject.screen_name);
xhr.setParam("replyto", conversationModel.get(conversationModel.count-1).newsitemobject.id)
}
xhr.post();
} catch(e){Helperjs.showMessage("Error",e.toString(),root)}
}
}
}
}
// //xhr.url= login.server + "/api/statuses/update.json";
// xhr.setUrl(login.server);
// xhr.setApi("/api/statuses/update");
// xhr.setParam("source", "Friendiqa");
// xhr.setParam("status", body);
// xhr.setParam("in_reply_to_status_id", conversationModel.get(conversationModel.count-1).newsitemobject.id)}
// else {//xhr.url= login.server + "/api/direct_messages/new.json";
// xhr.setUrl(login.server);
// xhr.setApi("/api/direct_messages/new");
// xhr.setParam("text", body);
// xhr.setParam("screen_name",conversationModel.get(conversationModel.count-1).newsitemobject.screen_name);
// xhr.setParam("replyto", conversationModel.get(conversationModel.count-1).newsitemobject.id)
// }
// xhr.post();
// } catch(e){Helperjs.showMessage("Error",e.toString(),root)}
// }
// }
// }
// }
@ -161,9 +164,10 @@ Rectangle {
source: "qrc:/js/newsworker.js"
}
BlueButton {
MButton {
id: closeButton
width:10*mm
height: 6*mm
width: 8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right

View file

@ -31,24 +31,28 @@
// message.qml
// message with buttons
import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick 2.4
import QtQuick.Controls 2.4
//import QtQuick.Dialogs 1.2
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/smiley.js" as Smileyjs
import "qrc:/js/news.js" as Newsjs
import "qrc:/qml/genericqml"
Rectangle{
color:"white"
// width:root.width-5*mm
// height:root.height-12*mm
//anchors.fill: parent
color:"#EEEEEE"
width:parent.width
height: (newsSwipeview.stacktype!="Notifications")?messageColumn.height+mm:0
id:messageSend
visible:(newsSwipeview.stacktype!="Notifications")?true:false
property string parentId: ""
//property var parentObject:({})
property bool conversation: false
property string reply_to_user:""
property alias bodyMessage: bodyField.text
property var attachImageURLs: [];
property int directmessage: 0;
//property int directmessage: 0;
property var contacts: []
property var groups: []
property var contact_allow:login.permissions[0]
@ -56,7 +60,40 @@ Rectangle{
property var group_allow:login.permissions[2]
property var group_deny:login.permissions[3]
function attachImage(url){ print("attachImage "+url)
onReply_to_userChanged: {
if (reply_to_user!=""){
receiverLabel.visible=true
}
}
function directmessagePrepare(friend){
messageSend.state="active";
reply_to_user=friend.screen_name;
receiverLabel.text=qsTr("to:")+ " "+ friend.screen_name;
}
function sendUrls(urls){
if((urls.length==1 && attachImageURLs.length==0)){
attachImage(urls);
attachImageURLs.push(urls);
messageSend.state="active";
}
}
function sendtext(text){
if(text){
if (text.subject=="undefined"){text.subject=""}
if(text.plaintext.lastIndexOf(".jpg")>-1 || text.plaintext.lastIndexOf(".jpeg")>-1 || text.plaintext.lastIndexOf(".png")>-1 || text.plaintext.lastIndexOf(".gif")>-1){
text.plaintext="<a href="+text.plaintext+"><img src="+text.plaintext+"></a>"}
bodyField.text=text.subject+"\n"+text.plaintext;
messageSend.state="active";
}
}
function attachImage(url){
var imageAttachmentObject=Qt.createQmlObject('import QtQuick 2.0; Image {id:imageAttachment'+attachImageURLs.length+'; source:"'+
url.toString()+'"; x:2*mm; width: 45*mm; height: 45*mm;fillMode: Image.PreserveAspectFit;MouseArea{anchors.fill:parent;onClicked:{attachImageURLs.splice(attachImageURLs.indexOf("'+
url+'"),1); imageAttachment'+attachImageURLs.length+'.destroy()}}}',messageColumn,"attachedImage");
@ -64,6 +101,7 @@ Rectangle{
function statusUpdate(title,status,in_reply_to_status_id,attachImageURL) {
//xhr.url= login.server + "/api/statuses/update.json";
newsBusy.running=true;
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/statuses/update");
@ -81,6 +119,7 @@ Rectangle{
}
function dmUpdate(title,text,replyto,screen_name,attachImageURL) {
newsBusy.running=true;
//xhr.url= login.server + "/api/direct_messages/new.json";
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
@ -93,103 +132,193 @@ Rectangle{
xhr.post();
}
Flickable{
anchors.fill: parent
contentHeight: messageColumn.height
boundsBehavior: Flickable.StopAtBounds
id:messageSend
function setParent(newsitemobject){
//print("Newsobject "+newsitemobject.id+ " "+JSON.stringify(newsitemobject.user));
if (newsitemobject!=""){
messageSend.state="conversation"
reply_to_user=newsitemobject.user.screen_name;
receiverLabel.text=qsTr("to:")+ " "+ newsitemobject.user.screen_name;
parentId=newsitemobject.id
} else {
messageSend.state=""
reply_to_user="";
receiverLabel.text=qsTr("to:");
parentId="";
bodyField.text="";
attachImageURLs.pop();
try{imageAttachment.destroy()}catch(e){}
}
}
function contactmenu(letter){
Newsjs.listFriends(login,db,function(contacts){
var contactitems="";
for (var i=0;i<contacts.length;i++){
if(Helperjs.getCount(db,login,"contacts","screen_name",contacts[i].screen_name)>1){
contacts[i].screen_name=contacts[i].screen_name+"+"+contacts[i].cid
}
contactitems=contactitems+"MenuItem{text:'"+contacts[i].screen_name+
"'; onTriggered:{if (newsSwipeview.stacktype=='DirectMessages'){reply_to_user='"+
contacts[i].screen_name+"'} else {bodyField.insert("+
bodyField.cursorPosition+",' "+contacts[i].screen_name.substring(1)+" ');bodyField.cursorPosition=bodyField.cursorPosition+"+contacts[i].screen_name.length+"}}}"
//}
}
var menuString="import QtQuick.Controls 2.4; Menu {width:40*mm; font.pixelSize: 3*mm; "+contactitems+"}";
var contactlistObject=Qt.createQmlObject(menuString,messageColumn,"contactmenuOutput");
if (contacts.length>0){contactlistObject.popup()}
},letter);
}
// Flickable{
// anchors.fill: parent
// contentHeight: messageColumn.height
// boundsBehavior: Flickable.StopAtBounds
Column {
y:0.5*mm
id:messageColumn
spacing: 0.5*mm
width: parent.width
height: 10*mm//implicitHeight
Label{
id:receiverLabel
x: 0.5*mm
width: parent.width-mm
font.pixelSize: 3*mm
text: newsSwipeview.stacktype=="DirectMessages"?qsTr("to:")+ " "+ reply_to_user:""
visible:false// ((parentId !== "") || (newsStack.parent.stacktype=="DirectMessages"))
MouseArea{
anchors.fill: parent
onClicked:{}
}
}
TextField {
id: titleField
width: parent.width
x: 0.5*mm
width: parent.width-mm
font.pixelSize: 3*mm
placeholderText: qsTr("Title (optional)")
visible: parentId === ""
visible: false//(parentId === "") && (bodyField.length>1)
onVisibleChanged: if ((visible==true)&&(conversation==true)){
conversationView.contentY=conversationView.contentY+titleField.height
}
}
Rectangle{
color: "white"
radius: 0.5*mm
x:mm
width: parent.width-2*mm
height:Math.max(bodyField.contentHeight+2*mm,10*mm)
height:Math.max(bodyField.contentHeight+4*mm,10*mm)
TextArea {
id: bodyField
anchors.fill: parent
font.pixelSize: 3*mm
font.family: "Noto Sans"
wrapMode: Text.Wrap
selectByMouse: true
placeholderText: conversation?"": qsTr("What's on your mind?")
textFormat: TextEdit.RichText //TextEdit.PlainText
onLineCountChanged: (conversation==true)?conversationView.contentY=conversationView.contentY+3*mm:newsView.contentY=newsView.contentY+3*mm
onLinkActivated:{Qt.openUrlExternally(link)}
onActiveFocusChanged:{
if (activeFocus==true){
if (conversation==true){
setParent(conversationModel.get(0).newsitemobject);
messageSend.state="conversation"
} else{
messageSend.state="active"
}
}
}
onTextChanged:{
if (text!=""){
//print(getText(bodyField.cursorPosition-2,bodyField.cursorPosition) +" preedit: "+ preeditText+cursorPosition);
var regex1 = /@[a-z]/;var regex2 = /![a-z]/;
//print(text.substring(cursorPosition-2,cursorPosition));
//if (regex.test(getText(bodyField.cursorPosition-2,bodyField.cursorPosition)) || regex.test(preeditText) || regex.test(text)){
if (regex1.test(getText(bodyField.cursorPosition-2,bodyField.cursorPosition)+preeditText) || regex2.test(getText(bodyField.cursorPosition-2,bodyField.cursorPosition)+preeditText)){
var letter=(getText(bodyField.cursorPosition-2,bodyField.cursorPosition)).match(/[a-z]/);
contactmenu(letter)
}
}}
}
}
// Row{
// spacing: 2
// width: parent.width
// CheckBox{
// id:dmCheckbox
// text:"DM"
// enabled: false
// checked: (directmessage==1)?true:false
// onClicked:{
// if(dmCheckbox.checkedState==Qt.Checked){directmessage=1}
// else if(dmCheckbox.checkedState==Qt.Unchecked){directmessage=0}
// }
// }
// Button{
// text:"\uf0c1"
// height:8*mm
// onClicked: {
// if(bodyField.selectedText==""){Helperjs.showMessage("Error","No text selected",messageSend)}
// else{urlTextEdit.text="";
// urlRectangle.visible=true}}
// }
// }
// Rectangle{
// id:urlRectangle
// height: 7*mm //parent.height
// width:parent.width-2*mm
// visible:false
// TextField{
// id:urlTextEdit
// width:parent.width-7*mm
// height:parent.height
// }
// Button{
// anchors.left:urlTextEdit.right
// anchors.leftMargin:mm
// height:8*mm
// text:"\u2713"
// onClicked: {if(urlTextEdit.text!=""){
// var start = bodyField.selectionStart;
// var text=bodyField.selectedText
// if(text.lastIndexOf(".jpg")>-1 || text.lastIndexOf(".jpeg")>-1 || text.lastIndexOf(".png")>-1){text="<img src="+text+">"}
// text = "[url="+urlTextEdit.text+"]" + text + "[/url]";
// bodyField.remove(start,bodyField.selectionEnd);
// bodyField.insert(start,text);}
// urlRectangle.visible=false}
// }
// }
Row{
spacing: 2
width: parent.width
CheckBox{
id:dmCheckbox
text:"DM"
enabled: false
checked: (directmessage==1)?true:false
onClicked:{
if(dmCheckbox.checkedState==Qt.Checked){directmessage=1}
else if(dmCheckbox.checkedState==Qt.Unchecked){directmessage=0}
}
}
BlueButton{
text:"\uf0c1"
onClicked: {
if(bodyField.selectedText==""){Helperjs.showMessage("Error","No text selected",messageSend)}
else{urlTextEdit.text="";
urlRectangle.visible=true}}
}
}
Rectangle{
id:urlRectangle
height: 7*mm //parent.height
width:parent.width-2*mm
visible:false
TextField{
id:urlTextEdit
width:parent.width-7*mm
height:parent.height
}
BlueButton{
anchors.left:urlTextEdit.right
anchors.leftMargin:mm
text:"\u2713"
onClicked: {if(urlTextEdit.text!=""){
var start = bodyField.selectionStart;
var text=bodyField.selectedText
if(text.lastIndexOf(".jpg")>-1 || text.lastIndexOf(".jpeg")>-1 || text.lastIndexOf(".png")>-1){text="<img src="+text+">"}
text = "[url="+urlTextEdit.text+"]" + text + "[/url]";
bodyField.remove(start,bodyField.selectionEnd);
bodyField.insert(start,text);}
urlRectangle.visible=false}
}
}
Row{
spacing:2
BlueButton{id:permButton
visible: (directmessage==1)?false:true
id:buttonRow
visible:false //(bodyField.length>1)||(attachImageURLs.length>0)
spacing: mm
height: 12*mm
MButton{id:permButton
visible: (newsSwipeview.stacktype!=="DirectMessages")
height: 6*mm
width: 7*mm
text: ((contact_allow.length==0)&&(contact_deny.length==0)&&(group_allow.length==0)&&(group_deny.length==0))?"\uf09c":"\uf023"
onClicked: { permissionDialog.visible=true;}
onClicked: { if (permissionDialog.visible==false){permissionDialog.visible=true} else{permissionDialog.visible=false}}
}
BlueButton {
MButton {
id: attachButton
height: 6*mm
width: 7*mm
text: "\uf03e"
visible:(directmessage==0)
visible:(newsSwipeview.stacktype!="DirectMessages")
onClicked: {
if (attachImageURLs.length>0){//Server currently accepts only one attachment
Helperjs.showMessage( qsTr("Error"),qsTr("Only one attachment supported at the moment.\n Remove other attachment first!"), messageColumn)
}
else{
// root.imagePicking=true;
root.imagePicking=false;
var imagePicker = Qt.createQmlObject('import QtQuick 2.0; import "qrc:/qml/genericqml";'+
osSettings.imagePickQml+'{multiple : false;onReady: {attachImageURLs.push(imageUrl);'+
'attachImage(imageUrl)}}',root,"imagePicker");
@ -197,55 +326,102 @@ Rectangle{
}
}
}
BlueButton{
id:contactButton
text:"\uf234"
visible:(directmessage==0)
onClicked:{
var contactitems="";
for (var i=0;i<contacts.length;i++){
if(contacts[i].network=="dfrn"){
if(Helperjs.getCount(db,login,"contacts","screen_name",contacts[i].screen_name)>1){
contacts[i].screen_name=contacts[i].screen_name+"+"+contacts[i].cid
}
contactitems=contactitems+"MenuItem{text:'"+contacts[i].screen_name+"'; onTriggered: bodyField.insert("+bodyField.cursorPosition+",' @"+contacts[i].screen_name+" ')}"
}}
var menuString="import QtQuick.Controls 1.4; Menu {"+contactitems+"}";
var contactlistObject=Qt.createQmlObject(menuString,messageColumn,"contactmenuOutput")
contactlistObject.popup() }
}
BlueButton{
MButton{
id:smileyButton
text: "\uf118"
onClicked: {smileyDialog.visible=true}
height: 6*mm
width: 7*mm
onClicked: {if (smileyDialog.visible==false){smileyDialog.visible=true} else{smileyDialog.visible=false}}
}
BlueButton {
MButton {
id: cancelButton
height: 6*mm
width: 7*mm
text: "\uf057"
onClicked: {
newstab.newstabstatus=login.newsViewType;
newsStack.pop(null)
bodyField.text="";
messageSend.state="";
permissionDialog.visible=false;
receiverLabel.visible=false;
reply_to_user="";
attachImage("");
attachImageURLs.pop();
}
}
BlueButton {
MButton {
id: sendButton
height: 6*mm
width: 7*mm
text: "\uf1d9"
onClicked: {
var title=titleField.text.replace("\"","\'");
var body=bodyField.getFormattedText(0,bodyField.length);
var dmbody=bodyField.getText(0,bodyField.length);
if (directmessage==0){
if (newsSwipeview.stacktype!=="DirectMessages"){
statusUpdate(title,body,parentId,attachImageURLs)}
else {dmUpdate(title,dmbody,parentId,reply_to_user) }
else {
if (reply_to_user!=""){dmUpdate(title,dmbody,parentId,reply_to_user)}
else{Helperjs.showMessage(qsTr("Error"),qsTr("No receiver supplied!"),root)}
}
if (conversation==true){
newstab.newstabstatus=login.newsViewType; newsStack.pop(null)
}
}
}
}
PermissionDialog{id:permissionDialog;x:mm;visible: false}
SmileyDialog{id:smileyDialog;x:mm;visible: false}
}
Component.onCompleted: if(attachImageURLs.length>0){attachImage(attachImageURLs[0])}
}
Component.onCompleted:{
//
//parentId=conversationModel.get(conversationModel.count-1).newsitemobject.id
//if(attachImageURLs.length>0){attachImage(attachImageURLs[0])}
newsStack.replySignal.connect(setParent);
root.directmessageSignal.connect(directmessagePrepare);
root.uploadSignal.connect(sendUrls);
root.sendtextSignal.connect(sendtext);
}
states: [ State {
name: "active"
PropertyChanges {
target: messageColumn; height: implicitHeight
}
PropertyChanges {
target: buttonRow; visible:true
}
PropertyChanges {
target: titleField; visible:(newsSwipeview.stacktype!="DirectMessages")//true
}
PropertyChanges {
target: receiverLabel; visible:(newsSwipeview.stacktype=="DirectMessages");
}
},
State {
name: "conversation"
PropertyChanges {
target: messageColumn; height: implicitHeight
}
PropertyChanges {
target: buttonRow; visible:true
}
PropertyChanges {
target: titleField; visible:(newsSwipeview.stacktype!="DirectMessages")
}
// PropertyChanges {
// target: receiverLabel; visible:true; text:qsTr("to")+": "+ conversationModel.get(0).newsitemobject.user.name
// }
// PropertyChanges {
// target: messageSend; reply_to_user: conversationModel.get(0).newsitemobject.user.screen_name
// }
// PropertyChanges {
// target: messageSend; parentId: conversationModel.get(0).newsitemobject.status_id
// }
} ]
}
//}

View file

@ -0,0 +1,579 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 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.11
import QtQuick.Controls 2.4
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/service.js" as Service
StackView{
id: newsStack
anchors.fill: parent
property string updateMethodNews: "refresh"
property var allchats: ({})
signal replySignal(var newsobject)
property int lastnewsid:0
function newstypeHandling(newstype){
newsBusy.running=true;
replySignal("");
//messagesend.state="";
newsModel.clear();
switch(newstype){
case "timeline":
newstab.newstabstatus="Timeline";
try{ Newsjs.newsfromdb(root.db,root.login,0, function(dbnews,lastid){
lastnewsid=lastid;
showNews(dbnews)
})}catch(e){Helperjs.showMessage("Error",e,root)};
break;
case "conversation":
newstab.newstabstatus="Conversations";
Newsjs.chatsfromdb(root.db,root.login,0,function(news,lastid){
lastnewsid=lastid;
showNews(news)});
break;
case "favorites":
newsStack.updateMethodNews="refresh";
newstab.newstabstatus="Favorites";
Service.updateView("Favorites");
break;
case "replies":
newsStack.updateMethodNews="refresh";
newstab.newstabstatus="Replies";
Service.updateView("Replies");
break;
case "publictimeline":
newsStack.updateMethodNews="refresh";
newstab.newstabstatus="Public Timeline";
Service.updateView("Public Timeline");
break;
case "groupnews":
newsStack.updateMethodNews="refresh";
Service.showGroups();
break;
case "search":
newsView.anchors.topMargin=7*mm;
newsBusy.running=false;
var component = Qt.createComponent("qrc:/qml/genericqml/Search.qml");
var searchItem = component.createObject(newsStack,{y:mm,width:root.width,height: 5*mm});
break;
case "refresh":
if (newstab.newstabstatus=="Timeline"){
newsStack.updateMethodNews="append"
} else {newsStack.updateMethodNews="refresh"}
//root.contactLoadType="news";
if (newsSwipeview.stacktype=="Home"){
Service.updateView(newstab.newstabstatus)
}
else if (newsSwipeview.stacktype=="DirectMessage"){
Service.updateView("Direct Messages")
}
else if (newsSwipeview.stacktype=="Notifications"){
Service.updateView("Notifications")
}
break;
default:
if (newstab.newstabstatus=="Timeline"){
newsStack.updateMethodNews="append"
} else {newsStack.updateMethodNews="refresh"}
//root.contactLoadType="news";
if (newsSwipeview.stacktype=="Home"){
Service.updateView(newstab.newstabstatus)
}
else if (newsSwipeview.stacktype=="Directmessage"){
Service.updateView("Direct Messages")
}
else if (newsSwipeview.stacktype=="Notifications"){
Service.updateView("Notifications")
}
}
}
function showNews(newsToShow){
try{
if (newsStack.depth>1){newsStack.pop()}
}catch(e){}
newsBusy.running=false;
var currentTime= new Date();
// downloadNotice.text=downloadNotice.text + "\n shownews start "+ Date.now();
//print("appendnews "+JSON.stringify(newsToShow))
var msg = {'currentTime': currentTime, 'model': newsModel,'news':newsToShow,'method':newsStack.updateMethodNews, 'options':globaloptions};
newsWorker.sendMessage(msg);
//newsStack.appendNews=false
}
function showContact(contact){ //print(JSON.stringify(contact));
//newstab.newstabstatus="Contact";
newsStack.push("qrc:/qml/newsqml/ContactPage.qml",{"contact": contact});
}
function search(term){//print("Search "+term)
if (term!=""){
newstab.newstabstatus="Search";
newsBusy.running=true;
newsStack.updateMethodNews="refresh";
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/search");
xhr.clearParams();
xhr.setParam("q",term)
xhr.get();}
newsView.anchors.topMargin=mm
}
Connections{
target:xhr
onError:{
Helperjs.showMessage(qsTr("Network Error"),"API:\n" +login.server+api+"\n Return: \n"+data,root);
}
onSuccess:{
// downloadNotice.text=downloadNotice.text+ "\n xhr finished "+Date.now();
Service.processNews(api,data);
}
}
Timer {id:replytimer; interval: 1000; running: false; repeat: false
onTriggered: {
newsBusy.running=true;
if(newstab.newstabstatus=="Conversation"){
showConversation(newsStack.timelineIndex-1,newsModel.get(0).newsitemobject)}
else{
if (newstab.newstabstatus=="Timeline"){
newsStack.updateMethodNews="append"
} else {newsStack.updateMethodNews="refresh"}
if (newsSwipeview.stacktype=="Home"){
Service.updateView(newstab.newstabstatus)
}
else if (newsSwipeview.stacktype=="DirectMessages"){
Service.updateView("Direct Messages")
}
else if (newsSwipeview.stacktype=="Replies"){
Service.updateView("Replies")
}
replySignal("")
//Service.updateView(newstab.newstabstatus)
}
}
}
initialItem: Rectangle {
id:newslistRectangle
y:1
color: "white"
// Button{
// id:newstabstatusButton
// anchors.top: parent.top
// anchors.topMargin: 0.5*mm
// height: 8*mm
// text: qsTr(newstab.newstabstatus)
// visible: newsStack.parent.stacktype=="standard"
// onClicked: {print(newsStack.parent.stacktype);
// newstabmenu.popup(2*mm,6*mm)
// }
// Menu{id:newstabmenu
// width: 40*mm
// delegate:MenuItem{
// contentItem: Text{
// font.pixelSize: 3.5*mm
// text:parent.text
// }
// background: Rectangle {
// implicitWidth: 40*mm; implicitHeight: 5*mm
// color: "#ffffff"
// border.color: "grey"
// }
// }
// Action {
// text: qsTr("Timeline")
// onTriggered: {
// }
// Action {
// text: qsTr("Conversations")
// onTriggered:{
// //newsModel.clear();
// newstab.newstabstatus="Conversations";
// Newsjs.chatsfromdb(db,root.login,function(news){showNews(news)})
// }
// }
// Action {
// text: qsTr("Favorites")
// onTriggered:{
// newsStack.updateMethodNews="refresh";
// newstab.newstabstatus="Favorites";
// Service.updateView("Favorites")
// }
// }
// Action {
// text: qsTr("Replies")
// onTriggered:{
// newsStack.updateMethodNews="refresh";
// newstab.newstabstatus="Replies";
// Service.updateView("Replies")
// }
// }
// Action {
// text: qsTr("Public timeline")
// onTriggered:{
// newsStack.updateMethodNews="refresh";
// newstab.newstabstatus="Public Timeline";
// Service.updateView("Public Timeline")
// }
// }
//// Action {
//// text: qsTr("Direct Messages")
//// onTriggered:{
//// newsStack.updateMethodNews="refresh";
//// newstab.newstabstatus="Direct Messages";
//// Service.updateView("Direct Messages")
//// }
//// }
//// Action {
//// text: qsTr("Notifications")
//// onTriggered:{
//// newsStack.updateMethodNews="refresh";
//// newstab.newstabstatus="Notifications";
//// Service.updateView("Notifications")
//// }
//// }
// Action {
// text: qsTr("Group news")
// onTriggered:
// {
// newsStack.updateMethodNews="refresh";
// Service.showGroups();
// }
// }
// Action {
// text: qsTr("Settings")
// onTriggered:
// {
// leftDrawer.open()
// }
// }
// Action {
// text: qsTr("Quit")
// onTriggered:{
// Service.cleanNews(root.db,function(){
// Service.cleanContacts(root.login,root.db,function(){
// Qt.quit()})
// })
// }
// }
// }
// }
// Row{
// spacing: mm
// anchors.top: parent.top
// anchors.topMargin: 0.5*mm
// anchors.right: parent.right
// Button {
// id: searchButton
// height: 8*mm
// text: "\uf002"
// visible: newsStack.parent.stacktype=="standard"
// onClicked: {
// newsView.anchors.topMargin=18*mm;
// var component = Qt.createComponent("qrc:/qml/genericqml/Search.qml");
// var searchItem = component.createObject(newsStack,{y:8*mm,width:root.width,height: 8*mm});
// }
// }
// Button {
// id: newMessageButton
// text: "\uf040"
// height: 8*mm
// onClicked: {
// var groups=[];
// Helperjs.readData(root.db,"groups",root.login.username,function(groupobject){
// groups=groupobject
// });
// newstab.newstabstatus="SendMessage";
// Helperjs.readData(root.db,"contacts",root.login.username,function(friends){
// newsStack.push("qrc:/qml/newsqml/MessageSend.qml",{"contacts": friends,"login":root.login})
// },"isFriend",1);
// }
// }
// BlueButton {
// id: quitButton
// text: "\uf08b"
// onClicked: {Service.cleanNews(root.db,function(){
// Service.cleanContacts(root.login,root.db,function(){
// Qt.quit() })
// })}
// }
// Button {
// id: update
// height: 8*mm
// text: "\uf021"
// onClicked: {
// if (newstab.newstabstatus=="Timeline"){
// newsStack.updateMethodNews="append"
// } else {newsStack.updateMethodNews="refresh"}
// //root.contactLoadType="news";
// if (newsStack.parent.stacktype=="standard"){
// Service.updateView(newstab.newstabstatus)
// }
// else if (newsStack.parent.stacktype=="directmessage"){
// Service.updateView("Direct Messages")
// }
// else if (newsStack.parent.stacktype=="notifications"){
// Service.updateView("Notifications")
// }
// }
// }
// }
Component { id:footerComponent
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:newsView.width
height:6*mm
Text{
font.pixelSize: 1.5*mm
anchors.centerIn: parent
text:qsTr("More")
}
MouseArea{anchors.fill:parent
onClicked:{
var currentTime= new Date();
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
var messagetype=0;
switch(newsSwipeview.stacktype){
case "Home":messagetype=0;break;
case "DirectMessages": messagetype=1;break;
case "Notifications":messagetype=2;break;
case "Replies":messagetype=3;break;
default:messagetype=0;
}
if(newstab.newstabstatus=="Timeline"){
Newsjs.newsfromdb(root.db,root.login, messagetype,function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true, 'options':globaloptions};
newsWorker.sendMessage(msg);
},false,lastnews_id)}
if(newstab.newstabstatus=="Conversations"){
Newsjs.chatsfromdb(root.db,root.login, messagetype,function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true, 'options':globaloptions};
newsWorker.sendMessage(msg);
},lastnews_id)}
// else if(newstab.newstabstatus=="Contact"){
// Newsjs.newsfromdb(root.db,root.login, function(news){
// var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
// newsWorker.sendMessage(msg);
// },newsModel.get(newsModel.count-1).newsitemobject.uid,lastnews_id)}
else if (newstab.newstabstatus=="Notifications"){}
else{
//newsStack.appendNews=true;
xhr.setParam("max_id",newsModel.get(newsModel.count-1).newsitemobject.id-1);
xhr.get()
}}
}
}
}
// Label{
// text:qsTr(stacktype)
// font.pixelSize: 3* mm
// anchors.horizontalCenter: parent.horizontalCenter
// anchors.margins: mm
// }
ListView {
id: newsView
property real oldContentY:0
property bool viewdragged: false
anchors.fill: parent
anchors.margins: mm
//anchors.topMargin: 6*mm
// anchors.leftMargin: mm; anchors.rightMargin: mm
// anchors.bottomMargin: mm
clip: true
spacing: 0
header: MessageSend{id:messagesend;onHeightChanged: newsView.positionViewAtBeginning()}
footer: footerComponent
model: newsModel
delegate: Newsitem{}
onDragStarted: oldContentY=contentY
onDragEnded: {
if(verticalOvershoot<-5*mm){
viewdragged=true
}
else{
if((contentY-oldContentY)>15*mm){
swipeIndicator.visible=false;
newsSwipeview.height=rootStackItem.height;
newsSwipeview.y=0;
rootStackItem.state="fullscreen"
}
else if ((contentY-oldContentY)<-15*mm){
swipeIndicator.visible=true;
newsSwipeview.height=rootStackItem.height-12*mm;
newsSwipeview.y=5*mm;
rootStackItem.state=""
}
}
}
onViewdraggedChanged: {
if (viewdragged){
var onlynew=true;
newsBusy.running=true;
if (newstab.newstabstatus=="Timeline"){
newsStack.updateMethodNews="append"
} else {newsStack.updateMethodNews="refresh"}
//root.contactLoadType="news";
if (newsSwipeview.stacktype=="Home"){
Newsjs.getLastNews(root.login,root.db,function(currentlastnews){
if (currentlastnews>lastnewsid){
if(newstab.newstabstatus=="Timeline"){
try{ Newsjs.newsfromdb(root.db,root.login,0, function(dbnews,lastid){
lastnewsid=lastid;
showNews(dbnews)
})}catch(e){Helperjs.showMessage("Error",e,root)};
}
if(newstab.newstabstatus=="Conversations"){
Newsjs.chatsfromdb(db,root.login,0,function(news,lastid){
lastnewsid=lastid;
showNews(news)});
}
} else {
Service.updateView(newstab.newstabstatus)
}
});
}
else if (newsSwipeview.stacktype=="DirectMessages"){
Service.updateView("Direct Messages")
}
else if (newsSwipeview.stacktype=="Notifications"){
Service.updateView("Notifications")
}
else if (newsSwipeview.stacktype=="Replies"){
Service.updateView("Replies")
}
viewdragged=false
}}
}
ListModel{id: newsModel}
WorkerScript {
id: newsWorker
source: "qrc:/js/newsworker.js"
}
BusyIndicator{
id: newsBusy
anchors.horizontalCenter: parent.horizontalCenter
anchors.top:parent.top
anchors.topMargin: 2*mm
width:10*mm
height: 10*mm
}
Rectangle{
id:downloadNotice
property alias text: noticeText.text
color:"white"
border.color:"grey"
z:1
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom:parent.bottom
anchors.bottomMargin: 2*mm
width: noticeText.width+2*mm
height: noticeText.height+2*mm
visible: (downloadNotice.text!="")
Text{
id:noticeText
color: "grey"
anchors.centerIn: parent
width: contentWidth
height: contentHeight
font.pixelSize: 2*mm
text:""
}
}
Component.onCompleted: {
//print(newsSwipeview.stacktype);
root.newstypeSignal.connect(newstypeHandling);
root.messageSignal.connect(onFriendsMessages);
root.contactdetailsSignal.connect(showContact);
root.newsSignal.connect(showNews);
try{newsModel.clear()} catch(e){}
swipeIndicator.visible=true;
newsSwipeview.height=rootStackItem.height-12*mm;
newsSwipeview.y=5*mm;
rootStackItem.state=""
// xhr.setLogin(login.username+":"+Qt.atob(login.password));
// xhr.setUrl(login.server);
// if((newsStack.parent.stacktype=="standard") && (root.news.length>0)){
// showNews(root.news)
// }
//else{
newstab.newstabstatus=login.newsViewType;
var messagetype=0;
switch(newsSwipeview.stacktype){
case "Home":messagetype=0;break;
case "DirectMessages": messagetype=1;break;
case "Notifications":messagetype=2;break;
case "Replies":messagetype=3;break;
default:messagetype=0;
}
if((login.newsViewType=="Conversations")&&(newsSwipeview.stacktype=="Home")){
Newsjs.chatsfromdb(db,login,messagetype,function(dbnews,lastid){
lastnewsid=lastid;
showNews(dbnews);
})
}
else{Newsjs.newsfromdb(db,login,messagetype,function(dbnews,lastid){
lastnewsid=lastid;
showNews(dbnews)
})}
//}
}
}
}

View file

@ -29,37 +29,16 @@
// 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.7
import QtQuick.Controls 1.4
import QtQuick.Controls 2.3 as QC2
import QtQuick 2.11
import QtQuick.Controls 2.4
//import QtQuick.Controls.Styles 2.3
import QtQuick.Dialogs 1.3
import "qrc:/qml/genericqml"
//import QtQuick.Dialogs 1.3
import "qrc:/qml/newsqml"
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/service.js" as Service
import AndroidNative 1.0
Item {
Connections{
target:newstab
onNewstabstatusChanged:{
newstabstatusButton.text= qsTr(newstab.newstabstatus)
}
}
Connections{
target:xhr
onError:{
Helperjs.showMessage(qsTr("Network Error"),"API:\n" +login.server+api+"\n Return: \n"+data,root);
}
onSuccess:{
// downloadNotice.text=downloadNotice.text+ "\n xhr finished "+Date.now();
Service.processNews(api,data);
}
}
// Connections{
// target:xhr
@ -80,43 +59,18 @@ Item {
// }
Timer {id:replytimer; interval: 1000; running: false; repeat: false
onTriggered: {
if(newstab.newstabstatus=="Conversation"){
showConversation(newsStack.timelineIndex-1,newsModel.get(0).newsitemobject)}
else{
Service.updateView(newstab.newstabstatus)
}
}
}
Timer {id:contacttimer; interval: 50; running: false; repeat: false
onTriggered: {
onTriggered: {//print("Contacttimer "+JSON.stringify(root.news));
// downloadNotice.text=downloadNotice.text + "\n contactTimer start "+ Date.now()
root.newContacts=Newsjs.findNewContacts(root.news,root.contactlist);
Newsjs.storeNews(login,db,root.news,root)
}
}
function showNews(newsToShow){
try{
if (newsStack.depth>1){newsStack.pop()}
}catch(e){}
newsBusy.running=false;
var currentTime= new Date();
// downloadNotice.text=downloadNotice.text + "\n shownews start "+ Date.now();
//print("appendnews "+newsStack.appendNews +JSON.stringify(newsToShow))
var msg = {'currentTime': currentTime, 'model': newsModel,'news':newsToShow,'method':newsStack.updateMethodNews, 'options':globaloptions};
newsWorker.sendMessage(msg);
//newsStack.appendNews=false
}
function showConversation(conversationIndex,newsitemobject){
if(newsitemobject.messagetype==0){
if(newsitemobject.messagetype==0 || newsitemobject.messagetype==3){
xhr.clearParams();
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
@ -134,31 +88,12 @@ Item {
}
}
function showContact(contact){
newstab.newstabstatus="Contact";
newsStack.push({item:"qrc:/qml/newsqml/ContactPage.qml",properties:{"contact": contact}});
}
function search(term){//print("Search "+term)
if (term!=""){
newstab.newstabstatus="Search";
newsBusy.running=true;
newsStack.updateMethodNews="refresh";
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/search");
xhr.clearParams();
xhr.setParam("q",term)
xhr.get();}
newsView.anchors.topMargin=7*mm
}
function onFriendsMessages(friend){
newstab.newstabstatus="Contact"
Newsjs.newsfromdb(db,root.login.username, function(dbnews){
Newsjs.newsfromdb(db,root.login.username, 0,function(dbnews){
if (dbnews.length==0){
Newsjs.newsfromdb(db,login.username,function(forumnews){
Newsjs.newsfromdb(db,login.username,0,function(forumnews){
showNews(forumnews)
},friend.url)
}
@ -166,303 +101,84 @@ Item {
},friend.id)
}
function onDirectMessage(friend){
//newstab.newstabstatus="SendMessage" ,"login":login ,
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"reply_to_user": friend,"directmessage":1, "login":root.login}});
}
function sendUrls(urls){print(root.currentIndex==0);
if((urls.length==1)&&(newsStack.depth<2)){
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"attachImageURLs":urls}})
}
}
function sendtext(text){
if(text&&(newsStack.depth<2)){
if (text.subject=="undefined"){text.subject=""}
if(text.plaintext.lastIndexOf(".jpg")>-1 || text.plaintext.lastIndexOf(".jpeg")>-1 || text.plaintext.lastIndexOf(".png")>-1 || text.plaintext.lastIndexOf(".gif")>-1){
text.plaintext="<a href="+text.plaintext+"><img src="+text.plaintext+"></a>"}
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"bodyMessage":text.subject+"\n"+text.plaintext}})
}
}
StackView{
id: newsStack
anchors.fill:parent
property string updateMethodNews: "refresh"
property var allchats: ({})
initialItem:Rectangle {
id:newslistRectangle
y:1
color: "white"
BlueButton{
id:newstabstatusButton
anchors.top: parent.top
anchors.topMargin: 0.5*mm
text: qsTr(newstab.newstabstatus)
onClicked: {newstabmenu.popup(2*mm,6*mm)}
QC2.Menu{id:newstabmenu
width: 40*mm
delegate:QC2.MenuItem{
contentItem: Text{
font.pixelSize: 3.5*mm
text:parent.text
}
background: Rectangle {
implicitWidth: 40*mm; implicitHeight: 5*mm
color: "#ffffff"
border.color: "grey"
}
}
QC2.Action {
text: qsTr("Timeline")
onTriggered: {
newstab.newstabstatus="Timeline";
//newsModel.clear();
try{ Newsjs.newsfromdb(root.db,root.login.username, function(dbnews){
showNews(dbnews)
})}catch(e){Helperjs.showMessage("Error",e,root)}}
}
QC2.Action {
text: qsTr("Conversations")
onTriggered:{
//newsModel.clear();
newstab.newstabstatus="Conversations";
Newsjs.chatsfromdb(db,root.login.username,function(news){showNews(news)})
}
}
QC2.Action {
text: qsTr("Favorites")
onTriggered:{
newsStack.updateMethodNews="refresh";
newstab.newstabstatus="Favorites";
Service.updateView("Favorites")
}
}
QC2.Action {
text: qsTr("Replies")
onTriggered:{
newsStack.updateMethodNews="refresh";
newstab.newstabstatus="Replies";
Service.updateView("Replies")
}
}
QC2.Action {
text: qsTr("Public timeline")
onTriggered:{
newsStack.updateMethodNews="refresh";
newstab.newstabstatus="Public Timeline";
Service.updateView("Public Timeline")
}
}
QC2.Action {
text: qsTr("Direct Messages")
onTriggered:{
newsStack.updateMethodNews="refresh";
newstab.newstabstatus="Direct Messages";
Service.updateView("Direct Messages")
}
}
QC2.Action {
text: qsTr("Notifications")
onTriggered:{
newsStack.updateMethodNews="refresh";
newstab.newstabstatus="Notifications";
Service.updateView("Notifications")
}
}
QC2.Action {
text: qsTr("Group news")
onTriggered:
{
newsStack.updateMethodNews="refresh";
Service.showGroups();
}
}
QC2.Action {
text: qsTr("Quit")
onTriggered:{
Service.cleanNews(root.db,function(){
Service.cleanContacts(root.login,root.db,function(){
Qt.quit()})
})
}
}
}
}
Row{
spacing: mm
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right: parent.right
BlueButton {
id: searchButton
text: "\uf002"
onClicked: {
newsView.anchors.topMargin=18*mm;
var component = Qt.createComponent("qrc:/qml/genericqml/Search.qml");
var searchItem = component.createObject(newsStack,{y:8*mm,width:root.width,height: 8*mm});
}
}
BlueButton {
id: newMessageButton
text: "\uf040"
onClicked: {
var groups=[];
Helperjs.readData(root.db,"groups",root.login.username,function(groupobject){
groups=groupobject
});
newstab.newstabstatus="SendMessage";
Helperjs.readData(root.db,"contacts",root.login.username,function(friends){
newsStack.push("qrc:/qml/newsqml/MessageSend.qml",{"contacts": friends,"login":root.login})
},"isFriend",1);
}
}
// BlueButton {
// id: quitButton
// text: "\uf08b"
// onClicked: {Service.cleanNews(root.db,function(){
// Service.cleanContacts(root.login,root.db,function(){
// Qt.quit() })
// })}
// }
BlueButton {
id: update
text: "\uf021"
onClicked: {
if (newstab.newstabstatus=="Timeline"){
newsStack.updateMethodNews="append"
} else {newsStack.updateMethodNews="refresh"}
//root.contactLoadType="news";
Service.updateView(newstab.newstabstatus)
}
}
}
Component { id:footerComponent
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:newsView.width
height:6*mm
Text{
font.pixelSize: 1.5*mm
anchors.centerIn: parent
text:qsTr("More")
}
MouseArea{anchors.fill:parent
onClicked:{
var currentTime= new Date();
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
if(newstab.newstabstatus=="Timeline"){
Newsjs.newsfromdb(root.db,root.login.username, function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true, 'options':globaloptions};
newsWorker.sendMessage(msg);
},false,lastnews_id)}
if(newstab.newstabstatus=="Conversations"){
Newsjs.chatsfromdb(root.db,root.login.username, function(news){
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true, 'options':globaloptions};
newsWorker.sendMessage(msg);
},lastnews_id)}
// else if(newstab.newstabstatus=="Contact"){
// Newsjs.newsfromdb(root.db,root.login.username, function(news){
// var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
// newsWorker.sendMessage(msg);
// },newsModel.get(newsModel.count-1).newsitemobject.uid,lastnews_id)}
else if (newstab.newstabstatus=="Notifications"){}
else{
//newsStack.appendNews=true;
xhr.setParam("max_id",newsModel.get(newsModel.count-1).newsitemobject.id-1);
xhr.get()
}}
}
}
}
ListView {
id: newsView
Label{
text:"\uf0c9 "
font.pixelSize: 5* mm
anchors.left: parent.left
anchors.margins: mm
color: "#B0BEC5"
MouseArea{
anchors.fill: parent
anchors.topMargin: 7*root.mm
anchors.leftMargin: 3*root.mm; anchors.rightMargin: root.mm
anchors.bottomMargin: 1*root.mm
clip: true
spacing: 0
footer: footerComponent
model: newsModel
delegate: Newsitem{}
//onContentYChanged:{if(contentY<-8*mm&&contentY>(-8*mm-1)){print("refreshing");
onDragEnded:{if(contentY<-5*mm){
var onlynew=true;
Service.updateView(newstab.newstabstatus)
}}
onClicked:{
leftDrawer.open()
}
ListModel{id: newsModel}
WorkerScript {
id: newsWorker
source: "qrc:/js/newsworker.js"
}
BusyIndicator{
id: newsBusy
anchors.horizontalCenter: newsView.horizontalCenter
anchors.top:newsView.top
anchors.topMargin: 2*mm
width:10*mm
height: 10*mm
}
Rectangle{
id:downloadNotice
property alias text: noticeText.text
color:"white"
border.color:"grey"
z:1
anchors.horizontalCenter: newsView.horizontalCenter
anchors.bottom:newsView.bottom
anchors.bottomMargin: 2*mm
width: noticeText.width+2*mm
height: noticeText.height+2*mm
visible: (downloadNotice.text!="")
Label{
text:qsTr(newsSwipeview.stacktype)
font.pixelSize: 3* mm
anchors.horizontalCenter: parent.horizontalCenter
anchors.margins: 2*mm
}
SwipeView{
id: newsSwipeview
property string stacktype:"Home"
currentIndex: 0
width: parent.width
height: parent.height-6*mm
y: 5*mm
function onDirectMessage(friend){currentIndex=2}
Text{
id:noticeText
color: "grey"
anchors.centerIn: parent
width: contentWidth
height: contentHeight
font.pixelSize: 2*mm
text:""
transitions: Transition {
PropertyAnimation { properties: "height";
easing.type: Easing.InOutQuad
duration: 1000
}
}
Component.onCompleted: {
root.messageSignal.connect(onFriendsMessages);
root.directmessageSignal.connect(onDirectMessage);
root.contactdetailsSignal.connect(showContact);
root.newsSignal.connect(showNews);
root.uploadSignal.connect(sendUrls);
root.sendtextSignal.connect(sendtext);
try{newsModel.clear()} catch(e){}
// xhr.setLogin(login.username+":"+Qt.atob(login.password));
// xhr.setUrl(login.server);
if(root.news.length>0){showNews(root.news)}
else{ newstab.newstabstatus=login.newsViewType;
if(login.newsViewType=="Timeline"){Newsjs.newsfromdb(db,login.username,function(dbnews){showNews(dbnews)})}
else{Newsjs.chatsfromdb(db,login.username,function(dbnews){
showNews(dbnews);
})}
onCurrentIndexChanged: {
switch(currentIndex){
case 0: stacktype="Home";break;
case 1: stacktype="Replies";break;
case 2: stacktype="DirectMessages";break;
case 3: stacktype="Notifications";break;
default: stacktype="Home";
}
}
//anchors.fill: parent
Loader{
id: friendstimeline
source:(newsSwipeview.currentIndex==0)? "qrc:/qml/newsqml/NewsStack.qml":""
//onLoaded: newsSwipeview.stacktype="Home"
}
Loader{
id: replies
//property string stacktype:"Replies"
source:(newsSwipeview.currentIndex==1)? "qrc:/qml/newsqml/NewsStack.qml":""
//onLoaded: newsSwipeview.stacktype="Replies"
}
Loader{
id: directmessages
property var friend:({})
source:(newsSwipeview.currentIndex==2)? "qrc:/qml/newsqml/NewsStack.qml":""
//onLoaded: newsSwipeview.stacktype="DirectMessages"
}
Loader{
id: notifications
//property string stacktype:"Notifications"
source:(newsSwipeview.currentIndex==3)? "qrc:/qml/newsqml/NewsStack.qml":""
//onLoaded: newsSwipeview.stacktype="Notifications"
}
Component.onCompleted: {root.directmessageSignal.connect(onDirectMessage);}
}
PageIndicator {
id: swipeIndicator
count: newsSwipeview.count
currentIndex: newsSwipeview.currentIndex
anchors.bottom: newsSwipeview.bottom
anchors.horizontalCenter: parent.horizontalCenter
}
}

View file

@ -30,8 +30,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 1.4
import QtQuick.Controls.Styles 1.4
import QtQuick.Controls 2.4
//import QtQuick.Controls.Styles 1.4
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
@ -62,7 +62,7 @@ Item {
Rectangle{
width:newsitem.width
height:newsitem.height-1
color: (newsitemobject.messagetype==1)?"#ffe6e6" : "white"
color: "white"//(newsitemobject.messagetype==1)?"#ffe6e6" : "white"
Row{id:toprow
Column {
@ -102,8 +102,7 @@ Item {
Label {
id:messageTypeLabel
color: "grey"
text: if (newsitemobject.messagetype==0){qsTr("Source: ")+newsitemobject.source
} else if (newsitemobject.messagetype==1){ qsTr("Direct Message")} else {" Notification"}
text: if (newsitemobject.messagetype==1){ qsTr("Direct Message")} else if(newsitemobject.messagetype==2) {" Notification"} else {qsTr("Source: ")+newsitemobject.source}
font.pixelSize: 1.5*mm
}
Label {
@ -117,6 +116,7 @@ Item {
id:replytoLabel
color: "grey"
font.pixelSize: 1.5*mm
font.family: "Noto Sans"
horizontalAlignment: Label.AlignRight
text: try {qsTr("In reply to ")+newsitemobject.reply_user.screen_name
}catch(e){" "}
@ -160,6 +160,7 @@ Item {
linkColor: "light green"
id: itemMessage
textFormat: Text.RichText
font.family: "Noto Sans"
text: newsitemobject.statusnet_html//newsitemobject.attachmentList.length>0?newsitemobject.text : newsitemobject.statusnet_html
width: newsitem.width-8*mm-2
height: implicitHeight
@ -178,7 +179,6 @@ Item {
}}
if (newsitemobject.attachmentList.length>0){
for(var attachments in newsitemobject.attachmentList){// (newsitemobject.attachmentList[attachments].url);
if(newsitemobject.attachmentList[attachments].mimetype.substring(0,5)=="image"){
var component = Qt.createComponent("qrc:/qml/newsqml/NewsImage.qml");
@ -191,8 +191,7 @@ Item {
else {//print(newsitemobject.attachmentList[attachments].url+" Type: "+newsitemobject.attachmentList[attachments].mimetype)
var component = Qt.createComponent("qrc:/qml/newsqml/NewsVideo.qml");
var videoQml = component.createObject(messageColumn,{"source":newsitemobject.attachmentList[attachments].url,"mimetype":newsitemobject.attachmentList[attachments].mimetype});
}
}
}
}
}
@ -289,9 +288,9 @@ Item {
CheckBox{
id:likeCheckbox
width:10*mm
visible: (newsitemobject.messagetype==0)? true:false
visible: ((newsitemobject.messagetype==0)||(newsitemobject.messagetype==3))? true:false
checked:(friendica_activities.self.liked==1)?true:false
style: CheckBoxStyle {
//style: CheckBoxStyle {
indicator: Rectangle{
implicitWidth: 10*mm
implicitHeight:3*mm
@ -299,11 +298,11 @@ Item {
anchors.centerIn: parent
font.pixelSize: 2.5*mm
font.family:fontAwesome.name
color:control.checked?"black": "grey"
text:control.checked?"\uf118"+"!":"\uf118"
}
color:likeCheckbox.checked?"black": "grey"
text:likeCheckbox.checked?"\uf118"+"!":"\uf118"
}
}
//}
onClicked: {
if(likeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"like",newsitemobject.id,root);dislikeCheckbox.checked=false; model.friendica_activities.self.liked=0 }
else{Newsjs.like(root.login,root.db,0,"like",newsitemobject.id,root); model.friendica_activities.self.liked=1}}
@ -311,9 +310,9 @@ Item {
CheckBox{
id: dislikeCheckbox
width:10*mm
visible: (newsitemobject.messagetype==0)? true:false
visible: ((newsitemobject.messagetype==0)||(newsitemobject.messagetype==3))? true:false
checked: (friendica_activities.self.disliked==1)?true:false
style: CheckBoxStyle {
//style: CheckBoxStyle {
indicator: Rectangle{
implicitWidth: 10*mm
implicitHeight:3*mm
@ -321,11 +320,11 @@ Item {
anchors.centerIn: parent
font.pixelSize: 2.5*mm
font.family:fontAwesome.name
color:control.checked?"black": "grey"
text: control.checked?"\uf119"+"!":"\uf119"
}
color:dislikeCheckbox.checked?"black": "grey"
text: dislikeCheckbox.checked?"\uf119"+"!":"\uf119"
}
}
//}
onClicked: {
if (dislikeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"dislike",newsitemobject.id,root);likeCheckbox.checked=false; model.friendica_activities.self.disliked=0}
else {Newsjs.like(root.login,root.db,0,"dislike",newsitemobject.id,root); model.friendica_activities.self.disliked=1}}
@ -333,20 +332,20 @@ Item {
CheckBox {
id:favoritedCheckbox
visible:(newsitemobject.messagetype==0)
visible:((newsitemobject.messagetype==0)||(newsitemobject.messagetype==3))
width: 10*mm
style: CheckBoxStyle {
//style: CheckBoxStyle {
indicator:Rectangle{
x:4*mm
width: 3*mm
implicitHeight:4*mm
Text{
color: control.checked?"black":"grey"
color: favoritedCheckbox.checked?"black":"grey"
font.pixelSize: 2.5*mm
text:"\uf005"
}
}
}
//}
checked:(newsitemobject.favorited>0)
onClicked:{
if(favoritedCheckbox.checkedState==Qt.Checked){
@ -401,21 +400,29 @@ Item {
Menu {
id:newsmenu
MenuItem {
width: 30*mm
delegate: MenuItem{
contentItem: Text{
font.pixelSize: 3*mm
text: parent.text
}
}
Action{
text: qsTr("Reply")
onTriggered: {
var directmessage=0;
if (newsitemobject.messagetype==1){ directmessage=1}
newsStack.push("qrc:/qml/newsqml/MessageSend.qml",{"reply_to_user": newsitemobject.user.screen_name,"parentId":newsitemobject.id,"login":root.login,"directmessage":directmessage});
replySignal(newsitemobject)
//newsStack.push("qrc:/qml/newsqml/MessageSend.qml",{"reply_to_user": newsitemobject.user.screen_name,"parentId":newsitemobject.id,"login":root.login,"directmessage":directmessage});
}
}
MenuItem {
Action {
text: qsTr("DM")
onTriggered: {
root.directmessageSignal(newsitemobject.user.screen_name);
}
}
MenuItem {
Action {
text: qsTr("Repost")
onTriggered: {
Newsjs.retweetNews(root.login,db,newsitemobject.id,root,function(reply){
@ -423,7 +430,7 @@ Item {
})
}
}
MenuItem {
Action {
text: qsTr("Conversation")
onTriggered: {
conversationsymbol.color="black";
@ -435,24 +442,31 @@ Item {
Menu{
title: qsTr("Attending")
MenuItem{
width: 20*mm
delegate: MenuItem{
contentItem: Text{
font.pixelSize: 3*mm
text: parent.text
}
}
Action{
text:qsTr("yes")
onTriggered: {Newsjs.attend(root.login,db,"yes",newsitemobject.id,root,function(){
model.friendica_activities.self.attending="yes";attending="yes"})
}
}
MenuItem{text:qsTr("maybe")
Action{text:qsTr("maybe")
onTriggered: {Newsjs.attend(root.login,db,"maybe",newsitemobject.id,root,function(){
model.friendica_activities.self.attending="maybe";attending="maybe"})
}
}
MenuItem{text:qsTr("no")
Action{text:qsTr("no")
onTriggered: {Newsjs.attend(root.login,db,"no",newsitemobject.id,root,function(){
model.friendica_activities.self.attending="no";attending="no"})}
}
}
MenuItem {
Action {
text: qsTr("Delete")
onTriggered: {
Newsjs.deleteNews(root.login,root.db,newsitemobject.id,newsitemobject.messagetype,root,function(reply){

View file

@ -30,6 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 2.3
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
@ -37,7 +38,7 @@ import "qrc:/qml/genericqml"
Rectangle{
id:permissionDialog
x: mm
width: messageColumn.width-5*mm
width: messageColumn.width-3*mm
height:root.height/3
function updatePerms(){
for (var i=0;i<groupModel.count;i++)
@ -64,6 +65,7 @@ Rectangle{
x:0.5*mm
y:0.5*mm
text: qsTr("Friends")
font.pixelSize: 2*mm
}
ListView {
id: contactView
@ -95,6 +97,7 @@ Rectangle{
Text{
color:"grey"
text:contact.screen_name
font.pixelSize: 2*mm
}
MouseArea{
anchors.fill: parent
@ -125,6 +128,7 @@ Rectangle{
x:contactView.width+2*mm
y:0.5*mm
text: qsTr("Groups")
font.pixelSize: 2*mm
}
ListView {
id: groupView
@ -156,6 +160,7 @@ Rectangle{
Text{
color:"grey"
text:group.groupname
font.pixelSize: 2*mm
}
MouseArea{
anchors.fill: parent
@ -178,8 +183,10 @@ Rectangle{
else {groupstatus="neutral"} }
}
}
BlueButton{
MButton{
x:0.5*mm
height: 6*mm
width: 8*mm
anchors.bottom: parent.bottom
anchors.bottomMargin:1
text:"\uf0c7"
@ -190,8 +197,10 @@ Rectangle{
Service.savePermissions(db,perms)
}
}
BlueButton{
MButton{
x:contactView.width+2*mm
height: 6*mm
width: 8*mm
anchors.bottom: parent.bottom
anchors.bottomMargin:1
text:"\u2713"

View file

@ -29,9 +29,10 @@
// 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.7
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import QtQuick 2.11
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.11
//import QtQuick.Controls.Styles 1.4
import "qrc:/js/smiley.js" as Smileyjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
@ -42,8 +43,10 @@ Rectangle{
width: messageColumn.width-5*mm
height:root.height/2
BlueButton{
Button{
id:closeButton
height: 6*mm
width: 8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
@ -52,34 +55,57 @@ Rectangle{
onClicked:{smileyDialog.visible=false}
}
TabView{
TabBar {
id: smileybar
width: parent.width
height: 9*mm
position:TabBar.Header
TabButton {
text:qsTr("Unicode")
font.pixelSize: 2*mm
}
TabButton {
text: qsTr("Standard")
font.pixelSize: 2*mm
}
TabButton {
text: qsTr("Addon")
font.pixelSize: 2*mm
}
TabButton {
text: qsTr("Adult")
font.pixelSize: 2*mm
}
}
StackLayout{
id:smileyTabView
tabPosition: Qt.BottomEdge
currentIndex: smileybar.currentIndex
anchors.top: closeButton.bottom
anchors.topMargin: 1*mm
width: smileyDialog.width-2*mm
height: smileyDialog.height-7*mm
currentIndex: 0
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {
color: "white"
implicitWidth: smileyTabView.width/4-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
}
// style: TabViewStyle {
// frameOverlap: 1
// tab: Rectangle {
// color: "white"
// implicitWidth: smileyTabView.width/4-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("Unicode")
Rectangle{
id: htmlGridTab
GridView {
@ -101,9 +127,7 @@ Rectangle{
}
}
}
}
Tab{
title: qsTr("Standard")
Rectangle{
id: coreGridTab
GridView {
@ -127,9 +151,7 @@ Rectangle{
}
}
}
}
Tab{
title: qsTr("Addon")
Rectangle{
id: addonGridTab
GridView {
@ -151,9 +173,8 @@ Rectangle{
}
}
}
}
Tab{
title: qsTr("Adult")
Rectangle{
id: adultGridTab
GridView {
@ -175,7 +196,7 @@ Rectangle{
}
}
}
}
@ -218,6 +239,4 @@ Rectangle{
}
}
}
}

View file

@ -30,7 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls 2.4
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/image.js" as Imagejs
import "qrc:/qml/genericqml"
@ -132,9 +132,11 @@ function updateImage(){
// }
// }
BlueButton{
Button{
id:closeButton
height: 8*mm
text: "\uf057"
font.pixelSize: 3*mm
onClicked:{photoStack.pop();
//imageDialog.destroy()
}
@ -236,7 +238,7 @@ function updateImage(){
source:"qrc:/images/addImage.png"
MouseArea{
anchors.fill: parent
onClicked:{print(imagePicking)
onClicked:{
imagePicking=true;
var imagePicker = Qt.createQmlObject('import QtQuick 2.0; import "qrc:/qml/genericqml";'+
osSettings.imagePickQml+'{multiple : false;onReady: {attachImageURLs.push(imageUrl);'+
@ -264,10 +266,12 @@ function updateImage(){
ListModel{id:albumModel}
BlueButton{
Button{
id:uploadButton
height: 8*mm
x:4*mm; y:root.width/2+18*mm //40*mm
text: imageId==""?qsTr("Upload"):qsTr("Change")
font.pixelSize: 3*mm
onClicked:{
if(album.currentText==""){Helperjs.showMessage(qsTr("Error"),qsTr(" No album name given"), imageDialog)}
else if (imageId!=""){uploadBusy.running=true; updateImage()}

View file

@ -30,7 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.5
import QtQuick.Controls 1.4
import QtQuick.Controls 2.4
import QtQml.Models 2.1
import "qrc:/js/image.js" as Imagejs
import "qrc:/js/helper.js" as Helperjs
@ -40,12 +40,13 @@ import "qrc:/qml/genericqml"
StackView{
id: photoStack
anchors.fill:parent
//anchors.fill:parent
initialItem:Rectangle {
id:fotorectangle
y:1
width:root.width-mm
height:root.height-5*mm
anchors.fill:parent
// y:1
// width:root.width-mm
// height:root.height-5*mm
color: '#fff'
property var newimages:[]
property int currentimageno: 0
@ -141,14 +142,14 @@ StackView{
function updatepic(method,type,id){
if(method=="update"){
Helperjs.readData(db,"imageData",login.username,function(url){
photoStack.push({
item:"qrc:/qml/photoqml/ImageUploadDialog.qml",properties:{attachImageURLs:[url[0].location+url[0].filename],imageId:id,currentAlbum:url[0].album}
})
photoStack.push(
"qrc:/qml/photoqml/ImageUploadDialog.qml",{"attachImageURLs":[url[0].location+url[0].filename],"imageId":id,"currentAlbum":url[0].album}
)
},"id",id)}
}
function uploadUrls(urls){
photoStack.push({item:"qrc:/qml/photoqml/ImageUploadDialog.qml",properties:{attachImageURLs:urls}})
photoStack.push("qrc:/qml/photoqml/ImageUploadDialog.qml",{"attachImageURLs":urls})
}
ProgressBar{
@ -162,35 +163,43 @@ StackView{
value: fotorectangle.currentimageno/fotorectangle.newimages.length
}
BlueButton{
MButton{
id: uploadPhoto
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right:updatePhotolist.left
anchors.rightMargin:mm
height: 6*mm
width: 8*mm
text:"\uf0ee"
onClicked: {print(root.imagePicking)
photoStack.push({item:"qrc:/qml/photoqml/ImageUploadDialog.qml",properties:{}});
onClicked: {
photoStack.push("qrc:/qml/photoqml/ImageUploadDialog.qml");
// var component = Qt.createComponent("qrc:/qml/photoqml/ImageUploadDialog.qml");
// var imageUpload = component.createObject(fotorectangle);
}}
BlueButton{
MButton{
id: updatePhotolist
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right:phototabstatusButton.left
anchors.rightMargin:mm
height: 6*mm
width: 8*mm
text:"\uf0ed"
Menu {
id:photoupdatemenu
width:40*mm
MenuItem {
text: qsTr("All Images")
font.pixelSize: 3*mm
onTriggered: {
Imagejs.requestList(root.login,root.db, false, fotostab,function(obj){fotorectangle.newimages=obj})}
}
MenuItem {
text: qsTr("Only new")
font.pixelSize: 3*mm
onTriggered: {
Imagejs.requestList(root.login,root.db, true,fotostab,function(obj){fotorectangle.newimages=obj})}
}
@ -198,17 +207,21 @@ StackView{
onClicked: {photoupdatemenu.popup()}
}
BlueButton{
MButton{
id: phototabstatusButton
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right: parent.right
anchors.rightMargin:2*mm
height: 6*mm
width: Math.max(10*mm,implicitWidth)
text: fotostab.phototabstatus=="Images"?qsTr("Own Images"):fotostab.phototabstatus
Menu {
id:phototabmenu
width: 40*mm
MenuItem {
text: qsTr("Own Images")
font.pixelSize: 3*mm
onTriggered: {
fotostab.phototabstatus="Images";
// phototabstatusButton.text=qsTr("Own images");
@ -267,8 +280,10 @@ StackView{
ListView { width: parent.width; height:parent.height; model: visualphotoModel.parts.browser; interactive: false }
BlueButton {
MButton {
id: backButton
height: 6*mm
width: 8*mm
text: "\uf057"
x: parent.width - backButton.width - 3*mm
y: -backButton.height - 4*mm

View file

@ -0,0 +1,14 @@
[Controls]
Style=Material
[Universal]
Theme=System
Accent=Red
[Material]
Theme=Light
Accent=LightBlue
Primary=BlueGrey,50
Background=Grey,50
Variant=Dense

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,6 @@
<RCC>
<qresource prefix="/">
<file>qtquickcontrols2.conf</file>
<file>qml/friendiqa.qml</file>
<file>qml/newsqml/NewsTab.qml</file>
<file>qml/newsqml/Newsitem.qml</file>
@ -16,7 +17,7 @@
<file>qml/photoqml/PhotogroupComponent.qml</file>
<file>qml/photoqml/PhotoTab.qml</file>
<file>qml/configqml/InfoBox.qml</file>
<file>qml/configqml/ConfigTab.qml</file>
<file>qml/configqml/ConfigPage.qml</file>
<file>js/layout.js</file>
<file>js/photoworker.js</file>
<file>js/service.js</file>
@ -225,5 +226,11 @@
<file>qml/newsqml/ContactPage.qml</file>
<file>qml/newsqml/NewsLink.qml</file>
<file>qml/configqml/RegisterPage.qml</file>
<file>qml/configqml/AccountPage.qml</file>
<file>qml/newsqml/NewsStack.qml</file>
<file>qml/configqml/SyncConfig.qml</file>
<file>qml/configqml/SyncComponent.qml</file>
<file>qml/genericqml/MButton.qml</file>
<file>qml/genericqml/LinuxSync.qml</file>
</qresource>
</RCC>

View file

@ -49,9 +49,9 @@ signals:
void alarmChanged(QString url);
public slots:
void setAlarm(int time);
void notify(QString title, QString text, int id);
private:
int m_time;

View file

@ -29,10 +29,9 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//#include <QtAndroidExtras/QAndroidJniObject>
//#include <QtAndroidExtras/QAndroidJniEnvironment>
#include "alarm.h"
#include <QtCore/QDebug>
#include "AndroidNative/systemdispatcher.h"
ALARM *ALARM::instance()
{
@ -44,33 +43,20 @@ ALARM::ALARM(QObject *parent) : QObject(parent){}
void ALARM::setAlarm(int interval)
{
qDebug() << interval;
// auto activity = QtAndroid::androidActivity();
// auto packageManager = activity.callObjectMethod("getPackageManager",
// "()Landroid/content/pm/PackageManager;");
// auto activityIntent = packageManager.callObjectMethod("getLaunchIntentForPackage",
// "(Ljava/lang/String;)Landroid/content/Intent;",
// activity.callObjectMethod("getPackageName",
// "()Ljava/lang/String;").object());
// auto pendingIntent = QAndroidJniObject::callStaticObjectMethod("android/app/PendingIntent", "getActivity",
// "(Landroid/content/Context;ILandroid/content/Intent;I)Landroid/app/PendingIntent;",
// activity.object(), jint(0), activityIntent.object(),
// QAndroidJniObject::getStaticField<jint>("android/content/Intent",
// "FLAG_ACTIVITY_CLEAR_TOP"));
// auto alarmManager = activity.callObjectMethod("getSystemService",
// "(Ljava/lang/String;)Ljava/lang/Object;",
// QAndroidJniObject::getStaticObjectField("android/content/Context",
// "ALARM_SERVICE",
// "Ljava/lang/String;").object());
// alarmManager.callMethod<void>("set",
// "(IJLandroid/app/PendingIntent;)V",
// QAndroidJniObject::getStaticField<jint>("android/app/AlarmManager", "RTC"),
// jlong(QDateTime::currentMSecsSinceEpoch() + 100), pendingIntent.object());
QVariantMap message;
message["value"] = interval;
AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setSchedule", message);
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.stopService", message);
}
void ALARM::notify(QString title, QString text, int id)
{
//qDebug() << "notify "<< title << text;
QVariantMap message;
message["title"] = title;
message["message"] = text;
message["id"] = id;
AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setNotification", message);
}

View file

@ -0,0 +1,73 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 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/>.
//#include <QtAndroidExtras/QAndroidJniObject>
//#include <QtAndroidExtras/QAndroidJniEnvironment>
#include "alarm.h"
#include <QtCore/QDebug>
#include <QtDBus/QtDBus>
//#include "AndroidNative/systemdispatcher.h"
ALARM *ALARM::instance()
{
static ALARM alarm;
return &alarm;
}
ALARM::ALARM(QObject *parent) : QObject(parent){}
void ALARM::setAlarm(int interval)
{
qDebug() << interval;
QVariantMap message;
message["value"] = interval;
// AndroidNative::SystemDispatcher::instance()->loadClass("androidnative.Util");
// AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.setSchedule", message);
//AndroidNative::SystemDispatcher::instance()->dispatch("androidnative.Util.stopService", message);
}
void ALARM::notify(QString title, QString text, int id)
{
qDebug() << title << text;
QVariantMap message;
message["title"] = title;
message["message"] = text;
QDBusConnection bus = QDBusConnection::sessionBus();
QDBusInterface dbus_iface("org.freedesktop.Notifications", "/org/freedesktop/Notifications",
"org.freedesktop.Notifications", bus);
QString appname="Friendiqa";
uint v=12321;
if (dbus_iface.isValid()){
dbus_iface.call("Notify",appname,v,"",title,text,"","",5000);
}
// AndroidNative::SystemDispatcher::instance()->dispatch("Notifier.notify", message);
}

View file

@ -1,5 +1,5 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify

View file

@ -1,5 +1,5 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify

View file

@ -1,5 +1,5 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
@ -31,12 +31,14 @@
#include <QApplication>
#include <QtQml/QQmlEngine>
//#include <QAndroidService>
//#include <QtAndroid>
#include <QtQuick>
#include <QtWebView>
#include "xhr.h"
#include "filesystem.h"
#include "updatenews.h"
#include "filesystem.h"
#include "remoteauthasyncimageprovider.h"
//#include "alarm.h"
//#include "AndroidNative/systemdispatcher.h"
//#include "AndroidNative/environment.h"
//#include "AndroidNative/debug.h"
@ -57,26 +59,39 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) {
int main(int argc, char *argv[]) {
//qDebug()<< "argv Friendiqa"<< argv[0] <<" argv2" <<argv[1];
if (qstrcmp(argv[1],"-service")==0){
//qDebug()<<"FriendiqaMain Service";
//QAndroidService app(argc, argv);
UPDATENEWS* updatenews= UPDATENEWS::instance();
updatenews->setDatabase();
updatenews->login();
updatenews->startsync();
//app.connect (updatenews,SIGNAL(quitapp()),&app,SLOT(quit()));
//QtAndroid::androidService().callMethod<void>("stopSelf");
//return app.exec();
}
else{
QApplication app(argc, argv);
QQuickView view;
QTranslator qtTranslator;
qtTranslator.load("friendiqa-" + QLocale::system().name(),":/translations");
app.installTranslator(&qtTranslator);
QtWebView::initialize();
RemoteAuthAsyncImageProvider *imageProvider = new RemoteAuthAsyncImageProvider;
view.engine()->addImageProvider("remoteauthimage",imageProvider);
view.rootContext()->setContextProperty("remoteauth", imageProvider);
auto offlineStoragePath=QUrl::fromLocalFile(view.engine()->offlineStorageDatabaseFilePath("Friendiqa"));
view.rootContext()->setContextProperty("offlineStoragePath", offlineStoragePath);
// XHR* xhr = XHR::instance();
// view.rootContext()->setContextProperty("xhr", xhr);
XHR* xhr = XHR::instance();
view.rootContext()->setContextProperty("xhr", xhr);
FILESYSTEM* filesystem = FILESYSTEM::instance();
view.rootContext()->setContextProperty("filesystem", filesystem);
ALARM* alarm = ALARM::instance();
view.rootContext()->setContextProperty("alarm", alarm);
UPDATENEWS* updatenews = UPDATENEWS::instance();
view.rootContext()->setContextProperty("updatenews", updatenews);
view.setSource(QUrl("qrc:/qml/friendiqa.qml"));
view.show();
view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
return app.exec();
}
}

View file

@ -1,5 +1,5 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify

View file

@ -1,5 +1,5 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify

View file

@ -45,7 +45,8 @@
#include <QSqlDatabase>
#include <QSqlError>
#include <QDateTime>
//#include "xhr.h"
//#include "AndroidNative/systemdispatcher.h"
UPDATENEWS *UPDATENEWS::instance()
@ -75,16 +76,12 @@ void UPDATENEWS::setDatabase()
QString db_url=qe.offlineStorageDatabaseFilePath("Friendiqa");
m_db = QSqlDatabase::addDatabase("QSQLITE");
m_db.setDatabaseName(QUrl("file://"+db_url+".sqlite").toLocalFile());
qDebug() << db_url;
//qDebug() << db_url;
if (!m_db.open())
{
qDebug() << "Error: connection with database fail " << m_db.lastError();
}
else
{
qDebug() << "Database: connection ok";
}
}
@ -103,37 +100,152 @@ void UPDATENEWS::login()
m_imagedir=query.value(3).toString();
xhr.setImagedir(m_imagedir);
QString isActive=query.value(7).toString();
updateInterval=query.value(5).toInt();
//UPDATENEWS::connect(&UPDATENEWS::getLogin,SIGNAL(loginChanged(QString)),this,SLOT(XHR::login(QString)));
}
//m_updateInterval=query.value(5).toInt();
m_api="/api/statuses/friends_timeline";
xhr.setApi(m_api);
if(updateInterval!=0){alarm.setAlarm(updateInterval);};
QSqlQuery syncquery("SELECT * FROM globaloptions",m_db);
// QSqlQuery delquery("DELETE FROM globaloptions WHERE k='sync_interval'",m_db);
// delquery.exec();
m_updateInterval=0;
syncindex=0;
synclist.clear();
//QSqlQuery syncquery("SELECT * FROM globaloptions WHERE k like 'sync_%' AND v=1",m_db);
while (syncquery.next()){
if (syncquery.value(0).toString()=="syncinterval"){
m_updateInterval=syncquery.value(1).toInt();
}
if (syncquery.value(0).toString().left(5)=="sync_" && syncquery.value(1).toInt()==1){
synclist.append(syncquery.value(0).toString());
//qDebug() << " sync " << syncquery.value(0).toString() << " " <<syncquery.value(1).toString();
}
if (syncquery.value(0).toString().left(7)=="notify_" && syncquery.value(1).toInt()==1){
notifylist.append(syncquery.value(0).toString());
//qDebug() << " notify " << syncquery.value(0).toString() << " " <<syncquery.value(1).toString();
}
}
// QSqlQuery notifyquery("SELECT * FROM globaloptions WHERE k like 'notify_%' AND v=1",m_db);
//qDebug() << "size " << notifyquery.size();
// while (notifyquery.next()){
// notifylist.append(syncquery.value(0).toString());
// qDebug() << " notify " << syncquery.value(0).toString();
//}
}
void UPDATENEWS::startsync()
{ //qDebug()<<"Friendiqa start syncing " <<synclist.length()<<" index "<<syncindex;
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)));
if (syncindex<synclist.length()){
if (synclist[syncindex]=="sync_Timeline"){
timeline();
} else if (synclist[syncindex]=="sync_Replies") {
replies();
} else if (synclist[syncindex]=="sync_DirectMessages") {
directmessages();
} else if (synclist[syncindex]=="sync_Notifications") {
notifications();
}
} else if (syncindex==synclist.length()) {
m_api="";
if(m_updateInterval!=0){
syncindex=0;
synclist.clear();
m_db.close();
m_db.removeDatabase(m_db.connectionName());
emit quitapp();
alarm.setAlarm(m_updateInterval);
m_updateInterval=0;
}
}
}
void UPDATENEWS::timeline()
{
QSqlQuery query("SELECT status_id FROM news WHERE username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){query.first();};
QString lastid=query.value(0).toString();
m_api="/api/statuses/friends_timeline";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT status_id FROM news WHERE messagetype=0 AND username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
xhr.setParam("count","50");
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)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::store(QByteArray serverreply,QString apiname)
void UPDATENEWS::replies()
{
m_api="/api/statuses/replies";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT status_id FROM news WHERE messagetype=3 AND username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
xhr.setParam("count","50");
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)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::directmessages()
{
m_api="/api/direct_messages/all";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
QSqlQuery query("SELECT status_id FROM news WHERE messagetype=1 AND username='"+ username +"' ORDER BY status_id DESC LIMIT 1",m_db);
if (query.isActive() && query.isSelect()){
if (query.first()){
QString lastid=query.value(0).toString();
xhr.setParam("since_id",lastid);
}
}
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)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::notifications()
{
m_api="/api/friendica/notifications";
xhr.clearParams();
xhr.setUrl(m_url);
xhr.setApi(m_api);
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)));
QObject::connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
}
void UPDATENEWS::store(QByteArray serverreply,QString apiname)
{ if (apiname!=m_api || xhr.downloadtype()!=""){} else {
QJsonDocument news;
//qDebug()<<apiname << serverreply;
QJsonParseError jsonerror;
news=QJsonDocument::fromJson(serverreply,&jsonerror);
if (news.isArray()){
for (int i=0; i < news.array().count();i++){
QJsonValue newsitem=news[i];
if (apiname=="/api/friendica/notifications"){
QSqlQuery testquery("SELECT status_id FROM news WHERE status_id=" + QString::number(newsitem["id"].toInt()) + " AND messagetype=2 AND username='"+ username +"'",m_db);
if (testquery.first()) {continue;}
}
QSqlQuery query(m_db);
query.prepare("INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,friendica_activities,friendica_activities_self,attachments,friendica_owner) " "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
query.bindValue(0,username);
@ -142,10 +254,10 @@ void UPDATENEWS::store(QByteArray serverreply,QString apiname)
QString sourcedate=newsitem["created_at"].toString();
QString formateddate=sourcedate.mid(0,3)+", "+sourcedate.mid(8,3)+sourcedate.mid(4,3)+sourcedate.mid(25,5)+sourcedate.mid(10,15);
query.bindValue(3,QDateTime::fromString(formateddate,Qt::RFC2822Date).toMSecsSinceEpoch() );
if(newsitem["in_reply_to_status_id"]!=QJsonValue::Null){query.bindValue(4, newsitem["in_reply_to_status_id"].toInt());};
if(newsitem["in_reply_to_status_id"]!=QJsonValue::Null){query.bindValue(4, newsitem["in_reply_to_status_id"].toInt());}
query.bindValue(5,newsitem["source"]);
query.bindValue(6,newsitem["id"].toInt());
if(newsitem["in_reply_to_user_id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["in_reply_to_user_id"].toInt());};
if(newsitem["in_reply_to_user_id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["in_reply_to_user_id"].toInt());}
query.bindValue(8,newsitem["geo"]);
query.bindValue( 9, newsitem["favorited"].toInt());
query.bindValue(10, newsitem["user"]["id"].toInt());
@ -168,7 +280,7 @@ void UPDATENEWS::store(QByteArray serverreply,QString apiname)
for (int e = 0; e < newsitem["friendica_activities"]["attendmaybe"].toArray().count();e++){
attendmaybeArray.append(newsitem["friendica_activities"]["attendmaybe"][e]["url"].toString());
}
};
}
QJsonArray friendica_activities; friendica_activities={likeArray,dislikeArray,attendyesArray,attendnoArray,attendmaybeArray};
QJsonDocument activities; activities.setArray(friendica_activities);
query.bindValue(13,activities.toJson(QJsonDocument::Compact).toBase64());
@ -176,25 +288,114 @@ void UPDATENEWS::store(QByteArray serverreply,QString apiname)
if (newsitem["attachments"]!=QJsonValue::Undefined){
query.bindValue(15, QJsonDocument(newsitem["attachments"].toArray()).toJson(QJsonDocument::Compact).toBase64());
};
}else {
query.bindValue(15, "");
}
query.bindValue(16, newsitem["friendica_owner"]["url"]);
query.exec() ;
if (newsitem["friendica_author"]!=QJsonValue::Undefined){
query.bindValue(16, newsitem["friendica_author"]["url"]);
}else {
query.bindValue(16, newsitem["user"]["url"]);
}
if (apiname=="/api/statuses/replies"){
query.bindValue(1,"3");
}
if (apiname == "/api/direct_messages/all"){
query.bindValue(1,"1");
query.bindValue(5,"Friendica");
if(newsitem["recipient"]["id"]!=QJsonValue::Null){ query.bindValue(7,newsitem["recipient"]["id"].toInt());}
query.bindValue(10, newsitem["sender_id"].toInt());
query.bindValue(11, newsitem["text"].toString().toUtf8().toBase64());
if(newsitem["friendica_parent_uri"]!=QJsonValue::Null){ query.bindValue(12,newsitem["friendica_parent_uri"]);}
query.bindValue(16, newsitem["sender"]["url"]);
}
if (apiname == "/api/friendica/notifications"){
query.bindValue(1,"2");
query.bindValue(3,QDateTime::fromString(newsitem["date"].toString(),"yyyy-MM-dd hh:mm:ss").toMSecsSinceEpoch());
query.bindValue(5,"Friendica");
QJsonObject cleancontact= findNotificationContact(newsitem["url"].toString());
query.bindValue(10, cleancontact["id"].toInt());
query.bindValue(11, newsitem["msg_html"].toString().toUtf8().toBase64());
if(newsitem["parent"]!=QJsonValue::Null){ query.bindValue(12,newsitem["parent"]);}
query.bindValue(16, newsitem["url"]);
}
if(!(query.exec())) {qDebug()<<query.lastError();}
// notifications
if (apiname=="/api/statuses/friends_timeline"){
if(notifylist.contains("notify_Timeline")){
alarm.notify("Home: "+ newsitem["user"]["name"].toString(),newsitem["text"].toString(),0);
}
}
if (apiname=="/api/statuses/replies"){
if(notifylist.contains("notify_Replies")){
alarm.notify("Replies: "+newsitem["user"]["name"].toString(),newsitem["text"].toString(),1);
}
}
if (apiname=="/api/direct_messages/all"){
if(notifylist.contains("notify_DirectMessages")){
alarm.notify("DirectMessage: "+newsitem["sender"]["name"].toString(),newsitem["text"].toString(),2);
}
}
if (apiname=="/api/friendica/notifications"){
if(notifylist.contains("notify_Notifications")){
alarm.notify("Notification: "+newsitem["name"].toString(),newsitem["text"].toString(),3);
}
}
}
else {emit this->error(m_api,QTextCodec::codecForName("utf-8")->toUnicode(serverreply));}
QList<QJsonValue> newcontacts=findNewContacts(news);
//qDebug()<< "new contacts count " << newcontacts.size();
if (newcontacts.size()>0){
updateContacts(newcontacts);
startImagedownload();
connect(&xhr, SIGNAL(downloaded(QString, QString, QString, int)), this, SLOT(updateImageLocation(QString,QString, QString, int)));
} else {
if(m_updateInterval!=0){
syncindex+=1;
startsync();
}
}
}
else {
qDebug()<< "Friendiqa updatenews error " << serverreply;
emit this->error(m_api,QTextCodec::codecForName("utf-8")->toUnicode(serverreply));
syncindex+=1;
startsync();
}
}
}
void UPDATENEWS::updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index){
if (downloadtype=="contactlist"){
QSqlQuery query("UPDATE contacts SET imageLocation='"+ filename +"' WHERE imageurl ='"+imageurl+ "' AND username = '" +username+"'",m_db);
QSqlQuery testquery("SELECT profile_image FROM contacts WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
testquery.first();
//qDebug()<< "update imageurl for " <<imageurl << " from " <<testquery.value(0).toString() <<" to "<< filename <<" index " << index << " newcontactnames.length " <<newcontactnames.length();
QSqlQuery query("UPDATE contacts SET profile_image='"+ filename +"' WHERE profile_image_url ='"+imageurl+ "' AND username = '" +username+"'",m_db);
query.exec();
if (index==(newcontactnames.length()-1)){
newcontactnames.clear();
newcontactimagelinks.clear();
if(m_updateInterval!=0){
syncindex+=1;
startsync();
}
}
}
}
QJsonObject UPDATENEWS::findNotificationContact(QString contacturl){
QSqlQuery query("SELECT id,url FROM contacts WHERE url='"+contacturl+"' AND username='"+ username+"'",m_db);
query.first();
QJsonObject contact{
{"id", query.value(0).toInt()},
{"url", query.value(1).toString()}
};
return contact;
}
QList <QJsonValue> UPDATENEWS::findNewContacts(QJsonDocument news){
@ -204,46 +405,46 @@ QList <QJsonValue> UPDATENEWS::findNewContacts(QJsonDocument news){
imageurls.append(query.value(0).toString());
}
QList<QJsonValue> newcontacts;
//qDebug()<<news.array().count();
//qDebug()<<"updatenews findcontacts news count "<<news.array().count();
for (int i=0; i<news.array().count();i++){
//main contacts
if(imageurls.contains(news[i]["user"]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["user"]["profile_image_url"].toString())){
if(imageurls.contains(news[i]["user"]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["user"]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["user"]);
newcontactimagelinks.append(news[i]["user"]["profile_image_url"].toString());
newcontactimagelinks.append(news[i]["user"]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["user"]["screen_name"].toString());
}
//like/dislike contacts
if (news[i].toObject().contains("friendica_activities") ){
for (int a=0; a < news[i]["friendica_activities"]["like"].toArray().count();a++){
if(imageurls.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString())){
if(imageurls.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["friendica_activities"]["like"][a]);
newcontactimagelinks.append(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString());
newcontactimagelinks.append(news[i]["friendica_activities"]["like"][a]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["friendica_activities"][a]["screen_name"].toString());
}
}
for (int b=0; b < news[i]["friendica_activities"]["dislike"].toArray().count();b++){
if(imageurls.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString())){
if(imageurls.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["friendica_activities"]["dislike"][b]);
newcontactimagelinks.append(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString());
newcontactimagelinks.append(news[i]["friendica_activities"]["dislike"][b]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["friendica_activities"][b]["screen_name"].toString());
}
}
}
//owner contacts
if (news[i].toObject().contains("friendica_owner") ){
if(imageurls.contains(news[i]["friendica_owner"]["profile_image_url"].toString()) || newcontactimagelinks.contains(news[i]["friendica_owner"]["profile_image_url"].toString())){
if (news[i].toObject().contains("friendica_author") ){
if(imageurls.contains(news[i]["friendica_author"]["profile_image_url"].toString().section('?',0,0)) || newcontactimagelinks.contains(news[i]["friendica_owner"]["profile_image_url"].toString().section('?',0,0))){
}
else{
newcontacts.append(news[i]["friendica_owner"]);
newcontactimagelinks.append(news[i]["friendica_owner"]["profile_image_url"].toString());
newcontactnames.append(news[i]["friendica_owner"]["screen_name"].toString());
newcontacts.append(news[i]["friendica_author"]);
newcontactimagelinks.append(news[i]["friendica_author"]["profile_image_url"].toString().section('?',0,0));
newcontactnames.append(news[i]["friendica_author"]["screen_name"].toString());
}
}
}
@ -256,7 +457,7 @@ void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
for (int i=0; i < contacts.count();i++){
QJsonValue contact=contacts[i];
QSqlQuery query(m_db);
qDebug() << "updatecontact " << contact["screen_name"];
//qDebug() << "updatecontact " << contact["screen_name"];
QSqlQuery testquery("SELECT url FROM contacts WHERE username='"+ username +"' AND url='" + contact["url"].toString() +"'",m_db);
if (testquery.first()){
query.prepare("UPDATE contacts SET id=?, name=?, screen_name=?, location=?,imageAge=?,"
@ -269,8 +470,8 @@ void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
query.bindValue(2, contact["screen_name"]);
query.bindValue(3, contact["location"]);
query.bindValue(4, currentTime);
query.bindValue(5, contact["profile_image_url"]);
if(contact["description"].isNull() ){query.bindValue(6,"");}else{query.bindValue(6, contact["description"].toString().toUtf8().toBase64());};
query.bindValue(5, contact["profile_image_url"].toString().section('?',0,0));
if(contact["description"].isNull() ){query.bindValue(6,"");}else{query.bindValue(6, contact["description"].toString().toUtf8().toBase64());}
query.bindValue(7,contact["protected"].toBool());
query.bindValue(8,contact["followers_count"].toInt());
query.bindValue(9,contact["friends_count"].toInt());
@ -290,7 +491,7 @@ void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
query.bindValue(21,contact["network"]);
qint64 timestamp=0;
QString timestamphelper=contact["profile_image_url"].toString();
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){};
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){}
query.bindValue(22,timestamp);
}
@ -307,8 +508,8 @@ void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
query.bindValue(3, contact["screen_name"]);
query.bindValue(4, contact["location"]);
query.bindValue(5, currentTime);
query.bindValue(6, contact["profile_image_url"]);
if(contact["description"].isNull() ){query.bindValue(7,"");}else{query.bindValue(7, contact["description"].toString().toUtf8().toBase64());};
query.bindValue(6, contact["profile_image_url"].toString().section('?',0,0));
if(contact["description"].isNull() ){query.bindValue(7,"");}else{query.bindValue(7, contact["description"].toString().toUtf8().toBase64());}
query.bindValue(8,"none");
query.bindValue(9, contact["url"].toString());
query.bindValue(10,contact["protected"].toBool());
@ -331,12 +532,12 @@ void UPDATENEWS::updateContacts(QList<QJsonValue> contacts){
query.bindValue(25, 0);
qint64 timestamp=0;
QString timestamphelper=contact["profile_image_url"].toString();
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){};
try {timestamp=timestamphelper.mid(timestamphelper.indexOf("?ts")+4,timestamphelper.length()).toUInt();} catch(...){}
query.bindValue(26,timestamp);
}
query.exec() ;
}
emit this->success(m_api);
}
QString UPDATENEWS::url() const
@ -346,6 +547,7 @@ QString UPDATENEWS::url() const
void UPDATENEWS::startImagedownload()
{
//qDebug() << "start image download";
xhr.setDownloadtype("contactlist");
xhr.setFilelist(newcontactimagelinks);
xhr.setContactlist(newcontactnames);
@ -355,5 +557,12 @@ void UPDATENEWS::startImagedownload()
void UPDATENEWS::showError(QString data, QString url,QString api, int code )
{
qDebug() << "showerror " << api << " data " << data;
emit this->error(api,data);
if (api!=m_api || xhr.downloadtype()!=""){} else{
if(m_updateInterval!=0){
syncindex+=1;
startsync();
}
}
}

View file

@ -37,6 +37,7 @@
#include <QSqlDatabase>
#include "xhr.h"
#include "alarm.h"
//#include "AndroidNative/systemdispatcher.h"
class UPDATENEWS : public QObject
{
@ -53,38 +54,25 @@ public:
signals:
// void loginChanged(QString login);
void urlChanged(QString url);
void success(QString api);
void error(QString api, QString content);
//void apiChanged(QString api);
// //network
// void success(QByteArray data, QString api);
// void error(QString data, QString url,QString api, int code);
// //network
void quitapp();
public slots:
void setUrl(QString url);
//void setLogin();
//QString login();
void setDatabase();
void login();
void timeline();
void replies();
void startsync();
void directmessages();
void notifications();
//void startservice(QString type,QVariantMap map);
void startImagedownload();
void updateImageLocation(QString downloadtype,QString imageurl, QString filename, int index);
void store(QByteArray serverreply,QString apiname);
void showError(QString data, QString url,QString api, int code);
// //network
// void onReplyError(QNetworkReply::NetworkError code);
// void onReplySuccess();
// void onReadyRead();
// void onSSLError(const QList<QSslError> &errors);
// void setParam(QString name, QString value);
// void clearParams();
// void get();
// //network
private:
QString m_url;
@ -92,9 +80,13 @@ private:
QString m_imagedir;
QString m_login;
QString username;
int syncindex;
QSqlDatabase m_db;
QList<QString> synclist;
QList <QString> notifylist;
QList<QJsonValue> findNewContacts(QJsonDocument news);
int updateInterval;
QJsonObject findNotificationContact(QString imagelink);
int m_updateInterval;
//void timeline();
//void store(QByteArray serverreply,QString apiname);
void updateContacts(QList<QJsonValue> contacts);
@ -103,19 +95,6 @@ private:
ALARM alarm;
QList<QString> newcontactimagelinks;
QList<QString> newcontactnames;
// //network
// QHash<QString, QString> params;
// QHash<QString, QString> files;
// QByteArray buffer;
// QNetworkAccessManager manager;
// QNetworkRequest request;
// QNetworkReply *reply;
// QNetworkConfiguration nc;
// QString bufferToString();
// //network
};
#endif // UPDATENEWS_H

View file

@ -1,5 +1,5 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify

View file

@ -1,5 +1,5 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify

View file

@ -1,5 +1,5 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
@ -154,7 +154,7 @@ QString XHR::downloadtype() const
return m_downloadtype;
}
QString XHR::networktype() const
QString XHR::networktype()
{
return nc.bearerTypeFamily() + nc.bearerTypeName();
}
@ -184,7 +184,6 @@ void XHR::download()
request.setRawHeader("Authorization", headerData.toLocal8Bit());
}
request.setUrl(requrl);
//qDebug() << requrl;
reply = manager.get(request);
reply->ignoreSslErrors();
connect(reply, &QNetworkReply::readyRead,this, &XHR::onReadyRead);
@ -202,10 +201,11 @@ void XHR::get()
while(i.hasNext()) {
i.next();
query.addQueryItem(i.key(), i.value());
//qDebug()<<i.key() << " value "<< i.value();
}
QUrl requrl(m_url+m_api);
qDebug() << requrl;
//qDebug() << "API "<< requrl<<m_api;
requrl.setQuery(query);
QByteArray loginData = m_login.toLocal8Bit().toBase64();
QString headerData = "Basic " + loginData;
@ -229,19 +229,19 @@ void XHR::getlist()
else {
XHR::setUrl(m_filelist.at(dlindex));}
XHR::download();
} else {dlindex=0;}
} else {dlindex=0;m_downloadtype="";m_contactlist.clear();m_filelist.clear();}
}
void XHR::post()
{
qDebug() << "start post to " << m_url;
//qDebug() << "start post to " << m_url;
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHashIterator<QString, QString> iparams(params);
while(iparams.hasNext()) {
iparams.next();
qDebug() << "\t add param " << iparams.key() << " : " << iparams.value();
//qDebug() << "\t add param " << iparams.key() << " : " << iparams.value();
QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + iparams.key() + "\""));
@ -256,7 +256,7 @@ void XHR::post()
ifiles.next();
uimg.setSource(ifiles.value());
qDebug() << "\t image: " << uimg.mimetype() << ", " << ifiles.key();
//qDebug() << "\t image: " << uimg.mimetype() << ", " << ifiles.key();
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(uimg.mimetype()));
@ -290,14 +290,14 @@ void XHR::onReplyError(QNetworkReply::NetworkError code)
void XHR::onReplySuccess()
{
qDebug() << "!";
//emit this->success( bufferToString(), m_api);
emit this->success( buffer, m_api);
emit this->success(buffer, m_api);
buffer.clear();
// reply->deleteLater();
}
void XHR::onRequestFinished()
{
qDebug()<<"download requestFinished ";
// Save the file here
if (buffer.isNull()){qDebug() << "File empty"<<m_url; buffer.clear(); emit this->error(m_downloadtype,m_url,m_api,1);}
else if (m_downloadtype=="picturelist") {

View file

@ -1,5 +1,5 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// https://github.com/lubuwest/Friendiqa
// Copyright (C) 2017 Marco R. <thomasschmidt45@gmx.net>
//
// This program is free software: you can redistribute it and/or modify
@ -49,7 +49,7 @@ class XHR : public QObject
Q_PROPERTY(QList<QString> contactlist READ contactlist WRITE setContactlist NOTIFY contactlistChanged)
Q_PROPERTY(QList<QString> filelist READ filelist WRITE setFilelist NOTIFY filelistChanged)
Q_PROPERTY(QString downloadtype READ downloadtype WRITE setDownloadtype NOTIFY downloadtypeChanged)
Q_PROPERTY(QString networktype READ networktype NOTIFY networktypeChanged)
Q_PROPERTY(QString networktype READ networktype() NOTIFY networktypeChanged)
public:
@ -65,7 +65,7 @@ public:
QList<QString> filelist() const;
QString imagedir() const;
QString downloadtype() const;
QString networktype() const;
QString networktype();
signals:
void urlChanged();
@ -98,6 +98,7 @@ public slots:
void get();
void getlist();
void download();
// void networktype();
private slots:

View file

@ -13,7 +13,7 @@
TEMPLATE = app
TARGET = friendiqa
CONFIG += release
QT += qml quick gui widgets sql webview
QT += qml quick gui widgets sql webview dbus
SOURCES += common/friendiqa.cpp \
common/uploadableimage.cpp \
@ -21,7 +21,7 @@ SOURCES += common/friendiqa.cpp \
common/filesystem.cpp \
common/remoteauthasyncimageprovider.cpp \
common/updatenews.cpp \
common/alarmandroid.cpp
common/alarmlinux.cpp
RESOURCES = application.qrc
@ -55,3 +55,5 @@ DISTFILES += \
qml/photoqml/*.qml \
qml/configqml/*.qml \
js/*.js \
qml/newsqml/NewsStack.qml \
qml/configqml/SyncComponent.qml

View file

@ -125,7 +125,8 @@ function friendicaRemoteAuthRequest(login,url,c_url,rootwindow,callback) {
function readData(database,table,username,callback,filter,filtervalue, sort) { // reads and applies data from DB
if (filter){
var where = " AND "+ filter +" = '" + filtervalue+"'";
if (username){var where = " AND "+ filter +" = '" + filtervalue+"'";} else{
var where = " WHERE "+ filter +" = '" + filtervalue+"'";}
} else { var where="";}
if (username){
var user = ' where username= "'+ username +'"';
@ -165,7 +166,7 @@ var where = " AND "+ filter +" = '" + filtervalue+"'";
});
}
function showMessage(header,message,rootwindow){print(message);
function showMessage(header,message,rootwindow){//print(message);
var cleanmessage=message.replace(/"/g,"-");
if(cleanmessage.length>200){cleanmessage=cleanmessage.slice(0,200)+'...'}
var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+cleanmessage+'"}';

View file

@ -36,7 +36,7 @@ function showFriends(db) {
}
function displayFriends(obj){
for (var i=0; i<obj.length; i++){
print(obj[i]);
//print(obj[i]);
if (obj[i]) {friendsModel.append({"friendName": obj[i]});
};

View file

@ -65,10 +65,15 @@ function requestGroups(login,database,rootwindow,callback){
});
})}
function listFriends(login,database,callback){
function listFriends(login,database,callback,filter){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var filtertext='';
try {filtertext=' AND screen_name like "' + filter+'%"'}catch(e){}
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from contacts WHERE username="'+login.username+'" AND isFriend>0'); // check for friends
//var result = tx.executeSql('SELECT * from contacts WHERE username="'+login.username+'" AND isFriend>0'+filtertext);
//print('SELECT * from contacts WHERE username="'+login.username+'"'+filtertext);
var result = tx.executeSql('SELECT * from contacts WHERE username="'+login.username+'" AND isFriend>0'+filtertext);
// check for friends
var contactlist=[];
for (var i=0;i<result.rows.length;i++){
contactlist.push(result.rows.item(i))
@ -88,13 +93,13 @@ function deleteGroup(login,database,rootwindow,group, callback){
});
}})}
function getLastNews(login,database){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var lastnewsid=0;
db.transaction( function(tx) {
function getLastNews(login,database,callback){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var lastnewsid=0;
db.transaction( function(tx) {
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" AND messagetype=0 ORDER BY status_id DESC LIMIT 1');
try{lastnewsid=result.rows.item(0).status_id;}catch(e){};
return lastnewsid
try{lastnewsid=result.rows.item(0).status_id;}catch(e){print(e)};
callback(lastnewsid)
})
}
@ -163,11 +168,11 @@ function findNewContacts(news,contacts){
}
}
if(news[i].hasOwnProperty('friendica_owner')){
var owner_url=news[i].friendica_owner.url;
if(news[i].hasOwnProperty('friendica_author')){
var owner_url=news[i].friendica_author.url;
if(contacts.indexOf(owner_url)==-1 && !(inArray(newContacts,"url",owner_url))){
news[i].friendica_owner.isFriend=0;
newContacts.push(news[i].friendica_owner);
news[i].friendica_author.isFriend=0;
newContacts.push(news[i].friendica_author);
}
}
}
@ -178,7 +183,7 @@ function storeNews(login,database,news,rootwindow){
// save news after contacts download, call next function
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
for (var i=0;i<news.length;i++){
//print('store news data for ' + news[i].id+JSON.stringify(news[i].friendica_activities));
//print('store news data for ' + news[i].id+JSON.stringify(news[i].friendica_author));
//var ausdruck=news[i];
var likearray=[];var dislikearray=[];var attendyesarray=[];var attendnoarray=[];var attendmaybearray=[];
if(news[i].hasOwnProperty('friendica_activities')){
@ -191,12 +196,12 @@ function storeNews(login,database,news,rootwindow){
var friendica_activities=[likearray,dislikearray,attendyesarray,attendnoarray,attendmaybearray]
var attachments="";if (news[i].attachments){attachments=Qt.btoa(JSON.stringify(news[i].attachments))}
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where username="'+login.username+'" AND status_id = "'+news[i].id+'" AND messagetype=0'); // check for news id
var result = tx.executeSql('SELECT * from news where username="'+login.username+'" AND status_id = "'+news[i].id+'" AND messagetype='+news[i].messagetype); // check for news id
if(result.rows.length === 1) {// use update
//print(news[i].id +' news exists, update it'+'UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", created_at="'+Date.parse(cleanDate(news[i].created_at))+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",friendica_activities="'+Qt.btoa(JSON.stringify(friendica_activities))+'",attachments="'+attachments+'",friendica_owner="'+news[i].friendica_owner.url+'" where username="'+login.username+'" AND status_id="'+news[i].status_id+'" AND messagetype=0')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", created_at="'+news[i].created_at+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",friendica_activities="'+Qt.btoa(JSON.stringify(friendica_activities))+'",attachments="'+attachments+'",friendica_owner="'+news[i].friendica_owner.url+'" where username="'+login.username+'" AND status_id="'+news[i].status_id+'" AND messagetype=0');
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype='+news[i].messagetype+', text="'+Qt.btoa(news[i].text)+'", created_at="'+news[i].created_at+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",friendica_activities="'+Qt.btoa(JSON.stringify(friendica_activities))+'",attachments="'+attachments+'",friendica_owner="'+news[i].friendica_author.url+'" where username="'+login.username+'" AND status_id="'+news[i].status_id+'" AND messagetype=0');
} else {// use insert
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,friendica_activities,friendica_activities_self,attachments,friendica_owner) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,0,Qt.btoa(news[i].text),news[i].created_at, news[i].in_reply_to_status_id, news[i].source, news[i].id,news[i].in_reply_to_user_id,news[i].geo,news[i].favorited, news[i].user.id,Qt.btoa(news[i].statusnet_html),news[i].statusnet_conversation_id, Qt.btoa(JSON.stringify(friendica_activities)),"[]",attachments,news[i].friendica_owner.url])}})
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,friendica_activities,friendica_activities_self,attachments,friendica_owner) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,news[i].messagetype,Qt.btoa(news[i].text),news[i].created_at, news[i].in_reply_to_status_id, news[i].source, news[i].id,news[i].in_reply_to_user_id,news[i].geo,news[i].favorited, news[i].user.id,Qt.btoa(news[i].statusnet_html),news[i].statusnet_conversation_id, Qt.btoa(JSON.stringify(friendica_activities)),"[]",attachments,news[i].friendica_author.url])}})
}
// getDirectMessage(login,database,rootwindow,callback)
}
@ -260,35 +265,41 @@ function getActivitiesUserData(allcontacts,userUrlArray){//print(JSON.stringify(
return helpArray
}
function newsfromdb(database,user,callback,contact,stop_time){
function newsfromdb(database,login,messagetype,callback,contact,stop_time){
// return news before stop_time (used by More button), in brackets of 20 entries, or by specified contact
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" AND messagetype=0 ORDER BY status_id DESC LIMIT 1');
try{var lastid=result.rows.item(0).status_id;}catch(e){var lastid=0};
if (!stop_time){var stop="";
try{var rs = tx.executeSql('select created_at from news WHERE username="'+user+'" ORDER BY created_at DESC LIMIT 1');
try{var rs = tx.executeSql('select created_at from news WHERE username="'+login.username+'" AND messagetype="'+messagetype+'" ORDER BY created_at DESC LIMIT 1');
stop="<="+rs.rows.item(0).created_at}catch(e){stop="<99999999999999"}}
else{var stop="<"+stop_time}
var contactfilter="";if(contact){contactfilter=" AND (uid='"+contact+"' OR friendica_owner='"+contact+"')"}
//print('select * from news WHERE username="'+username+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
var newsrs=tx.executeSql('select * from news WHERE username="'+user+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
var newsrs=tx.executeSql('select * from news WHERE username="'+login.username+'" AND messagetype="'+messagetype+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
var newsArray=[];
var allcontacts=getAllContacts(database,user);
var allcontacts=getAllContacts(database,login.username);
for(var i = 0; i < newsrs.rows.length; i++) {
newsArray.push(newsrs.rows.item(i));
newsArray[i].statusnet_html=Qt.atob(newsArray[i].statusnet_html);
newsArray[i].text=Qt.atob(newsArray[i].text);
newsArray[i].id=newsArray[i].status_id;
newsArray[i]=fetchUsersForNews(database,user,newsArray[i],allcontacts);
if (newsArray[i].attachments!==null){newsArray[i].attachments=JSON.parse(Qt.atob(newsArray[i].attachments))};
newsArray[i].friendica_author=newsArray[i].friendica_owner
newsArray[i]=fetchUsersForNews(database,login.username,newsArray[i],allcontacts);
if (newsArray[i].attachments!="" && newsArray[i].attachments!==null){newsArray[i].attachments=JSON.parse(Qt.atob(newsArray[i].attachments))};
}
callback(newsArray)});
callback(newsArray,lastid)});
}
function fetchUsersForNews(database,username,news,allcontacts){//print(JSON.stringify(news))
function fetchUsersForNews(database,username,news,allcontacts){//print("fetchusers "+JSON.stringify(news))
news.user=objFromArray(allcontacts,"id",news.uid);
if(news.in_reply_to_user_id){news.reply_user=objFromArray(allcontacts,"id",news.in_reply_to_user_id)}
//news.friendica_owner_object=objFromArray(allcontacts,"url",news.friendica_owner);
news.friendica_owner=objFromArray(allcontacts,"url",news.friendica_owner);
news.friendica_author=objFromArray(allcontacts,"url",news.friendica_author);
if (news.messagetype==0){
var friendicaArray=JSON.parse(Qt.atob(news.friendica_activities));
delete news.friendica_activities;
@ -413,7 +424,7 @@ function conversationfromdb(database,user,conversationId,callback){
newsArray[i].text=Qt.atob(newsArray[i].text);
newsArray[i].id=newsArray[i].status_id;
newsArray[i]=fetchUsersForNews(database,user,newsArray[i],allcontacts);
if (newsArray[i].attachments!==null){newsArray[i].attachments=JSON.parse(Qt.atob(newsArray[i].attachments))};
if (helpernews.attachments!="" && newsArray[i].attachments!==null){newsArray[i].attachments=JSON.parse(Qt.atob(newsArray[i].attachments))};
}
callback(newsArray)})
}
@ -443,32 +454,36 @@ function requestFavorites(login,database,contacts,rootwindow,callback){
// callback(newsArray);
// }})}
function chatsfromdb(database,user,callback,stop_time){
function chatsfromdb(database,login,messagetype,callback,stop_time){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
if (!stop_time){var stop="";
try{var rs = tx.executeSql('select created_at from news WHERE username="'+username+'" ORDER BY created_at DESC LIMIT 1');
try{var rs = tx.executeSql('select created_at from news WHERE username="'+login.username+'" AND messagetype="'+messagetype+'" ORDER BY created_at DESC LIMIT 1');
stop="<="+rs.rows.item(0).created_at}catch(e){stop="<99999999999999"}}
else{var stop="<"+stop_time}
var conversationsrs=tx.executeSql('select DISTINCT statusnet_conversation_id from news WHERE username="'+user+'" AND created_at'+stop+' ORDER BY created_at DESC LIMIT 20'); //+' ORDER BY created_at DESC LIMIT 20');
var conversationsrs=tx.executeSql('select DISTINCT statusnet_conversation_id from news WHERE username="'+login.username+'" AND created_at'+stop+' AND messagetype="'+messagetype+'" ORDER BY created_at DESC LIMIT 20'); //+' ORDER BY created_at DESC LIMIT 20');
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" AND messagetype=0 ORDER BY status_id DESC LIMIT 1');
try{var lastid=result.rows.item(0).status_id;}catch(e){var lastid=0};
var conversations=[];
for(var i = 0; i < conversationsrs.rows.length; i++) {
conversations.push(conversationsrs.rows.item(i).statusnet_conversation_id);
}
var newsArray=[];
var allcontacts=getAllContacts(database,user);
var allcontacts=getAllContacts(database,login.username);
for(var j = 0; j< conversations.length; j++) {
var newsrs=tx.executeSql('select * from news WHERE username="'+user+'" AND statusnet_conversation_id="'+conversations[j] +'" ORDER BY created_at ASC');
var newsrs=tx.executeSql('select * from news WHERE username="'+login.username+'" AND statusnet_conversation_id="'+conversations[j] +'" AND messagetype="'+messagetype+'" ORDER BY created_at ASC');
var helpernews=newsrs.rows.item(0);
helpernews.newscount=newsrs.rows.length;
helpernews=fetchUsersForNews(database,user,helpernews,allcontacts);
helpernews=fetchUsersForNews(database,login.username,helpernews,allcontacts);
helpernews.statusnet_html=Qt.atob(helpernews.statusnet_html);
helpernews.text=Qt.atob(helpernews.text);
helpernews.id=helpernews.status_id;
if (helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
if (helpernews.attachments!="" && helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
newsArray.push(helpernews);
}
callback(newsArray);
callback(newsArray,lastid);
})}
@ -495,7 +510,7 @@ function allchatsfromdb(database,user,callback){
helpernews.statusnet_html=Qt.atob(helpernews.statusnet_html);
helpernews.text=Qt.atob(helpernews.text);
helpernews.id=helpernews.status_id;
if (helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
if (helpernews.attachments!="" && helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
newsArray.push(helpernews);
countArray.push(newsrs.rows.length)
}
@ -520,7 +535,7 @@ function oldchatfromdb(database,user,conversationId,lastpost,allcontacts,callbac
helpernews.statusnet_html=Qt.atob(helpernews.statusnet_html);
helpernews.text=Qt.atob(helpernews.text);
helpernews.id=helpernews.status_id;
if (helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
if (helpernews.attachments!="" && helpernews.attachments!==null){helpernews.attachments=JSON.parse(Qt.atob(helpernews.attachments))};
callback(helpernews,newscount);}
// var conversationobject={news:helpernews,newscount:newscount};
// return conversationobject;

View file

@ -53,9 +53,12 @@ else{
// newsitemobject.user.profile_image_url="";
// newsitemobject.user.name="";
// }
var forumname="";try{if (newsitemobject.messagetype==0&&newsitemobject.hasOwnProperty('friendica_owner')&&((newsitemobject.friendica_owner.url)!=(newsitemobject.user.url))){
//print(newsitemobject.friendica_owner+" Friendica Owner "+JSON.stringify(newsitemobject));
forumname=" via "+newsitemobject.friendica_owner.name
var forumname="";
try{if (newsitemobject.messagetype==0&&newsitemobject.hasOwnProperty('friendica_author')&&
((newsitemobject.friendica_author.url)!=(newsitemobject.user.url))&&((newsitemobject.friendica_author.url)!=null)){
print(" Friendica Author "+JSON.stringify(newsitemobject.friendica_author));
forumname=" via "+newsitemobject.user.name;
newsitemobject.user=newsitemobject.friendica_author;
}}catch(e){print("forum name "+e)}
var likeText="";var dislikeText="";var attendyesText="";var attendnoText="";var attendmaybeText=""; var self={};
try{if (newsitemobject.messagetype==0&&newsitemobject.hasOwnProperty('friendica_activities')){
@ -166,7 +169,6 @@ else{
// }
newsitemobject.attachmentList=attachmentList;
var seconds=(msg.currentTime-newsitemobject.created_at)/1000;
var timestring="";
if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");}

View file

@ -38,7 +38,7 @@
function initDatabase(database) { // initialize the database object
var db =Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
print('initDatabase()'+database[0]+database[1]+database[2]+database[3])
//print('initDatabase()'+database[0]+database[1]+database[2]+database[3])
db.transaction( function(tx) {
//var version=tx.executeSql('PRAGMA user_version');print(JSON.stringify(version.rows.item(0)))
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)');
@ -194,13 +194,11 @@ function storeConfig(database,obj) { // stores config to DB
//print(JSON.stringify(obj));
var result = tx.executeSql('SELECT * from config WHERE username="'+obj.username+'"');
if(result.rows.length === 1) {// use update
var result2 = tx.executeSql('UPDATE config SET server="'+obj.server+'",password="'+obj.password+'", imagestore="'+obj.imagestore+'", maxnews='+obj.maxnews+', timerInterval='+obj.interval+', newsViewType="'+obj.newsViewType+'", isActive=0 WHERE username="'+obj.username +'"');
var result2 = tx.executeSql('UPDATE config SET server="'+obj.server+'",password="'+obj.password+'", imagestore="'+obj.imagestore+'", maxnews=0, timerInterval=0, newsViewType="'+obj.newsViewType+'", isActive=0 WHERE username="'+obj.username +'"');
var result3 = tx.executeSql('UPDATE config SET isActive=1 WHERE username !="'+obj.username +'"');
var result4 = tx.executeSql('UPDATE config SET maxnews='+obj.maxnews);
} else {// use insert print('... does not exists, create it')
var result2 = tx.executeSql('INSERT INTO config VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)', [obj.server, obj.username, obj.password, obj.imagestore, obj.maxnews, obj.interval,obj.newsViewType,0,"[[],[],[],[]]",0,"","",""]);
var result2 = tx.executeSql('INSERT INTO config VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)', [obj.server, obj.username, obj.password, obj.imagestore, 0, 0,obj.newsViewType,0,"[[],[],[],[]]",0,"","",""]);
var result3 = tx.executeSql('UPDATE config SET isActive=1 WHERE username !="'+obj.username +'"');
var result4 = tx.executeSql('UPDATE config SET maxnews='+obj.maxnews);
}
})}
@ -283,7 +281,7 @@ function readConfig(database,callback,filter,filtervalue) { // reads config
for(var i = 0; i < rs.rows.length; i++) {
rsArray.push(rs.rows.item(i))
}
var rsObject={server:rsArray[0].server,username:rsArray[0].username, password:rsArray[0].password,imagestore:rsArray[0].imagestore,maxnews:rsArray[0].maxnews,isActive:rsArray[0].isActive,timerInterval:rsArray[0].timerInterval, newsViewType:rsArray[0].newsViewType,permissions:JSON.parse(rsArray[0].permissions),maxContactAge:rsArray[0].maxContactAge,APIVersion:rsArray[0].APIVersion,addons:rsArray[0].addons};
var rsObject={server:rsArray[0].server,username:rsArray[0].username, password:rsArray[0].password,imagestore:rsArray[0].imagestore,isActive:rsArray[0].isActive, newsViewType:rsArray[0].newsViewType,permissions:JSON.parse(rsArray[0].permissions),maxContactAge:rsArray[0].maxContactAge,APIVersion:rsArray[0].APIVersion,addons:rsArray[0].addons};
} else {var rsObject=""}
callback(rsObject)}}
)
@ -318,6 +316,7 @@ function updateglobaloptions(database,key,value){
result = tx.executeSql('INSERT INTO globaloptions (k,v) VALUES (?,?)', [key,value])
}
})
root.globaloptions[key]=value;
}
function deleteConfig(database,userobj,callback) { // delete user data from DB
@ -338,8 +337,9 @@ function deleteConfig(database,userobj,callback) { // delete user data from DB
function cleanNews(database,callback){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
db.transaction( function(tx) {
var maxnewsrs = tx.executeSql("SELECT DISTINCT maxnews FROM config");
var maxnews=maxnewsrs.rows.item(0).maxnews;
//var maxnewsrs = tx.executeSql("SELECT DISTINCT maxnews FROM config");
var maxnewsrs = tx.executeSql("SELECT v FROM globaloptions WHERE k='max_news'");
var maxnews=1000; if(maxnewsrs.rows.length>0){ maxnews=maxnewsrs.rows.item(0).v};
var newscountrs = tx.executeSql('SELECT COUNT(*) from news');
var newscount = newscountrs.rows.item(0)["COUNT(*)"];//print("newscount "+newscount)
if (newscount>maxnews){
@ -384,6 +384,7 @@ function updateContactInDB(login,database,isFriend,contact){// for newstab and f
}
function processNews(api,data){
//print(api + data);
try{var newslist=JSON.parse(data)} catch(e){newsBusy.running=false;};
if (data==""){}
else if (typeof(newslist)=='undefined'){
@ -393,6 +394,7 @@ function processNews(api,data){
Helperjs.showMessage(qsTr("JSON status Error"),"API:\n" +login.server+api+"\n Return: \n"+data,root)
}
else if (!(Array.isArray(newslist))){
//print("processNews not array"+newslist+JSON.stringify(newslist));
replytimer.restart()
}
else {
@ -407,6 +409,8 @@ function processNews(api,data){
newslist[n].uid=newslist[n].sender.id;
newslist[n].statusnet_conversation_id=newslist[n].friendica_parent_uri;
newslist[n].user=cleanUser(newslist[n].sender);
newslist[n].friendica_owner=newslist[n].user;
newslist[n].friendica_author=newslist[n].user;
newslist[n].statusnet_html=newslist[n].text;
}}
else if (api=="/api/friendica/notifications"){
@ -418,6 +422,8 @@ function processNews(api,data){
newslist[n].user={"profile_image_url": newslist[n].photo,"name": newslist[n].name," url":newslist[n].url, "created_at":newslist[n].date};
newslist[n].user=cleanUser(newslist[n].user);
}
newslist[n].friendica_author=newslist[n].user;
newslist[n].friendica_owner=newslist[n].user;
newslist[n].statusnet_html=newslist[n].msg_html;
newslist[n].text=newslist[n].msg;
}
@ -427,8 +433,9 @@ function processNews(api,data){
var commentCount=[];
for (var n in newslist){
newslist[n].created_at=Date.parse(Newsjs.cleanDate(newslist[n].created_at));
newslist[n].messagetype=0;
newslist[n].user=cleanUser(newslist[n].user)
if (api=="/api/statuses/replies"){newslist[n].messagetype=3}else{newslist[n].messagetype=0;}
newslist[n].friendica_author=cleanUser(newslist[n].friendica_author);
newslist[n].user=cleanUser(newslist[n].user);
if(newslist[n].in_reply_to_user_id){newslist[n].reply_user=Newsjs.objFromArray(allcontacts,"id",newslist[n].in_reply_to_user_id)}
//print (JSON.stringify(newslist[n].user))
if(newslist[n].hasOwnProperty('friendica_activities')){
@ -448,8 +455,8 @@ function processNews(api,data){
newslist[n].friendica_activities.attendmaybe[r]=cleanUser(newslist[n].friendica_activities.attendmaybe[r]);
}
}
if(!(newslist[n].hasOwnProperty('friendica_owner'))){
newslist[n].friendica_owner=newslist[n].user
if(!(newslist[n].hasOwnProperty('friendica_author'))){
newslist[n].friendica_author=newslist[n].user
}
var conversationindex=conversationIds.indexOf(newslist[n].statusnet_conversation_id);
@ -488,11 +495,13 @@ function processNews(api,data){
else if (api=="/api/statuses/user_timeline"){
newstab.contactposts=newslist
}
else if (newstab.newstabstatus==="Conversations"){
showNews(chatlist);root.news=newslist}
else {showNews(newslist);root.news=newslist};
else if ((api!="/api/direct_messages/all")&&(api!="/api/friendica/notifications")&&(newstab.newstabstatus==="Conversations")){
showNews(chatlist);root.news=newslist
}
else {
showNews(newslist);root.news=newslist};
var newstabarray=["Conversations","Favorites","Timeline","DirectMessage"];
var newstabarray=["Conversations","Favorites","Timeline","DirectMessage","Replies"];
if (newstabarray.indexOf(newstab.newstabstatus)>-1){contacttimer.start()}
}
@ -509,26 +518,28 @@ function cleanUser(user){
}
function updateView(viewtype){
newsBusy.running=true;
//messageSend.state="";
//newsBusy.running=true;
//downloadNotice.text="xhr start "+Date.now()
switch(viewtype){
case "Conversations":
var lastnews=Newsjs.getLastNews(login,db);
Newsjs.getLastNews(login,db,function(lastnews){
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/statuses/friends_timeline");
xhr.clearParams();
xhr.setParam("since_id",lastnews);
xhr.setParam("count",50)
xhr.setParam("count",50)});
break;
case "Timeline":
var lastnews=Newsjs.getLastNews(login,db);
var lastnews=Newsjs.getLastNews(login,db,function(lastnews){
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/statuses/friends_timeline");
xhr.clearParams();
xhr.setParam("since_id",lastnews);
xhr.setParam("count",50)
});
break;
case "Search":
xhr.setLogin(login.username+":"+Qt.atob(login.password));
@ -566,7 +577,7 @@ function updateView(viewtype){
xhr.clearParams();
break;
default:
var lastnews=Newsjs.getLastNews(login,db);
Newsjs.getLastNews(login,db,function(lastnews){
xhr.setLogin(login.username+":"+Qt.atob(login.password));
xhr.setUrl(login.server);
xhr.setApi("/api/statuses/friends_timeline");
@ -574,6 +585,7 @@ function updateView(viewtype){
xhr.setParam("since_id",lastnews);
xhr.setParam("count",50)
newstab.newstabstatus="Conversations";
});
}
xhr.get();

View file

@ -29,8 +29,8 @@
// 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.0
import QtQuick.Controls 1.4
import QtQuick 2.11
//import QtQuick.Controls 2.4
Item {
id: calendarDay

View file

@ -30,10 +30,10 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 2.3
import QtQuick.Controls 2.4
import QtQml 2.2
import Qt.labs.calendar 1.0
import QtQuick.Controls 1.2 as Oldcontrol
//import QtQuick.Controls 1.2 as Oldcontrol
import QtQuick.Layouts 1.3
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
@ -42,9 +42,10 @@ import "qrc:/qml/genericqml"
Rectangle {
id:calendarrectangle
y:1
width:root.width-mm
height:root.height-5*mm
// y:1
// width:root.width-mm
// height:root.height-5*mm
anchors.fill: parent
color: '#fff'
property date currentTime: new Date()
property int offsetTime: currentTime.getTimezoneOffset() * 60 * 1000
@ -83,30 +84,35 @@ Rectangle {
}
BlueButton{
MButton{
id: updateEvents
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right:calendartabstatusButton.left
anchors.rightMargin:mm
height: 6*mm
width: 8*mm
text:"\uf021"
onClicked: {
Service.getEvents(db,login, calendartab,function(){
showEvents("")
})}}
BlueButton{
MButton{
id: calendartabstatusButton
anchors.top: parent.top
anchors.topMargin: 0.5*mm
anchors.right: parent.right
anchors.rightMargin:2*mm
height: 6*mm
width: Math.max(10*mm,implicitWidth)
text: calendartab.calendartabstatus=="Events"?qsTr("Events"):calendartabstatus
Oldcontrol.Menu {
Menu {
id:calendartabmenu
Oldcontrol.MenuItem {
width: 40*mm
MenuItem {
text: qsTr("Own Calendar")
font.pixelSize: 3*mm
onTriggered: {
calendartab.calendartabstatus="Events";
// calendartabstatusButton.text=qsTr("own Calendar");
@ -146,6 +152,7 @@ Rectangle {
DayOfWeekRow{
locale: monthgrid.locale
Layout.fillWidth: true
font.pixelSize: 3*mm
}
MonthGrid {

View file

@ -30,7 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls 2.4
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
@ -45,12 +45,14 @@ Rectangle{
y:mm
property var daylist:[]
BlueButton{
MButton{
id:closeButton
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
height: 6*mm
width: 8*mm
text: "\uf057"
onClicked:{eventList.destroy()}
}

View file

@ -0,0 +1,463 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 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.7
import QtQuick.Dialogs 1.2
import QtQuick.Controls 2.4
import "qrc:/js/service.js" as Service
import "qrc:/js/layout.js" as Layoutjs
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/configqml"
import "qrc:/qml/genericqml"
Page{
id:accountPage
width: root.width
height: root.height
property var users:[]
property var userdata: ({})
function setServericon(server){
try {Helperjs.friendicaWebRequest(server+"/api/statusnet/config",accountPage, function (obj){
var serverdata = JSON.parse(obj);
servericon.visible=true;
servericon.source=serverdata.site.logo})} catch(e){print(e)}
}
Button{
id:userButton
height: 8*mm
text:qsTr("User")
font.pixelSize: 3*mm
x: mm
y: mm
width: root.width/2
onClicked:{
var useritems="";
for (var i=0;i<accountPage.users.length;i++){
useritems=useritems+"MenuItem{font.pixelSize: 3*mm; text:'"+accountPage.users[i].username+
"'; onTriggered: {Service.readConfig(db,function(obj){
userButton.text=obj.username;
servername.text=obj.server;
accountPage.setServericon(obj.server);
username.text= obj.username;
password.text=Qt.atob(obj.password);
imagestore.text=obj.imagestore;
newsTypeField.text=obj.newsViewType;
if( obj.isActive==0){userButton.font.bold='true'} else {userButton.font.bold='false'}
},'username','"+ accountPage.users[i].username+"')}}"
}
var menuString="import QtQuick.Controls 2.4;import 'qrc:/js/service.js' as Service; Menu {"+useritems+"}";
var userlistObject=Qt.createQmlObject(menuString,accountPage,"usermenuOutput")
userlistObject.popup() }
}
Text {
text: qsTr("Server")
font.pixelSize:3*mm
x: 4*mm; y: 10*mm
}
Text {
text: qsTr("Nickname")
font.pixelSize:3*mm
x: 4*mm; y: 20*mm
}
Text {
text: qsTr("Password")
font.pixelSize:3*mm
x: 4*mm; y: 30*mm
}
Text {
text: qsTr("Image dir.")
font.pixelSize:3*mm
x: 4*mm; y: 40*mm
}
// Text {
// text: qsTr("Max. News")
// font.pixelSize:3*mm
// x: 4*mm; y: 50*mm
// }
Text {
text: qsTr("News as")
font.pixelSize:3*mm
x: 4*mm; y: 50*mm
}
// Text {
// text: qsTr("Show Website")
// x: 4*mm; y:80*mm; width: 20*mm
// }
Image{
id:servericon
x:4*mm;y:13.5*mm
width:5*mm; height: 5*mm
visible: false
source:""
MouseArea{
anchors.fill:parent
onClicked:{
Service.showServerConfig(servername.text, accountPage, function(configString){
var serverconfigObject=Qt.createQmlObject(configString,accountPage,"serverconfigOutput");})
}
}
}
Button{
id:serverSearchButton
text:"\uf002"
font.pixelSize: 3*mm
x:4*mm
y:13.5*mm
width: 5*mm; height:5*mm
visible: servericon.visible?false:true
onClicked:{Qt.openUrlExternally(Qt.resolvedUrl("https://dir.friendica.social/servers"))}
}
Rectangle{color: "light grey"; x: 10*mm; y: 13.5*mm; width: root.width-12*mm; height: 5*mm;}
Flickable {
id: servernameFlickable
x: 10*mm; y: 13.5*mm; width: root.width-12*mm; height: 5*mm;
contentWidth: servername.paintedWidth
contentHeight: servername.paintedHeight
clip: true
TextEdit {
id: servername
width: servernameFlickable.width
height: servernameFlickable.height
focus: true
font.pixelSize:3*mm
text:"https://"
onEditingFinished:{
if((servername.text).substring(0,11) =="https://http"){
serverstring.text= (serverstring.text).substring(8)
}
accountPage.setServericon(servername.text)
}
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,servernameFlickable)
}
}
Rectangle{
color: "light grey"
x: 4*mm; y: 23.5*mm; width: root.width-14*mm; height: 5*mm;
TextInput {
id: username
anchors.fill: parent
font.pixelSize:3*mm
selectByMouse: true
onEditingFinished:{
if (username.text.indexOf('@')>-1){
Helperjs.showMessage(qsTr("Error"),qsTr("Nicknames containing @ symbol currently not supported"),accountPage)
}
}
}
}
Button {
x: root.width-9*mm; y: 23.5*mm; width:5*mm; height:5*mm
text: "\uf234"
font.pixelSize: 3*mm
onClicked: {
configStack.push({item:"qrc:/qml/configqml/RegisterPage.qml",properties:{url:servername.text+"/register?nickname="+username.getText(0,username.length)}})
}
}
Rectangle{
color: "light grey"
x: 4*mm; y: 33.5*mm; width: root.width-6*mm; height: 5*mm;
TextInput {
id: password
anchors.fill: parent
font.pixelSize:3*mm
selectByMouse: true
echoMode: TextInput.PasswordEchoOnEdit
}
}
Rectangle{color: "light grey"; x: 4*mm; y: 43.5*mm; width: root.width-14*mm; height: 5*mm;}
Flickable {
id: imagestoreFlickable
x: 4*mm; y: 43.5*mm; width: root.width-14*mm; height: 5*mm;
clip: true
TextInput {
id: imagestore
width: imagestoreFlickable.width
height: imagestoreFlickable.height
font.pixelSize:3*mm
wrapMode: TextEdit.NoWrap
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
}
}
FileDialog {
id: imagestoreDialog
title: "Please choose a directory"
folder: shortcuts.pictures
selectFolder: true
onAccepted: {
var imagestoreString=imagestoreDialog.folder.toString();
imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
imagestore.text=imagestoreString
}
}
Button {
x: root.width-9*mm; y: 43.5*mm; width: 5*mm; height: 5*mm;
text: "..."
font.pixelSize: 3*mm
onClicked:
{imagestoreDialog.open()}
}
// Slider{ id: maxNews
// x:19*mm; y: 53.5*mm;width: root.width/2;height:5*mm
// from: 0;to:2000; stepSize: 100
// }
// Rectangle{color: "light grey"; x: 4*mm; y: 53.5*mm; width: 9*mm; height: 5*mm;
// TextEdit{id:maxNewsText;
// anchors.fill: parent
// font.pixelSize:3*mm
// verticalAlignment:TextEdit.AlignRight
// text:maxNews.value
// focus: true
// selectByMouse: true
// }
// }
Rectangle{
x: 4*mm; y: 53.5*mm; width: newsTypeField.contentWidth+2*mm; height: 5*mm;
color:"light grey"
Text{
id: newsTypeField
anchors.fill: parent
font.pixelSize:3*mm
text:"Conversations"
}
MouseArea{
anchors.fill:parent
onClicked:newstypemenu.popup()
}
}
BusyIndicator{
id: accountBusy
anchors.horizontalCenter: parent.horizontalCenter
y: 63.5*mm
width:10*mm
height: 10*mm
running: false
}
// CheckBox{
// id:showwebsiteCheckbox
// x:35*mm;y:80*mm
// onClicked:{
// if (checked==true){
// Service.updateglobaloptions(root.db,"showWebsiteForLinks","true")
// root.globaloptions.showWebsiteForLinks="true"
// }
// else {
// Service.updateglobaloptions(root.db,"showWebsiteForLinks","false")
// root.globaloptions.showWebsiteForLinks="false"
// }
// }
// }
Button {
x: 4*mm; y: 63.5*mm
height: 8*mm
text: qsTr("Confirm")
font.pixelSize: 3*mm
onClicked:{
accountBusy.running=true;
var userconfig={server: servername.text, username: username.text, password:Qt.btoa(password.text), imagestore:imagestore.text, maxnews:"",interval: "",newsViewType:newsTypeField.text};
var errormessage="";
if (servername.text==""){errormessage=qsTr("No server given! ")}
else if (username.text==""){errormessage+=qsTr("No nickname given! ")}
else if (password.text=="") {errormessage+=qsTr("No password 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){
accountBusy.running=false;
var credentials=JSON.parse(obj);
if (credentials.hasOwnProperty('status')){
Helperjs.showMessage(qsTr("Error"),qsTr("Wrong password!"),root)
}
else{
filesystem.Directory=userconfig.imagestore;
filesystem.makeDir("contacts");
filesystem.makeDir("albums");
Service.storeConfig(db,userconfig);
Service.readConfig(db,function(userconfig){
Helperjs.readData(db,"config","",function(storedUsers){
storedUsers.sort(function(obj1, obj2) {
return obj1.isActive - obj2.isActive;
});
accountPage.users=storedUsers});
//reset values
root.login=userconfig;
root.news=[];
},"isActive",0);
//Service.requestProfile(userconfig,db,root,function(nc){root.newContacts=nc});
Helperjs.showMessage(qsTr("Success"),qsTr("Name")+": "+credentials.name+"\nScreen Name: "+credentials.screen_name,root)
}
});
}
else {Helperjs.showMessage(qsTr("Error"), errormessage,root)}
}}
Button {
x: parent.width/2+2*mm; y: mm; width: 5*mm; height: 8*mm;
text: "-"
font.pixelSize: 3*mm
onClicked:{
var userconfig={server: servername.text, username: username.text, password: Qt.btoa(password.text)};
Service.deleteConfig(db,userconfig,function(){
filesystem.Directory=imagestore.text+"contacts";
filesystem.rmDir();
filesystem.Directory=imagestore.text+"albums";
filesystem.rmDir();
servername.text="https://";
servericon.visible=false;
servericon.source="";
username.text="";
password.text="";
imagestore.text="";
//maxNews.value=0;
newsTypeField.text="Conversations";
//messageIntervalSlider.value=30;
userButton.text=qsTr("User");
Helperjs.readData(db,"config","",function(storedUsers){
storedUsers.sort(function(obj1, obj2) {
return obj1.isActive - obj2.isActive;
})
accountPage.users=storedUsers;})
})
}}
Button {
x: parent.width/2+8*mm; y: mm; width: 5*mm; height: 8*mm;
text: "+"
font.pixelSize: 3*mm
onClicked:{
servername.text="https://"
servericon.visible=false;
servericon.source="";
username.text=""
password.text=""
imagestore.text=""
//maxNews.value=0
newsTypeField.text="Conversations"
//messageIntervalSlider.value=30
userButton.text=qsTr("User")
}
}
Button {
x: parent.width/2+14*mm; y: mm; width: 5*mm; height: 8*mm;
text: "?"
font.pixelSize: 3*mm
onClicked:{
root.push("qrc:/qml/configqml/InfoBox.qml");
}
}
Button{
id:closeButton
height: 8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
font.pixelSize: 3*mm
onClicked:{root.pop()}
}
Menu {
id:newstypemenu
MenuItem {
font.pixelSize: 3*mm
text: qsTr("Timeline")
onTriggered: {newsTypeField.text="Timeline"}
}
MenuItem {
font.pixelSize: 3*mm
text: qsTr("Conversations")
onTriggered: {newsTypeField.text="Conversations"}
}
}
Component.onCompleted: {
try{Helperjs.readData(db,"config","",function(storedUsers){
storedUsers.sort(function(obj1, obj2) {
return obj1.isActive - obj2.isActive;
})
accountPage.users=storedUsers;
Service.readConfig(db,function(obj){
userButton.text=obj.username;
servername.text=obj.server;
accountPage.setServericon(obj.server);
username.text= obj.username;
password.text=Qt.atob(obj.password);
imagestore.text=obj.imagestore;
//maxNews.value=obj.maxnews;
newsTypeField.text=obj.newsViewType;
//messageIntervalSlider.value=obj.timerInterval;
if( obj.isActive==0){userButton.font.bold='true'} else {userButton.font.bold='false'}
},"isActive",0)
})
// Service.readGlobaloptions(db,function(go){
// if (root.globaloptions.showWebsiteForLinks!="false"){showwebsiteCheckbox.checked=true}
// })
}
catch (e){print(e)
// Helperjs.friendicaWebRequest("https://dir.friendica.social/servers/surprise",accountPage,function(html){
// print(html);
// var bpos=html.indexOf("base ");
// var baseurl=html.substring(html.indexOf("http",bpos),html.indexOf('"',html.indexOf("http",bpos)));
// servername.text=baseurl
// })
}
}
}

View file

@ -0,0 +1,227 @@
// This file is part of Friendiqa
// https://git.friendi.ca/lubuwest/Friendiqa
// Copyright (C) 2017 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.11
import QtQuick.Dialogs 1.2
import QtQuick.Controls 2.4
import "qrc:/js/service.js" as Service
//import "qrc:/js/layout.js" as Layoutjs
//import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/configqml"
import "qrc:/qml/genericqml"
Page{
//anchors.fill: parent
width:root.width
height:root.height
//contentHeight: configBackground.height
//boundsBehavior: Flickable.StopAtBounds
// Rectangle{
// id:configBackground
// color: "white"
// anchors.fill: parent
// width:parent.width
// height:Math.max(90*mm,root.height-12*mm)
// property var users:[]
// property bool registeredUser: true
// property var userdata: ({})
// Text {
// text: qsTr("Image dir.")
// //text: qsTr("Max. News")
// font.pixelSize:3*mm
// x: 4*mm; y: 10*mm
// }
Text {
text: qsTr("Max. News")
//text: qsTr("News as")
font.pixelSize:3*mm
x: 4*mm; y:10*mm
}
// Text {
// text: qsTr("Show Website")
// x: 4*mm; y: 40*mm; width: 20*mm
// }
// Rectangle{color: "light grey"; x: 4*mm; y: 13.5*mm; width: root.width-14*mm; height: 5*mm;}
// Flickable {
// id: imagestoreFlickable
// x: 4*mm; y: 13.5*mm; width: root.width-14*mm; height: 5*mm;
// clip: true
// TextInput {
// id: imagestore
// width: imagestoreFlickable.width
// height: imagestoreFlickable.height
// font.pixelSize:3*mm
// wrapMode: TextEdit.NoWrap
// onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
// }
// }
// FileDialog {
// id: imagestoreDialog
// title: "Please choose a directory"
// folder: shortcuts.pictures
// selectFolder: true
// onAccepted: {
// var imagestoreString=imagestoreDialog.folder.toString();
// imagestoreString=imagestoreString.replace(/^(file:\/{2})/,"")+"/"
// imagestore.text=imagestoreString
// }
// }
// Button {
// x: root.width-9*mm; y: 13.5*mm; width: 7*mm; height: 8*mm;
// text: "..."
// onClicked:
// {imagestoreDialog.open()}
// }
Slider{ id: maxNews
x:19*mm; y: 13.5*mm;width: root.width/2;height:5*mm
from: 0;to:2000; stepSize: 100
value: root.globaloptions.hasOwnProperty("max_news")?root.globaloptions.max_news:1000
}
Rectangle{color: "light grey"; x: 4*mm; y: 13.5*mm; width: 9*mm; height: 5*mm;
radius: 0.5*mm
TextEdit{id:maxNewsText;
anchors.fill: parent
font.pixelSize:3*mm
verticalAlignment:TextEdit.AlignRight
text:maxNews.value
focus: true
selectByMouse: true
onTextChanged: {
Service.updateglobaloptions(root.db,"max_news",text);
}
}
}
Rectangle{
x: 4*mm; y:23.5*mm; width: parent.width - 14*mm; height: 5*mm;
color:"light grey"
radius: 0.5*mm
Text{
anchors.fill: parent
font.pixelSize:3*mm
text:qsTr("Sync")
}
MouseArea{
anchors.fill:parent
onClicked:root.push("qrc:qml/configqml/SyncConfig.qml");
}
}
// Slider{ id: messageIntervalSlider
// x:22*mm; y: 73.5*mm;width: root.width/2;height:5*mm
// from: 0;to:120; stepSize: 15
// }
// Rectangle{
// x: 4*mm; y: 73.5*mm; width: 9*mm; height: 5*mm;
// TextEdit{
// id: messageIntervalField
// anchors.fill: parent
// font.pixelSize:3*mm
// verticalAlignment:TextEdit.AlignRight
// text:messageIntervalSlider.value
// focus: true
// selectByMouse: true
// }
// }
// Text{x: 14*mm; y: 73.5*mm; width: 5*mm; height: 5*mm;
// font.pixelSize:3*mm
// text:qsTr("Min.")
// }
// CheckBox{
// id:showwebsiteCheckbox
// x:35*mm;y:80*mm
// onClicked:{
// if (checked==true){
// Service.updateglobaloptions(root.db,"showWebsiteForLinks","true")
// root.globaloptions.showWebsiteForLinks="true"
// }
// else {
// Service.updateglobaloptions(root.db,"showWebsiteForLinks","false")
// root.globaloptions.showWebsiteForLinks="false"
// }
// }
// }
MButton {
anchors.right: closeButton.left; anchors.rightMargin: mm;
anchors.top: parent.top
anchors.topMargin: 1*mm
width: 8*mm; height: 6*mm;
text: "?"
font.pixelSize: 3*mm
onClicked:{
root.push("qrc:/qml/configqml/InfoBox.qml");
}
}
MButton{
id:closeButton
height: 6*mm
width :8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
font.pixelSize: 3*mm
onClicked:{root.pop()}
}
// Menu {
// id:newstypemenu
// MenuItem {
// text: qsTr("Timeline")
// onTriggered: {newsTypeField.text="Timeline"}
// }
// MenuItem {
// text: qsTr("Conversations")
// onTriggered: {newsTypeField.text="Conversations"}
// }
// }
// Component.onCompleted: {
// Service.readGlobaloptions(db,function(go){
// if(go.hasOwnProperty("max_news")){maxNews.value=go.max_news}else{maxNews.value=1000}
// //if (root.globaloptions.showWebsiteForLinks!="false"){showwebsiteCheckbox.checked=true}
// })
// }
}

View file

@ -30,7 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls 2.4
import "qrc:/qml/genericqml"
Rectangle{
@ -41,11 +41,12 @@ Rectangle{
anchors.top:closeButton.bottom
anchors.topMargin: mm
textFormat: Text.RichText
width: parent.width
width: root.width-mm
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
text: "<b>Friendiqa v0.4 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
text: "<b>Friendiqa v0.5 </b><br>Licensed under GPL 3 with the exception of OpenSSL <br> "+
"Profile <a href='https://freunde.ma-nic.de/profile/friendiqa'>https://freunde.ma-nic.de/profile/friendiqa</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>"+
"Most of C++ code by <a href='https://kirgroup.com/profile/fabrixxm'>Fabio</a><br>"+
"QML and Javascript code by <a href='https://freunde.ma-nic.de/profile/marco'>Marco</a><br>"+
"Qt Framework <a href='https://www.qt.io'>www.qt.io</a><br>"+
@ -56,13 +57,16 @@ Rectangle{
onLinkActivated:{
Qt.openUrlExternally(link)}
}
BlueButton{
Button{
id:closeButton
height: 6*mm
width: 8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
onClicked:{configStack.pop()}
font.pixelSize: 3*mm
onClicked:{root.pop()}
}
}

View file

@ -34,7 +34,7 @@ QtObject{
property real appWidth: 500
property real appHeight: 500
property int backKey: Qt.Key_Escape
property string osType: "Android"
property string osType: "Linux"
//property string attachImageDir:filesystem.homePath+"/Pictures/"
property string imagePickQml: "ImagePickerLinux"
}

View file

@ -30,6 +30,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import QtQuick 2.9
import QtQuick.Controls 2.5
import QtWebView 1.1
import "qrc:/qml/genericqml"
@ -45,17 +46,21 @@ Rectangle{
width:parent.width
y:7*mm
MouseArea {anchors.fill:parent;
onClicked:{print(url)}
onClicked:{
//print(url)
}
onLoadingChanged: print(loadProgress)
}
BlueButton{
//onLoadingChanged: print(loadProgress)
}
Button{
id:closeButton
height:8*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
font.pixelSize: 3*mm
onClicked:{configStack.pop()}
}
}

Some files were not shown because too many files have changed in this diff Show more