Version 0.002 Release version
19
README.md
|
@ -22,17 +22,20 @@ Currently supported:
|
||||||
* Liking, disliking, favoriting
|
* Liking, disliking, favoriting
|
||||||
* Update fetches new posts since last in local DB
|
* Update fetches new posts since last in local DB
|
||||||
* More shows older posts from local DB
|
* More shows older posts from local DB
|
||||||
* New Message with images, also possible as DM, Contact selection
|
* New Message with images, also possible as DM, Contact/Group access rights
|
||||||
|
|
||||||
|
|
||||||
ToDo:
|
ToDo:
|
||||||
* Test new Aspargus features
|
* Nice symbols for liking, disliking
|
||||||
* Nice symbols for liking, disliking and menu for deletion, reposting and answering (currently press on Contact picture, press on news would interfere with external link functionality)
|
* Videos and other binary data as attachment (sending and receiving)
|
||||||
* Videos as attachment (sending and receiving)
|
|
||||||
* Rich text editing in Send Dialog
|
* Rich text editing in Send Dialog
|
||||||
|
* Attachments for Direct messages (currently not supported in API
|
||||||
|
* Better image selection (currently ugly file dialog)
|
||||||
|
|
||||||
|
|
||||||
# Friends #
|
# Friends #
|
||||||
Currently supported:
|
Currently supported:
|
||||||
|
* Tabs for friends, other contacts and groups
|
||||||
* Grid of all known contacts with locally downloaded pictures
|
* Grid of all known contacts with locally downloaded pictures
|
||||||
* Large friend item for addional information and functionality
|
* Large friend item for addional information and functionality
|
||||||
* Show news of contact from local database
|
* Show news of contact from local database
|
||||||
|
@ -42,7 +45,6 @@ Currently supported:
|
||||||
|
|
||||||
ToDo:
|
ToDo:
|
||||||
* More information for contact from description page, possibly private information for friends
|
* More information for contact from description page, possibly private information for friends
|
||||||
* Filter contacts for friends, forums,groups etc.
|
|
||||||
* Groups: create, change, delete
|
* Groups: create, change, delete
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,25 +55,24 @@ Currently supported:
|
||||||
* Show albums and images of contacts
|
* Show albums and images of contacts
|
||||||
|
|
||||||
ToDo:
|
ToDo:
|
||||||
* Better download mechanism for own images
|
|
||||||
* Private images of friends
|
* Private images of friends
|
||||||
* Support for all themes of friends
|
* Support for all themes of friends
|
||||||
* Delete downloaded own images
|
* Delete downloaded own images
|
||||||
|
* Pinch to zoom, swipe to scroll
|
||||||
|
|
||||||
|
|
||||||
# Config #
|
# Config #
|
||||||
Currently supported:
|
Currently supported:
|
||||||
* Multiple accounts
|
* Multiple accounts
|
||||||
* Maximum news (deleted after use of Quit button)
|
* Maximum news (deleted after use of Quit button)
|
||||||
|
* View mode for news (tree or timeline)
|
||||||
|
|
||||||
ToDo
|
ToDo
|
||||||
* OAuth?
|
* OAuth?
|
||||||
* View mode for news (chronological or tree)
|
|
||||||
|
|
||||||
|
|
||||||
# Other #
|
# Other #
|
||||||
ToDo
|
ToDo
|
||||||
* Friendstab and Newstab buggy after account change, restart helps
|
|
||||||
* Calendar tab, video tab
|
* Calendar tab, video tab
|
||||||
* Photo upload to album (needs API change)
|
* Photo upload to album (needs API change)
|
||||||
* Translation
|
* Translation
|
||||||
|
@ -81,5 +82,5 @@ ToDo
|
||||||
## License ##
|
## License ##
|
||||||
v0.001 for Friendica < 3.5
|
v0.001 for Friendica < 3.5
|
||||||
v0.002 for Friendica >= 3.5
|
v0.002 for Friendica >= 3.5
|
||||||
Pubished under the [GPL v3](http://gplv3.fsf.org).
|
Published under the [GPL v3](http://gplv3.fsf.org).
|
||||||
|
|
||||||
|
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 15 KiB |
35
TODO.txt
|
@ -1,35 +0,0 @@
|
||||||
TODO
|
|
||||||
======
|
|
||||||
|
|
||||||
|
|
||||||
Layout
|
|
||||||
____________
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Config
|
|
||||||
____________
|
|
||||||
|
|
||||||
- Server Domain
|
|
||||||
- SSL Check
|
|
||||||
- OAuth?
|
|
||||||
|
|
||||||
Fotos erhalten
|
|
||||||
_______________
|
|
||||||
|
|
||||||
- Liste der Fotos mit api/friendica/photos/list
|
|
||||||
- Daten der Fotos als JSON über api/friendica/photo.xml?photo_id=[ID], "album" als Feld vorhanden
|
|
||||||
- Raw data in File?
|
|
||||||
- Download/Sortieren der Fotos?
|
|
||||||
|
|
||||||
Fotos senden
|
|
||||||
____________
|
|
||||||
|
|
||||||
- Upload über api/media/upload.xml?media= (raw data)?
|
|
||||||
- Berechtigungen? Album?
|
|
||||||
- Album erstellen/bearbeiten
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<manifest package="org.qtproject.friendiqa" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="0.2" android:versionCode="2" android:installLocation="auto">
|
||||||
|
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="Friendiqa" android:icon="@drawable/icon" android:logo="@drawable/icon">
|
||||||
|
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:name="org.qtproject.qt5.android.bindings.QtActivity" android:label="Friendiqa" android:screenOrientation="unspecified" android:launchMode="singleTop">
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN"/>
|
||||||
|
<category android:name="android.intent.category.LAUNCHER"/>
|
||||||
|
</intent-filter>
|
||||||
|
<meta-data android:name="android.app.lib_name" android:value="friendiqa"/>
|
||||||
|
<meta-data android:name="android.app.qt_sources_resource_id" android:resource="@array/qt_sources"/>
|
||||||
|
<meta-data android:name="android.app.repository" android:value="default"/>
|
||||||
|
<meta-data android:name="android.app.qt_libs_resource_id" android:resource="@array/qt_libs"/>
|
||||||
|
<meta-data android:name="android.app.bundled_libs_resource_id" android:resource="@array/bundled_libs"/>
|
||||||
|
<!-- Deploy Qt libs as part of package -->
|
||||||
|
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
|
||||||
|
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
|
||||||
|
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
|
||||||
|
<!-- Run with local libs -->
|
||||||
|
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
|
||||||
|
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
|
||||||
|
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
|
||||||
|
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
|
||||||
|
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
|
||||||
|
<!-- Messages maps -->
|
||||||
|
<meta-data android:value="@string/ministro_not_found_msg" android:name="android.app.ministro_not_found_msg"/>
|
||||||
|
<meta-data android:value="@string/ministro_needed_msg" android:name="android.app.ministro_needed_msg"/>
|
||||||
|
<meta-data android:value="@string/fatal_error_msg" android:name="android.app.fatal_error_msg"/>
|
||||||
|
<!-- Messages maps -->
|
||||||
|
|
||||||
|
|
||||||
|
<meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/splash"/>
|
||||||
|
|
||||||
|
<!-- Background running -->
|
||||||
|
<!-- Warning: changing this value to true may cause unexpected crashes if the
|
||||||
|
application still try to draw after
|
||||||
|
"applicationStateChanged(Qt::ApplicationSuspended)"
|
||||||
|
signal is sent! -->
|
||||||
|
<meta-data android:name="android.app.background_running" android:value="false"/>
|
||||||
|
<!-- Background running -->
|
||||||
|
</activity>
|
||||||
|
</application>
|
||||||
|
<uses-sdk android:minSdkVersion="18" android:targetSdkVersion="21"/>
|
||||||
|
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
|
||||||
|
|
||||||
|
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
|
||||||
|
Remove the comment if you do not require these default permissions. -->
|
||||||
|
<!-- %%INSERT_PERMISSIONS -->
|
||||||
|
|
||||||
|
<!-- The following comment will be replaced upon deployment with default features based on the dependencies of the application.
|
||||||
|
Remove the comment if you do not require these default features. -->
|
||||||
|
<!-- %%INSERT_FEATURES -->
|
||||||
|
|
||||||
|
</manifest>
|
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 1.5 KiB |
After Width: | Height: | Size: 11 KiB |
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version='1.0' encoding='utf-8'?>
|
||||||
|
<resources>
|
||||||
|
<array name="qt_sources">
|
||||||
|
<item>https://download.qt-project.org/ministro/android/qt5/qt-5.4</item>
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<!-- The following is handled automatically by the deployment tool. It should
|
||||||
|
not be edited manually. -->
|
||||||
|
|
||||||
|
<array name="bundled_libs">
|
||||||
|
<!-- %%INSERT_EXTRA_LIBS%% -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<array name="qt_libs">
|
||||||
|
<!-- %%INSERT_QT_LIBS%% -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<array name="bundled_in_lib">
|
||||||
|
<!-- %%INSERT_BUNDLED_IN_LIB%% -->
|
||||||
|
</array>
|
||||||
|
<array name="bundled_in_assets">
|
||||||
|
<!-- %%INSERT_BUNDLED_IN_ASSETS%% -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
</resources>
|
|
@ -0,0 +1,27 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>qml/friendiqa.qml</file>
|
||||||
|
<file>qml/newsqml/NewsTab.qml</file>
|
||||||
|
<file>qml/newsqml/Newsitem.qml</file>
|
||||||
|
<file>qml/newsqml/MessageSend.qml</file>
|
||||||
|
<file>qml/newsqml/PermissionDialog.qml</file>
|
||||||
|
<file>qml/contactqml/FriendsTab.qml</file>
|
||||||
|
<file>qml/contactqml/GroupComponent.qml</file>
|
||||||
|
<file>qml/contactqml/ContactComponent.qml</file>
|
||||||
|
<file>qml/contactqml/ContactDetailsComponent.qml</file>
|
||||||
|
<file>qml/genericqml/BlueButton.qml</file>
|
||||||
|
<file>qml/photoqml/PhotoComponent.qml</file>
|
||||||
|
<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>js/layout.js</file>
|
||||||
|
<file>js/photoworker.js</file>
|
||||||
|
<file>js/service.js</file>
|
||||||
|
<file>js/news.js</file>
|
||||||
|
<file>js/newsworker.js</file>
|
||||||
|
<file>js/helper.js</file>
|
||||||
|
<file>images/defaultcontact.jpg</file>
|
||||||
|
<file>qml/newsqml/Conversation.qml</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "filesystem.h"
|
||||||
|
|
||||||
|
FILESYSTEM *FILESYSTEM::instance()
|
||||||
|
{
|
||||||
|
static FILESYSTEM filesystem;
|
||||||
|
return &filesystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILESYSTEM::FILESYSTEM(QObject *parent) : QObject(parent){}
|
||||||
|
|
||||||
|
void FILESYSTEM::setDirectory(QString Directory)
|
||||||
|
{
|
||||||
|
if (Directory!=m_Directory) {
|
||||||
|
m_Directory = Directory;
|
||||||
|
emit directoryChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FILESYSTEM::Directory() const
|
||||||
|
{
|
||||||
|
return m_Directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FILESYSTEM::makeDir(QString name)
|
||||||
|
{
|
||||||
|
QDir dir(m_Directory);
|
||||||
|
if (dir.mkdir(name)){
|
||||||
|
emit success(name);
|
||||||
|
}
|
||||||
|
else {emit error(name,1);}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FILESYSTEM::rmDir()
|
||||||
|
{
|
||||||
|
QDir dir(m_Directory);
|
||||||
|
if (dir.removeRecursively()){
|
||||||
|
emit success(m_Directory);
|
||||||
|
}
|
||||||
|
else {emit error(m_Directory,1);}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FILESYSTEM::rmFile(QString name)
|
||||||
|
{
|
||||||
|
QDir dir(m_Directory);
|
||||||
|
if(dir.remove(name)){
|
||||||
|
emit success(name);
|
||||||
|
}
|
||||||
|
else {emit error(name,1);}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef FILESYSTEM_H
|
||||||
|
#define FILESYSTEM_H
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class FILESYSTEM : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString Directory READ Directory WRITE setDirectory NOTIFY directoryChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
static FILESYSTEM *instance();
|
||||||
|
explicit FILESYSTEM(QObject *parent = 0);
|
||||||
|
void setDirectory(QString Directory);
|
||||||
|
QString Directory() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void directoryChanged();
|
||||||
|
void success(QString data);
|
||||||
|
void error(QString data, int code);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
//void setDirectory(QString Directory);
|
||||||
|
void makeDir(QString name);
|
||||||
|
void rmDir();
|
||||||
|
void rmFile(QString name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_Directory;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILSYSTEM_H
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QtQml/QQmlEngine>
|
||||||
|
#include <QtQuick>
|
||||||
|
#include "xhr.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
QQuickView view;
|
||||||
|
|
||||||
|
|
||||||
|
XHR* xhr = XHR::instance();
|
||||||
|
view.rootContext()->setContextProperty("xhr", xhr);
|
||||||
|
FILESYSTEM* filesystem = FILESYSTEM::instance();
|
||||||
|
view.rootContext()->setContextProperty("filesystem", filesystem);
|
||||||
|
view.setSource(QUrl("qrc:/qml/friendiqa.qml"));
|
||||||
|
view.show();
|
||||||
|
view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
|
||||||
|
return app.exec();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
#include "uploadableimage.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
void UploadableImage::setSource(const QString &a) {
|
||||||
|
if (a != m_source) {
|
||||||
|
m_source = a;
|
||||||
|
//m_base64 = "";
|
||||||
|
m_mimetype = "";
|
||||||
|
m_filename = "";
|
||||||
|
|
||||||
|
qDebug() << "UploadableImage::setSource : " << m_source;
|
||||||
|
|
||||||
|
if (m_source=="") {
|
||||||
|
emit sourceChanged();
|
||||||
|
//emit base64Changed();
|
||||||
|
emit mimetypeChanged();
|
||||||
|
emit filenameChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage fullimage = QImage(QUrl(m_source).toLocalFile());
|
||||||
|
if (fullimage.width() > 800 || fullimage.height() > 800) {
|
||||||
|
if (fullimage.width() > fullimage.height()) {
|
||||||
|
m_image = fullimage.scaledToWidth(800);
|
||||||
|
} else {
|
||||||
|
m_image = fullimage.scaledToHeight(800);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_image = fullimage;
|
||||||
|
}
|
||||||
|
qDebug() << "UploadableImage::setSource : " << m_image.width() << "x" << m_image.height();
|
||||||
|
emit sourceChanged();
|
||||||
|
|
||||||
|
QFileInfo fi(m_source);
|
||||||
|
|
||||||
|
m_filename = fi.fileName();
|
||||||
|
emit filenameChanged();
|
||||||
|
|
||||||
|
QString filetype = fi.suffix().toUpper();
|
||||||
|
if (filetype!="PNG" && filetype!="JPG") {
|
||||||
|
filetype = "JPG";
|
||||||
|
}
|
||||||
|
qDebug() << "UploadableImage::setSource : " << "Saving as " << filetype;
|
||||||
|
|
||||||
|
m_mimetype = "image/"+filetype.toLower();
|
||||||
|
emit mimetypeChanged();
|
||||||
|
|
||||||
|
/*
|
||||||
|
QByteArray byteArray;
|
||||||
|
QBuffer buffer(&byteArray);
|
||||||
|
m_image.save(&buffer, filetype.toLatin1().constData());
|
||||||
|
QString b64 = QString::fromLatin1(byteArray.toBase64().data());
|
||||||
|
|
||||||
|
for(int k=0; k<b64.length(); k+=76) {
|
||||||
|
m_base64 += b64.mid(k,76) + "\n";
|
||||||
|
}
|
||||||
|
m_base64 = m_base64.trimmed();
|
||||||
|
|
||||||
|
emit base64Changed();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UploadableImage::source() const {
|
||||||
|
return m_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
//QString UploadableImage::base64() const {
|
||||||
|
// return m_base64;
|
||||||
|
//}
|
||||||
|
|
||||||
|
QString UploadableImage::filename() const {
|
||||||
|
return m_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UploadableImage::mimetype() const {
|
||||||
|
return m_mimetype;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray UploadableImage::bytes() {
|
||||||
|
QByteArray byteArray;
|
||||||
|
QBuffer buffer(&byteArray);
|
||||||
|
m_image.save(&buffer, "PNG");
|
||||||
|
return byteArray;
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef UPLOADABLEIMAGE_H
|
||||||
|
#define UPLOADABLEIMAGE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
|
class UploadableImage : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
|
||||||
|
//Q_PROPERTY(QString base64 READ base64 NOTIFY base64Changed)
|
||||||
|
Q_PROPERTY(QString filename READ filename NOTIFY filenameChanged)
|
||||||
|
Q_PROPERTY(QString mimetype READ mimetype NOTIFY mimetypeChanged)
|
||||||
|
Q_PROPERTY(QByteArray bytes READ bytes)
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setSource(const QString &a);
|
||||||
|
QString source() const;
|
||||||
|
|
||||||
|
//QString base64() const;
|
||||||
|
QString filename() const;
|
||||||
|
QString mimetype() const;
|
||||||
|
|
||||||
|
QByteArray bytes();
|
||||||
|
signals:
|
||||||
|
void sourceChanged();
|
||||||
|
//void base64Changed();
|
||||||
|
void filenameChanged();
|
||||||
|
void mimetypeChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_source;
|
||||||
|
QImage m_image;
|
||||||
|
//QString m_base64;
|
||||||
|
QString m_filename;
|
||||||
|
QString m_mimetype;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // UPLOADABLEIMAGE_H
|
|
@ -0,0 +1,235 @@
|
||||||
|
#include "xhr.h"
|
||||||
|
|
||||||
|
#include <QHttpPart>
|
||||||
|
#include <QTextCodec>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
#include "uploadableimage.h"
|
||||||
|
|
||||||
|
XHR *XHR::instance()
|
||||||
|
{
|
||||||
|
static XHR xhr;
|
||||||
|
return &xhr;
|
||||||
|
}
|
||||||
|
|
||||||
|
XHR::XHR(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setUrl(QString url)
|
||||||
|
{
|
||||||
|
if (url!=m_url) {
|
||||||
|
m_url = url;
|
||||||
|
emit urlChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setLogin(QString login)
|
||||||
|
{
|
||||||
|
if (login!=m_login) {
|
||||||
|
m_login = login;
|
||||||
|
emit loginChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setFilename(QString filename)
|
||||||
|
{
|
||||||
|
if (filename!=m_filename) {
|
||||||
|
m_filename = filename;
|
||||||
|
emit filenameChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setDownloadtype(QString downloadtype)
|
||||||
|
{
|
||||||
|
if (downloadtype!=m_downloadtype) {
|
||||||
|
m_downloadtype = downloadtype;
|
||||||
|
emit downloadtypeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::url() const
|
||||||
|
{
|
||||||
|
return m_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::login() const
|
||||||
|
{
|
||||||
|
return m_login;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::filename() const
|
||||||
|
{
|
||||||
|
return m_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::downloadtype() const
|
||||||
|
{
|
||||||
|
return m_downloadtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setParam(QString name, QString value)
|
||||||
|
{
|
||||||
|
params.insert(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setImageFileParam(QString name, QString url)
|
||||||
|
{
|
||||||
|
files.insert(name, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::clearParams()
|
||||||
|
{
|
||||||
|
files.clear();
|
||||||
|
params.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::download()
|
||||||
|
{
|
||||||
|
QUrl requrl(m_url);
|
||||||
|
//qDebug()<< "replyerror"<<reply->error();
|
||||||
|
// qDebug() << "start download of " << requrl;
|
||||||
|
request.setUrl(requrl);
|
||||||
|
reply = manager.get(request);
|
||||||
|
// qDebug() << "reply " << reply->header(QNetworkRequest::LocationHeader)<<reply->header(QNetworkRequest::LastModifiedHeader);
|
||||||
|
// qDebug() << "request " << request.url();
|
||||||
|
// reply->ignoreSslErrors();
|
||||||
|
connect(reply, &QNetworkReply::readyRead,this, &XHR::onReadyRead);
|
||||||
|
//connect(reply,SIGNAL(downloadProgress(qint64,qint64)), this,SLOT(updateDownloadProgress(qint64,qint64)));
|
||||||
|
connect(reply, &QNetworkReply::finished,this, &XHR::onRequestFinished);
|
||||||
|
//connect(reply, SIGNAL(finished()),this, SLOT(onRequestFinished()));
|
||||||
|
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::get()
|
||||||
|
{
|
||||||
|
QUrlQuery query;
|
||||||
|
|
||||||
|
QHashIterator<QString, QString> i(params);
|
||||||
|
while(i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
query.addQueryItem(i.key(), i.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl requrl(m_url);
|
||||||
|
requrl.setQuery(query);
|
||||||
|
|
||||||
|
QByteArray loginData = m_login.toLocal8Bit().toBase64();
|
||||||
|
QString headerData = "Basic " + loginData;
|
||||||
|
request.setRawHeader("Authorization", headerData.toLocal8Bit());
|
||||||
|
|
||||||
|
|
||||||
|
request.setUrl(requrl);
|
||||||
|
reply = manager.get(request);
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
|
||||||
|
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
|
||||||
|
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::post()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
QHttpPart textPart;
|
||||||
|
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + iparams.key() + "\""));
|
||||||
|
|
||||||
|
|
||||||
|
textPart.setBody(iparams.value().toUtf8());
|
||||||
|
multiPart->append(textPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
UploadableImage uimg;
|
||||||
|
QHashIterator<QString, QString> ifiles(files);
|
||||||
|
while(ifiles.hasNext()) {
|
||||||
|
ifiles.next();
|
||||||
|
|
||||||
|
uimg.setSource(ifiles.value());
|
||||||
|
qDebug() << "\t image: " << uimg.mimetype() << ", " << ifiles.key();
|
||||||
|
|
||||||
|
QHttpPart imagePart;
|
||||||
|
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(uimg.mimetype()));
|
||||||
|
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + ifiles.key() + "\"; filename=\""+uimg.filename()+"\""));
|
||||||
|
imagePart.setBody(uimg.bytes());
|
||||||
|
multiPart->append(imagePart);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray loginData = m_login.toLocal8Bit().toBase64();
|
||||||
|
QString headerData = "Basic " + loginData;
|
||||||
|
request.setRawHeader(QByteArray("Authorization"), headerData.toLocal8Bit());
|
||||||
|
|
||||||
|
request.setUrl(m_url);
|
||||||
|
reply = manager.post(request, multiPart);
|
||||||
|
qDebug() << "\t request sent";
|
||||||
|
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
|
||||||
|
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
|
||||||
|
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
|
||||||
|
qDebug() << "\t reply signals connected";
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::onReplyError(QNetworkReply::NetworkError code)
|
||||||
|
{
|
||||||
|
qDebug() << code;
|
||||||
|
emit this->error( bufferToString(), (int) code);
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::onReplySuccess()
|
||||||
|
{
|
||||||
|
qDebug() << "!";
|
||||||
|
emit this->success( bufferToString() );
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::onRequestFinished()
|
||||||
|
{
|
||||||
|
// Save the file here
|
||||||
|
//qDebug() << "buffer downloaded "<<buffer;
|
||||||
|
if (buffer.isNull()){qDebug() << "File empty"<<m_url; buffer.clear(); emit this->error(m_downloadtype,1);}
|
||||||
|
else {QFile file(m_filename);
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
|
file.write(buffer);
|
||||||
|
buffer.clear();
|
||||||
|
file.close();
|
||||||
|
//qDebug() << m_url << "File downloaded "<<file.fileName();
|
||||||
|
emit this->downloaded(m_downloadtype);
|
||||||
|
//reply->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::onReadyRead()
|
||||||
|
{
|
||||||
|
qDebug() << ".";
|
||||||
|
buffer += reply->readAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
//void XHR::updateDownloadProgress(qint64 bytesRead, qint64 totalBytes)
|
||||||
|
//{
|
||||||
|
// qDebug() << "Bytes: " << bytesRead<<" / "<<totalBytes;
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
void XHR::onSSLError(const QList<QSslError> &errors)
|
||||||
|
{
|
||||||
|
qDebug() << "XHR::onSSLError :" ;
|
||||||
|
QListIterator<QSslError> ierrs(errors);
|
||||||
|
while(ierrs.hasNext()) {
|
||||||
|
qDebug() << "\t" << ierrs.next().errorString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::bufferToString()
|
||||||
|
{
|
||||||
|
return QTextCodec::codecForName("utf-8")->toUnicode(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef XHR_H
|
||||||
|
#define XHR_H
|
||||||
|
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class XHR : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
|
||||||
|
Q_PROPERTY(QString login READ login WRITE setLogin NOTIFY loginChanged)
|
||||||
|
Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged)
|
||||||
|
Q_PROPERTY(QString downloadtype READ downloadtype WRITE setDownloadtype NOTIFY downloadtypeChanged)
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
static XHR *instance();
|
||||||
|
|
||||||
|
explicit XHR(QObject *parent = 0);
|
||||||
|
|
||||||
|
QString url() const;
|
||||||
|
QString login() const;
|
||||||
|
QString filename() const;
|
||||||
|
QString downloadtype() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void urlChanged();
|
||||||
|
void loginChanged();
|
||||||
|
void filenameChanged();
|
||||||
|
void downloadtypeChanged();
|
||||||
|
void downloaded(QString data);
|
||||||
|
void success(QString data);
|
||||||
|
void error(QString data, int code);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setUrl(QString url);
|
||||||
|
void setLogin(QString login);
|
||||||
|
void setDownloadtype(QString downloadtype);
|
||||||
|
void setFilename(QString filename);
|
||||||
|
void setParam(QString name, QString value);
|
||||||
|
void setImageFileParam(QString name, QString url);
|
||||||
|
void clearParams();
|
||||||
|
void post();
|
||||||
|
void get();
|
||||||
|
void download();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onReplyError(QNetworkReply::NetworkError code);
|
||||||
|
void onReplySuccess();
|
||||||
|
void onRequestFinished();
|
||||||
|
void onReadyRead();
|
||||||
|
void onSSLError(const QList<QSslError> &errors);
|
||||||
|
//void updateDownloadProgress(qint64 bytesRead, qint64 totalBytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray buffer;
|
||||||
|
QString m_url;
|
||||||
|
QString m_login;
|
||||||
|
QString m_filename;
|
||||||
|
QString m_downloadtype;
|
||||||
|
QHash<QString, QString> params;
|
||||||
|
QHash<QString, QString> files;
|
||||||
|
|
||||||
|
QNetworkAccessManager manager;
|
||||||
|
QNetworkRequest request;
|
||||||
|
QNetworkReply *reply;
|
||||||
|
|
||||||
|
QString bufferToString();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // XHR_H
|
|
@ -0,0 +1,55 @@
|
||||||
|
# NOTICE:
|
||||||
|
#
|
||||||
|
# Application name defined in TARGET has a corresponding QML filename.
|
||||||
|
# If name defined in TARGET is changed, the following needs to be done
|
||||||
|
# to match new name:
|
||||||
|
# - corresponding QML filename must be changed
|
||||||
|
# - desktop icon filename must be changed
|
||||||
|
# - desktop filename must be changed
|
||||||
|
# - icon definition filename in desktop file must be changed
|
||||||
|
# - translation filenames have to be changed
|
||||||
|
|
||||||
|
# The name of your application
|
||||||
|
TARGET = friendiqa
|
||||||
|
CONFIG += debug
|
||||||
|
QT += qml quick gui widgets
|
||||||
|
|
||||||
|
SOURCES += common/friendiqa.cpp \
|
||||||
|
common/uploadableimage.cpp \
|
||||||
|
common/xhr.cpp \
|
||||||
|
common/filesystem.cpp
|
||||||
|
|
||||||
|
RESOURCES = application.qrc
|
||||||
|
|
||||||
|
OTHER_FILES += qml/friendiqa.qml \
|
||||||
|
translations/*.ts \
|
||||||
|
qml/*.qml
|
||||||
|
qml/newsqml/*.qml
|
||||||
|
qml/contactqml/*.qml
|
||||||
|
qml/photoqml/*.qml
|
||||||
|
qml/configqml/*.qml
|
||||||
|
js/*.js
|
||||||
|
|
||||||
|
# German translation is enabled as an example. If you aren't
|
||||||
|
# planning to localize your app, remember to comment out the
|
||||||
|
# following TRANSLATIONS line. And also do not forget to
|
||||||
|
# modify the localized app name in the the .desktop file.
|
||||||
|
TRANSLATIONS += translations/friendiqa-de.ts
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
common/uploadableimage.h \
|
||||||
|
common/xhr.h \
|
||||||
|
common/filesystem.h
|
||||||
|
|
||||||
|
DISTFILES += \
|
||||||
|
android/AndroidManifest.xml \
|
||||||
|
android/gradle/wrapper/gradle-wrapper.jar \
|
||||||
|
android/gradlew \
|
||||||
|
android/res/values/libs.xml \
|
||||||
|
android/build.gradle \
|
||||||
|
android/gradle/wrapper/gradle-wrapper.properties \
|
||||||
|
android/gradlew.bat
|
||||||
|
|
||||||
|
ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,12 @@
|
||||||
|
WorkerScript.onMessage = function(msg) {
|
||||||
|
msg.model.clear();
|
||||||
|
for (var j=0;j<msg.albums.length;j++){
|
||||||
|
if (msg.albums[j]) {
|
||||||
|
var albumobject=msg.albums[j];
|
||||||
|
var data=({"albumobject": albumobject,"foreignPicture": msg.foreignPicture})}
|
||||||
|
// print("Albums:"+j+msg.albums.length+JSON.stringify(data));
|
||||||
|
msg.model.append(data);}
|
||||||
|
if (j==msg.albums.length){
|
||||||
|
msg.model.sync()
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
.pragma library
|
||||||
|
.import QtQuick.LocalStorage 2.0 as Sql
|
||||||
|
|
||||||
|
function friendicaRequest(login,api,rootwindow,callback) {
|
||||||
|
var xhrequest= new XMLHttpRequest();
|
||||||
|
xhrequest.onreadystatechange = function() {
|
||||||
|
//print(api+JSON.stringify(login));
|
||||||
|
if(xhrequest.readyState === XMLHttpRequest.DONE) {
|
||||||
|
try{ if (xhrequest.responseText!=""){
|
||||||
|
callback(xhrequest.responseText)
|
||||||
|
}else{
|
||||||
|
showMessage("Error","API:" +api+"\n NO RESPONSE",rootwindow);
|
||||||
|
callback(xhrequest.responseText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e){
|
||||||
|
showMessage("Error", api+" "+e,rootwindow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhrequest.open("GET", login.server+api,true,login.username,Qt.atob(login.password));
|
||||||
|
xhrequest.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function friendicaPostRequest(login,api,rootwindow,callback) {
|
||||||
|
var xhrequest= new XMLHttpRequest();
|
||||||
|
xhrequest.onreadystatechange = function() {
|
||||||
|
//print(api+JSON.stringify(login));
|
||||||
|
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
|
||||||
|
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
|
||||||
|
try{ if (xhrequest.responseText!=""){
|
||||||
|
callback(xhrequest.responseText)
|
||||||
|
}else{
|
||||||
|
showMessage("Error",api+" NO RESPONSE",rootwindow)
|
||||||
|
callback(xhrequest.responseText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e){
|
||||||
|
showMessage("Error", api+" "+e,rootwindow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhrequest.open("POST", login.server+api,true,login.username,Qt.atob(login.password));
|
||||||
|
xhrequest.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function friendicaWebRequest(url,rootwindow,callback) {
|
||||||
|
var xhrequest = new XMLHttpRequest();
|
||||||
|
xhrequest.onreadystatechange = function() {
|
||||||
|
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
|
||||||
|
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
|
||||||
|
try{ callback(xhrequest.responseText);
|
||||||
|
}
|
||||||
|
catch (e){
|
||||||
|
showMessage("Error",url+" "+e, rootwindow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhrequest.open("GET", url,true);
|
||||||
|
xhrequest.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function readData(database,table,username,callback,filter,filtervalue) { // reads and applies data from DB
|
||||||
|
if (filter){
|
||||||
|
var where = " AND "+ filter +" = '" + filtervalue+"'";
|
||||||
|
} else { var where="";}
|
||||||
|
if (username){
|
||||||
|
var user = ' where username= "'+ username +'"';
|
||||||
|
} else { var user='';}
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
if(!db) { return; }
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
//print('select * from '+table+user+where);
|
||||||
|
var rsArray=[];
|
||||||
|
var rs = tx.executeSql('select * from '+table+user+where);
|
||||||
|
for(var i = 0; i < rs.rows.length; i++) {
|
||||||
|
rsArray.push(rs.rows.item(i))
|
||||||
|
}
|
||||||
|
callback(rsArray);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function readField(field,database,table, username, callback,filter,filtervalue) { // reads and applies data from DB
|
||||||
|
if (filter){
|
||||||
|
var where = " AND "+ filter +" = '" + filtervalue+"'";
|
||||||
|
} else { var where="";}
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
if(!db) { return; }
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
//print('... read from database ' + field)
|
||||||
|
var rsArray=[];
|
||||||
|
//print('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC');
|
||||||
|
var rs = tx.executeSql('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC');
|
||||||
|
for(var i = 0; i < rs.rows.length; i++) {
|
||||||
|
rsArray.push(rs.rows.item(i)[field])
|
||||||
|
}
|
||||||
|
callback(rsArray);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMessage(header,message,rootwindow){
|
||||||
|
var cleanmessage=message.replace(/"/g,"-");
|
||||||
|
var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+cleanmessage+'"}';
|
||||||
|
var messageObject=Qt.createQmlObject(messageString,rootwindow,"messageOutput");
|
||||||
|
}
|
||||||
|
|
||||||
|
function inArray(list, prop, val) {
|
||||||
|
if (list.length > 0 ) {
|
||||||
|
for (var i in list) { if (list[i][prop] === val) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} return -1;
|
||||||
|
}
|
||||||
|
function cleanArray(array) {
|
||||||
|
var arraystring=JSON.stringify(array);
|
||||||
|
arraystring=arraystring.replace(/[\[\]]/g , '');
|
||||||
|
return arraystring;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
function showFriends(db) {
|
||||||
|
Service.readActiveConfig(db,function(login){
|
||||||
|
Service.requestFriends(login.url,login.user,login.password,displayFriends);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function displayFriends(obj){
|
||||||
|
for (var i=0; i<obj.length; i++){
|
||||||
|
print(obj[i]);
|
||||||
|
if (obj[i]) {friendsModel.append({"friendName": obj[i]});
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
function ensureVisibility(c,f)
|
||||||
|
{
|
||||||
|
if (f.contentX >= c.x)
|
||||||
|
f.contentX = c.x;
|
||||||
|
else if (f.contentX+f.width <= c.x+c.width)
|
||||||
|
f.contentX = c.x+c.width-f.width;
|
||||||
|
if (f.contentY >= c.y)
|
||||||
|
f.contentY = c.y;
|
||||||
|
else if (f.contentY+f.height <= c.y+c.height)
|
||||||
|
f.contentY = c.y+c.height-f.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createObject(objectQml,qmlParameters,parentitem,callback) {
|
||||||
|
var component = Qt.createComponent(objectQml);
|
||||||
|
if (component.status === Component.Ready || component.status === Component.Error)
|
||||||
|
finishCreation(component,qmlParameters,parentitem,callback);
|
||||||
|
else
|
||||||
|
component.statusChanged.connect(finishCreation(qmlParameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishCreation(component,qmlParameters,parentitem,callback) {
|
||||||
|
if (component.status === Component.Ready) {
|
||||||
|
var createdObject = component.createObject(parentitem, qmlParameters);
|
||||||
|
if (createdObject === null)
|
||||||
|
print("Error creating image"); }
|
||||||
|
else if (component.status === Component.Error)
|
||||||
|
print("Error loading component:"+component.errorString());
|
||||||
|
else {print("created")}
|
||||||
|
//callback(createdObject);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,399 @@
|
||||||
|
.pragma library
|
||||||
|
.import QtQuick.LocalStorage 2.0 as Sql
|
||||||
|
.import "qrc:/js/helper.js" as Helperjs
|
||||||
|
|
||||||
|
function requestFriends(login,database,rootwindow,callback){
|
||||||
|
// return array of friends
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('UPDATE contacts SET isFriend=0 where username="'+login.username+'"')}); // clean old friends
|
||||||
|
Helperjs.friendicaRequest(login,"/api/statuses/friends", rootwindow,function (obj){
|
||||||
|
var friends=JSON.parse(obj);
|
||||||
|
for (var i=0;i<friends.length;i++){ friends[i].isFriend=1}
|
||||||
|
callback(friends)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestGroups(login,database,rootwindow,callback){
|
||||||
|
// retrieve, save and return groups. Other features currently not implemented
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
Helperjs.friendicaRequest(login,"/api/friendica/group_show",rootwindow, function (obj){
|
||||||
|
var groups=JSON.parse(obj);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('DELETE from groups where username="'+login.username+'"'); // clean old groups
|
||||||
|
for (var i=0;i<groups.length;i++){
|
||||||
|
var memberarray=[]; for (var user in groups[i].user){memberarray.push(parseInt(groups[i].user[user].id))}
|
||||||
|
//print("Members: "+groups[i].user)
|
||||||
|
var result2 = tx.executeSql('INSERT INTO groups VALUES (?,?,?,?)', [login.username,groups[i].name,groups[i].gid,JSON.stringify(memberarray)])}
|
||||||
|
callback()
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
|
||||||
|
function getFriendsTimeline(login,database,contacts,onlynew,rootwindow,callback){
|
||||||
|
// retrieve and return timeline since last news, return contacts which are not friends and older than 2 days for update (friends can be updated in Contactstab)
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var parameter = "";
|
||||||
|
if(onlynew){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'); // check for last news id
|
||||||
|
try{parameter="&since_id="+result.rows.item(0).status_id;}catch(e){};})}
|
||||||
|
var newContacts=[];
|
||||||
|
//print("/api/statuses/friends_timeline"+parameter);
|
||||||
|
Helperjs.friendicaRequest(login,"/api/statuses/friends_timeline"+parameter, rootwindow,function (obj){
|
||||||
|
var news=JSON.parse(obj);
|
||||||
|
var newContacts=findNewContacts(news,contacts);
|
||||||
|
callback(news,newContacts)
|
||||||
|
})}
|
||||||
|
|
||||||
|
function getCurrentContacts(login,database,callback){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var contactlist=[];
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT id from contacts WHERE username="'+login.username+'" AND isFriend=1'); // check for friends
|
||||||
|
for (var i=0;i<result.rows.length;i++){
|
||||||
|
contactlist.push(result.rows.item(i).id )
|
||||||
|
}
|
||||||
|
var lastDate=Date.now()-172800000;// 2 days old
|
||||||
|
print('SELECT id from contacts WHERE username="'+login.username+'" AND isFriend=0 AND imageAge>'+lastDate);
|
||||||
|
var result2 = tx.executeSql('SELECT id from contacts WHERE username="'+login.username+'" AND isFriend=0 AND imageAge > '+lastDate);
|
||||||
|
for (var j=0;j<result2.rows.length;j++){
|
||||||
|
contactlist.push(result2.rows.item(j).id )
|
||||||
|
}
|
||||||
|
})
|
||||||
|
callback(contactlist)
|
||||||
|
}
|
||||||
|
|
||||||
|
function findNewContacts(news,contacts){
|
||||||
|
var newContacts=[];
|
||||||
|
for (var i=0;i<news.length;i++){
|
||||||
|
var id=parseInt(news[i].user.id);
|
||||||
|
if(contacts.indexOf(id)==-1 && !(inArray(newContacts,"id",id))){
|
||||||
|
news[i].user.isFriend=0;
|
||||||
|
newContacts.push(news[i].user);
|
||||||
|
}
|
||||||
|
if (news[i].friendica_activities.like.length>0){
|
||||||
|
for (var j=0;j<news[i].friendica_activities.like.length;j++){
|
||||||
|
var like_id=parseInt(news[i].friendica_activities.like[j].id);
|
||||||
|
if(contacts.indexOf(like_id)==-1 && !(inArray(newContacts,"id",like_id))){
|
||||||
|
news[i].friendica_activities.like[j].isFriend=0;
|
||||||
|
newContacts.push(news[i].friendica_activities.like[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (news[i].friendica_activities.dislike.length>0){
|
||||||
|
for (var k=0;j<news[k].friendica_activities.dislike.length;k++){
|
||||||
|
var dislike_id=parseInt(news[i].friendica_activities.dislike[k].id);
|
||||||
|
if(contacts.indexOf(dislike_id)==-1 && !(inArray(newContacts,"id",dislike_id))){
|
||||||
|
news[i].friendica_activities.dislike[k].isFriend=0;
|
||||||
|
newContacts.push(news[i].friendica_activities.dislike[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newContacts
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeNews(login,database,news,rootwindow,callback){
|
||||||
|
// 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));
|
||||||
|
var ausdruck=news[i];
|
||||||
|
var likearray=[]; for (var user in news[i].friendica_activities.like){likearray.push(parseInt(news[i].friendica_activities.like[user].id))}
|
||||||
|
var dislikearray=[]; for (var user in news[i].friendica_activities.dislike){parseInt(news[i].friendica_activities.dislike[user].id)}
|
||||||
|
var attendyesarray=[]; for (var user in news[i].friendica_activities.attendyes){attendyesarray.push(parseInt(news[i].friendica_activities.attendyes[user].id))}
|
||||||
|
var attendnoarray=[]; for (var user in news[i].friendica_activities.attendno){attendnoarray.push(parseInt(news[i].friendica_activities.attendno[user].id))}
|
||||||
|
var attendmaybearray=[]; for (var user in news[i].friendica_activities.attendmaybe){attendmaybearray.push(parseInt(news[i].friendica_activities.attendmaybe[user].id))}
|
||||||
|
var friendica_activities=[likearray,dislikearray,attendyesarray,attendnoarray,attendmaybearray]
|
||||||
|
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
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
print(news[i].id +' news exists, update it')
|
||||||
|
result = tx.executeSql('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="'+JSON.stringify(friendica_activities)+'" 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) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,0,Qt.btoa(news[i].text),Date.parse(cleanDate(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, JSON.stringify(friendica_activities),"[]"])}})
|
||||||
|
}
|
||||||
|
getDirectMessage(login,database,rootwindow,callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDirectMessage(login,database,rootwindow,callback){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var parameter = "";
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" AND messagetype=1 ORDER BY status_id DESC LIMIT 1'); // check for last news id
|
||||||
|
try{parameter="&since_id="+result.rows.item(0).status_id;}catch(e){};})
|
||||||
|
Helperjs.friendicaRequest(login,"/api/direct_messages/all"+parameter,rootwindow, function (obj){
|
||||||
|
var messages=JSON.parse(obj);
|
||||||
|
for (var i=0;i<messages.length;i++){
|
||||||
|
//print('store message data for '+JSON.stringify(messages[i]));
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT * from news where username= "'+login.username+'" AND status_id = "'+messages[i].id+'" AND messagetype=1'); // check for news id
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
print(messages[i].id +' directmessage exists, update it')
|
||||||
|
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=1, text="'+Qt.btoa(messages[i].text)+'", created_at="'+Date.parse(cleanDate(messages[i].created_at))+'", source="Friendica", status_id="'+messages[i].id+'", uid="'+messages[i].sender.id+'", statusnet_html="'+Qt.btoa(messages[i].text)+'", statusnet_conversation_id="'+messages[i].friendica_parent_uri+'" where username="'+login.username+'" AND status_id="'+messages[i].status_id+'" AND messagetype=1');
|
||||||
|
} else {// use insert
|
||||||
|
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,source,status_id,uid,statusnet_html,statusnet_conversation_id) VALUES (?,?,?,?,?,?,?,?,?)', [login.username,1,Qt.btoa(messages[i].text),Date.parse(cleanDate(messages[i].created_at)), "Friendica", messages[i].id, messages[i].sender.id,Qt.btoa(messages[i].text),messages[i].friendica_parent_uri])}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(login.newsViewType=="Timeline"){newsfromdb(database,login.username,callback)}
|
||||||
|
else{chatsfromdb(database,login.username,callback)}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNotifications(login,database,rootwindow,callback){
|
||||||
|
Helperjs.friendicaRequest(login,"/api/friendica/notifications", rootwindow,function (obj){
|
||||||
|
var messages=JSON.parse(obj);
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
for (var i=0;i<messages.length;i++){
|
||||||
|
//print('store message data for '+JSON.stringify(messages[i]));
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT * from news where username="'+login.username+'" AND status_id = "'+messages[i].id+'" AND messagetype=2'); // check for news id
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
print(messages[i].id +' Notification exists, update it')
|
||||||
|
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=2, text="'+Qt.btoa(messages[i].msg_html)+'", created_at="'+Date.parse(messages[i].date)+'", source="Friendica", status_id="'+messages[i].id+'", uid="'+messages[i].uid+'", statusnet_html="'+Qt.btoa(messages[i].msg_html)+'", statusnet_conversation_id="'+messages[i].parent+'" where username="'+login.username+'" AND status_id="'+messages[i].id+'" AND messagetype=2');
|
||||||
|
} else {// use insert
|
||||||
|
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,source,status_id, uid,statusnet_html,statusnet_conversation_id) VALUES (?,?,?,?,?,?,?,?,?)', [login.username,2,Qt.btoa(messages[i].msg_html),Date.parse(messages[i].date),"Friendica", messages[i].id, messages[i].uid,Qt.btoa(messages[i].msg_html),messages[i].parent])}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var newsrs=tx.executeSql('select * from news WHERE username="'+login.username+'" AND messagetype=2 ORDER BY status_id DESC LIMIT 20');
|
||||||
|
var newsArray=[];
|
||||||
|
for(var j = 0; j < newsrs.rows.length; j++) {
|
||||||
|
newsArray.push(newsrs.rows.item(j));
|
||||||
|
callback(newsArray);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})}
|
||||||
|
|
||||||
|
function getActivitiesUserData(database,username,useridArray){
|
||||||
|
var helpArray=[];
|
||||||
|
for (var i=0;i<useridArray.length;i++){
|
||||||
|
Helperjs.readData(database,"contacts",username,function(userdata){
|
||||||
|
helpArray.push(userdata[0]);
|
||||||
|
},"id",useridArray[i]);
|
||||||
|
}
|
||||||
|
return helpArray
|
||||||
|
}
|
||||||
|
|
||||||
|
function newsfromdb(database,username,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) {
|
||||||
|
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');
|
||||||
|
stop="<="+rs.rows.item(0).created_at}catch(e){stop="<99999999999999"}}
|
||||||
|
else{var stop="<"+stop_time}
|
||||||
|
var contactfilter="";if(contact){contactfilter=" AND uid='"+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="'+username+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
|
||||||
|
var newsArray=[];
|
||||||
|
for(var i = 0; i < newsrs.rows.length; i++) {
|
||||||
|
newsArray.push(newsrs.rows.item(i));
|
||||||
|
Helperjs.readData(database,"contacts",username,function(userdata){
|
||||||
|
newsArray[i].user=userdata[0];
|
||||||
|
},"id",newsArray[i].uid);
|
||||||
|
if(newsArray[i].in_reply_to_user_id){
|
||||||
|
Helperjs.readData(database,"contacts",username,function(replytodata){
|
||||||
|
newsArray[i].reply_user=replytodata[0];
|
||||||
|
},"id",newsArray[i].in_reply_to_user_id);
|
||||||
|
}
|
||||||
|
if (newsArray[i].messagetype==0){
|
||||||
|
for(var j=0;j<newsArray[i].friendica_activities.length;j++){
|
||||||
|
newsArray[i]=fetchUsersForNews(database,username,newsArray[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(newsArray)});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchUsersForNews(database,username,news){
|
||||||
|
Helperjs.readData(database,"contacts",username,function(userdata){
|
||||||
|
news.user=userdata[0];
|
||||||
|
//print("Fetch user"+JSON.stringify(news.user));
|
||||||
|
},"id",news.uid);
|
||||||
|
if(news.in_reply_to_user_id){
|
||||||
|
Helperjs.readData(database,"contacts",username,function(replytodata){
|
||||||
|
news.reply_user=replytodata[0];
|
||||||
|
//print("Fetch reply to"+JSON.stringify(news.reply_user));
|
||||||
|
},"id",news.in_reply_to_user_id);
|
||||||
|
}
|
||||||
|
if (news.messagetype==0){
|
||||||
|
for(var j=0;j<news.friendica_activities.length;j++)
|
||||||
|
{var friendicaArray=JSON.parse(news.friendica_activities);
|
||||||
|
// print("Array: "+friendicaArray[1]);
|
||||||
|
news.like=getActivitiesUserData(database,username,friendicaArray[0]);
|
||||||
|
news.dislike=getActivitiesUserData(database,username,friendicaArray[1]);
|
||||||
|
news.attendyes=getActivitiesUserData(database,username,friendicaArray[2]);
|
||||||
|
news.attendno=getActivitiesUserData(database,username,friendicaArray[3]);
|
||||||
|
news.attendmaybe=getActivitiesUserData(database,username,friendicaArray[4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return news
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteNews(login,database,newsid,messagetype,rootwindow,callback){
|
||||||
|
var api="" ;
|
||||||
|
if (messagetype==0){ api="/api/statuses/destroy?id="}
|
||||||
|
else if (messagetype==1){ api="/api/direct_messages/destroy?id="}
|
||||||
|
else if (messagetype==2){ api="/api/friendica/notifications/seen?id="}
|
||||||
|
Helperjs.friendicaPostRequest(login,api+newsid, rootwindow,function (obj){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {var result = tx.executeSql('DELETE from news where username="'+login.username+'" AND messagetype='+messagetype+' AND status_id ='+newsid); // delete news id
|
||||||
|
callback(obj)
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
|
||||||
|
function retweetNews(login,database,newsid,rootwindow,callback){
|
||||||
|
Helperjs.friendicaPostRequest(login,"/api/statuses/retweet?id="+newsid, rootwindow,function (obj){
|
||||||
|
var answer=JSON.parse(obj);
|
||||||
|
if(answer.status.error){Helperjs.showMessage("Repost",answer.status.code,rootwindow);}
|
||||||
|
else{Helperjs.showMessage("Repost",obj,rootwindow)}
|
||||||
|
})}
|
||||||
|
|
||||||
|
function favorite(login,favorite,newsid,rootwindow){
|
||||||
|
// toggle favorites
|
||||||
|
if(favorite){ Helperjs.friendicaPostRequest(login,"/api/favorites/create?id="+newsid, rootwindow,function (obj){
|
||||||
|
print("Favorite "+obj);
|
||||||
|
})}
|
||||||
|
else {Helperjs.friendicaPostRequest(login,"/api/favorites/destroy?id="+newsid, rootwindow,function (obj){
|
||||||
|
print("Favorite destroyed "+obj);
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
|
||||||
|
function likerequest(login,database,verb,newsid,rootwindow){
|
||||||
|
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/"+verb+"?id="+newsid, rootwindow,function (obj){
|
||||||
|
if (obj=='"ok"'){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var currentActivities_rs=tx.executeSql('select friendica_activities_self from news WHERE username="'+login.username+'" AND status_id='+newsid) ;
|
||||||
|
var currentActivities=JSON.parse(currentActivities_rs.rows.item(0).friendica_activities_self);
|
||||||
|
print(verb+"currentActivities "+JSON.stringify(currentActivities));
|
||||||
|
if ((verb=="like")&&(currentActivities.indexOf(1)==-1)){ currentActivities.push(1);
|
||||||
|
if (currentActivities.indexOf(2)!=-1){currentActivities.splice(currentActivities.indexOf(2),1)}
|
||||||
|
}
|
||||||
|
if ((verb=="dislike")&&(currentActivities.indexOf(2)==-1)){ currentActivities.push(2);
|
||||||
|
if (currentActivities.indexOf(1)!=-1){currentActivities.splice(currentActivities.indexOf(1),1)}
|
||||||
|
}
|
||||||
|
if (verb=="unlike"){ if (currentActivities.indexOf(1)!=-1){currentActivities.splice(currentActivities.indexOf(1),1)}}
|
||||||
|
if (verb=="undislike"){ if (currentActivities.indexOf(2)!=-1){currentActivities.splice(currentActivities.indexOf(2),1)}}
|
||||||
|
print(JSON.stringify(currentActivities));
|
||||||
|
var result = tx.executeSql('UPDATE news SET friendica_activities_self ="'+JSON.stringify(currentActivities)+'" where username="'+login.username+'" AND status_id ='+newsid);
|
||||||
|
})}
|
||||||
|
else{print("likerequest"+obj)}})
|
||||||
|
}
|
||||||
|
|
||||||
|
function like(login,database,toggle,verb,newsid,rootwindow){
|
||||||
|
if(verb=="like"&& toggle==1){likerequest(login,database,"like",newsid,rootwindow);
|
||||||
|
}
|
||||||
|
if(verb=="dislike"&& toggle==1){likerequest(login,database,"dislike",newsid,rootwindow);
|
||||||
|
}
|
||||||
|
if(toggle==0){
|
||||||
|
likerequest(login,database,"un"+verb,newsid,rootwindow);}
|
||||||
|
}
|
||||||
|
|
||||||
|
function attend(login,database,attend,newsid,rootwindow,callback){
|
||||||
|
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/attend"+attend+"?id="+newsid, rootwindow,function (obj){
|
||||||
|
var attendReturn=JSON.parse(obj);
|
||||||
|
// print("attend: "+obj);
|
||||||
|
if (attendReturn=="OK")
|
||||||
|
{var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var currentActivities_rs=tx.executeSql('select friendica_activities_self from news WHERE username="'+login.username+'" AND status_id='+newsid) ;
|
||||||
|
var currentActivities=JSON.parse(currentActivities_rs.rows.item(0));
|
||||||
|
print("currentActivities "+JSON.stringify(currentActivities));
|
||||||
|
if ((attend=="attendyes")&&(currentActivities.indexOf(3)==-1)){
|
||||||
|
currentActivities.push(3);
|
||||||
|
currentActivities.splice(currentActivities.indexOf(4),1)
|
||||||
|
currentActivities.splice(currentActivities.indexOf(5),1)
|
||||||
|
}
|
||||||
|
if ((attend=="attendno")&&(currentActivities.indexOf(4)==-1)){
|
||||||
|
currentActivities.push(4);
|
||||||
|
currentActivities.splice(currentActivities.indexOf(3),1)
|
||||||
|
currentActivities.splice(currentActivities.indexOf(5),1)
|
||||||
|
}
|
||||||
|
if ((attend=="attendmaybe")&&(currentActivities.indexOf(5)==-1)){
|
||||||
|
currentActivities.push(5);
|
||||||
|
currentActivities.splice(currentActivities.indexOf(3),1)
|
||||||
|
currentActivities.splice(currentActivities.indexOf(4),1)
|
||||||
|
}
|
||||||
|
var result = tx.executeSql('UPDATE news SET friendica_activities_self ="'+JSON.stringify(currentActivities)+'" where username="'+login.username+'" AND status_id ='+newsid);
|
||||||
|
callback();
|
||||||
|
})}})}
|
||||||
|
|
||||||
|
function requestConversation(login,database,newsid,contacts,rootwindow,callback){
|
||||||
|
Helperjs.friendicaRequest(login,"/api/conversation/show?id="+newsid,rootwindow, function (obj){
|
||||||
|
var news=JSON.parse(obj);
|
||||||
|
var newContacts=findNewContacts(news,contacts);
|
||||||
|
// storeNews(login,database,news,rootwindow,callback)
|
||||||
|
callback(news,newContacts)
|
||||||
|
})}
|
||||||
|
|
||||||
|
function conversationfromdb(database,user,conversationId,callback){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var newsrs=tx.executeSql('select * from news WHERE username="'+user+'" AND statusnet_conversation_id="'+conversationId+'" ORDER BY created_at ASC');
|
||||||
|
var newsArray=[];
|
||||||
|
for(var i = 0; i < newsrs.rows.length; i++) {
|
||||||
|
newsArray.push(newsrs.rows.item(i));
|
||||||
|
newsArray[i]=fetchUsersForNews(database,user,newsArray[i])
|
||||||
|
}
|
||||||
|
callback(newsArray);} )}
|
||||||
|
|
||||||
|
function requestFavorites(login,database,contacts,rootwindow,callback){
|
||||||
|
Helperjs.friendicaRequest(login,"/api/favorites",rootwindow, function (obj){
|
||||||
|
//print(obj+JSON.stringify(obj));
|
||||||
|
var news=JSON.parse(obj);
|
||||||
|
var newContacts=findNewContacts(news,contacts);
|
||||||
|
// storeNews(login,database,news,rootwindow,callback)
|
||||||
|
callback(news,newContacts)
|
||||||
|
})}
|
||||||
|
|
||||||
|
function favoritesfromdb(database,user,callback){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
print('select * from news WHERE username="'+user+'" AND favorited=1 ORDER BY status_id DESC');
|
||||||
|
var newsrs=tx.executeSql('select * from news WHERE username="'+user+'" AND favorited=1 ORDER BY status_id DESC');
|
||||||
|
var newsArray=[];
|
||||||
|
for(var i = 0; i < newsrs.rows.length; i++) {
|
||||||
|
newsArray.push(newsrs.rows.item(i));
|
||||||
|
newsArray[i]=fetchUsersForNews(database,user,newsArray[i]);
|
||||||
|
callback(newsArray);
|
||||||
|
}})}
|
||||||
|
|
||||||
|
function chatsfromdb(database,user,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');
|
||||||
|
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');
|
||||||
|
var conversations=[];
|
||||||
|
for(var i = 0; i < conversationsrs.rows.length; i++) {
|
||||||
|
conversations.push(conversationsrs.rows.item(i).statusnet_conversation_id);
|
||||||
|
}
|
||||||
|
var newsArray=[];
|
||||||
|
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');
|
||||||
|
// if(newsrs.rows.length>1){
|
||||||
|
var helpernews=newsrs.rows.item(0);
|
||||||
|
helpernews.newscount=newsrs.rows.length;
|
||||||
|
helpernews=fetchUsersForNews(database,user,helpernews)
|
||||||
|
newsArray.push(helpernews);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
callback(newsArray);
|
||||||
|
})}
|
||||||
|
|
||||||
|
function inArray(list, prop, val) {
|
||||||
|
if (list.length > 0 ) {
|
||||||
|
for (var i in list) {if (list[i][prop] == val) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanDate(date){
|
||||||
|
var cleanedDate= date.slice(0,3)+", "+date.slice(8,11)+date.slice(4,7)+date.slice(25,30)+date.slice(10,25);
|
||||||
|
return cleanedDate
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
WorkerScript.onMessage = function(msg) {
|
||||||
|
if(msg.appendnews!==true){ msg.model.clear()};
|
||||||
|
|
||||||
|
for (var j=0;j<msg.news.length;j++){
|
||||||
|
if (msg.news[j]) {
|
||||||
|
var newsitemobject=msg.news[j];
|
||||||
|
//print("Newsitem"+JSON.stringify(newsitemobject));
|
||||||
|
if (newsitemobject.messagetype==2){
|
||||||
|
newsitemobject.user={};
|
||||||
|
newsitemobject.user.profile_image="";
|
||||||
|
newsitemobject.user.profile_image_url="";
|
||||||
|
newsitemobject.user.name="";
|
||||||
|
}
|
||||||
|
var likeText="";var dislikeText="";var attendyesText="";var attendnoText="";var attendmaybeText=""; var self={};
|
||||||
|
if (newsitemobject.messagetype==0){
|
||||||
|
if (newsitemobject.like.length>0){
|
||||||
|
if (newsitemobject.like.length==1){likeText= Qt.atob(newsitemobject.like[0].name)+" "+ qsTr("likes this.")}
|
||||||
|
else {likeText= newsitemobject.like.length+" "+ qsTr("like this.")}
|
||||||
|
}
|
||||||
|
if (newsitemobject.dislike.length>0){
|
||||||
|
if (newsitemobject.dislike.length==1){dislikeText= QT.atob(newsitemobject.dislike[0].name)+" "+ qsTr("doesn't like this.")}
|
||||||
|
else {dislikeText= newsitemobject.dislike.length+" "+ qsTr("don't like this.")}
|
||||||
|
}
|
||||||
|
if (newsitemobject.attendyes.length>0){
|
||||||
|
if (newsitemobject.attendyes.length==1){attendyesText= Qt.atob(newsitemobject.attendyes[0].name)+" "+ qsTr("will attend.")}
|
||||||
|
else {attendyesText= newsitemobject.attendyes.length+" "+ qsTr("persons will attend.")}
|
||||||
|
}
|
||||||
|
if (newsitemobject.attendno.length>0){
|
||||||
|
if (newsitemobject.attendno.length==1){attendnoText= Qt.atob(newsitemobject.attendno[0].name)+" "+ qsTr("will not attend.")}
|
||||||
|
else {attendnoText= newsitemobject.attendno.length+" "+ qsTr("persons will not attend.")}
|
||||||
|
}
|
||||||
|
if (newsitemobject.attendmaybe.length>0){
|
||||||
|
if (newsitemobject.attendmaybe.length==1){attendmaybeText= Qt.atob(newsitemobject.attendmaybe[0].name)+" "+ qsTr("may attend.")}
|
||||||
|
else {attendmaybeText= newsitemobject.attendmaybe.length+" "+ qsTr("persons may attend.")}
|
||||||
|
}
|
||||||
|
var friendica_activities_self=JSON.parse(newsitemobject.friendica_activities_self);
|
||||||
|
if (friendica_activities_self.indexOf(3)!=-1){self.attending=qsTr("yes")}
|
||||||
|
if (friendica_activities_self.indexOf(4)!=-1){self.attending=qsTr("no")}
|
||||||
|
if (friendica_activities_self.indexOf(5)!=-1){self.attending=qsTr("maybe")}
|
||||||
|
if (friendica_activities_self.indexOf(1)!=-1){self.liked=1}
|
||||||
|
if (friendica_activities_self.indexOf(2)!=-1){self.disliked=1}
|
||||||
|
}
|
||||||
|
var friendica_activities={likeText:likeText,dislikeText:dislikeText,attendyesText:attendyesText,attendnoText:attendnoText,attendmaybeText:attendmaybeText,self:self}
|
||||||
|
//print(JSON.stringify(friendica_activities) ) ;
|
||||||
|
var seconds=(msg.currentTime-newsitemobject.created_at)/1000;
|
||||||
|
var timestring="";
|
||||||
|
if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<90){timestring=Math.round(seconds/60)+" "+qsTr("minute") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<3600){timestring=Math.round(seconds/60)+" "+qsTr("minutes") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<5400){timestring=Math.round(seconds/3600)+" "+qsTr("hour") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<86400){timestring=Math.round(seconds/3600)+" "+qsTr("hours") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<129600){timestring=Math.round(seconds/86400)+" "+qsTr("day") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<3888000){timestring=Math.round(seconds/86400)+" "+qsTr("days") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<5832000){timestring=Math.round(seconds/3888000)+" "+qsTr("month") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<69984000){timestring=Math.round(seconds/3888000)+" "+qsTr("months") +" "+qsTr("ago");}
|
||||||
|
else {timestring=Math.round(seconds/69984000)+" "+qsTr("years") +" "+qsTr("ago");}
|
||||||
|
var data=({"newsitemobject": newsitemobject,"dateDiff":timestring,"friendica_activities":friendica_activities})}
|
||||||
|
//print("News:"+j+msg.news.length+JSON.stringify(data));
|
||||||
|
msg.model.append(data);}
|
||||||
|
if (j==msg.news.length){
|
||||||
|
msg.model.sync()
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
WorkerScript.onMessage = function(msg) {
|
||||||
|
if (msg.firstalbum==0){msg.model.clear();}
|
||||||
|
var limit=0; if (msg.albums.length-msg.firstalbum<20){limit=msg.albums.length} else{limit=msg.firstalbum+20}
|
||||||
|
for (var j=msg.firstalbum;j<limit;j++){
|
||||||
|
if (msg.albums[msg.firstalbum]) {
|
||||||
|
// print("album"+msg.albums[j].name);
|
||||||
|
if(msg.foreignPicture){
|
||||||
|
var albumname=msg.albums[j].name.trim();var albumlink=msg.albums[j].link
|
||||||
|
}else{
|
||||||
|
var albumname=msg.albums[j].toString();var albumlink=""}
|
||||||
|
msg.model.append({"albumlink":albumlink,"foreignPicture":msg.foreignPicture,"albumname":albumname});
|
||||||
|
msg.model.sync()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,272 @@
|
||||||
|
//.pragma library
|
||||||
|
.import QtQuick.LocalStorage 2.0 as Sql
|
||||||
|
.import "qrc:/js/helper.js" as Helperjs
|
||||||
|
.import "qrc:/js/news.js" as Newsjs
|
||||||
|
|
||||||
|
// IMAGE FUNCTIONS
|
||||||
|
|
||||||
|
function requestList(login,database,rootwindow,callback) {
|
||||||
|
//get list of own images and call download function
|
||||||
|
Helperjs.friendicaRequest(login,"/api/friendica/photos/list", rootwindow,function (helperobject){
|
||||||
|
//print("return"+helperobject);
|
||||||
|
var obj=JSON.parse(helperobject);
|
||||||
|
Helperjs.readField("id",database,"imageData",login.username,function(AllStoredImages){
|
||||||
|
if (AllStoredImages.length>0){
|
||||||
|
for(var i=0;i< AllStoredImages.length;i++){
|
||||||
|
var position=Helperjs.inArray(obj,"resourceID",AllStoredImages[i]);
|
||||||
|
if (position>-1){obj.splice(position,1)}
|
||||||
|
//obj.splice(obj.indexOf(AllStoredImages[i]),1);// list of objects instead of list!!!
|
||||||
|
}}
|
||||||
|
callback(obj)
|
||||||
|
})
|
||||||
|
})}
|
||||||
|
|
||||||
|
function dataRequest(login,photoID,database,rootwindow) {
|
||||||
|
// check if image exist and call download function
|
||||||
|
Helperjs.friendicaRequest(login,"/api/friendica/photo?photo_id="+photoID, rootwindow, function (image){
|
||||||
|
try{ if(image==""){currentimageno=currentimageno+1}else{
|
||||||
|
var obj = JSON.parse(image);
|
||||||
|
var helpfilename=obj.filename.substring(0,obj.filename.lastIndexOf("."));
|
||||||
|
var filesuffix="";
|
||||||
|
if (obj.type=="image/jpeg"){filesuffix=".jpg"}
|
||||||
|
else if (obj.type=="image/png"){filesuffix=".png"}
|
||||||
|
else {filesuffix=""}
|
||||||
|
|
||||||
|
if (helpfilename==""){// check if file has any filename
|
||||||
|
obj.filename=obj["id"]+filesuffix;
|
||||||
|
}
|
||||||
|
else{obj.filename=helpfilename+filesuffix}
|
||||||
|
|
||||||
|
var link="";
|
||||||
|
if(obj["link"][0]){link=obj["link"][0]} else{link=obj["link"]["4"]}
|
||||||
|
xhr.setUrl(Qt.resolvedUrl(link));
|
||||||
|
xhr.setFilename(login.imagestore+'albums/'+obj.album+"/"+obj["filename"]);
|
||||||
|
xhr.setDownloadtype("picture");
|
||||||
|
xhr.download();
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT * from imageData where id = "'+obj["id"]+'"');
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
result = tx.executeSql('UPDATE imageData SET username ="' +login.username+ '",id="'+obj.id+'", created="'+obj.created+'", edited="'+obj.edited+'", profile="'+obj.profile+'", link="'+obj["link"]["4"]+'", filename="'+obj.filename+'",title="'+obj.title+'", desc="'+obj.desc+'", type="'+obj.type+'", width="'+obj.width+'", height="'+obj.height+'", album="'+obj.album+'", location="file://'+login.imagestore+'albums/'+obj.album+'/" where id="'+obj["id"]+'"');
|
||||||
|
} else {// use insert print('... does not exists, create it')
|
||||||
|
result = tx.executeSql('INSERT INTO imageData VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,obj.id,obj.created,obj.edited, obj.title, obj.desc, obj.album, obj.filename, obj.type, obj.height, obj.width,obj. profile,obj["link"]["4"],'file://'+login.imagestore+'albums/'+obj.album+"/"]);
|
||||||
|
}
|
||||||
|
})}}
|
||||||
|
catch (e){print("Data retrieval failure! "+ e+obj);}
|
||||||
|
})}
|
||||||
|
|
||||||
|
|
||||||
|
function deleteImageData(database,user,field,selection,callback) { // does nothing useful at the moment
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
//print(' delete Image Data() for ' + field +"="+selection)
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
result = tx.executeSql('UPDATE imageData SET data="" where '+ field +'="'+selection+'"');
|
||||||
|
callback(result)})
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestFriendsAlbumPictures(login,friend,rootwindow,callback){
|
||||||
|
// screenscraping of albums page of contact without user and password
|
||||||
|
Helperjs.friendicaWebRequest(friend.url.replace("profile","photos"),rootwindow,function(photohtml){
|
||||||
|
//print(photohtml);
|
||||||
|
var photoarray=[];
|
||||||
|
var arr = photohtml.split("sidebar-photos-albums-li");
|
||||||
|
for (var i=2;i<arr.length;i++){
|
||||||
|
var albumlink = arr[i].substring(arr[i].indexOf('http'),arr[i].indexOf('class')-2);
|
||||||
|
var albumname=arr[i].substring(arr[i].indexOf('/span')+6,arr[i].indexOf('</a>')-1);
|
||||||
|
var album={'link':albumlink,'name':albumname}
|
||||||
|
photoarray.push(album);
|
||||||
|
}
|
||||||
|
callback(photoarray)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestFriendsPictures(link,rootwindow,callback){
|
||||||
|
// screenscraping of pictures page for given album
|
||||||
|
Helperjs.friendicaWebRequest(link,rootwindow,function(photohtml){
|
||||||
|
var photoarray=[];
|
||||||
|
var basehtml=photohtml.substring(photohtml.indexOf('<base')+12,photohtml.indexOf('/>',photohtml.indexOf('<base'))-2);
|
||||||
|
|
||||||
|
// old theme
|
||||||
|
if (photohtml.indexOf("photo-album-image-wrapper-end")>-1){ //theme 1
|
||||||
|
var arr = photohtml.split("photo-album-image-wrapper-end");}
|
||||||
|
|
||||||
|
// other themes
|
||||||
|
if (photohtml.indexOf("photo-album-wrapper")>-1){ //theme 2
|
||||||
|
var photoarea=photohtml.substring(photohtml.indexOf("photo-album-wrapper"),photohtml.indexOf("photo-album-end"))
|
||||||
|
var arr = photoarea.split("</a>");}
|
||||||
|
|
||||||
|
for (var i=0;i<arr.length-1;i++){
|
||||||
|
var photoname=arr[i].substring(arr[i].lastIndexOf('alt')+5,arr[i].lastIndexOf('title')-2);
|
||||||
|
var thumblink=arr[i].substring(arr[i].lastIndexOf('<img')+10,arr[i].lastIndexOf('alt')-2);
|
||||||
|
|
||||||
|
var imagetype=thumblink.substring(thumblink.lastIndexOf("."));
|
||||||
|
var photolink=thumblink.substring(0,thumblink.length-imagetype.length-2)+"-0"+imagetype
|
||||||
|
if(thumblink.substring(0,4)!=="http"){thumblink=basehtml+thumblink}
|
||||||
|
if(photolink.substring(0,4)!=="http"){photolink=basehtml+photolink}
|
||||||
|
var photo={'link':photolink,'name':photoname,'thumb':thumblink}
|
||||||
|
photoarray.push(photo);
|
||||||
|
}
|
||||||
|
callback(photoarray)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CONFIG FUNCTIONS
|
||||||
|
|
||||||
|
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])
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS imageData(username TEXT,id INT, created TEXT,edited TEXT, title TEXT, desc TEXT, album TEXT,filename TEXT, type TEXT, height INT, width INT, profile INT, link TEXT,location TEXT)');
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS config(server TEXT, username TEXT, password TEXT, imagestore TEXT, maxnews INT, timerInterval INT, newsViewType TEXT,isActive INT, permissions TEXT,maxContactAge INT,APIVersion TEXT)');
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS news(username TEXT, messagetype INT, text TEXT, created_at INT, in_reply_to_status_id INT, source TEXT, status_id INT, in_reply_to_user_id INT, geo TEXT,favorited TEXT, uid INT, statusnet_html TEXT, statusnet_conversation_id TEXT,friendica_activities TEXT, friendica_activities_self TEXT)');
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS contacts(username TEXT, id INT, name TEXT, screen_name TEXT, location TEXT,imageAge INT, profile_image_url TEXT, description TEXT, profile_image BLOB, url TEXT, protected TEXT, followers_count INT, friends_count INT, created_at INT, favourites_count TEXT, utc_offset TEXT, time_zone TEXT, statuses_count INT, following TEXT, verified TEXT, statusnet_blocking TEXT, notifications TEXT, statusnet_profile_url TEXT, cid INT, network TEXT, isFriend INT)');
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS groups(username TEXT, groupname TEXT, gid INT, members TEXT)');
|
||||||
|
})}
|
||||||
|
|
||||||
|
function savePermissions(database,obj) { // stores config to DB
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var permissions=JSON.stringify(obj)
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql( 'UPDATE config SET permissions="'+permissions+'" WHERE username="'+obj.username +'"');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeConfig(database,obj) { // stores config to DB
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
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+",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, 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);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
|
||||||
|
function getServerConfig(database,login,rootwindow,callback){
|
||||||
|
// check server with given credentials
|
||||||
|
try {Helperjs.friendicaRequest(login,"/api/statusnet/config",rootwindow, function (obj){
|
||||||
|
var serverconfig = JSON.parse(obj);
|
||||||
|
var serverconfigString="import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:'Server';standardButtons: StandardButton.Ok;text: 'SUCCESS! \nName: "+serverconfig.site.name+"\nLanguage: "+serverconfig.site.language+
|
||||||
|
"\nEmail: "+serverconfig.site.email+"\nTimezone: "+serverconfig.site.timezone+"\nClosed: "+serverconfig.site.closed+
|
||||||
|
"\nText limit: "+serverconfig.site.textlimit+"\nShort Url length: "+serverconfig.site.shorturllength+
|
||||||
|
"\nFriendica version: "+serverconfig.site.friendica.FRIENDICA_VERSION+"\nDFRN version: "+serverconfig.site.friendica.DFRN_PROTOCOL_VERSION +
|
||||||
|
"\nDB Update version: "+serverconfig.site.friendica.DB_UPDATE_VERSION+"'}";
|
||||||
|
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('UPDATE config SET APIVersion="'+ serverconfig.site.friendica.FRIENDICA_VERSION+'" WHERE username="'+login.username +'"')})
|
||||||
|
|
||||||
|
callback(serverconfigString);
|
||||||
|
})}
|
||||||
|
catch (e){callback (e);
|
||||||
|
}}
|
||||||
|
|
||||||
|
function readConfig(database,callback,filter,filtervalue) { // reads config
|
||||||
|
if (filter){var where = " WHERE "+ filter +" = '" + filtervalue+"'"} else { var where=""}
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3],initDatabase(database));
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var tables = tx.executeSql("SELECT * FROM sqlite_master WHERE type='table'");
|
||||||
|
if (tables.rows.length==0){print("no database");callback("")} else {
|
||||||
|
var rs = tx.executeSql('select * from config'+where);
|
||||||
|
var rsArray=[];
|
||||||
|
if (rs.rows.length>0){
|
||||||
|
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};
|
||||||
|
} else {var rsObject=""}
|
||||||
|
callback(rsObject)}}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function readActiveConfig(database){
|
||||||
|
var obj;
|
||||||
|
readConfig(database,function(config){obj=config},"isActive", 0);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteConfig(database,userobj,callback) { // delete user data from DB
|
||||||
|
if (userobj){var where = " WHERE username='"+ userobj.username+"' and server='"+userobj.server+"'";} else { return "no user selected!";}
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
if(!db) { return; }
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var rs = tx.executeSql('delete from config'+where);
|
||||||
|
callback(rs);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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 newscountrs = tx.executeSql('SELECT COUNT(*) from news');
|
||||||
|
var newscount = newscountrs.rows.item(0)["COUNT(*)"];
|
||||||
|
if (newscount>maxnews){var lastvalidtimers= tx.executeSql('select created_at from news ORDER BY created_at DESC LIMIT ' +(newscount-maxnews));
|
||||||
|
var lastvalidtime=lastvalidtimers.rows.item(maxnews).created_at;
|
||||||
|
var deleters = tx.executeSql('DELETE from news WHERE created_at<='+lastvalidtime)}
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function processNews(callback){
|
||||||
|
Newsjs.getCurrentContacts(login,db,function(contacts){
|
||||||
|
contactlist=contacts});
|
||||||
|
|
||||||
|
if (contactLoadType=="news"){
|
||||||
|
if(root.news.length==0){}
|
||||||
|
else{// show news
|
||||||
|
Newsjs.storeNews(login,db,news,root,function(dbnews){
|
||||||
|
root.newsSignal(dbnews);
|
||||||
|
newstab.newstabstatus=login.newsViewType
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
else if (contactLoadType=="friends"){// show friends
|
||||||
|
root.friendsSignal(login.username);
|
||||||
|
Newsjs.getCurrentContacts(login,db,function(contacts){
|
||||||
|
contactlist=contacts;
|
||||||
|
})}
|
||||||
|
|
||||||
|
else if (contactLoadType=="conversation"){
|
||||||
|
var conversationid=news[0].statusnet_conversation_id
|
||||||
|
if (!isNaN(parseInt(conversationid))){//no directmessage conversation
|
||||||
|
Newsjs.storeNews(root.login,root.db,news,root,function(){
|
||||||
|
Newsjs.conversationfromdb(db,root.login.username,conversationid, function(newsarray){
|
||||||
|
newstab.conversation=newsarray;
|
||||||
|
})
|
||||||
|
})}
|
||||||
|
else {newstab.conversation=news}//only DM conversations from database
|
||||||
|
}
|
||||||
|
else if (contactLoadType=="favorites"){//show favorited news
|
||||||
|
Newsjs.storeNews(root.login,root.db,news,root,function(){
|
||||||
|
Newsjs.favoritesfromdb(db,login.username,function(newsarray){
|
||||||
|
root.newsSignal(newsarray);
|
||||||
|
newstab.newstabstatus="Favorites";
|
||||||
|
})
|
||||||
|
})}
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateContactInDB(login,database,isFriend,contact){// for newstab and friendstab
|
||||||
|
var suffix=contact.profile_image_url.substring(contact.profile_image_url.lastIndexOf("."), contact.profile_image_url.length);
|
||||||
|
var imagename=login.imagestore+"contacts/"+contact.screen_name.trim()+suffix;
|
||||||
|
contacttimer.restart();
|
||||||
|
var currentTime=Date.now();
|
||||||
|
xhr.setUrl(Qt.resolvedUrl(contact.profile_image_url));
|
||||||
|
xhr.setFilename(imagename);
|
||||||
|
xhr.setDownloadtype("contact");
|
||||||
|
xhr.download();
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var result;
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
result = tx.executeSql('SELECT * from contacts where username="'+root.login.username+'" AND id = '+contact.id); // check for news id
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
result = tx.executeSql('UPDATE contacts SET username="'+login.username+'", id='+contact.id+', name="'+Qt.btoa(contact.name)+'", screen_name="'+contact.screen_name+'", location="'+contact.location+'",imageAge='+currentTime+', profile_image_url="'+contact.profile_image_url+'", description="'+Qt.btoa(contact.description)+'", profile_image="'+imagename+'", url="'+contact.url+'" , protected="'+contact.protected+'", followers_count='+contact.followers_count+', friends_count='+contact.friends_count+', created_at="'+ Date.parse(Newsjs.cleanDate(contact.created_at))+'", favourites_count="'+contact.favorites_count+'", utc_offset="'+contact.utc_offset+'", time_zone="'+contact.time_zone+'", statuses_count='+contact.statuses_count+', following="'+contact.following+'", verified ="'+contact.verified+'", statusnet_blocking="'+contact.statusnet_blocking+'", notifications="'+contact.notifictions+'", statusnet_profile_url="'+contact.statusnet_profile_url+'", cid='+contact.cid+', network="'+contact.network+'", isFriend='+isFriend+' where username="'+root.login.username+'" AND id='+contact.id);
|
||||||
|
} else {// use insert
|
||||||
|
result = tx.executeSql('INSERT INTO contacts VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,contact.id,Qt.btoa(contact.name),contact.screen_name,contact.location,currentTime,contact.profile_image_url, Qt.btoa(contact.description),imagename,contact.url,contact.protected,contact.followers_count, contact.friends_count,Date.parse(Newsjs.cleanDate(contact.created_at)),contact.favorites_count,contact.utc_offset,contact.time_zone,contact.statuses_count,contact.following,contact.verfied,contact.statusnet_blocking,contact.notifications,contact.statusnet_profile_url,contact.cid,contact.network,isFriend]);}
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,314 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
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"
|
||||||
|
|
||||||
|
StackView{
|
||||||
|
id: configStack
|
||||||
|
anchors.fill:parent
|
||||||
|
initialItem: Flickable{
|
||||||
|
width:root.width-5*mm
|
||||||
|
height:root.height-12*mm
|
||||||
|
contentHeight: configBackground.height
|
||||||
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
Rectangle{
|
||||||
|
id:configBackground
|
||||||
|
color: "grey"
|
||||||
|
width:parent.width
|
||||||
|
height:Math.max(90*mm,root.height-12*mm)
|
||||||
|
property var users:[]
|
||||||
|
BlueButton{
|
||||||
|
id:userButton
|
||||||
|
text:qsTr("User")
|
||||||
|
y:mm
|
||||||
|
width: root.width/2
|
||||||
|
onClicked:{
|
||||||
|
var useritems="";
|
||||||
|
for (var i=0;i<configBackground.users.length;i++){
|
||||||
|
|
||||||
|
useritems=useritems+"MenuItem{text:'"+configBackground.users[i].username+
|
||||||
|
"'; onTriggered: {Service.readConfig(db,function(obj){
|
||||||
|
userButton.text=obj.username;
|
||||||
|
servername.text=obj.server;
|
||||||
|
username.text= obj.username;
|
||||||
|
password.text=Qt.atob(obj.password);
|
||||||
|
imagestore.text=obj.imagestore;
|
||||||
|
maxNews.value=obj.maxnews;
|
||||||
|
newsTypeField.text=obj.newsViewType;
|
||||||
|
if( obj.isActive==0){isActiveField.text=qsTr('yes')} else {isActiveField.text=qsTr('no')}
|
||||||
|
},'username','"+configBackground.users[i].username+"')}}"
|
||||||
|
}
|
||||||
|
var menuString="import QtQuick.Controls 1.4;import 'qrc:/js/service.js' as Service; Menu {"+useritems+"}";
|
||||||
|
var userlistObject=Qt.createQmlObject(menuString,configBackground,"usermenuOutput")
|
||||||
|
userlistObject.popup() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Server"
|
||||||
|
x: 4*mm; y: 10*mm
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "User"
|
||||||
|
x: 4*mm; y: 20*mm
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Password"
|
||||||
|
x: 4*mm; y: 30*mm
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "Image dir."
|
||||||
|
x: 4*mm; y: 40*mm
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Max. News"
|
||||||
|
x: 4*mm; y: 50*mm
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "News as"
|
||||||
|
x: 4*mm; y: 60*mm
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "is Active"
|
||||||
|
x: 4*mm; y: 70*mm
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{color: "white"; x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;}
|
||||||
|
Flickable {
|
||||||
|
id: servernameFlickable
|
||||||
|
x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;
|
||||||
|
contentWidth: servername.paintedWidth
|
||||||
|
contentHeight: servername.paintedHeight
|
||||||
|
clip: true
|
||||||
|
TextEdit {
|
||||||
|
id: servername
|
||||||
|
width: servernameFlickable.width
|
||||||
|
height: servernameFlickable.height
|
||||||
|
focus: true
|
||||||
|
text:"https://..."
|
||||||
|
//wrapMode: TextEdit.NoWrap
|
||||||
|
//validator: RegExpValidator { regExp: /^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]]){2,4}([[a-zA-Z0-9]\/+=%&_\.~?\-]*))*$/}
|
||||||
|
// onEditingFinished:{}
|
||||||
|
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,servernameFlickable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
color: "white"
|
||||||
|
x: 25*mm; y: 20*mm; width: root.width/2; height: 5*mm;
|
||||||
|
TextInput {
|
||||||
|
id: username
|
||||||
|
anchors.fill: parent
|
||||||
|
selectByMouse: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
color: "white"
|
||||||
|
x: 25*mm; y: 30*mm; width: root.width/2; height: 5*mm;
|
||||||
|
TextInput {
|
||||||
|
id: password
|
||||||
|
anchors.fill: parent
|
||||||
|
selectByMouse: true
|
||||||
|
echoMode: TextInput.PasswordEchoOnEdit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{color: "white"; x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;}
|
||||||
|
Flickable {
|
||||||
|
id: imagestoreFlickable
|
||||||
|
x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;
|
||||||
|
clip: true
|
||||||
|
TextInput {
|
||||||
|
id: imagestore
|
||||||
|
width: imagestoreFlickable.width
|
||||||
|
height: imagestoreFlickable.height
|
||||||
|
wrapMode: TextEdit.NoWrap
|
||||||
|
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Slider{ id: maxNews
|
||||||
|
x:37*mm; y: 50*mm;width: root.width/3;height:5*mm
|
||||||
|
minimumValue: 0;maximumValue:100000; stepSize: 1000
|
||||||
|
}
|
||||||
|
Rectangle{color: "white"; x: 25*mm; y: 50*mm; width: 9*mm; height: 5*mm;
|
||||||
|
TextEdit{id:maxNewsText;
|
||||||
|
anchors.fill: parent
|
||||||
|
verticalAlignment:TextEdit.AlignRight
|
||||||
|
text:maxNews.value
|
||||||
|
focus: true
|
||||||
|
selectByMouse: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
x: 25*mm; y: 60*mm; width: root.width/2; height: 5*mm;
|
||||||
|
Text{
|
||||||
|
id: newsTypeField
|
||||||
|
anchors.fill: parent
|
||||||
|
text:"Timeline"
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill:parent
|
||||||
|
onClicked:newstypemenu.popup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
x: 25*mm; y: 70*mm; width: root.width/2; height: 5*mm;
|
||||||
|
Text{
|
||||||
|
id: isActiveField
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
console.log("You chose: " + imagestoreDialog.folder)
|
||||||
|
}
|
||||||
|
onRejected: {console.log("Canceled")}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: root.width/2+18*mm; y: 40*mm; width: 7*mm; height: 5*mm;
|
||||||
|
text: "..."
|
||||||
|
onClicked:
|
||||||
|
{imagestoreDialog.open()}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: 25*mm; y: 80*mm
|
||||||
|
text: "Update"
|
||||||
|
onClicked:{
|
||||||
|
var userconfig={server: servername.text, username: username.text, password:Qt.btoa(password.text), imagestore:imagestore.text,maxnews:maxNewsText.text,newsViewType:newsTypeField.text};
|
||||||
|
var errormessage="";
|
||||||
|
if (servername.text==""){errormessage=qsTr("No server given! ")}
|
||||||
|
//if (!servername.acceptableInput){errormessage+=qsTr("Server name not valid! ")}
|
||||||
|
else if (username.text==""){errormessage+=qsTr("No username 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=="") {
|
||||||
|
filesystem.Directory=userconfig.imagestore;
|
||||||
|
filesystem.makeDir("contacts");
|
||||||
|
filesystem.makeDir("albums");
|
||||||
|
Service.storeConfig(db,userconfig);
|
||||||
|
Service.readConfig(db,function(userconfig){
|
||||||
|
Service.getServerConfig(db,userconfig,configBackground, function(obj){
|
||||||
|
var serverString=obj;
|
||||||
|
var serverconfigObject=Qt.createQmlObject(serverString,configBackground,"serverconfigOutput");
|
||||||
|
Helperjs.readData(db,"config","",function(storedUsers){
|
||||||
|
storedUsers.sort(function(obj1, obj2) {
|
||||||
|
return obj1.isActive - obj2.isActive;
|
||||||
|
});
|
||||||
|
configBackground.users=storedUsers});
|
||||||
|
isActiveField.text="yes"
|
||||||
|
//reset values
|
||||||
|
root.login=userconfig;
|
||||||
|
root.contactlist=[];
|
||||||
|
root.news=[]
|
||||||
|
root.newContacts=[]
|
||||||
|
root.currentContact= 0
|
||||||
|
root.contactLoadType= ""
|
||||||
|
root.currentIndex=0;
|
||||||
|
newstab.active=true;
|
||||||
|
})},"isActive",0);
|
||||||
|
}
|
||||||
|
else {Helperjs.show("Error", errormessage,root)}
|
||||||
|
}}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: root.width/2+2*mm; y: mm; width: 5*mm; height: 5*mm;
|
||||||
|
text: "-"
|
||||||
|
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://...";
|
||||||
|
username.text="";
|
||||||
|
password.text="";
|
||||||
|
imagestore.text="";
|
||||||
|
maxNews.value=0;
|
||||||
|
newsTypeField.text="Timeline";
|
||||||
|
isActiveField.text="";
|
||||||
|
userButton.text=qsTr("User");
|
||||||
|
Helperjs.readData(db,"config","",function(storedUsers){
|
||||||
|
storedUsers.sort(function(obj1, obj2) {
|
||||||
|
return obj1.isActive - obj2.isActive;
|
||||||
|
})
|
||||||
|
configBackground.users=storedUsers;})
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: root.width/2+8*mm; y: mm; width: 5*mm; height: 5*mm;
|
||||||
|
text: "+"
|
||||||
|
onClicked:{
|
||||||
|
servername.text="https://..."
|
||||||
|
username.text=""
|
||||||
|
password.text=""
|
||||||
|
imagestore.text=""
|
||||||
|
maxNews.value=0
|
||||||
|
newsTypeField.text="Timeline"
|
||||||
|
isActiveField.text=""
|
||||||
|
userButton.text=qsTr("User")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: root.width/2+14*mm; y: mm; width: 5*mm; height: 5*mm;
|
||||||
|
text: "?"
|
||||||
|
onClicked:{
|
||||||
|
configStack.push({item:"qrc:/qml/configqml/InfoBox.qml"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id:newstypemenu
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Timeline")
|
||||||
|
onTriggered: {newsTypeField.text="Timeline"}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Tree")
|
||||||
|
onTriggered: {newsTypeField.text="Tree"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
try{Helperjs.readData(db,"config","",function(storedUsers){
|
||||||
|
storedUsers.sort(function(obj1, obj2) {
|
||||||
|
return obj1.isActive - obj2.isActive;
|
||||||
|
})
|
||||||
|
configBackground.users=storedUsers;
|
||||||
|
Service.readConfig(db,function(obj){
|
||||||
|
userButton.text=obj.username;
|
||||||
|
servername.text=obj.server;
|
||||||
|
username.text= obj.username;
|
||||||
|
password.text=Qt.atob(obj.password);
|
||||||
|
imagestore.text=obj.imagestore;
|
||||||
|
maxNews.value=obj.maxnews;
|
||||||
|
newsTypeField.text=obj.newsViewType;
|
||||||
|
if( obj.isActive==0){isActiveField.text=qsTr('yes')} else {isActiveField.text=qsTr('no')}},"isActive",0
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
catch (e){print(e)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
Rectangle{
|
||||||
|
color:"white"
|
||||||
|
width:infoBoxText.contentWidth
|
||||||
|
height:infoBoxText.contentHeight
|
||||||
|
Text{id:infoBoxText
|
||||||
|
textFormat: Text.RichText
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
text: "<b>Friendiqa v0.002 </b><br>Licensed under GPL 3<br> "+
|
||||||
|
"Profile <a href='https://freunde.ma-nic.de/profile/friendiqa'>https://freunde.ma-nic.de/profile/friendiqa</a><br>"+
|
||||||
|
"Sourcecode: <a href='https://github.com/LubuWest/Friendiqa'>https://github.com/LubuWest/Friendica</a><br>"+
|
||||||
|
"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>"
|
||||||
|
onLinkActivated:{
|
||||||
|
Qt.openUrlExternally(link)}
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
text:qsTr("Close")
|
||||||
|
onClicked:{configStack.pop()}
|
||||||
|
anchors.top:infoBoxText.bottom
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import "qrc:/js/layout.js" as Layoutjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: contactComponent
|
||||||
|
property var createdAtDate: new Date(contact.created_at)
|
||||||
|
property var linkUrl: contact.network!=="dfrn"?contact.url:contact.url.replace("profile","dfrn_request")
|
||||||
|
Rectangle {
|
||||||
|
id: wrapper
|
||||||
|
width: 16*mm
|
||||||
|
height: 15*mm
|
||||||
|
border.color: "grey"
|
||||||
|
color:"white"
|
||||||
|
Image {
|
||||||
|
id: photoImage
|
||||||
|
x:1
|
||||||
|
y:1
|
||||||
|
width: 10*mm
|
||||||
|
height:10*mm
|
||||||
|
source:(contact.profile_image!="")? "file://"+contact.profile_image : contact.profile_image_url
|
||||||
|
onStatusChanged: if (photoImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: namelabel
|
||||||
|
x: 1
|
||||||
|
width: wrapper.width-4
|
||||||
|
height: 3*mm
|
||||||
|
text: contact.screen_name
|
||||||
|
elide:Text.ElideRight
|
||||||
|
anchors.topMargin: 0
|
||||||
|
anchors.left: photoImage.left
|
||||||
|
color: "#303030"
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
anchors.top: photoImage.bottom
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
id:infobutton
|
||||||
|
width: 5*mm
|
||||||
|
height: 5*mm
|
||||||
|
color:"transparent"
|
||||||
|
text:"?"
|
||||||
|
anchors.left: photoImage.right
|
||||||
|
anchors.leftMargin: 3
|
||||||
|
anchors.topMargin: 3
|
||||||
|
anchors.top: parent.top
|
||||||
|
onClicked:{
|
||||||
|
contactComponent.state="large";
|
||||||
|
var component = Qt.createComponent("qrc:/qml/contactqml/ContactDetailsComponent.qml");
|
||||||
|
if (component.status== Component.Ready){
|
||||||
|
var contactDetails = component.createObject(wrapper,{"contact": contact})}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "large"
|
||||||
|
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:friendsTabView.width-4*mm; text:Qt.atob(contact.name)+" (@"+contact.screen_name+")"}
|
||||||
|
PropertyChanges { target: contactComponent; z: 2 }
|
||||||
|
PropertyChanges { target: wrapper; width:friendsTabView.width-3*mm;height:friendsTabView.height-10*mm}
|
||||||
|
PropertyChanges { target: photoImage; width:15*mm;height:15*mm }
|
||||||
|
PropertyChanges { target:contactComponent.GridView.view;contentY:contactComponent.y;contentX:contactComponent.x;interactive:false}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id: detailsrectangle
|
||||||
|
anchors.top: namelabel.bottom
|
||||||
|
anchors.topMargin: 2*mm
|
||||||
|
//opacity: 0
|
||||||
|
|
||||||
|
ScrollView{
|
||||||
|
horizontalScrollBarPolicy:Qt.ScrollBarAlwaysOff
|
||||||
|
frameVisible: true
|
||||||
|
//Flickable{
|
||||||
|
id:namelabelflickable
|
||||||
|
width: root.width-10*mm
|
||||||
|
height:friendsTabView.height-45*mm
|
||||||
|
//boundsBehavior:Flickable.StopAtBounds
|
||||||
|
//flickableDirection:Flickable.VerticalFlick
|
||||||
|
//contentWidth:width
|
||||||
|
//contentHeight: namelabeltext.height
|
||||||
|
clip:true
|
||||||
|
Text{
|
||||||
|
id:namelabeltext
|
||||||
|
width: namelabelflickable.width
|
||||||
|
height: implicitHeight
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
textFormat:Text.RichText
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
text:"<b>"+qsTr("Description")+": </b> "+Qt.atob(contact.description)+"<br> <b>"+qsTr("Location")+":</b> "+contact.location+"<br> <b>"+qsTr("Posts")+":</b> "+contact.statuses_count+
|
||||||
|
"<br> <b>"+qsTr("URL")+":</b> <a href='"+ linkUrl+"'>"+linkUrl+"</a><br> <b>"+
|
||||||
|
qsTr("Created at")+":</b> "+createdAtDate.toLocaleString(Qt.locale())
|
||||||
|
onLinkActivated: {
|
||||||
|
Qt.openUrlExternally(link)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row{
|
||||||
|
anchors.top: namelabelflickable.bottom
|
||||||
|
anchors.topMargin: 2*mm
|
||||||
|
spacing:4
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id:photobutton
|
||||||
|
text:"Photos"
|
||||||
|
visible:contact.network=="dfrn"? 1:0
|
||||||
|
onClicked:{contactComponent.state="";detailsrectangle.destroy();
|
||||||
|
root.currentIndex=2;
|
||||||
|
fotostab.active=true;
|
||||||
|
root.fotoSignal(contact) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id:messagebutton
|
||||||
|
text:"Messages"
|
||||||
|
onClicked:{contactComponent.state="";detailsrectangle.destroy();
|
||||||
|
root.currentIndex=0;
|
||||||
|
newstab.active=true;
|
||||||
|
root.messageSignal(contact.id) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id:dmbutton
|
||||||
|
visible: contact.following=="true"?true:false
|
||||||
|
text: "DM"
|
||||||
|
onClicked:{contactComponent.state="";detailsrectangle.destroy();
|
||||||
|
root.currentIndex=0;
|
||||||
|
newstab.active=true;
|
||||||
|
root.directmessageSignal(contact.screen_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id: closeButton
|
||||||
|
text: "close"
|
||||||
|
onClicked:{contactComponent.state="";detailsrectangle.destroy()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,197 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/js/news.js" as Newsjs
|
||||||
|
import "qrc:/qml/contactqml"
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
y:1
|
||||||
|
color: "white"
|
||||||
|
TabView{
|
||||||
|
id:friendsTabView
|
||||||
|
tabPosition: Qt.TopEdge
|
||||||
|
x:mm
|
||||||
|
y:mm
|
||||||
|
width: root.width-2*mm
|
||||||
|
height: root.height-10*mm
|
||||||
|
currentIndex: 0
|
||||||
|
|
||||||
|
signal contactsSignal(var username)
|
||||||
|
signal groupsSignal(var username)
|
||||||
|
onCurrentIndexChanged:{
|
||||||
|
if (currentIndex==0){root.friendsSignal(root.login.username)}
|
||||||
|
else if (currentIndex==1){contactsSignal(root.login.username)}
|
||||||
|
else if (currentIndex==2){groupsSignal(root.login.username)}
|
||||||
|
}
|
||||||
|
style: TabViewStyle {
|
||||||
|
frameOverlap: 1
|
||||||
|
tab: Rectangle {
|
||||||
|
color: "white"
|
||||||
|
//border.color: "light grey"
|
||||||
|
implicitWidth: root.width/3-2*mm
|
||||||
|
implicitHeight: 4*mm
|
||||||
|
Text { id: text
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: styleData.title
|
||||||
|
color: "dark grey"
|
||||||
|
font.pixelSize:2.5*mm
|
||||||
|
font.bold: styleData.selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame: Rectangle { color: "light grey" }
|
||||||
|
tabsAlignment:Qt.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Friends")
|
||||||
|
Rectangle{
|
||||||
|
id: friendsGridTab
|
||||||
|
function showFriends(username){
|
||||||
|
try {friendsModel.clear()} catch(e){print(e)};
|
||||||
|
Helperjs.readData(db,"contacts",username,function(friendsobject){
|
||||||
|
for (var i=0;i<friendsobject.length;i++){
|
||||||
|
friendsModel.append({"contact":friendsobject[i]});
|
||||||
|
}},"isFriend",1)
|
||||||
|
}
|
||||||
|
Connections{
|
||||||
|
target:root
|
||||||
|
onLoginChanged:{showFriends()}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
id: updateFriendsButton
|
||||||
|
text: qsTr("Update")
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
onClicked: {
|
||||||
|
try {friendsModel.clear()} catch(e){print(e)};
|
||||||
|
root.contactLoadType="friends";
|
||||||
|
Newsjs.requestFriends(root.login,db,root,function(nc){
|
||||||
|
root.newContacts=nc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar{
|
||||||
|
id: newContactsProgress
|
||||||
|
width: 15*mm
|
||||||
|
height: updateFriendsButton.height
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right:updateFriendsButton.left
|
||||||
|
anchors.rightMargin:mm
|
||||||
|
visible: (root.currentContact!=root.newContacts.length)?true:false
|
||||||
|
value: root.currentContact/root.newContacts.length
|
||||||
|
}
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: friendsView
|
||||||
|
x:mm
|
||||||
|
y:updateFriendsButton.height+2*mm
|
||||||
|
width:friendsGridTab.width-2*mm
|
||||||
|
height:friendsGridTab.height-updateFriendsButton.height-2*mm
|
||||||
|
clip: true
|
||||||
|
cellHeight: 16*mm
|
||||||
|
cellWidth: 17*mm
|
||||||
|
add: Transition {
|
||||||
|
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
|
||||||
|
}
|
||||||
|
model: friendsModel
|
||||||
|
delegate: ContactComponent { }
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id:friendsModel}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.friendsSignal.connect(showFriends);
|
||||||
|
showFriends(root.login.username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Other Contacts")
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id: contactsGridTab
|
||||||
|
function showContacts(username){
|
||||||
|
try {contactsModel.clear()} catch(e){print(e)};
|
||||||
|
Helperjs.readData(db, "contacts",root.login.username,function(contactsobject){
|
||||||
|
for (var j=0;j<contactsobject.length;j++){
|
||||||
|
contactsModel.append({"contact":contactsobject[j]});
|
||||||
|
}
|
||||||
|
},"isFriend",0)}
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: contactsView
|
||||||
|
x:mm
|
||||||
|
y:2*mm
|
||||||
|
width:contactsGridTab.width-2*mm
|
||||||
|
height:contactsGridTab.height-2*mm
|
||||||
|
clip: true
|
||||||
|
cellHeight: 16*mm
|
||||||
|
cellWidth: 17*mm
|
||||||
|
add: Transition {
|
||||||
|
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
|
||||||
|
}
|
||||||
|
model: contactsModel
|
||||||
|
delegate: ContactComponent { }
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: contactsModel}
|
||||||
|
Component.onCompleted: {
|
||||||
|
friendsTabView.contactsSignal.connect(showContacts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Groups")
|
||||||
|
Rectangle{
|
||||||
|
id: groupsGridTab
|
||||||
|
function showGroups(username){
|
||||||
|
try {groupsModel.clear()} catch(e){print(e)};
|
||||||
|
Helperjs.readData(db, "groups",root.login.username,function(groupsobject){
|
||||||
|
for (var j=0;j<groupsobject.length;j++){
|
||||||
|
groupsModel.append({"group":groupsobject[j]});
|
||||||
|
}})}
|
||||||
|
BlueButton {
|
||||||
|
id: updateGroupsButton
|
||||||
|
text: qsTr("Update")
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
onClicked: {
|
||||||
|
Newsjs.requestGroups(root.login,root.db,root,function(){
|
||||||
|
showGroups(root.login.username)})}
|
||||||
|
}
|
||||||
|
GridView {
|
||||||
|
id: groupsView
|
||||||
|
x:mm
|
||||||
|
y:updateGroupsButton.height+2*mm
|
||||||
|
width:groupsGridTab.width-2*mm
|
||||||
|
height:groupsGridTab.height-updateGroupsButton.height-2*mm
|
||||||
|
clip: true
|
||||||
|
cellHeight: 16*mm
|
||||||
|
cellWidth: 17*mm
|
||||||
|
add: Transition {
|
||||||
|
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
|
||||||
|
}
|
||||||
|
model: groupsModel
|
||||||
|
delegate: GroupComponent { }
|
||||||
|
}
|
||||||
|
ListModel{
|
||||||
|
id: groupsModel
|
||||||
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
friendsTabView.groupsSignal.connect(showGroups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: groupComponent
|
||||||
|
Rectangle {
|
||||||
|
id: wrapper
|
||||||
|
width: 16*mm
|
||||||
|
height: 15*mm
|
||||||
|
border.color: "grey"
|
||||||
|
color:"white"
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: photoImage
|
||||||
|
x:1
|
||||||
|
y:1
|
||||||
|
width: 10*mm
|
||||||
|
height:10*mm
|
||||||
|
source:"qrc:/images/defaultcontact.jpg"
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id: namelabel
|
||||||
|
x: 1
|
||||||
|
width: wrapper.width-2
|
||||||
|
height: 3*mm
|
||||||
|
text: group.groupname
|
||||||
|
|
||||||
|
color: "#303030"
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
anchors.top: photoImage.bottom
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
id:infobutton
|
||||||
|
width: 5*mm
|
||||||
|
height: 5*mm
|
||||||
|
color:"transparent"
|
||||||
|
text:"?"
|
||||||
|
anchors.left: photoImage.right
|
||||||
|
anchors.leftMargin: 3
|
||||||
|
anchors.topMargin: 3
|
||||||
|
anchors.top: parent.top
|
||||||
|
onClicked:{
|
||||||
|
Helperjs.readField("members",root.db,"groups",root.login.username,function(groups){
|
||||||
|
try {groupModel.clear()}catch (e){print(e)}
|
||||||
|
var groupmembers=JSON.parse(groups);
|
||||||
|
for (var user in groupmembers){
|
||||||
|
Helperjs.readData(root.db,"contacts",root.login.username,function(userdata){
|
||||||
|
if (userdata[0]){groupModel.append({"groupmember":userdata[0]})}
|
||||||
|
},"id",groupmembers[user])}
|
||||||
|
},"groupname",group.groupname);
|
||||||
|
groupComponent.state="large"}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id: detailsrectangle
|
||||||
|
anchors.top: namelabel.bottom
|
||||||
|
anchors.topMargin: 2*mm
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
Component { id:groupMember
|
||||||
|
Rectangle{
|
||||||
|
border.color: "#EEEEEE"
|
||||||
|
border.width: 1
|
||||||
|
width:parent.width
|
||||||
|
height:6*mm
|
||||||
|
Image {
|
||||||
|
id: memberImage
|
||||||
|
x:1
|
||||||
|
y:1
|
||||||
|
width: 5*mm
|
||||||
|
height:5*mm
|
||||||
|
source:(groupmember.isFriend==1)? "file://"+groupmember.profile_image :groupmember.profile_image_url
|
||||||
|
onStatusChanged: if (photoImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
|
||||||
|
}
|
||||||
|
Text{
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
anchors.left: memberImage.right
|
||||||
|
anchors.margins: 1*mm
|
||||||
|
text:Qt.atob(groupmember.name)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
ListView{
|
||||||
|
id: groupListView
|
||||||
|
x:1
|
||||||
|
//anchors.top: parent.top
|
||||||
|
width: root.width-10*mm
|
||||||
|
height:groupsView.height -28*mm
|
||||||
|
clip: true
|
||||||
|
spacing: 2
|
||||||
|
model: groupModel
|
||||||
|
delegate: groupMember
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: groupModel}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id: closeButton
|
||||||
|
anchors.top: groupListView.bottom
|
||||||
|
x:1
|
||||||
|
text: qsTr("close")
|
||||||
|
onClicked:{groupComponent.state=""}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "large"
|
||||||
|
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:groupsView.width}
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.LocalStorage 2.0
|
||||||
|
import QtQuick.Window 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
|
||||||
|
import QtQml.Models 2.1
|
||||||
|
import "qrc:/js/news.js" as Newsjs
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
//import "qrc:/js/layout.js" as Layoutjs
|
||||||
|
//import "qrc:/js/helper.js" as Helperjs
|
||||||
|
//import "qrc:/qml"
|
||||||
|
|
||||||
|
TabView{
|
||||||
|
id:root
|
||||||
|
tabPosition: Qt.BottomEdge
|
||||||
|
width: Screen.desktopAvailableWidth
|
||||||
|
height: Screen.desktopAvailableHeight
|
||||||
|
focus:true
|
||||||
|
property var db: ["Friendiqa", "1.0", "Stores Friendica data", 100000000]
|
||||||
|
property var login: Service.readActiveConfig(db)
|
||||||
|
property var contactlist: []
|
||||||
|
property real mm: Screen.pixelDensity
|
||||||
|
signal messageSignal(var friend)
|
||||||
|
signal fotoSignal(var friend)
|
||||||
|
signal directmessageSignal(var friend)
|
||||||
|
signal newsSignal(var news)
|
||||||
|
signal friendsSignal(var username)
|
||||||
|
|
||||||
|
currentIndex: (login=="")? 3:0
|
||||||
|
|
||||||
|
property var news:[]
|
||||||
|
property var newContacts:[]
|
||||||
|
property int currentContact: 0
|
||||||
|
property string contactLoadType: ""
|
||||||
|
|
||||||
|
onLoginChanged:{
|
||||||
|
Newsjs.getCurrentContacts(login,db,function(contacts){
|
||||||
|
contactlist=contacts});
|
||||||
|
}
|
||||||
|
onNewContactsChanged:{
|
||||||
|
if(newContacts.length>0){// download first contact image and update db
|
||||||
|
Service.updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])}
|
||||||
|
else if (contactLoadType!=""){
|
||||||
|
Service.processNews(function(){
|
||||||
|
root.contactLoadType="";
|
||||||
|
root.news=[];
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCurrentContactChanged:{// download next contact image after photoplaceholder is finished saving and update db
|
||||||
|
if(currentContact<newContacts.length){
|
||||||
|
Service.updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])}
|
||||||
|
else if (contactLoadType!=""){
|
||||||
|
Service.processNews(function(){
|
||||||
|
root.contactLoadType="";
|
||||||
|
root.news=[];
|
||||||
|
root.newContacts=[];
|
||||||
|
root.currentContact=0;
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target:xhr
|
||||||
|
onDownloaded:{if(data=="contact"){contacttimer.stop();root.currentContact=root.currentContact+1}}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target:xhr
|
||||||
|
onError:{print("Error"+data);
|
||||||
|
if (data=="contact"){
|
||||||
|
var database=LocalStorage.openDatabaseSync(root.db[0],root.db[1],root.db[2],root.db[3]);
|
||||||
|
var result;
|
||||||
|
database.transaction( function(tx) {
|
||||||
|
//print('UPDATE contacts SET profile_image="" where username="'+root.login.username+'" AND id = '+newContacts[currentContact].id);
|
||||||
|
result = tx.executeSql('UPDATE contacts SET profile_image="" where username="'+root.login.username+'" AND id = '+newContacts[currentContact].id);
|
||||||
|
root.currentContact=root.currentContact+1;contacttimer.stop()})}
|
||||||
|
}}
|
||||||
|
|
||||||
|
Timer {id:contacttimer; interval: 5000; running: false; repeat: false
|
||||||
|
onTriggered: {
|
||||||
|
var database=LocalStorage.openDatabaseSync(root.db[0],root.db[1],root.db[2],root.db[3]);
|
||||||
|
database.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('UPDATE contacts SET profile_image="" where username="'+root.login.username+'" AND id = '+newContacts[currentContact].id);
|
||||||
|
root.currentContact=root.currentContact+1})}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReleased: {
|
||||||
|
if (event.key === Qt.Key_Back) {
|
||||||
|
if (currentIndex==0){
|
||||||
|
newstab.active=true;
|
||||||
|
if (newstab.newstabstatus!=login.newsViewType){
|
||||||
|
newstab.newstabstatus=login.newsViewType;
|
||||||
|
if(login.newsViewType=="Timeline"){Newsjs.newsfromdb(db,login.username,function(dbnews){
|
||||||
|
newsSignal(dbnews)
|
||||||
|
})}
|
||||||
|
else{Newsjs.chatsfromdb(db,login.username,function(dbnews){
|
||||||
|
newsSignal(dbnews)
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
else{Service.cleanNews(root.db,function(){Qt.quit()})}
|
||||||
|
}
|
||||||
|
else {currentIndex=0}
|
||||||
|
event.accepted = true
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
style: TabViewStyle {
|
||||||
|
frameOverlap: 1
|
||||||
|
tab: Rectangle {
|
||||||
|
color: styleData.selected?"white":"light blue"
|
||||||
|
border.color: "light grey"
|
||||||
|
implicitWidth: root.width/4-2*mm
|
||||||
|
implicitHeight: 4*mm
|
||||||
|
Text { id: text
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: styleData.title
|
||||||
|
color: "black"
|
||||||
|
font.pixelSize:3*mm
|
||||||
|
font.bold: styleData.selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame: Rectangle { color: "light grey" }
|
||||||
|
tabsAlignment:Qt.AlignHCenter
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("News")
|
||||||
|
id: newstab
|
||||||
|
property string newstabstatus:login.newsViewType
|
||||||
|
property var conversation
|
||||||
|
source:(root.currentIndex==0)? "qrc:/qml/newsqml/NewsTab.qml":""
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Contacts")
|
||||||
|
id: friendstab
|
||||||
|
source: (root.currentIndex==1)?"qrc:/qml/contactqml/FriendsTab.qml":""
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Photos")
|
||||||
|
id: fotostab
|
||||||
|
property string phototabstatus:"Images"
|
||||||
|
source: (root.currentIndex==2)?"qrc:/qml/photoqml/PhotoTab.qml":""
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Config")
|
||||||
|
source: (root.currentIndex==3)?"qrc:/qml/configqml/ConfigTab.qml":""
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
Rectangle{
|
||||||
|
id: blueButton
|
||||||
|
width: mainText.width+2*mm
|
||||||
|
height: mainText.height+2*mm
|
||||||
|
color:"light blue"
|
||||||
|
|
||||||
|
border.color:"grey"
|
||||||
|
border.width:1
|
||||||
|
radius: mm
|
||||||
|
property alias text: mainText.text
|
||||||
|
signal clicked
|
||||||
|
state:""
|
||||||
|
|
||||||
|
Text{
|
||||||
|
id:mainText
|
||||||
|
color: "black"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: contentWidth
|
||||||
|
height: contentHeight
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
text: ""
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
id:buttonArea
|
||||||
|
anchors.fill:parent
|
||||||
|
onPressed: blueButton.state="Pressed"
|
||||||
|
onReleased: blueButton.state=""
|
||||||
|
onClicked: {parent.clicked()}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State { name: "Pressed"
|
||||||
|
PropertyChanges { target: blueButton; color: "lightsteelblue"} }
|
||||||
|
//State { name: "RELEASED" PropertyChanges { target: button; color: "lightsteelblue"}
|
||||||
|
]
|
||||||
|
transitions: [
|
||||||
|
Transition { to:"*"
|
||||||
|
ColorAnimation { target: blueButton; duration: 100} }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
// ConversationStack with buttons
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
import "qrc:/qml"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id:conversationStack
|
||||||
|
property var news
|
||||||
|
y:1
|
||||||
|
color: "white"
|
||||||
|
width:root.width-2*mm
|
||||||
|
height:root.height-8*mm
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: conversationView
|
||||||
|
x:3*mm
|
||||||
|
y:8*mm
|
||||||
|
width: conversationStack.width-4*mm
|
||||||
|
height: conversationStack.height-10*mm
|
||||||
|
clip: true
|
||||||
|
spacing: 0
|
||||||
|
model: conversationModel
|
||||||
|
delegate: Newsitem{}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: conversationModel}
|
||||||
|
|
||||||
|
WorkerScript {
|
||||||
|
id: conversationWorker
|
||||||
|
source: "qrc:/js/newsworker.js"
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
id: closeButton
|
||||||
|
width:10*mm
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 1*mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 1*mm
|
||||||
|
text: qsTr("Close")
|
||||||
|
onClicked: {
|
||||||
|
newstab.newstabstatus=login.newsViewType;
|
||||||
|
newsStack.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
var currentTime= new Date();
|
||||||
|
var msg = {'currentTime': currentTime, 'model': conversationModel,'news':news};
|
||||||
|
conversationWorker.sendMessage(msg)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,199 @@
|
||||||
|
// message.qml
|
||||||
|
// message with buttons
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQml 2.2
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Flickable{
|
||||||
|
width:root.width-5*mm
|
||||||
|
height:root.height-12*mm
|
||||||
|
contentHeight: messageColumn.height
|
||||||
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
id:messageSend
|
||||||
|
//property var login
|
||||||
|
property string parentId: ""
|
||||||
|
property string reply_to_user:""
|
||||||
|
property string attachImageURL: "";
|
||||||
|
property int directmessage: 0;
|
||||||
|
property var contacts: []
|
||||||
|
property var groups: []
|
||||||
|
property var contact_allow:login.permissions[0]
|
||||||
|
property var contact_deny:login.permissions[1]
|
||||||
|
property var group_allow:login.permissions[2]
|
||||||
|
property var group_deny:login.permissions[3]
|
||||||
|
|
||||||
|
function statusUpdate(title,status,in_reply_to_status_id,attachImageURL) {
|
||||||
|
xhr.url= login.server + "/api/statuses/update.xml";
|
||||||
|
xhr.setLogin(login.username+":"+Qt.atob(login.password));
|
||||||
|
xhr.clearParams();
|
||||||
|
xhr.setParam("source", "Friendiqa");
|
||||||
|
xhr.setParam("status", status);
|
||||||
|
if (parentId!="") {xhr.setParam("in_reply_to_status_id", parentId)};
|
||||||
|
if (title!=="") {xhr.setParam("title", title)};
|
||||||
|
if (group_allow.length>0) {xhr.setParam("group_allow", Helperjs.cleanArray(group_allow))};
|
||||||
|
if (group_deny.length>0) {xhr.setParam("group_deny", Helperjs.cleanArray(group_deny))};
|
||||||
|
if (contact_allow.length>0) {xhr.setParam("contact_allow", Helperjs.cleanArray(contact_allow))};
|
||||||
|
if (contact_deny.length>0) {xhr.setParam("contact_deny", Helperjs.cleanArray(contact_deny))};
|
||||||
|
if (attachImageURL!=="") {xhr.setImageFileParam("media", attachImageURL )};
|
||||||
|
xhr.post();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dmUpdate(title,text,replyto,screen_name,attachImageURL) {
|
||||||
|
xhr.url= login.server + "/api/direct_messages/new.xml";
|
||||||
|
xhr.setLogin(login.username+":"+Qt.atob(login.password));
|
||||||
|
xhr.clearParams();
|
||||||
|
xhr.setParam("text", text);
|
||||||
|
xhr.setParam("screen_name", screen_name);
|
||||||
|
if (parentId!="") {xhr.setParam("replyto", replyto)};
|
||||||
|
if (title!=="") {xhr.setParam("title", title)};
|
||||||
|
xhr.post();
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id:messageColumn
|
||||||
|
spacing: 2
|
||||||
|
width: parent.width
|
||||||
|
TextField {
|
||||||
|
id: titleField
|
||||||
|
width: parent.width
|
||||||
|
placeholderText: qsTr("Title (optional)")
|
||||||
|
visible: messageSend.parentId === ""
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: bodyField
|
||||||
|
width: parent.width
|
||||||
|
height: 30*mm
|
||||||
|
wrapMode: TextEdit.Wrap
|
||||||
|
textFormat: TextEdit.PlainText
|
||||||
|
}
|
||||||
|
|
||||||
|
Row{
|
||||||
|
spacing: 2
|
||||||
|
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:qsTr("Url")
|
||||||
|
onClicked: {
|
||||||
|
if(bodyField.selectedText==""){Helperjs.showMessage("Error","No text selected",messageSend)}
|
||||||
|
else{urlTextEdit.text="";
|
||||||
|
urlRectangle.visible=true}}
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
id:urlRectangle
|
||||||
|
height:parent.height
|
||||||
|
width:37*mm
|
||||||
|
visible:false
|
||||||
|
TextField{
|
||||||
|
id:urlTextEdit
|
||||||
|
width:30*mm
|
||||||
|
height:parent.height
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
anchors.left:urlTextEdit.right
|
||||||
|
anchors.leftMargin:mm
|
||||||
|
text:qsTr("\u2713")
|
||||||
|
onClicked: {if(urlTextEdit.text!=""){
|
||||||
|
var start = bodyField.selectionStart;
|
||||||
|
var end = bodyField.selectionEnd;
|
||||||
|
var text = bodyField.getText(start,end);
|
||||||
|
text = "[url="+urlTextEdit.text+"]" + text + "[/url]";
|
||||||
|
bodyField.remove(start,end);
|
||||||
|
bodyField.insert(start,text);}
|
||||||
|
urlRectangle.visible=false}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Row{
|
||||||
|
spacing:2
|
||||||
|
BlueButton{
|
||||||
|
visible: (directmessage==1)?false:true
|
||||||
|
text:qsTr("Permissions")
|
||||||
|
onClicked: {
|
||||||
|
var component = Qt.createComponent("qrc:/qml/newsqml/PermissionDialog.qml");
|
||||||
|
var permissions = component.createObject(messageColumn);
|
||||||
|
}}
|
||||||
|
BlueButton {
|
||||||
|
id: attachButton
|
||||||
|
text: qsTr("Attach")
|
||||||
|
visible:(directmessage==0)
|
||||||
|
onClicked: {
|
||||||
|
if (attachImageURL!=""){
|
||||||
|
Helperjs.showMessage( qsTr("Error"),qsTr("Only one attachment. Remove other attachment first!"), messageColumn)}
|
||||||
|
else{
|
||||||
|
try{imageAttachmentObject.destroy()}catch(e){print(e)}
|
||||||
|
imageAttachmentDialog.open()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
id:contactButton
|
||||||
|
text:qsTr("cc")
|
||||||
|
visible:(directmessage==0)
|
||||||
|
onClicked:{
|
||||||
|
var contactitems="";
|
||||||
|
for (var i=0;i<contacts.length;i++){
|
||||||
|
contactitems=contactitems+"MenuItem{text:'"+contacts[i].screen_name+"'; onTriggered: bodyField.insert(0,' @"+contacts[i].screen_name+" ')}"
|
||||||
|
}
|
||||||
|
var menuString="import QtQuick.Controls 1.4; Menu {"+contactitems+"}";
|
||||||
|
var contactlistObject=Qt.createQmlObject(menuString,messageSend,"contactmenuOutput")
|
||||||
|
contactlistObject.popup() }
|
||||||
|
}
|
||||||
|
BlueButton {
|
||||||
|
id: cancelButton
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
onClicked: {newstab.newstabstatus=login.newsViewType;
|
||||||
|
|
||||||
|
newsStack.pop()}
|
||||||
|
}
|
||||||
|
BlueButton {
|
||||||
|
id: sendButton
|
||||||
|
text: qsTr("Send")
|
||||||
|
onClicked: {
|
||||||
|
//print("login: "+login.server+login.username);
|
||||||
|
var title=titleField.text.replace("\"","\'");
|
||||||
|
var body=bodyField.getText(0,bodyField.length);
|
||||||
|
if (directmessage==0){
|
||||||
|
statusUpdate(title,body,messageSend.parentId,attachImageURL.toString())}
|
||||||
|
else {dmUpdate(title,body,"",messageSend.reply_to_user) }
|
||||||
|
newsStack.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FileDialog {
|
||||||
|
id: imageAttachmentDialog
|
||||||
|
title: "Please choose a picture"
|
||||||
|
folder: shortcuts.pictures
|
||||||
|
nameFilters: [ "Image files (*.jpg *.png)", "All files (*)" ]
|
||||||
|
selectedNameFilter:"Image files (*.jpg *.png)"
|
||||||
|
selectFolder: false
|
||||||
|
onAccepted: {
|
||||||
|
if( attachImageURL==""){attachImageURL=imageAttachmentDialog.fileUrl;
|
||||||
|
var imageAttachmentObject=Qt.createQmlObject('import QtQuick 2.0; Image {id:imageAttachment; source:"'+
|
||||||
|
attachImageURL.toString()+'"; width: 15*mm; height: 15*mm;fillMode: Image.PreserveAspectFit;MouseArea{anchors.fill:parent;onClicked:{attachImageURL="";imageAttachment.destroy()}}}',messageColumn,"attachedImage");
|
||||||
|
console.log("You chose: " + attachImageURL)}
|
||||||
|
else{attachImageURL=imageAttachmentDialog.fileUrl;}
|
||||||
|
|
||||||
|
}
|
||||||
|
onRejected: {
|
||||||
|
//console.log("Canceled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
//import QtQuick.LocalStorage 2.0 as Sql
|
||||||
|
import "qrc:/qml"
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
import "qrc:/js/news.js" as Newsjs
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Connections{
|
||||||
|
target:newstab
|
||||||
|
onNewstabstatusChanged:{
|
||||||
|
newstabstatusButton.text= qsTr(newstab.newstabstatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Connections{
|
||||||
|
target:newstab
|
||||||
|
onConversationChanged:{
|
||||||
|
newsBusy.running=false;
|
||||||
|
newstab.newstabstatus="Conversation";
|
||||||
|
newsStack.push({item:"qrc:/qml/newsqml/Conversation.qml",properties:{"news": conversation}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Connections{
|
||||||
|
target:root
|
||||||
|
onCurrentContactChanged:{
|
||||||
|
if (root.newContacts.length>0){
|
||||||
|
print(Qt.atob(root.newContacts[root.currentContact].name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function showNews(newsToShow){
|
||||||
|
if (newsStack.depth>1){newsStack.pop()}
|
||||||
|
newsBusy.running=false;
|
||||||
|
var currentTime= new Date();
|
||||||
|
var msg = {'currentTime': currentTime, 'model': newsModel,'news':newsToShow};
|
||||||
|
newsWorker.sendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFriendsMessages(friend){
|
||||||
|
newstab.newstabstatus="Contact";
|
||||||
|
Newsjs.newsfromdb(db,root.login.username, function(dbnews){showNews(dbnews)},friend)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDirectMessage(friend){
|
||||||
|
newstab.newstabstatus="SendMessage"
|
||||||
|
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"reply_to_user": friend,"directmessage":1,"login":root.login}});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
StackView{
|
||||||
|
id: newsStack
|
||||||
|
anchors.fill:parent
|
||||||
|
|
||||||
|
initialItem:Rectangle {
|
||||||
|
y:1
|
||||||
|
color: "white"
|
||||||
|
width:root.width-2*mm
|
||||||
|
height:root.height-8*mm
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id:newstabstatusButton
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 0.5*mm
|
||||||
|
text: qsTr(newstab.newstabstatus)
|
||||||
|
onClicked: {newstabmenu.popup()}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row{
|
||||||
|
spacing: mm
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 0.5*mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
id: newMessageButton
|
||||||
|
width:10*mm
|
||||||
|
text: qsTr("+")
|
||||||
|
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({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"contacts": friends,"login":root.login}})
|
||||||
|
},"isFriend",1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlueButton {
|
||||||
|
id: quitButton
|
||||||
|
width:10*mm
|
||||||
|
text: qsTr("Quit")
|
||||||
|
onClicked: {Service.cleanNews(root.db,function(){Qt.quit() })}
|
||||||
|
}
|
||||||
|
BlueButton {
|
||||||
|
id: update
|
||||||
|
text: "Update"
|
||||||
|
onClicked: {
|
||||||
|
newsBusy.running=true;
|
||||||
|
newstab.newstabstatus=login.newsViewType;
|
||||||
|
root.contactLoadType="news";
|
||||||
|
var onlynew=true;
|
||||||
|
Newsjs.getFriendsTimeline(login,db,contactlist,onlynew,newstab,function(ns,nc){
|
||||||
|
root.news=ns;root.newContacts=nc;root.currentContact=0;
|
||||||
|
if (ns.length==0){// update last 20 existing news for changes and likes
|
||||||
|
onlynew=false;
|
||||||
|
Newsjs.getFriendsTimeline(login,db,contactlist,onlynew,newstab,function(rns,rnc){
|
||||||
|
root.contactLoadType="news";
|
||||||
|
root.news=rns;root.newContacts=rnc;root.currentContact=0})
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Component { id:footerComponent
|
||||||
|
Rectangle{
|
||||||
|
border.color: "#EEEEEE"
|
||||||
|
border.width: 1
|
||||||
|
width:parent.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();
|
||||||
|
if(newstab.newstabstatus=="Timeline"){
|
||||||
|
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
|
||||||
|
Newsjs.newsfromdb(root.db,root.login.username, function(news){
|
||||||
|
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
|
||||||
|
newsWorker.sendMessage(msg);
|
||||||
|
},false,lastnews_id)}
|
||||||
|
if(newstab.newstabstatus=="Tree"){
|
||||||
|
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
|
||||||
|
Newsjs.chatsfromdb(root.db,root.login.username, function(news){
|
||||||
|
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
|
||||||
|
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,newsModel.get(newsModel.count-1).newsitemobject.created_at)}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
id: newsView
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.topMargin: 8*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{}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id:newstabmenu
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Timeline")
|
||||||
|
onTriggered: {
|
||||||
|
newstab.newstabstatus="Timeline";
|
||||||
|
newsModel.clear();
|
||||||
|
Newsjs.newsfromdb(root.db,root.login.username, function(dbnews){
|
||||||
|
showNews(dbnews)
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Favorites")
|
||||||
|
onTriggered:{
|
||||||
|
newstab.newstabstatus="Favorites";
|
||||||
|
root.contactLoadType="favorites";
|
||||||
|
newsBusy.running=true;
|
||||||
|
Newsjs.requestFavorites(root.login,db,root.contactlist,root,function(ns,nc){
|
||||||
|
root.news=ns; root.newContacts=nc;root.currentContact=0;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Tree")
|
||||||
|
onTriggered:{
|
||||||
|
newsModel.clear();
|
||||||
|
newstab.newstabstatus="Tree";
|
||||||
|
Newsjs.chatsfromdb(db,root.login.username,function(news){showNews(news)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Notifications")
|
||||||
|
onTriggered:{
|
||||||
|
newstab.newstabstatus="Notifications";
|
||||||
|
newsBusy.running=true;
|
||||||
|
Newsjs.getNotifications(root.login,db,root,function(news){
|
||||||
|
showNews(news)}
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.messageSignal.connect(onFriendsMessages);
|
||||||
|
root.directmessageSignal.connect(onDirectMessage);
|
||||||
|
root.newsSignal.connect(showNews);
|
||||||
|
try{newsModel.clear()} catch(e){}
|
||||||
|
if(login.newsViewType=="Timeline"){Newsjs.newsfromdb(db,login.username,function(dbnews){showNews(dbnews)})}
|
||||||
|
else{Newsjs.chatsfromdb(db,login.username,function(dbnews){showNews(dbnews)})}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,343 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.LocalStorage 2.0
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import "qrc:/js/news.js" as Newsjs
|
||||||
|
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: newsitem
|
||||||
|
width: newsView.width
|
||||||
|
height:Math.max((itemMessage.height+topFlow.height+friendicaActivities.height+4*mm),profileImage.height+user_name.height+mm)
|
||||||
|
|
||||||
|
property string conversation_id: ""
|
||||||
|
property string attending: ""
|
||||||
|
onAttendingChanged: {attendLabel.visible=true;
|
||||||
|
attendLabel.text= qsTr("attending: ")+ qsTr(attending)}
|
||||||
|
signal replyto(string parent_id)
|
||||||
|
function showConversation(){
|
||||||
|
conversationsymbol.color="black";
|
||||||
|
newsBusy.running=true;
|
||||||
|
root.contactLoadType="conversation";
|
||||||
|
//newstabstatus="Conversation";
|
||||||
|
|
||||||
|
if(newsitemobject.messagetype==0){
|
||||||
|
Newsjs.requestConversation(root.login,db,newsitemobject.status_id,root.contactlist,root,function(ns,nc){
|
||||||
|
root.news=ns;root.newContacts=nc;root.currentContact=0;
|
||||||
|
})}
|
||||||
|
else{Newsjs.conversationfromdb(root.db,root.login.username,newsitemobject.statusnet_conversation_id, function(newsarray){
|
||||||
|
root.news=newsarray;root.newContacts=[];root.currentContact=1;
|
||||||
|
})}}
|
||||||
|
|
||||||
|
Rectangle{width:newsitem.width; height: 1; anchors.bottom: newsitem.bottom; color:"light grey"}
|
||||||
|
//MouseArea{
|
||||||
|
// anchors.fill: parent;
|
||||||
|
// enabled: (newstabstatus=="Chats")
|
||||||
|
// onClicked: {showConversation()}
|
||||||
|
//}
|
||||||
|
Rectangle{
|
||||||
|
width:newsitem.width
|
||||||
|
height:newsitem.height-1
|
||||||
|
color: (newsitemobject.messagetype==1)?"#ffe6e6" : "white"
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: authorcolumn
|
||||||
|
width: 8*mm
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id:profileImage
|
||||||
|
source: (newsitemobject.user.profile_image!="")? "file://"+newsitemobject.user.profile_image : newsitemobject.user.profile_image_url
|
||||||
|
x:1
|
||||||
|
width: 7*mm
|
||||||
|
height: 7*mm
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill: parent
|
||||||
|
onPressAndHold: { newsmenu.popup()}
|
||||||
|
}
|
||||||
|
onStatusChanged: if (profileImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id:user_name
|
||||||
|
color: "grey"
|
||||||
|
//height:3.5*mm
|
||||||
|
width:parent.width
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
text: Qt.atob(newsitemobject.user.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
id:newscolumn
|
||||||
|
width: newsitem.width-8*mm
|
||||||
|
anchors.left: authorcolumn.right
|
||||||
|
|
||||||
|
Flow{
|
||||||
|
id:topFlow
|
||||||
|
spacing: mm
|
||||||
|
width:parent.width
|
||||||
|
Label {
|
||||||
|
id:messageTypeLabel
|
||||||
|
color: "grey"
|
||||||
|
text: if (newsitemobject.messagetype==0){qsTr("Source: ")+newsitemobject.source
|
||||||
|
} else if (newsitemobject.messagetype==1){ qsTr("Direct Message")} else {" Notification"}
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id:createdAtLabel
|
||||||
|
color: "grey"
|
||||||
|
//height:3.5*mm
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
horizontalAlignment: Label.AlignRight
|
||||||
|
text: dateDiff
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id:replytoLabel
|
||||||
|
color: "grey"
|
||||||
|
//height:3.5*mm
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
horizontalAlignment: Label.AlignRight
|
||||||
|
text: try {qsTr("In reply to ")+newsitemobject.reply_user.screen_name
|
||||||
|
}catch(e){" "}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id:newscountLabel
|
||||||
|
visible:((newstabstatus=="Tree")&&(newsitemobject.newscount>1))?true:false
|
||||||
|
color: "grey"
|
||||||
|
height:3.5*mm
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
font.bold: true
|
||||||
|
horizontalAlignment: Label.AlignRight
|
||||||
|
text: try {(newsitemobject.newscount-1)+qsTr(" comments") }catch(e){" "}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill:parent
|
||||||
|
onClicked: showConversation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
color: "#404040"
|
||||||
|
linkColor: "light green"
|
||||||
|
id: itemMessage
|
||||||
|
textFormat: Text.RichText
|
||||||
|
text: Qt.atob(newsitemobject.statusnet_html)
|
||||||
|
width: newsitem.width-8*mm-2
|
||||||
|
height: implicitHeight
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
onLinkActivated:{
|
||||||
|
Qt.openUrlExternally(link)}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row{id:friendicaActivities
|
||||||
|
spacing:mm
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.likeText
|
||||||
|
}
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.dislikeText
|
||||||
|
}
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.attendyesText
|
||||||
|
}
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.attendnoText
|
||||||
|
}
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.attendmaybeText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
CheckBox{id:likeCheckbox
|
||||||
|
height:3*mm
|
||||||
|
width:8*mm
|
||||||
|
visible: (newsitemobject.messagetype==0)? true:false
|
||||||
|
checked:(friendica_activities.self.liked==1)?true:false
|
||||||
|
style: CheckBoxStyle {
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 7*mm
|
||||||
|
implicitHeight: 3*mm
|
||||||
|
color:"white"
|
||||||
|
}
|
||||||
|
indicator:
|
||||||
|
Rectangle{
|
||||||
|
implicitWidth: 3*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
color:control.checked?"yellow":"white"
|
||||||
|
x: 5*mm
|
||||||
|
Text{
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
color:"grey"
|
||||||
|
text:":-)"
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
if(likeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"like",newsitemobject.status_id,root);dislikeCheckbox.checked=false; model.friendica_activities.self.liked=0 }
|
||||||
|
else{Newsjs.like(root.login,root.db,0,"like",newsitemobject.status_id,root); model.friendica_activities.self.liked=1}}
|
||||||
|
}
|
||||||
|
CheckBox{id: dislikeCheckbox
|
||||||
|
height:3*mm
|
||||||
|
width:8*mm
|
||||||
|
visible: (newsitemobject.messagetype==0)? true:false
|
||||||
|
checked: (friendica_activities.self.disliked==1)?true:false
|
||||||
|
style: CheckBoxStyle {
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 7*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
color:"white"
|
||||||
|
}
|
||||||
|
indicator:
|
||||||
|
Rectangle{
|
||||||
|
implicitWidth: 3*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
color:control.checked?"yellow":"white"
|
||||||
|
x:5*mm
|
||||||
|
Text{
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
color:"grey"
|
||||||
|
text:":-("
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
if (dislikeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"dislike",newsitemobject.status_id,root);likeCheckbox.checked=false; model.friendica_activities.self.disliked=0}
|
||||||
|
else {Newsjs.like(root.login,root.db,0,"dislike",newsitemobject.status_id,root); model.friendica_activities.self.disliked=1}}
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
id:favoritedCheckbox
|
||||||
|
visible:(newsitemobject.messagetype==0)
|
||||||
|
style: CheckBoxStyle {
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 6*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
color:"transparent"
|
||||||
|
}
|
||||||
|
indicator:
|
||||||
|
Rectangle{x:3*mm
|
||||||
|
width: 3*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
Text{
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color:control.checked?"black":"grey"
|
||||||
|
text:"\u2605"
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
checked:(newsitemobject.favorited>0)
|
||||||
|
onClicked:{
|
||||||
|
if(favoritedCheckbox.checkedState==Qt.Checked)
|
||||||
|
{Newsjs.favorite(login,true,newsitemobject.status_id,root); model.newsitemobject.favorited=1}
|
||||||
|
else if(favoritedCheckbox.checkedState==Qt.Unchecked)
|
||||||
|
{Newsjs.favorite(login,false,newsitemobject.status_id,root);model.newsitemobject.favorited=0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
width: 4*mm
|
||||||
|
height: 3*mm
|
||||||
|
color:"transparent"
|
||||||
|
Text{
|
||||||
|
id:newsmenusymbol
|
||||||
|
color: "grey"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
font.bold: true
|
||||||
|
text: "\u22EE"
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill:parent
|
||||||
|
onClicked: {newsmenu.popup()}}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
width: 4*mm
|
||||||
|
height: 3*mm
|
||||||
|
color:"transparent"
|
||||||
|
//visible:(newsitemobject.in_reply_to_status_id!="")?true:false
|
||||||
|
Text{
|
||||||
|
id:conversationsymbol
|
||||||
|
color: "grey"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
text: "\u21C4"
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill:parent
|
||||||
|
onClicked: showConversation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id:attendLabel
|
||||||
|
visible: false
|
||||||
|
color: "grey"
|
||||||
|
height:3.5*mm
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
horizontalAlignment: Label.AlignRight
|
||||||
|
text: (friendica_activities.self.attending)?qsTr("attending: ")+ qsTr(attending):""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id:newsmenu
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Reply")
|
||||||
|
onTriggered: {
|
||||||
|
var directmessage=0;
|
||||||
|
if (newsitemobject.messagetype==1){ directmessage=1}
|
||||||
|
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"reply_to_user": newsitemobject.user.screen_name,"parentId":newsitemobject.status_id,"login":root.login,"directmessage":directmessage}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("DM")
|
||||||
|
onTriggered: {
|
||||||
|
root.directmessageSignal(newsitemobject.user.screen_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Repost")
|
||||||
|
onTriggered: {
|
||||||
|
Newsjs.retweetNews(root.login,db,newsitemobject.status_id,root,function(reply){
|
||||||
|
print(reply);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Conversation")
|
||||||
|
onTriggered: showConversation()
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu{
|
||||||
|
title: qsTr("Attending")
|
||||||
|
MenuItem{text:qsTr("yes")
|
||||||
|
onTriggered: {Newsjs.attend(root.login,db,"yes",newsitemobject.status_id,root,function(){
|
||||||
|
newsitem.attending="yes";
|
||||||
|
attendLabel.visible=true})}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem{text:qsTr("maybe")
|
||||||
|
onTriggered: {Newsjs.attend(root.login,db,"maybe",newsitemobject.status_id,root,function(){
|
||||||
|
newsitem.attending="maybe"})}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem{text:qsTr("no")
|
||||||
|
onTriggered: {Newsjs.attend(root.login,db,"no",newsitemobject.status_id,root,function(){
|
||||||
|
newsitem.attending="no"})}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Delete")
|
||||||
|
onTriggered: {
|
||||||
|
Newsjs.deleteNews(root.login,root.db,newsitemobject.status_id,newsitemobject.messagetype,root,function(reply){
|
||||||
|
newsModel.remove(index);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQml.Models 2.1
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id:permissionDialog
|
||||||
|
x: mm
|
||||||
|
width: messageColumn.width-5*mm
|
||||||
|
height:root.height/3
|
||||||
|
function updatePerms(){
|
||||||
|
for (var i=0;i<groupModel.count;i++)
|
||||||
|
{if (groupModel.get(i).groupstatus=="positive"){
|
||||||
|
group_allow.push(groupModel.get(i).group.gid)
|
||||||
|
}
|
||||||
|
if (groupModel.get(i).groupstatus=="negative"){
|
||||||
|
group_deny.push(groupModel.get(i).group.gid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var j=0;j<contactModel.count;j++)
|
||||||
|
{//print("contact: "+JSON.stringify(contactModel.get(j).contact));
|
||||||
|
if (contactModel.get(j).contactstatus=="positive"){
|
||||||
|
print(JSON.stringify(contact_allow));
|
||||||
|
contact_allow.push(contactModel.get(j).contact.cid)
|
||||||
|
}
|
||||||
|
if (contactModel.get(j).contactstatus=="negative"){
|
||||||
|
contact_deny.push(contactModel.get(j).contact.cid)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
Text{
|
||||||
|
x:0.5*mm
|
||||||
|
y:0.5*mm
|
||||||
|
text: "Contacts"
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
id: contactView
|
||||||
|
x:0.5*mm
|
||||||
|
y:5.5*mm
|
||||||
|
width: permissionDialog.width/2-2*mm
|
||||||
|
height: permissionDialog.height-14*mm
|
||||||
|
clip: true
|
||||||
|
spacing: 1
|
||||||
|
model: contactModel
|
||||||
|
delegate: contactItem
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: contactModel}
|
||||||
|
Component{
|
||||||
|
id:contactItem
|
||||||
|
Rectangle{
|
||||||
|
id:contactitemRect
|
||||||
|
width:contactView.width
|
||||||
|
height: 5*mm
|
||||||
|
property string contactstatus
|
||||||
|
onContactstatusChanged:{
|
||||||
|
if(contactstatus=="positive"){contactitemRect.color="light green"}
|
||||||
|
else if (contactstatus=="negative"){contactitemRect.color= "red"}
|
||||||
|
else{contactitemRect.color= "white"}}
|
||||||
|
color: "white"
|
||||||
|
border.color:"grey"
|
||||||
|
Text{
|
||||||
|
color:"grey"
|
||||||
|
text:contact.screen_name
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked:{
|
||||||
|
if(contactModel.get(index).contactstatus=="neutral"){
|
||||||
|
contactModel.set(index,{"contactstatus":"positive"});
|
||||||
|
contactstatus="positive"
|
||||||
|
}
|
||||||
|
else if (contactModel.get(index).contactstatus=="positive"){
|
||||||
|
contactModel.set(index,{"contactstatus":"negative"})
|
||||||
|
contactstatus="negative"
|
||||||
|
}
|
||||||
|
else{contactModel.set(index,{"contactstatus":"neutral"});
|
||||||
|
contactstatus="neutral";
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
Component.onCompleted:{
|
||||||
|
if (contactModel.get(index).contactstatus=="positive"){
|
||||||
|
contactstatus="positive"
|
||||||
|
}
|
||||||
|
else if (contactModel.get(index).contactstatus=="negative"){
|
||||||
|
contactstatus="negative"
|
||||||
|
}
|
||||||
|
else {contactstatus="neutral"} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text{
|
||||||
|
x:contactView.width+2*mm
|
||||||
|
y:0.5*mm
|
||||||
|
text: "Groups"
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
id: groupView
|
||||||
|
x:contactView.width+2*mm
|
||||||
|
y:5.5*mm
|
||||||
|
width: permissionDialog.width/2-2*mm
|
||||||
|
height: permissionDialog.height-14*mm
|
||||||
|
clip: true
|
||||||
|
spacing: 1
|
||||||
|
model: groupModel
|
||||||
|
delegate: groupItem
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: groupModel}
|
||||||
|
Component{
|
||||||
|
id:groupItem
|
||||||
|
Rectangle{
|
||||||
|
id:groupitemRect
|
||||||
|
width:groupView.width
|
||||||
|
height: 5*mm
|
||||||
|
property string groupstatus:"neutral"
|
||||||
|
onGroupstatusChanged:
|
||||||
|
{if(groupstatus=="positive"){groupitemRect.color="light green"}
|
||||||
|
else if (groupstatus=="negative"){groupitemRect.color= "red"}
|
||||||
|
else{groupitemRect.color= "white"}}
|
||||||
|
color: "white"
|
||||||
|
border.color:"grey"
|
||||||
|
Text{
|
||||||
|
color:"grey"
|
||||||
|
text:group.groupname
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked:{
|
||||||
|
if(groupModel.get(index).groupstatus=="neutral"){
|
||||||
|
groupModel.set(index,{"groupstatus":"positive"});
|
||||||
|
groupstatus="positive"}
|
||||||
|
else if (groupModel.get(index).groupstatus=="positive"){
|
||||||
|
groupModel.set(index,{"groupstatus":"negative"});
|
||||||
|
groupstatus="negative"}
|
||||||
|
else{groupModel.set(index,{"groupstatus":"neutral"})
|
||||||
|
groupstatus="neutral"}
|
||||||
|
}}
|
||||||
|
Component.onCompleted:{ if (groupModel.get(index).groupstatus=="positive"){
|
||||||
|
groupstatus="positive"
|
||||||
|
}
|
||||||
|
else if (groupModel.get(index).groupstatus=="negative"){
|
||||||
|
groupstatus="negative"
|
||||||
|
}
|
||||||
|
else {groupstatus="neutral"} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
x:0.5*mm
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin:1
|
||||||
|
text:qsTr("Save")
|
||||||
|
onClicked:{
|
||||||
|
updatePerms();
|
||||||
|
var perms=[];
|
||||||
|
perms.push(contact_allow,contact_deny,group_allow,group_deny); Service.savePermissions(db,perms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
x:contactView.width+2*mm
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin:1
|
||||||
|
text:qsTr("Done")
|
||||||
|
onClicked:{//var group_allow=[];var group_deny=[];
|
||||||
|
|
||||||
|
//print("contacts: "+Helperjs.cleanArray(contact_allow))
|
||||||
|
permissionDialog.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted:{
|
||||||
|
|
||||||
|
Helperjs.readData(db,"contacts",login.username,function(contacts){
|
||||||
|
for (var name in contacts){
|
||||||
|
var contactstatus="neutral";
|
||||||
|
if (contact_allow.indexOf(contacts[name].cid)>-1){contactstatus="positive";print(contacts[name].cid+" pos")}
|
||||||
|
else if (contact_deny.indexOf(contacts[name].cid)>-1){contactstatus="negative"}
|
||||||
|
contactModel.append({"contact":contacts[name],"contactstatus":contactstatus})
|
||||||
|
}},"isFriend",1);
|
||||||
|
|
||||||
|
Helperjs.readData(db,"groups",login.username,function(owngroups){
|
||||||
|
for (var number in owngroups){
|
||||||
|
var groupstatus= "neutral";
|
||||||
|
if (group_allow.indexOf(owngroups[number].gid)>-1){groupstatus="positive"}
|
||||||
|
else if (group_deny.indexOf(owngroups[number].gid)>-1){groupstatus="negative"}
|
||||||
|
groupModel.append({"group":owngroups[number],"groupstatus":groupstatus})
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
//import QtQuick.LocalStorage 2.0
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
|
||||||
|
Package {
|
||||||
|
Item { id: stackItem; Package.name: 'stack'; z: stackItem.PathView.z;width:16.5*mm;height:16.5*mm}
|
||||||
|
Item { id: listItem; Package.name: 'list'; width: root.width-1*mm; height: root.height-8*mm; }
|
||||||
|
Item { id: gridItem; Package.name: 'grid';}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: photoWrapper
|
||||||
|
width: 16.5*mm; height: 16.5*mm
|
||||||
|
z: stackItem.PathView.z
|
||||||
|
property string hqphotolink: photoLink
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: placeHolder
|
||||||
|
color: 'lightblue'; antialiasing: true
|
||||||
|
anchors.fill:parent
|
||||||
|
}
|
||||||
|
|
||||||
|
BusyIndicator { anchors.centerIn: parent; running: realImage.status != Image.Ready }
|
||||||
|
Image {
|
||||||
|
id: realImage;
|
||||||
|
// property string hqphotolink: photoLink
|
||||||
|
width: photoWrapper.width; height: photoWrapper.height
|
||||||
|
antialiasing: true;
|
||||||
|
asynchronous: true
|
||||||
|
cache: false
|
||||||
|
fillMode: Image.PreserveAspectFit;
|
||||||
|
source: imageLocation
|
||||||
|
// onStatusChanged: if (realImage.status == Image.Ready) print(realImage.paintedHeight+"x"+realImage.paintedWidth)
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
id:phototextRectangle
|
||||||
|
color:"black"
|
||||||
|
z:3
|
||||||
|
opacity: 0.5
|
||||||
|
width:phototext.contentWidth
|
||||||
|
height: phototext.contentHeight
|
||||||
|
anchors.bottom: photoWrapper.bottom
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id:phototext
|
||||||
|
z:4
|
||||||
|
text: photoDescription.trim()
|
||||||
|
width:15*mm
|
||||||
|
anchors.bottom: photoWrapper.bottom
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
wrapMode:Text.Wrap
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
width: realImage.paintedWidth; height: realImage.paintedHeight; anchors.centerIn: realImage
|
||||||
|
onClicked: {
|
||||||
|
if (albumWrapper.state == 'inGrid') {
|
||||||
|
gridItem.GridView.view.currentIndex = index;
|
||||||
|
//print("photoLink"+realImage.photoLink)
|
||||||
|
albumWrapper.state = 'fullscreen'
|
||||||
|
} else {
|
||||||
|
gridItem.GridView.view.currentIndex = index;
|
||||||
|
albumWrapper.state = 'inGrid'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: 'stacked'; when: albumWrapper.state == ''
|
||||||
|
ParentChange { target: photoWrapper; parent: stackItem; }//x: 1*mm; y: 1*mm }
|
||||||
|
PropertyChanges { target: photoWrapper; opacity: stackItem.PathView.onPath ? 1.0 : 0.0 }
|
||||||
|
PropertyChanges { target: phototext; opacity: 0.0 }
|
||||||
|
PropertyChanges { target: phototextRectangle; opacity: 0.0 }
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: 'inGrid'; when: albumWrapper.state == 'inGrid'
|
||||||
|
ParentChange { target: photoWrapper; parent: gridItem; x: 1*mm; y: 1*mm;}
|
||||||
|
PropertyChanges { target: phototext; opacity: 1.0 }
|
||||||
|
PropertyChanges { target: phototextRectangle; opacity: 0.5 }
|
||||||
|
PropertyChanges { target: placeHolder; opacity: 1.0 }
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: 'fullscreen'; when: albumWrapper.state == 'fullscreen'
|
||||||
|
ParentChange {
|
||||||
|
target: photoWrapper; parent: listItem; x: 1; y: 1;
|
||||||
|
width: root.width-mm; height: root.height-8*mm
|
||||||
|
}
|
||||||
|
PropertyChanges { target: placeHolder; opacity: 0.0 }
|
||||||
|
PropertyChanges { target: realImage; source: photoWrapper.hqphotolink}
|
||||||
|
PropertyChanges { target: phototext; anchors.bottom: realImage.bottom}
|
||||||
|
PropertyChanges { target: phototext; width:realImage.width }
|
||||||
|
PropertyChanges { target: phototextRectangle; anchors.bottom: realImage.bottom }
|
||||||
|
PropertyChanges { target: realImage; width: Math.min(listItem.width,sourceSize.width);height: Math.min(listItem.height,sourceSize.height) }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id:photoPlaceholder
|
||||||
|
property string imageName:"x.jpg"
|
||||||
|
property string downloadtype:""
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
onStatusChanged: {
|
||||||
|
if (photoPlaceholder.status == Image.Ready) {
|
||||||
|
//print("Source: "+source+"Photo width"+width+" height"+height+" Ratio "+ fillMode);
|
||||||
|
var saveprocess=photoPlaceholder.grabToImage(function(result){
|
||||||
|
var saveresult=result.saveToFile(imageName.toString());
|
||||||
|
if (saveresult){
|
||||||
|
if ((downloadtype=="picture")&&(newImages.length>0)){
|
||||||
|
photoPlaceholder.destroy();
|
||||||
|
currentImageNo=currentImageNo+1
|
||||||
|
}
|
||||||
|
S }});
|
||||||
|
}}}
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQml.Models 2.1
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/photoqml"
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id:fotorectangle
|
||||||
|
property string phototabstatus:"Images"
|
||||||
|
onPhototabstatusChanged:{phototabstatusButton.text=qsTr(phototabstatus)}
|
||||||
|
|
||||||
|
y:1
|
||||||
|
width:root.width-mm
|
||||||
|
height:root.height-5*mm
|
||||||
|
color: '#fff'
|
||||||
|
property var newimages:[]
|
||||||
|
property int currentimageno: 0
|
||||||
|
//onLoginChanged:{var msg = {'model': photogroupModel,'albums':[],'firstalbum':0,'foreignPicture':false};
|
||||||
|
// photoWorker.sendMessage(msg);
|
||||||
|
//}
|
||||||
|
onNewimagesChanged:{
|
||||||
|
if(newimages.length>0){
|
||||||
|
Helperjs.readField("album",root.db,"imageData",root.login.username,function(albums){
|
||||||
|
//print("albums"+JSON.stringify(albums)+JSON.stringify(newimages[currentimageno]));
|
||||||
|
for (var i=0;i<newimages.length;i++){
|
||||||
|
if(albums.indexOf(newimages[i].album)==-1){
|
||||||
|
filesystem.Directory=root.login.imagestore+"/albums";
|
||||||
|
filesystem.makeDir(newimages[i].album)}}
|
||||||
|
})
|
||||||
|
//print("Current image number"+currentImageNo)
|
||||||
|
Service.dataRequest(root.login,newimages[currentimageno].id,root.db,fotostab);
|
||||||
|
newImagesProgress.visible=true //download first image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCurrentimagenoChanged:{
|
||||||
|
if(currentimageno<newimages.length){Service.dataRequest(root.login,newimages[currentimageno].id,root.db,fotostab)};
|
||||||
|
if(currentimageno==newimages.length){newImagesProgress.visible=false;showOwnFotos();
|
||||||
|
newimages=[];currentimageno=0}
|
||||||
|
// download next image if photoplaceholder is finished saving
|
||||||
|
}
|
||||||
|
|
||||||
|
function showOwnFotos(){
|
||||||
|
try {photogroupModel.clear()}catch (e){print(e)}
|
||||||
|
Helperjs.readField("album",root.db, "imageData",root.login.username,function(albums){
|
||||||
|
if (albums[0]) {
|
||||||
|
var msg = { 'model': photogroupModel,'albums':albums,'firstalbum':0,'foreignPicture': false};
|
||||||
|
photoWorker.sendMessage(msg);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Connections{
|
||||||
|
target:root
|
||||||
|
onLoginChanged:{var msg = {'model': photogroupModel,'albums':[],'firstalbum':0,'foreignPicture':false};
|
||||||
|
photoWorker.sendMessage(msg);}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target:xhr
|
||||||
|
onDownloaded:{if(data=="picture"){currentimageno=currentimageno+1}}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target:xhr
|
||||||
|
onError:{if(data=="picture"){print("Error"+data);
|
||||||
|
currentimageno=currentimageno+1}}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFriendsFotos(friend){
|
||||||
|
fotostab.phototabstatus=friend.screen_name;
|
||||||
|
//print("Friend "+friend.url);
|
||||||
|
try {photogroupModel.clear()}catch (e){print(e)}
|
||||||
|
Service.requestFriendsAlbumPictures(root.login,friend,fotostab,function(albums){
|
||||||
|
var msg = {'model': photogroupModel,'albums':albums,'firstalbum':0,'foreignPicture':true};
|
||||||
|
photoWorker.sendMessage(msg);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar{
|
||||||
|
id: newImagesProgress
|
||||||
|
width: 15*mm
|
||||||
|
height: updatePhotolist.height
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right:updatePhotolist.left
|
||||||
|
anchors.rightMargin:mm
|
||||||
|
visible: false
|
||||||
|
value: currentimageno/newimages.length
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id: updatePhotolist
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 0.5*mm
|
||||||
|
anchors.right:phototabstatusButton.left
|
||||||
|
anchors.rightMargin:mm
|
||||||
|
text: qsTr("Update")
|
||||||
|
onClicked: {
|
||||||
|
Service.requestList(root.login,root.db, fotostab,function(obj){
|
||||||
|
newimages=obj;print("newimages"+JSON.stringify(obj))
|
||||||
|
})}}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id: phototabstatusButton
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 0.5*mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin:2*mm
|
||||||
|
text: qsTr(phototabstatus)
|
||||||
|
onClicked: {phototabmenu.popup()}
|
||||||
|
}
|
||||||
|
Menu {
|
||||||
|
id:phototabmenu
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Own Images")
|
||||||
|
onTriggered: {
|
||||||
|
phototabstatus="Images";
|
||||||
|
showOwnFotos()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DelegateModel{
|
||||||
|
id: visualphotoModel
|
||||||
|
delegate: PhotogroupComponent{}
|
||||||
|
model: photogroupModel
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{
|
||||||
|
id: photogroupModel
|
||||||
|
}
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: albumgridview
|
||||||
|
cellWidth: 17*mm
|
||||||
|
cellHeight: 17*mm
|
||||||
|
x: mm;y:8*mm
|
||||||
|
width: parent.width-2*mm; height: parent.height-9*mm
|
||||||
|
clip: true
|
||||||
|
model: visualphotoModel.parts.album
|
||||||
|
footer:
|
||||||
|
Rectangle{
|
||||||
|
border.color: "#EEEEEE"
|
||||||
|
border.width: 1
|
||||||
|
width:12*mm
|
||||||
|
height:6*mm
|
||||||
|
Text{
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text:qsTr("More")
|
||||||
|
}
|
||||||
|
MouseArea{anchors.fill:parent
|
||||||
|
onClicked:{
|
||||||
|
var lastalbum_id=photogroupModel.get(photogroupModel.count-1);
|
||||||
|
if(photogroupModel.get(photogroupModel.count-1).foreignPictures==false){Service.requestFriendsAlbumPictures(friend,fotostab,function(albums){
|
||||||
|
var msg = {'model': photogroupModel,'albums':albums,'firstalbum':lastalbum_id+1,'foreignPicture':true};
|
||||||
|
photoWorker.sendMessage(msg); })}
|
||||||
|
else { Helperjs.readField("album",root.db, "imageData",root.login.username,function(albums){
|
||||||
|
var msg = { 'model': photogroupModel,'albums':albums,'foreignPicture': false,'firstalbum':lastalbum_id+1};
|
||||||
|
photoWorker.sendMessage(msg)})}
|
||||||
|
}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle { id: photoBackground; color: 'light grey'; width: parent.width; height: parent.height; opacity: 0; visible: opacity != 0.0 }
|
||||||
|
|
||||||
|
ListView { anchors.fill: parent; model: visualphotoModel.parts.browser; interactive: false }
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
id: backButton
|
||||||
|
text: qsTr("Back")
|
||||||
|
x: parent.width - backButton.width - 3*mm
|
||||||
|
y: -backButton.height - 4*mm
|
||||||
|
onClicked: {photoBackground.opacity=0}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {anchors.fill: parent; model: visualphotoModel.parts.fullscreen; interactive: false }
|
||||||
|
WorkerScript{id: photoWorker;source: "qrc:/js/photoworker.js"}
|
||||||
|
|
||||||
|
Component.onCompleted: { root.fotoSignal.connect(onFriendsFotos);}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.LocalStorage 2.0
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import QtQml.Models 2.1
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
|
||||||
|
Package {
|
||||||
|
Item {
|
||||||
|
Package.name: 'browser'
|
||||||
|
GridView {
|
||||||
|
id: photosGridView; model: visualModel.parts.grid; width: albumgridview.width; height: albumgridview.height
|
||||||
|
cellWidth: 16.5*mm; cellHeight: 16.5*mm; interactive: false;anchors.margins:2*mm
|
||||||
|
onCurrentIndexChanged: photosListView.positionViewAtIndex(currentIndex, ListView.Contain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Package.name: 'fullscreen'
|
||||||
|
ListView {
|
||||||
|
id: photosListView; model: visualModel.parts.list; orientation: Qt.Horizontal
|
||||||
|
width: parent.width; height: parent.height; interactive: false
|
||||||
|
onCurrentIndexChanged: photosGridView.positionViewAtIndex(currentIndex, GridView.Contain)
|
||||||
|
highlightRangeMode: ListView.StrictlyEnforceRange; snapMode: ListView.SnapOneItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Package.name: 'album'
|
||||||
|
id: albumWrapper; width: 16.5*mm; height: 16.5*mm //-albumtext.contentHeight
|
||||||
|
|
||||||
|
DelegateModel {
|
||||||
|
id: visualModel; delegate: PhotoComponent { }
|
||||||
|
model: photoModel
|
||||||
|
}
|
||||||
|
|
||||||
|
PathView {
|
||||||
|
id: photosPathView;
|
||||||
|
model: visualModel.parts.stack;
|
||||||
|
pathItemCount: 1
|
||||||
|
anchors.centerIn: parent;
|
||||||
|
path: Path {
|
||||||
|
PathAttribute { name: 'z'; value: 9999.0 }
|
||||||
|
PathLine { x: 1; y: 1 }
|
||||||
|
PathAttribute { name: 'z'; value: 0.0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
color:"black"
|
||||||
|
opacity: 0.5
|
||||||
|
width:albumtext.contentWidth
|
||||||
|
height: albumtext.contentHeight
|
||||||
|
anchors.bottom: albumWrapper.bottom
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id:albumtext
|
||||||
|
text: albumname //foreignPicture ? album.name.trim() : album
|
||||||
|
width:albumWrapper.width-1*mm
|
||||||
|
height: albumtext.contentHeight
|
||||||
|
wrapMode:Text.Wrap
|
||||||
|
color: "white"
|
||||||
|
font.family: "Monospace"
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
anchors.bottom: albumWrapper.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{
|
||||||
|
id: photoModel
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted:{
|
||||||
|
try {photoModel.clear()}catch (e){print(e)}
|
||||||
|
if(foreignPicture){
|
||||||
|
//print("Albumlink"+album.link);
|
||||||
|
Service.requestFriendsPictures(albumlink,fotostab,function(obj){
|
||||||
|
if (obj) {
|
||||||
|
for (var k=0;k<obj.length;k++){
|
||||||
|
//print("Photomodel:"+obj[k].thumb+obj[k].name+obj[k].link);
|
||||||
|
photoModel.append({"imageLocation": obj[k].thumb,"photoDescription":obj[k].name,"photoLink":obj[k].link})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
else{
|
||||||
|
Helperjs.readData(db,"imageData",root.login.username,function(obj){
|
||||||
|
// obj.sort(function(obj1,obj2){return obj1.data-obj2.data});
|
||||||
|
if (obj) {
|
||||||
|
for (var k=0;k<obj.length;k++){
|
||||||
|
// print("Photomodel:"+obj[k].location+obj[k].filename);
|
||||||
|
photoModel.append({"imageLocation": obj[k].location+obj[k].filename,"photoDescription":obj[k].filename,"photoLink":obj[k].location+obj[k].filename})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},"album",albumname)}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: albumWrapper.state = 'inGrid'
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: 'inGrid'
|
||||||
|
PropertyChanges { target: photosGridView; interactive: true }
|
||||||
|
PropertyChanges { target: photoBackground; opacity: 1 }
|
||||||
|
PropertyChanges { target: backButton; onClicked: albumWrapper.state = ''; y: 6 }
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: 'fullscreen'; extend: 'inGrid'
|
||||||
|
PropertyChanges { target: photosGridView; interactive: false }
|
||||||
|
PropertyChanges { target: photosListView; interactive: true }
|
||||||
|
PropertyChanges { target: photoBackground; opacity: 1 }
|
||||||
|
PropertyChanges { target: backButton; y: -backButton.height - 8 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
} //album Ende
|
||||||
|
} //Package Ende
|
||||||
|
//item Ende
|
|
@ -0,0 +1,27 @@
|
||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>qml/friendiqa.qml</file>
|
||||||
|
<file>qml/newsqml/NewsTab.qml</file>
|
||||||
|
<file>qml/newsqml/Newsitem.qml</file>
|
||||||
|
<file>qml/newsqml/MessageSend.qml</file>
|
||||||
|
<file>qml/newsqml/PermissionDialog.qml</file>
|
||||||
|
<file>qml/contactqml/FriendsTab.qml</file>
|
||||||
|
<file>qml/contactqml/GroupComponent.qml</file>
|
||||||
|
<file>qml/contactqml/ContactComponent.qml</file>
|
||||||
|
<file>qml/contactqml/ContactDetailsComponent.qml</file>
|
||||||
|
<file>qml/genericqml/BlueButton.qml</file>
|
||||||
|
<file>qml/photoqml/PhotoComponent.qml</file>
|
||||||
|
<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>js/layout.js</file>
|
||||||
|
<file>js/photoworker.js</file>
|
||||||
|
<file>js/service.js</file>
|
||||||
|
<file>js/news.js</file>
|
||||||
|
<file>js/newsworker.js</file>
|
||||||
|
<file>js/helper.js</file>
|
||||||
|
<file>images/defaultcontact.jpg</file>
|
||||||
|
<file>qml/newsqml/Conversation.qml</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "filesystem.h"
|
||||||
|
|
||||||
|
FILESYSTEM *FILESYSTEM::instance()
|
||||||
|
{
|
||||||
|
static FILESYSTEM filesystem;
|
||||||
|
return &filesystem;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILESYSTEM::FILESYSTEM(QObject *parent) : QObject(parent){}
|
||||||
|
|
||||||
|
void FILESYSTEM::setDirectory(QString Directory)
|
||||||
|
{
|
||||||
|
if (Directory!=m_Directory) {
|
||||||
|
m_Directory = Directory;
|
||||||
|
emit directoryChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString FILESYSTEM::Directory() const
|
||||||
|
{
|
||||||
|
return m_Directory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FILESYSTEM::makeDir(QString name)
|
||||||
|
{
|
||||||
|
QDir dir(m_Directory);
|
||||||
|
if (dir.mkdir(name)){
|
||||||
|
emit success(name);
|
||||||
|
}
|
||||||
|
else {emit error(name,1);}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FILESYSTEM::rmDir()
|
||||||
|
{
|
||||||
|
QDir dir(m_Directory);
|
||||||
|
if (dir.removeRecursively()){
|
||||||
|
emit success(m_Directory);
|
||||||
|
}
|
||||||
|
else {emit error(m_Directory,1);}
|
||||||
|
}
|
||||||
|
|
||||||
|
void FILESYSTEM::rmFile(QString name)
|
||||||
|
{
|
||||||
|
QDir dir(m_Directory);
|
||||||
|
if(dir.remove(name)){
|
||||||
|
emit success(name);
|
||||||
|
}
|
||||||
|
else {emit error(name,1);}
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef FILESYSTEM_H
|
||||||
|
#define FILESYSTEM_H
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class FILESYSTEM : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString Directory READ Directory WRITE setDirectory NOTIFY directoryChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
static FILESYSTEM *instance();
|
||||||
|
explicit FILESYSTEM(QObject *parent = 0);
|
||||||
|
void setDirectory(QString Directory);
|
||||||
|
QString Directory() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void directoryChanged();
|
||||||
|
void success(QString data);
|
||||||
|
void error(QString data, int code);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
//void setDirectory(QString Directory);
|
||||||
|
void makeDir(QString name);
|
||||||
|
void rmDir();
|
||||||
|
void rmFile(QString name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_Directory;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // FILSYSTEM_H
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QtQml/QQmlEngine>
|
||||||
|
#include <QtQuick>
|
||||||
|
#include "xhr.h"
|
||||||
|
#include "filesystem.h"
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
QQuickView view;
|
||||||
|
|
||||||
|
|
||||||
|
XHR* xhr = XHR::instance();
|
||||||
|
view.rootContext()->setContextProperty("xhr", xhr);
|
||||||
|
FILESYSTEM* filesystem = FILESYSTEM::instance();
|
||||||
|
view.rootContext()->setContextProperty("filesystem", filesystem);
|
||||||
|
view.setSource(QUrl("qrc:/qml/friendiqa.qml"));
|
||||||
|
view.show();
|
||||||
|
view.connect(view.rootContext()->engine(), SIGNAL(quit()), &app, SLOT(quit()));
|
||||||
|
return app.exec();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
#include "uploadableimage.h"
|
||||||
|
|
||||||
|
|
||||||
|
#include <QBuffer>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
void UploadableImage::setSource(const QString &a) {
|
||||||
|
if (a != m_source) {
|
||||||
|
m_source = a;
|
||||||
|
//m_base64 = "";
|
||||||
|
m_mimetype = "";
|
||||||
|
m_filename = "";
|
||||||
|
|
||||||
|
qDebug() << "UploadableImage::setSource : " << m_source;
|
||||||
|
|
||||||
|
if (m_source=="") {
|
||||||
|
emit sourceChanged();
|
||||||
|
//emit base64Changed();
|
||||||
|
emit mimetypeChanged();
|
||||||
|
emit filenameChanged();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QImage fullimage = QImage(QUrl(m_source).toLocalFile());
|
||||||
|
if (fullimage.width() > 800 || fullimage.height() > 800) {
|
||||||
|
if (fullimage.width() > fullimage.height()) {
|
||||||
|
m_image = fullimage.scaledToWidth(800);
|
||||||
|
} else {
|
||||||
|
m_image = fullimage.scaledToHeight(800);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
m_image = fullimage;
|
||||||
|
}
|
||||||
|
qDebug() << "UploadableImage::setSource : " << m_image.width() << "x" << m_image.height();
|
||||||
|
emit sourceChanged();
|
||||||
|
|
||||||
|
QFileInfo fi(m_source);
|
||||||
|
|
||||||
|
m_filename = fi.fileName();
|
||||||
|
emit filenameChanged();
|
||||||
|
|
||||||
|
QString filetype = fi.suffix().toUpper();
|
||||||
|
if (filetype!="PNG" && filetype!="JPG") {
|
||||||
|
filetype = "JPG";
|
||||||
|
}
|
||||||
|
qDebug() << "UploadableImage::setSource : " << "Saving as " << filetype;
|
||||||
|
|
||||||
|
m_mimetype = "image/"+filetype.toLower();
|
||||||
|
emit mimetypeChanged();
|
||||||
|
|
||||||
|
/*
|
||||||
|
QByteArray byteArray;
|
||||||
|
QBuffer buffer(&byteArray);
|
||||||
|
m_image.save(&buffer, filetype.toLatin1().constData());
|
||||||
|
QString b64 = QString::fromLatin1(byteArray.toBase64().data());
|
||||||
|
|
||||||
|
for(int k=0; k<b64.length(); k+=76) {
|
||||||
|
m_base64 += b64.mid(k,76) + "\n";
|
||||||
|
}
|
||||||
|
m_base64 = m_base64.trimmed();
|
||||||
|
|
||||||
|
emit base64Changed();
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UploadableImage::source() const {
|
||||||
|
return m_source;
|
||||||
|
}
|
||||||
|
|
||||||
|
//QString UploadableImage::base64() const {
|
||||||
|
// return m_base64;
|
||||||
|
//}
|
||||||
|
|
||||||
|
QString UploadableImage::filename() const {
|
||||||
|
return m_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString UploadableImage::mimetype() const {
|
||||||
|
return m_mimetype;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray UploadableImage::bytes() {
|
||||||
|
QByteArray byteArray;
|
||||||
|
QBuffer buffer(&byteArray);
|
||||||
|
m_image.save(&buffer, "PNG");
|
||||||
|
return byteArray;
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
#ifndef UPLOADABLEIMAGE_H
|
||||||
|
#define UPLOADABLEIMAGE_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QQuickItem>
|
||||||
|
#include <QImage>
|
||||||
|
|
||||||
|
class UploadableImage : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
|
||||||
|
//Q_PROPERTY(QString base64 READ base64 NOTIFY base64Changed)
|
||||||
|
Q_PROPERTY(QString filename READ filename NOTIFY filenameChanged)
|
||||||
|
Q_PROPERTY(QString mimetype READ mimetype NOTIFY mimetypeChanged)
|
||||||
|
Q_PROPERTY(QByteArray bytes READ bytes)
|
||||||
|
|
||||||
|
public:
|
||||||
|
void setSource(const QString &a);
|
||||||
|
QString source() const;
|
||||||
|
|
||||||
|
//QString base64() const;
|
||||||
|
QString filename() const;
|
||||||
|
QString mimetype() const;
|
||||||
|
|
||||||
|
QByteArray bytes();
|
||||||
|
signals:
|
||||||
|
void sourceChanged();
|
||||||
|
//void base64Changed();
|
||||||
|
void filenameChanged();
|
||||||
|
void mimetypeChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString m_source;
|
||||||
|
QImage m_image;
|
||||||
|
//QString m_base64;
|
||||||
|
QString m_filename;
|
||||||
|
QString m_mimetype;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // UPLOADABLEIMAGE_H
|
|
@ -0,0 +1,235 @@
|
||||||
|
#include "xhr.h"
|
||||||
|
|
||||||
|
#include <QHttpPart>
|
||||||
|
#include <QTextCodec>
|
||||||
|
#include <QUrlQuery>
|
||||||
|
|
||||||
|
#include "uploadableimage.h"
|
||||||
|
|
||||||
|
XHR *XHR::instance()
|
||||||
|
{
|
||||||
|
static XHR xhr;
|
||||||
|
return &xhr;
|
||||||
|
}
|
||||||
|
|
||||||
|
XHR::XHR(QObject *parent) : QObject(parent)
|
||||||
|
{
|
||||||
|
request.setSslConfiguration(QSslConfiguration::defaultConfiguration());
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setUrl(QString url)
|
||||||
|
{
|
||||||
|
if (url!=m_url) {
|
||||||
|
m_url = url;
|
||||||
|
emit urlChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setLogin(QString login)
|
||||||
|
{
|
||||||
|
if (login!=m_login) {
|
||||||
|
m_login = login;
|
||||||
|
emit loginChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setFilename(QString filename)
|
||||||
|
{
|
||||||
|
if (filename!=m_filename) {
|
||||||
|
m_filename = filename;
|
||||||
|
emit filenameChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setDownloadtype(QString downloadtype)
|
||||||
|
{
|
||||||
|
if (downloadtype!=m_downloadtype) {
|
||||||
|
m_downloadtype = downloadtype;
|
||||||
|
emit downloadtypeChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::url() const
|
||||||
|
{
|
||||||
|
return m_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::login() const
|
||||||
|
{
|
||||||
|
return m_login;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::filename() const
|
||||||
|
{
|
||||||
|
return m_filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::downloadtype() const
|
||||||
|
{
|
||||||
|
return m_downloadtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setParam(QString name, QString value)
|
||||||
|
{
|
||||||
|
params.insert(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::setImageFileParam(QString name, QString url)
|
||||||
|
{
|
||||||
|
files.insert(name, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::clearParams()
|
||||||
|
{
|
||||||
|
files.clear();
|
||||||
|
params.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::download()
|
||||||
|
{
|
||||||
|
QUrl requrl(m_url);
|
||||||
|
//qDebug()<< "replyerror"<<reply->error();
|
||||||
|
// qDebug() << "start download of " << requrl;
|
||||||
|
request.setUrl(requrl);
|
||||||
|
reply = manager.get(request);
|
||||||
|
// qDebug() << "reply " << reply->header(QNetworkRequest::LocationHeader)<<reply->header(QNetworkRequest::LastModifiedHeader);
|
||||||
|
// qDebug() << "request " << request.url();
|
||||||
|
// reply->ignoreSslErrors();
|
||||||
|
connect(reply, &QNetworkReply::readyRead,this, &XHR::onReadyRead);
|
||||||
|
//connect(reply,SIGNAL(downloadProgress(qint64,qint64)), this,SLOT(updateDownloadProgress(qint64,qint64)));
|
||||||
|
connect(reply, &QNetworkReply::finished,this, &XHR::onRequestFinished);
|
||||||
|
//connect(reply, SIGNAL(finished()),this, SLOT(onRequestFinished()));
|
||||||
|
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::get()
|
||||||
|
{
|
||||||
|
QUrlQuery query;
|
||||||
|
|
||||||
|
QHashIterator<QString, QString> i(params);
|
||||||
|
while(i.hasNext()) {
|
||||||
|
i.next();
|
||||||
|
query.addQueryItem(i.key(), i.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
QUrl requrl(m_url);
|
||||||
|
requrl.setQuery(query);
|
||||||
|
|
||||||
|
QByteArray loginData = m_login.toLocal8Bit().toBase64();
|
||||||
|
QString headerData = "Basic " + loginData;
|
||||||
|
request.setRawHeader("Authorization", headerData.toLocal8Bit());
|
||||||
|
|
||||||
|
|
||||||
|
request.setUrl(requrl);
|
||||||
|
reply = manager.get(request);
|
||||||
|
|
||||||
|
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
|
||||||
|
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
|
||||||
|
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::post()
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
QHttpPart textPart;
|
||||||
|
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + iparams.key() + "\""));
|
||||||
|
|
||||||
|
|
||||||
|
textPart.setBody(iparams.value().toUtf8());
|
||||||
|
multiPart->append(textPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
UploadableImage uimg;
|
||||||
|
QHashIterator<QString, QString> ifiles(files);
|
||||||
|
while(ifiles.hasNext()) {
|
||||||
|
ifiles.next();
|
||||||
|
|
||||||
|
uimg.setSource(ifiles.value());
|
||||||
|
qDebug() << "\t image: " << uimg.mimetype() << ", " << ifiles.key();
|
||||||
|
|
||||||
|
QHttpPart imagePart;
|
||||||
|
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(uimg.mimetype()));
|
||||||
|
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"" + ifiles.key() + "\"; filename=\""+uimg.filename()+"\""));
|
||||||
|
imagePart.setBody(uimg.bytes());
|
||||||
|
multiPart->append(imagePart);
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray loginData = m_login.toLocal8Bit().toBase64();
|
||||||
|
QString headerData = "Basic " + loginData;
|
||||||
|
request.setRawHeader(QByteArray("Authorization"), headerData.toLocal8Bit());
|
||||||
|
|
||||||
|
request.setUrl(m_url);
|
||||||
|
reply = manager.post(request, multiPart);
|
||||||
|
qDebug() << "\t request sent";
|
||||||
|
connect(reply, &QNetworkReply::finished, this, &XHR::onReplySuccess);
|
||||||
|
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(onReplyError(QNetworkReply::NetworkError)));
|
||||||
|
connect(reply, &QNetworkReply::readyRead, this, &XHR::onReadyRead);
|
||||||
|
connect(reply, &QNetworkReply::sslErrors, this, &XHR::onSSLError);
|
||||||
|
qDebug() << "\t reply signals connected";
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::onReplyError(QNetworkReply::NetworkError code)
|
||||||
|
{
|
||||||
|
qDebug() << code;
|
||||||
|
emit this->error( bufferToString(), (int) code);
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::onReplySuccess()
|
||||||
|
{
|
||||||
|
qDebug() << "!";
|
||||||
|
emit this->success( bufferToString() );
|
||||||
|
reply->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::onRequestFinished()
|
||||||
|
{
|
||||||
|
// Save the file here
|
||||||
|
//qDebug() << "buffer downloaded "<<buffer;
|
||||||
|
if (buffer.isNull()){qDebug() << "File empty"<<m_url; buffer.clear(); emit this->error(m_downloadtype,1);}
|
||||||
|
else {QFile file(m_filename);
|
||||||
|
file.open(QIODevice::WriteOnly);
|
||||||
|
file.write(buffer);
|
||||||
|
buffer.clear();
|
||||||
|
file.close();
|
||||||
|
//qDebug() << m_url << "File downloaded "<<file.fileName();
|
||||||
|
emit this->downloaded(m_downloadtype);
|
||||||
|
//reply->deleteLater();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void XHR::onReadyRead()
|
||||||
|
{
|
||||||
|
qDebug() << ".";
|
||||||
|
buffer += reply->readAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
//void XHR::updateDownloadProgress(qint64 bytesRead, qint64 totalBytes)
|
||||||
|
//{
|
||||||
|
// qDebug() << "Bytes: " << bytesRead<<" / "<<totalBytes;
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
void XHR::onSSLError(const QList<QSslError> &errors)
|
||||||
|
{
|
||||||
|
qDebug() << "XHR::onSSLError :" ;
|
||||||
|
QListIterator<QSslError> ierrs(errors);
|
||||||
|
while(ierrs.hasNext()) {
|
||||||
|
qDebug() << "\t" << ierrs.next().errorString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QString XHR::bufferToString()
|
||||||
|
{
|
||||||
|
return QTextCodec::codecForName("utf-8")->toUnicode(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
#ifndef XHR_H
|
||||||
|
#define XHR_H
|
||||||
|
|
||||||
|
#include <QNetworkAccessManager>
|
||||||
|
#include <QNetworkReply>
|
||||||
|
#include <QNetworkRequest>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class XHR : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QString url READ url WRITE setUrl NOTIFY urlChanged)
|
||||||
|
Q_PROPERTY(QString login READ login WRITE setLogin NOTIFY loginChanged)
|
||||||
|
Q_PROPERTY(QString filename READ filename WRITE setFilename NOTIFY filenameChanged)
|
||||||
|
Q_PROPERTY(QString downloadtype READ downloadtype WRITE setDownloadtype NOTIFY downloadtypeChanged)
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
static XHR *instance();
|
||||||
|
|
||||||
|
explicit XHR(QObject *parent = 0);
|
||||||
|
|
||||||
|
QString url() const;
|
||||||
|
QString login() const;
|
||||||
|
QString filename() const;
|
||||||
|
QString downloadtype() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void urlChanged();
|
||||||
|
void loginChanged();
|
||||||
|
void filenameChanged();
|
||||||
|
void downloadtypeChanged();
|
||||||
|
void downloaded(QString data);
|
||||||
|
void success(QString data);
|
||||||
|
void error(QString data, int code);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void setUrl(QString url);
|
||||||
|
void setLogin(QString login);
|
||||||
|
void setDownloadtype(QString downloadtype);
|
||||||
|
void setFilename(QString filename);
|
||||||
|
void setParam(QString name, QString value);
|
||||||
|
void setImageFileParam(QString name, QString url);
|
||||||
|
void clearParams();
|
||||||
|
void post();
|
||||||
|
void get();
|
||||||
|
void download();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void onReplyError(QNetworkReply::NetworkError code);
|
||||||
|
void onReplySuccess();
|
||||||
|
void onRequestFinished();
|
||||||
|
void onReadyRead();
|
||||||
|
void onSSLError(const QList<QSslError> &errors);
|
||||||
|
//void updateDownloadProgress(qint64 bytesRead, qint64 totalBytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QByteArray buffer;
|
||||||
|
QString m_url;
|
||||||
|
QString m_login;
|
||||||
|
QString m_filename;
|
||||||
|
QString m_downloadtype;
|
||||||
|
QHash<QString, QString> params;
|
||||||
|
QHash<QString, QString> files;
|
||||||
|
|
||||||
|
QNetworkAccessManager manager;
|
||||||
|
QNetworkRequest request;
|
||||||
|
QNetworkReply *reply;
|
||||||
|
|
||||||
|
QString bufferToString();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // XHR_H
|
|
@ -0,0 +1,44 @@
|
||||||
|
# NOTICE:
|
||||||
|
#
|
||||||
|
# Application name defined in TARGET has a corresponding QML filename.
|
||||||
|
# If name defined in TARGET is changed, the following needs to be done
|
||||||
|
# to match new name:
|
||||||
|
# - corresponding QML filename must be changed
|
||||||
|
# - desktop icon filename must be changed
|
||||||
|
# - desktop filename must be changed
|
||||||
|
# - icon definition filename in desktop file must be changed
|
||||||
|
# - translation filenames have to be changed
|
||||||
|
|
||||||
|
# The name of your application
|
||||||
|
TARGET = friendiqa
|
||||||
|
CONFIG += debug
|
||||||
|
QT += qml quick gui widgets
|
||||||
|
|
||||||
|
SOURCES += common/friendiqa.cpp \
|
||||||
|
common/uploadableimage.cpp \
|
||||||
|
common/xhr.cpp \
|
||||||
|
common/filesystem.cpp
|
||||||
|
|
||||||
|
RESOURCES = application.qrc
|
||||||
|
|
||||||
|
OTHER_FILES += qml/friendiqa.qml \
|
||||||
|
translations/*.ts \
|
||||||
|
qml/*.qml
|
||||||
|
qml/newsqml/*.qml
|
||||||
|
qml/contactqml/*.qml
|
||||||
|
qml/photoqml/*.qml
|
||||||
|
qml/configqml/*.qml
|
||||||
|
js/*.js
|
||||||
|
|
||||||
|
# German translation is enabled as an example. If you aren't
|
||||||
|
# planning to localize your app, remember to comment out the
|
||||||
|
# following TRANSLATIONS line. And also do not forget to
|
||||||
|
# modify the localized app name in the the .desktop file.
|
||||||
|
TRANSLATIONS += translations/friendiqa-de.ts
|
||||||
|
|
||||||
|
HEADERS += \
|
||||||
|
common/uploadableimage.h \
|
||||||
|
common/xhr.h \
|
||||||
|
common/filesystem.h
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 1.1 KiB |
|
@ -0,0 +1,12 @@
|
||||||
|
WorkerScript.onMessage = function(msg) {
|
||||||
|
msg.model.clear();
|
||||||
|
for (var j=0;j<msg.albums.length;j++){
|
||||||
|
if (msg.albums[j]) {
|
||||||
|
var albumobject=msg.albums[j];
|
||||||
|
var data=({"albumobject": albumobject,"foreignPicture": msg.foreignPicture})}
|
||||||
|
// print("Albums:"+j+msg.albums.length+JSON.stringify(data));
|
||||||
|
msg.model.append(data);}
|
||||||
|
if (j==msg.albums.length){
|
||||||
|
msg.model.sync()
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
.pragma library
|
||||||
|
.import QtQuick.LocalStorage 2.0 as Sql
|
||||||
|
|
||||||
|
function friendicaRequest(login,api,rootwindow,callback) {
|
||||||
|
var xhrequest= new XMLHttpRequest();
|
||||||
|
xhrequest.onreadystatechange = function() {
|
||||||
|
//print(api+JSON.stringify(login));
|
||||||
|
if(xhrequest.readyState === XMLHttpRequest.DONE) {
|
||||||
|
try{ if (xhrequest.responseText!=""){
|
||||||
|
callback(xhrequest.responseText)
|
||||||
|
}else{
|
||||||
|
showMessage("Error","API:" +api+"\n NO RESPONSE",rootwindow);
|
||||||
|
callback(xhrequest.responseText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e){
|
||||||
|
showMessage("Error", api+" "+e,rootwindow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhrequest.open("GET", login.server+api,true,login.username,Qt.atob(login.password));
|
||||||
|
xhrequest.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function friendicaPostRequest(login,api,rootwindow,callback) {
|
||||||
|
var xhrequest= new XMLHttpRequest();
|
||||||
|
xhrequest.onreadystatechange = function() {
|
||||||
|
//print(api+JSON.stringify(login));
|
||||||
|
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
|
||||||
|
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
|
||||||
|
try{ if (xhrequest.responseText!=""){
|
||||||
|
callback(xhrequest.responseText)
|
||||||
|
}else{
|
||||||
|
showMessage("Error",api+" NO RESPONSE",rootwindow)
|
||||||
|
callback(xhrequest.responseText)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (e){
|
||||||
|
showMessage("Error", api+" "+e,rootwindow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhrequest.open("POST", login.server+api,true,login.username,Qt.atob(login.password));
|
||||||
|
xhrequest.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function friendicaWebRequest(url,rootwindow,callback) {
|
||||||
|
var xhrequest = new XMLHttpRequest();
|
||||||
|
xhrequest.onreadystatechange = function() {
|
||||||
|
if (xhrequest.readyState === XMLHttpRequest.HEADERS_RECEIVED) {
|
||||||
|
} else if(xhrequest.readyState === XMLHttpRequest.DONE) {
|
||||||
|
try{ callback(xhrequest.responseText);
|
||||||
|
}
|
||||||
|
catch (e){
|
||||||
|
showMessage("Error",url+" "+e, rootwindow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xhrequest.open("GET", url,true);
|
||||||
|
xhrequest.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
function readData(database,table,username,callback,filter,filtervalue) { // reads and applies data from DB
|
||||||
|
if (filter){
|
||||||
|
var where = " AND "+ filter +" = '" + filtervalue+"'";
|
||||||
|
} else { var where="";}
|
||||||
|
if (username){
|
||||||
|
var user = ' where username= "'+ username +'"';
|
||||||
|
} else { var user='';}
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
if(!db) { return; }
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
//print('select * from '+table+user+where);
|
||||||
|
var rsArray=[];
|
||||||
|
var rs = tx.executeSql('select * from '+table+user+where);
|
||||||
|
for(var i = 0; i < rs.rows.length; i++) {
|
||||||
|
rsArray.push(rs.rows.item(i))
|
||||||
|
}
|
||||||
|
callback(rsArray);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function readField(field,database,table, username, callback,filter,filtervalue) { // reads and applies data from DB
|
||||||
|
if (filter){
|
||||||
|
var where = " AND "+ filter +" = '" + filtervalue+"'";
|
||||||
|
} else { var where="";}
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
if(!db) { return; }
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
//print('... read from database ' + field)
|
||||||
|
var rsArray=[];
|
||||||
|
//print('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC');
|
||||||
|
var rs = tx.executeSql('select DISTINCT '+field+' from '+table+' WHERE username="'+username+'"'+where+' ORDER BY '+field+' ASC');
|
||||||
|
for(var i = 0; i < rs.rows.length; i++) {
|
||||||
|
rsArray.push(rs.rows.item(i)[field])
|
||||||
|
}
|
||||||
|
callback(rsArray);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMessage(header,message,rootwindow){
|
||||||
|
var cleanmessage=message.replace(/"/g,"-");
|
||||||
|
var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+cleanmessage+'"}';
|
||||||
|
var messageObject=Qt.createQmlObject(messageString,rootwindow,"messageOutput");
|
||||||
|
}
|
||||||
|
|
||||||
|
function inArray(list, prop, val) {
|
||||||
|
if (list.length > 0 ) {
|
||||||
|
for (var i in list) { if (list[i][prop] === val) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} return -1;
|
||||||
|
}
|
||||||
|
function cleanArray(array) {
|
||||||
|
var arraystring=JSON.stringify(array);
|
||||||
|
arraystring=arraystring.replace(/[\[\]]/g , '');
|
||||||
|
return arraystring;
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
function showFriends(db) {
|
||||||
|
Service.readActiveConfig(db,function(login){
|
||||||
|
Service.requestFriends(login.url,login.user,login.password,displayFriends);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function displayFriends(obj){
|
||||||
|
for (var i=0; i<obj.length; i++){
|
||||||
|
print(obj[i]);
|
||||||
|
if (obj[i]) {friendsModel.append({"friendName": obj[i]});
|
||||||
|
};
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
function ensureVisibility(c,f)
|
||||||
|
{
|
||||||
|
if (f.contentX >= c.x)
|
||||||
|
f.contentX = c.x;
|
||||||
|
else if (f.contentX+f.width <= c.x+c.width)
|
||||||
|
f.contentX = c.x+c.width-f.width;
|
||||||
|
if (f.contentY >= c.y)
|
||||||
|
f.contentY = c.y;
|
||||||
|
else if (f.contentY+f.height <= c.y+c.height)
|
||||||
|
f.contentY = c.y+c.height-f.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createObject(objectQml,qmlParameters,parentitem,callback) {
|
||||||
|
var component = Qt.createComponent(objectQml);
|
||||||
|
if (component.status === Component.Ready || component.status === Component.Error)
|
||||||
|
finishCreation(component,qmlParameters,parentitem,callback);
|
||||||
|
else
|
||||||
|
component.statusChanged.connect(finishCreation(qmlParameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishCreation(component,qmlParameters,parentitem,callback) {
|
||||||
|
if (component.status === Component.Ready) {
|
||||||
|
var createdObject = component.createObject(parentitem, qmlParameters);
|
||||||
|
if (createdObject === null)
|
||||||
|
print("Error creating image"); }
|
||||||
|
else if (component.status === Component.Error)
|
||||||
|
print("Error loading component:"+component.errorString());
|
||||||
|
else {print("created")}
|
||||||
|
//callback(createdObject);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,399 @@
|
||||||
|
.pragma library
|
||||||
|
.import QtQuick.LocalStorage 2.0 as Sql
|
||||||
|
.import "qrc:/js/helper.js" as Helperjs
|
||||||
|
|
||||||
|
function requestFriends(login,database,rootwindow,callback){
|
||||||
|
// return array of friends
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('UPDATE contacts SET isFriend=0 where username="'+login.username+'"')}); // clean old friends
|
||||||
|
Helperjs.friendicaRequest(login,"/api/statuses/friends", rootwindow,function (obj){
|
||||||
|
var friends=JSON.parse(obj);
|
||||||
|
for (var i=0;i<friends.length;i++){ friends[i].isFriend=1}
|
||||||
|
callback(friends)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestGroups(login,database,rootwindow,callback){
|
||||||
|
// retrieve, save and return groups. Other features currently not implemented
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
Helperjs.friendicaRequest(login,"/api/friendica/group_show",rootwindow, function (obj){
|
||||||
|
var groups=JSON.parse(obj);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('DELETE from groups where username="'+login.username+'"'); // clean old groups
|
||||||
|
for (var i=0;i<groups.length;i++){
|
||||||
|
var memberarray=[]; for (var user in groups[i].user){memberarray.push(parseInt(groups[i].user[user].id))}
|
||||||
|
//print("Members: "+groups[i].user)
|
||||||
|
var result2 = tx.executeSql('INSERT INTO groups VALUES (?,?,?,?)', [login.username,groups[i].name,groups[i].gid,JSON.stringify(memberarray)])}
|
||||||
|
callback()
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
|
||||||
|
function getFriendsTimeline(login,database,contacts,onlynew,rootwindow,callback){
|
||||||
|
// retrieve and return timeline since last news, return contacts which are not friends and older than 2 days for update (friends can be updated in Contactstab)
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var parameter = "";
|
||||||
|
if(onlynew){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'); // check for last news id
|
||||||
|
try{parameter="&since_id="+result.rows.item(0).status_id;}catch(e){};})}
|
||||||
|
var newContacts=[];
|
||||||
|
//print("/api/statuses/friends_timeline"+parameter);
|
||||||
|
Helperjs.friendicaRequest(login,"/api/statuses/friends_timeline"+parameter, rootwindow,function (obj){
|
||||||
|
var news=JSON.parse(obj);
|
||||||
|
var newContacts=findNewContacts(news,contacts);
|
||||||
|
callback(news,newContacts)
|
||||||
|
})}
|
||||||
|
|
||||||
|
function getCurrentContacts(login,database,callback){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var contactlist=[];
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT id from contacts WHERE username="'+login.username+'" AND isFriend=1'); // check for friends
|
||||||
|
for (var i=0;i<result.rows.length;i++){
|
||||||
|
contactlist.push(result.rows.item(i).id )
|
||||||
|
}
|
||||||
|
var lastDate=Date.now()-172800000;// 2 days old
|
||||||
|
print('SELECT id from contacts WHERE username="'+login.username+'" AND isFriend=0 AND imageAge>'+lastDate);
|
||||||
|
var result2 = tx.executeSql('SELECT id from contacts WHERE username="'+login.username+'" AND isFriend=0 AND imageAge > '+lastDate);
|
||||||
|
for (var j=0;j<result2.rows.length;j++){
|
||||||
|
contactlist.push(result2.rows.item(j).id )
|
||||||
|
}
|
||||||
|
})
|
||||||
|
callback(contactlist)
|
||||||
|
}
|
||||||
|
|
||||||
|
function findNewContacts(news,contacts){
|
||||||
|
var newContacts=[];
|
||||||
|
for (var i=0;i<news.length;i++){
|
||||||
|
var id=parseInt(news[i].user.id);
|
||||||
|
if(contacts.indexOf(id)==-1 && !(inArray(newContacts,"id",id))){
|
||||||
|
news[i].user.isFriend=0;
|
||||||
|
newContacts.push(news[i].user);
|
||||||
|
}
|
||||||
|
if (news[i].friendica_activities.like.length>0){
|
||||||
|
for (var j=0;j<news[i].friendica_activities.like.length;j++){
|
||||||
|
var like_id=parseInt(news[i].friendica_activities.like[j].id);
|
||||||
|
if(contacts.indexOf(like_id)==-1 && !(inArray(newContacts,"id",like_id))){
|
||||||
|
news[i].friendica_activities.like[j].isFriend=0;
|
||||||
|
newContacts.push(news[i].friendica_activities.like[j]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (news[i].friendica_activities.dislike.length>0){
|
||||||
|
for (var k=0;j<news[k].friendica_activities.dislike.length;k++){
|
||||||
|
var dislike_id=parseInt(news[i].friendica_activities.dislike[k].id);
|
||||||
|
if(contacts.indexOf(dislike_id)==-1 && !(inArray(newContacts,"id",dislike_id))){
|
||||||
|
news[i].friendica_activities.dislike[k].isFriend=0;
|
||||||
|
newContacts.push(news[i].friendica_activities.dislike[k]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return newContacts
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeNews(login,database,news,rootwindow,callback){
|
||||||
|
// 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));
|
||||||
|
var ausdruck=news[i];
|
||||||
|
var likearray=[]; for (var user in news[i].friendica_activities.like){likearray.push(parseInt(news[i].friendica_activities.like[user].id))}
|
||||||
|
var dislikearray=[]; for (var user in news[i].friendica_activities.dislike){parseInt(news[i].friendica_activities.dislike[user].id)}
|
||||||
|
var attendyesarray=[]; for (var user in news[i].friendica_activities.attendyes){attendyesarray.push(parseInt(news[i].friendica_activities.attendyes[user].id))}
|
||||||
|
var attendnoarray=[]; for (var user in news[i].friendica_activities.attendno){attendnoarray.push(parseInt(news[i].friendica_activities.attendno[user].id))}
|
||||||
|
var attendmaybearray=[]; for (var user in news[i].friendica_activities.attendmaybe){attendmaybearray.push(parseInt(news[i].friendica_activities.attendmaybe[user].id))}
|
||||||
|
var friendica_activities=[likearray,dislikearray,attendyesarray,attendnoarray,attendmaybearray]
|
||||||
|
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
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
print(news[i].id +' news exists, update it')
|
||||||
|
result = tx.executeSql('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="'+JSON.stringify(friendica_activities)+'" 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) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,0,Qt.btoa(news[i].text),Date.parse(cleanDate(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, JSON.stringify(friendica_activities),"[]"])}})
|
||||||
|
}
|
||||||
|
getDirectMessage(login,database,rootwindow,callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
function getDirectMessage(login,database,rootwindow,callback){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var parameter = "";
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT status_id from news WHERE username="'+login.username+'" AND messagetype=1 ORDER BY status_id DESC LIMIT 1'); // check for last news id
|
||||||
|
try{parameter="&since_id="+result.rows.item(0).status_id;}catch(e){};})
|
||||||
|
Helperjs.friendicaRequest(login,"/api/direct_messages/all"+parameter,rootwindow, function (obj){
|
||||||
|
var messages=JSON.parse(obj);
|
||||||
|
for (var i=0;i<messages.length;i++){
|
||||||
|
//print('store message data for '+JSON.stringify(messages[i]));
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT * from news where username= "'+login.username+'" AND status_id = "'+messages[i].id+'" AND messagetype=1'); // check for news id
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
print(messages[i].id +' directmessage exists, update it')
|
||||||
|
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=1, text="'+Qt.btoa(messages[i].text)+'", created_at="'+Date.parse(cleanDate(messages[i].created_at))+'", source="Friendica", status_id="'+messages[i].id+'", uid="'+messages[i].sender.id+'", statusnet_html="'+Qt.btoa(messages[i].text)+'", statusnet_conversation_id="'+messages[i].friendica_parent_uri+'" where username="'+login.username+'" AND status_id="'+messages[i].status_id+'" AND messagetype=1');
|
||||||
|
} else {// use insert
|
||||||
|
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,source,status_id,uid,statusnet_html,statusnet_conversation_id) VALUES (?,?,?,?,?,?,?,?,?)', [login.username,1,Qt.btoa(messages[i].text),Date.parse(cleanDate(messages[i].created_at)), "Friendica", messages[i].id, messages[i].sender.id,Qt.btoa(messages[i].text),messages[i].friendica_parent_uri])}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if(login.newsViewType=="Timeline"){newsfromdb(database,login.username,callback)}
|
||||||
|
else{chatsfromdb(database,login.username,callback)}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNotifications(login,database,rootwindow,callback){
|
||||||
|
Helperjs.friendicaRequest(login,"/api/friendica/notifications", rootwindow,function (obj){
|
||||||
|
var messages=JSON.parse(obj);
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
for (var i=0;i<messages.length;i++){
|
||||||
|
//print('store message data for '+JSON.stringify(messages[i]));
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT * from news where username="'+login.username+'" AND status_id = "'+messages[i].id+'" AND messagetype=2'); // check for news id
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
print(messages[i].id +' Notification exists, update it')
|
||||||
|
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=2, text="'+Qt.btoa(messages[i].msg_html)+'", created_at="'+Date.parse(messages[i].date)+'", source="Friendica", status_id="'+messages[i].id+'", uid="'+messages[i].uid+'", statusnet_html="'+Qt.btoa(messages[i].msg_html)+'", statusnet_conversation_id="'+messages[i].parent+'" where username="'+login.username+'" AND status_id="'+messages[i].id+'" AND messagetype=2');
|
||||||
|
} else {// use insert
|
||||||
|
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,source,status_id, uid,statusnet_html,statusnet_conversation_id) VALUES (?,?,?,?,?,?,?,?,?)', [login.username,2,Qt.btoa(messages[i].msg_html),Date.parse(messages[i].date),"Friendica", messages[i].id, messages[i].uid,Qt.btoa(messages[i].msg_html),messages[i].parent])}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var newsrs=tx.executeSql('select * from news WHERE username="'+login.username+'" AND messagetype=2 ORDER BY status_id DESC LIMIT 20');
|
||||||
|
var newsArray=[];
|
||||||
|
for(var j = 0; j < newsrs.rows.length; j++) {
|
||||||
|
newsArray.push(newsrs.rows.item(j));
|
||||||
|
callback(newsArray);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})}
|
||||||
|
|
||||||
|
function getActivitiesUserData(database,username,useridArray){
|
||||||
|
var helpArray=[];
|
||||||
|
for (var i=0;i<useridArray.length;i++){
|
||||||
|
Helperjs.readData(database,"contacts",username,function(userdata){
|
||||||
|
helpArray.push(userdata[0]);
|
||||||
|
},"id",useridArray[i]);
|
||||||
|
}
|
||||||
|
return helpArray
|
||||||
|
}
|
||||||
|
|
||||||
|
function newsfromdb(database,username,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) {
|
||||||
|
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');
|
||||||
|
stop="<="+rs.rows.item(0).created_at}catch(e){stop="<99999999999999"}}
|
||||||
|
else{var stop="<"+stop_time}
|
||||||
|
var contactfilter="";if(contact){contactfilter=" AND uid='"+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="'+username+'" AND created_at'+stop+contactfilter+' ORDER BY created_at DESC LIMIT 20');
|
||||||
|
var newsArray=[];
|
||||||
|
for(var i = 0; i < newsrs.rows.length; i++) {
|
||||||
|
newsArray.push(newsrs.rows.item(i));
|
||||||
|
Helperjs.readData(database,"contacts",username,function(userdata){
|
||||||
|
newsArray[i].user=userdata[0];
|
||||||
|
},"id",newsArray[i].uid);
|
||||||
|
if(newsArray[i].in_reply_to_user_id){
|
||||||
|
Helperjs.readData(database,"contacts",username,function(replytodata){
|
||||||
|
newsArray[i].reply_user=replytodata[0];
|
||||||
|
},"id",newsArray[i].in_reply_to_user_id);
|
||||||
|
}
|
||||||
|
if (newsArray[i].messagetype==0){
|
||||||
|
for(var j=0;j<newsArray[i].friendica_activities.length;j++){
|
||||||
|
newsArray[i]=fetchUsersForNews(database,username,newsArray[i])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
callback(newsArray)});
|
||||||
|
}
|
||||||
|
|
||||||
|
function fetchUsersForNews(database,username,news){
|
||||||
|
Helperjs.readData(database,"contacts",username,function(userdata){
|
||||||
|
news.user=userdata[0];
|
||||||
|
//print("Fetch user"+JSON.stringify(news.user));
|
||||||
|
},"id",news.uid);
|
||||||
|
if(news.in_reply_to_user_id){
|
||||||
|
Helperjs.readData(database,"contacts",username,function(replytodata){
|
||||||
|
news.reply_user=replytodata[0];
|
||||||
|
//print("Fetch reply to"+JSON.stringify(news.reply_user));
|
||||||
|
},"id",news.in_reply_to_user_id);
|
||||||
|
}
|
||||||
|
if (news.messagetype==0){
|
||||||
|
for(var j=0;j<news.friendica_activities.length;j++)
|
||||||
|
{var friendicaArray=JSON.parse(news.friendica_activities);
|
||||||
|
// print("Array: "+friendicaArray[1]);
|
||||||
|
news.like=getActivitiesUserData(database,username,friendicaArray[0]);
|
||||||
|
news.dislike=getActivitiesUserData(database,username,friendicaArray[1]);
|
||||||
|
news.attendyes=getActivitiesUserData(database,username,friendicaArray[2]);
|
||||||
|
news.attendno=getActivitiesUserData(database,username,friendicaArray[3]);
|
||||||
|
news.attendmaybe=getActivitiesUserData(database,username,friendicaArray[4]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return news
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteNews(login,database,newsid,messagetype,rootwindow,callback){
|
||||||
|
var api="" ;
|
||||||
|
if (messagetype==0){ api="/api/statuses/destroy?id="}
|
||||||
|
else if (messagetype==1){ api="/api/direct_messages/destroy?id="}
|
||||||
|
else if (messagetype==2){ api="/api/friendica/notifications/seen?id="}
|
||||||
|
Helperjs.friendicaPostRequest(login,api+newsid, rootwindow,function (obj){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {var result = tx.executeSql('DELETE from news where username="'+login.username+'" AND messagetype='+messagetype+' AND status_id ='+newsid); // delete news id
|
||||||
|
callback(obj)
|
||||||
|
});
|
||||||
|
})}
|
||||||
|
|
||||||
|
function retweetNews(login,database,newsid,rootwindow,callback){
|
||||||
|
Helperjs.friendicaPostRequest(login,"/api/statuses/retweet?id="+newsid, rootwindow,function (obj){
|
||||||
|
var answer=JSON.parse(obj);
|
||||||
|
if(answer.status.error){Helperjs.showMessage("Repost",answer.status.code,rootwindow);}
|
||||||
|
else{Helperjs.showMessage("Repost",obj,rootwindow)}
|
||||||
|
})}
|
||||||
|
|
||||||
|
function favorite(login,favorite,newsid,rootwindow){
|
||||||
|
// toggle favorites
|
||||||
|
if(favorite){ Helperjs.friendicaPostRequest(login,"/api/favorites/create?id="+newsid, rootwindow,function (obj){
|
||||||
|
print("Favorite "+obj);
|
||||||
|
})}
|
||||||
|
else {Helperjs.friendicaPostRequest(login,"/api/favorites/destroy?id="+newsid, rootwindow,function (obj){
|
||||||
|
print("Favorite destroyed "+obj);
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
|
||||||
|
function likerequest(login,database,verb,newsid,rootwindow){
|
||||||
|
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/"+verb+"?id="+newsid, rootwindow,function (obj){
|
||||||
|
if (obj=='"ok"'){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var currentActivities_rs=tx.executeSql('select friendica_activities_self from news WHERE username="'+login.username+'" AND status_id='+newsid) ;
|
||||||
|
var currentActivities=JSON.parse(currentActivities_rs.rows.item(0).friendica_activities_self);
|
||||||
|
print(verb+"currentActivities "+JSON.stringify(currentActivities));
|
||||||
|
if ((verb=="like")&&(currentActivities.indexOf(1)==-1)){ currentActivities.push(1);
|
||||||
|
if (currentActivities.indexOf(2)!=-1){currentActivities.splice(currentActivities.indexOf(2),1)}
|
||||||
|
}
|
||||||
|
if ((verb=="dislike")&&(currentActivities.indexOf(2)==-1)){ currentActivities.push(2);
|
||||||
|
if (currentActivities.indexOf(1)!=-1){currentActivities.splice(currentActivities.indexOf(1),1)}
|
||||||
|
}
|
||||||
|
if (verb=="unlike"){ if (currentActivities.indexOf(1)!=-1){currentActivities.splice(currentActivities.indexOf(1),1)}}
|
||||||
|
if (verb=="undislike"){ if (currentActivities.indexOf(2)!=-1){currentActivities.splice(currentActivities.indexOf(2),1)}}
|
||||||
|
print(JSON.stringify(currentActivities));
|
||||||
|
var result = tx.executeSql('UPDATE news SET friendica_activities_self ="'+JSON.stringify(currentActivities)+'" where username="'+login.username+'" AND status_id ='+newsid);
|
||||||
|
})}
|
||||||
|
else{print("likerequest"+obj)}})
|
||||||
|
}
|
||||||
|
|
||||||
|
function like(login,database,toggle,verb,newsid,rootwindow){
|
||||||
|
if(verb=="like"&& toggle==1){likerequest(login,database,"like",newsid,rootwindow);
|
||||||
|
}
|
||||||
|
if(verb=="dislike"&& toggle==1){likerequest(login,database,"dislike",newsid,rootwindow);
|
||||||
|
}
|
||||||
|
if(toggle==0){
|
||||||
|
likerequest(login,database,"un"+verb,newsid,rootwindow);}
|
||||||
|
}
|
||||||
|
|
||||||
|
function attend(login,database,attend,newsid,rootwindow,callback){
|
||||||
|
Helperjs.friendicaPostRequest(login,"/api/friendica/activity/attend"+attend+"?id="+newsid, rootwindow,function (obj){
|
||||||
|
var attendReturn=JSON.parse(obj);
|
||||||
|
// print("attend: "+obj);
|
||||||
|
if (attendReturn=="OK")
|
||||||
|
{var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var currentActivities_rs=tx.executeSql('select friendica_activities_self from news WHERE username="'+login.username+'" AND status_id='+newsid) ;
|
||||||
|
var currentActivities=JSON.parse(currentActivities_rs.rows.item(0));
|
||||||
|
print("currentActivities "+JSON.stringify(currentActivities));
|
||||||
|
if ((attend=="attendyes")&&(currentActivities.indexOf(3)==-1)){
|
||||||
|
currentActivities.push(3);
|
||||||
|
currentActivities.splice(currentActivities.indexOf(4),1)
|
||||||
|
currentActivities.splice(currentActivities.indexOf(5),1)
|
||||||
|
}
|
||||||
|
if ((attend=="attendno")&&(currentActivities.indexOf(4)==-1)){
|
||||||
|
currentActivities.push(4);
|
||||||
|
currentActivities.splice(currentActivities.indexOf(3),1)
|
||||||
|
currentActivities.splice(currentActivities.indexOf(5),1)
|
||||||
|
}
|
||||||
|
if ((attend=="attendmaybe")&&(currentActivities.indexOf(5)==-1)){
|
||||||
|
currentActivities.push(5);
|
||||||
|
currentActivities.splice(currentActivities.indexOf(3),1)
|
||||||
|
currentActivities.splice(currentActivities.indexOf(4),1)
|
||||||
|
}
|
||||||
|
var result = tx.executeSql('UPDATE news SET friendica_activities_self ="'+JSON.stringify(currentActivities)+'" where username="'+login.username+'" AND status_id ='+newsid);
|
||||||
|
callback();
|
||||||
|
})}})}
|
||||||
|
|
||||||
|
function requestConversation(login,database,newsid,contacts,rootwindow,callback){
|
||||||
|
Helperjs.friendicaRequest(login,"/api/conversation/show?id="+newsid,rootwindow, function (obj){
|
||||||
|
var news=JSON.parse(obj);
|
||||||
|
var newContacts=findNewContacts(news,contacts);
|
||||||
|
// storeNews(login,database,news,rootwindow,callback)
|
||||||
|
callback(news,newContacts)
|
||||||
|
})}
|
||||||
|
|
||||||
|
function conversationfromdb(database,user,conversationId,callback){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var newsrs=tx.executeSql('select * from news WHERE username="'+user+'" AND statusnet_conversation_id="'+conversationId+'" ORDER BY created_at ASC');
|
||||||
|
var newsArray=[];
|
||||||
|
for(var i = 0; i < newsrs.rows.length; i++) {
|
||||||
|
newsArray.push(newsrs.rows.item(i));
|
||||||
|
newsArray[i]=fetchUsersForNews(database,user,newsArray[i])
|
||||||
|
}
|
||||||
|
callback(newsArray);} )}
|
||||||
|
|
||||||
|
function requestFavorites(login,database,contacts,rootwindow,callback){
|
||||||
|
Helperjs.friendicaRequest(login,"/api/favorites",rootwindow, function (obj){
|
||||||
|
//print(obj+JSON.stringify(obj));
|
||||||
|
var news=JSON.parse(obj);
|
||||||
|
var newContacts=findNewContacts(news,contacts);
|
||||||
|
// storeNews(login,database,news,rootwindow,callback)
|
||||||
|
callback(news,newContacts)
|
||||||
|
})}
|
||||||
|
|
||||||
|
function favoritesfromdb(database,user,callback){
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
print('select * from news WHERE username="'+user+'" AND favorited=1 ORDER BY status_id DESC');
|
||||||
|
var newsrs=tx.executeSql('select * from news WHERE username="'+user+'" AND favorited=1 ORDER BY status_id DESC');
|
||||||
|
var newsArray=[];
|
||||||
|
for(var i = 0; i < newsrs.rows.length; i++) {
|
||||||
|
newsArray.push(newsrs.rows.item(i));
|
||||||
|
newsArray[i]=fetchUsersForNews(database,user,newsArray[i]);
|
||||||
|
callback(newsArray);
|
||||||
|
}})}
|
||||||
|
|
||||||
|
function chatsfromdb(database,user,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');
|
||||||
|
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');
|
||||||
|
var conversations=[];
|
||||||
|
for(var i = 0; i < conversationsrs.rows.length; i++) {
|
||||||
|
conversations.push(conversationsrs.rows.item(i).statusnet_conversation_id);
|
||||||
|
}
|
||||||
|
var newsArray=[];
|
||||||
|
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');
|
||||||
|
// if(newsrs.rows.length>1){
|
||||||
|
var helpernews=newsrs.rows.item(0);
|
||||||
|
helpernews.newscount=newsrs.rows.length;
|
||||||
|
helpernews=fetchUsersForNews(database,user,helpernews)
|
||||||
|
newsArray.push(helpernews);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
callback(newsArray);
|
||||||
|
})}
|
||||||
|
|
||||||
|
function inArray(list, prop, val) {
|
||||||
|
if (list.length > 0 ) {
|
||||||
|
for (var i in list) {if (list[i][prop] == val) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanDate(date){
|
||||||
|
var cleanedDate= date.slice(0,3)+", "+date.slice(8,11)+date.slice(4,7)+date.slice(25,30)+date.slice(10,25);
|
||||||
|
return cleanedDate
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
WorkerScript.onMessage = function(msg) {
|
||||||
|
if(msg.appendnews!==true){ msg.model.clear()};
|
||||||
|
|
||||||
|
for (var j=0;j<msg.news.length;j++){
|
||||||
|
if (msg.news[j]) {
|
||||||
|
var newsitemobject=msg.news[j];
|
||||||
|
//print("Newsitem"+JSON.stringify(newsitemobject));
|
||||||
|
if (newsitemobject.messagetype==2){
|
||||||
|
newsitemobject.user={};
|
||||||
|
newsitemobject.user.profile_image="";
|
||||||
|
newsitemobject.user.profile_image_url="";
|
||||||
|
newsitemobject.user.name="";
|
||||||
|
}
|
||||||
|
var likeText="";var dislikeText="";var attendyesText="";var attendnoText="";var attendmaybeText=""; var self={};
|
||||||
|
if (newsitemobject.messagetype==0){
|
||||||
|
if (newsitemobject.like.length>0){
|
||||||
|
if (newsitemobject.like.length==1){likeText= Qt.atob(newsitemobject.like[0].name)+" "+ qsTr("likes this.")}
|
||||||
|
else {likeText= newsitemobject.like.length+" "+ qsTr("like this.")}
|
||||||
|
}
|
||||||
|
if (newsitemobject.dislike.length>0){
|
||||||
|
if (newsitemobject.dislike.length==1){dislikeText= QT.atob(newsitemobject.dislike[0].name)+" "+ qsTr("doesn't like this.")}
|
||||||
|
else {dislikeText= newsitemobject.dislike.length+" "+ qsTr("don't like this.")}
|
||||||
|
}
|
||||||
|
if (newsitemobject.attendyes.length>0){
|
||||||
|
if (newsitemobject.attendyes.length==1){attendyesText= Qt.atob(newsitemobject.attendyes[0].name)+" "+ qsTr("will attend.")}
|
||||||
|
else {attendyesText= newsitemobject.attendyes.length+" "+ qsTr("persons will attend.")}
|
||||||
|
}
|
||||||
|
if (newsitemobject.attendno.length>0){
|
||||||
|
if (newsitemobject.attendno.length==1){attendnoText= Qt.atob(newsitemobject.attendno[0].name)+" "+ qsTr("will not attend.")}
|
||||||
|
else {attendnoText= newsitemobject.attendno.length+" "+ qsTr("persons will not attend.")}
|
||||||
|
}
|
||||||
|
if (newsitemobject.attendmaybe.length>0){
|
||||||
|
if (newsitemobject.attendmaybe.length==1){attendmaybeText= Qt.atob(newsitemobject.attendmaybe[0].name)+" "+ qsTr("may attend.")}
|
||||||
|
else {attendmaybeText= newsitemobject.attendmaybe.length+" "+ qsTr("persons may attend.")}
|
||||||
|
}
|
||||||
|
var friendica_activities_self=JSON.parse(newsitemobject.friendica_activities_self);
|
||||||
|
if (friendica_activities_self.indexOf(3)!=-1){self.attending=qsTr("yes")}
|
||||||
|
if (friendica_activities_self.indexOf(4)!=-1){self.attending=qsTr("no")}
|
||||||
|
if (friendica_activities_self.indexOf(5)!=-1){self.attending=qsTr("maybe")}
|
||||||
|
if (friendica_activities_self.indexOf(1)!=-1){self.liked=1}
|
||||||
|
if (friendica_activities_self.indexOf(2)!=-1){self.disliked=1}
|
||||||
|
}
|
||||||
|
var friendica_activities={likeText:likeText,dislikeText:dislikeText,attendyesText:attendyesText,attendnoText:attendnoText,attendmaybeText:attendmaybeText,self:self}
|
||||||
|
//print(JSON.stringify(friendica_activities) ) ;
|
||||||
|
var seconds=(msg.currentTime-newsitemobject.created_at)/1000;
|
||||||
|
var timestring="";
|
||||||
|
if (seconds<60) {timestring=seconds+" "+qsTr("seconds") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<90){timestring=Math.round(seconds/60)+" "+qsTr("minute") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<3600){timestring=Math.round(seconds/60)+" "+qsTr("minutes") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<5400){timestring=Math.round(seconds/3600)+" "+qsTr("hour") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<86400){timestring=Math.round(seconds/3600)+" "+qsTr("hours") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<129600){timestring=Math.round(seconds/86400)+" "+qsTr("day") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<3888000){timestring=Math.round(seconds/86400)+" "+qsTr("days") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<5832000){timestring=Math.round(seconds/3888000)+" "+qsTr("month") +" "+qsTr("ago");}
|
||||||
|
else if (seconds<69984000){timestring=Math.round(seconds/3888000)+" "+qsTr("months") +" "+qsTr("ago");}
|
||||||
|
else {timestring=Math.round(seconds/69984000)+" "+qsTr("years") +" "+qsTr("ago");}
|
||||||
|
var data=({"newsitemobject": newsitemobject,"dateDiff":timestring,"friendica_activities":friendica_activities})}
|
||||||
|
//print("News:"+j+msg.news.length+JSON.stringify(data));
|
||||||
|
msg.model.append(data);}
|
||||||
|
if (j==msg.news.length){
|
||||||
|
msg.model.sync()
|
||||||
|
};
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
WorkerScript.onMessage = function(msg) {
|
||||||
|
if (msg.firstalbum==0){msg.model.clear();}
|
||||||
|
var limit=0; if (msg.albums.length-msg.firstalbum<20){limit=msg.albums.length} else{limit=msg.firstalbum+20}
|
||||||
|
for (var j=msg.firstalbum;j<limit;j++){
|
||||||
|
if (msg.albums[msg.firstalbum]) {
|
||||||
|
// print("album"+msg.albums[j].name);
|
||||||
|
if(msg.foreignPicture){
|
||||||
|
var albumname=msg.albums[j].name.trim();var albumlink=msg.albums[j].link
|
||||||
|
}else{
|
||||||
|
var albumname=msg.albums[j].toString();var albumlink=""}
|
||||||
|
msg.model.append({"albumlink":albumlink,"foreignPicture":msg.foreignPicture,"albumname":albumname});
|
||||||
|
msg.model.sync()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,272 @@
|
||||||
|
//.pragma library
|
||||||
|
.import QtQuick.LocalStorage 2.0 as Sql
|
||||||
|
.import "qrc:/js/helper.js" as Helperjs
|
||||||
|
.import "qrc:/js/news.js" as Newsjs
|
||||||
|
|
||||||
|
// IMAGE FUNCTIONS
|
||||||
|
|
||||||
|
function requestList(login,database,rootwindow,callback) {
|
||||||
|
//get list of own images and call download function
|
||||||
|
Helperjs.friendicaRequest(login,"/api/friendica/photos/list", rootwindow,function (helperobject){
|
||||||
|
//print("return"+helperobject);
|
||||||
|
var obj=JSON.parse(helperobject);
|
||||||
|
Helperjs.readField("id",database,"imageData",login.username,function(AllStoredImages){
|
||||||
|
if (AllStoredImages.length>0){
|
||||||
|
for(var i=0;i< AllStoredImages.length;i++){
|
||||||
|
var position=Helperjs.inArray(obj,"resourceID",AllStoredImages[i]);
|
||||||
|
if (position>-1){obj.splice(position,1)}
|
||||||
|
//obj.splice(obj.indexOf(AllStoredImages[i]),1);// list of objects instead of list!!!
|
||||||
|
}}
|
||||||
|
callback(obj)
|
||||||
|
})
|
||||||
|
})}
|
||||||
|
|
||||||
|
function dataRequest(login,photoID,database,rootwindow) {
|
||||||
|
// check if image exist and call download function
|
||||||
|
Helperjs.friendicaRequest(login,"/api/friendica/photo?photo_id="+photoID, rootwindow, function (image){
|
||||||
|
try{ if(image==""){currentimageno=currentimageno+1}else{
|
||||||
|
var obj = JSON.parse(image);
|
||||||
|
var helpfilename=obj.filename.substring(0,obj.filename.lastIndexOf("."));
|
||||||
|
var filesuffix="";
|
||||||
|
if (obj.type=="image/jpeg"){filesuffix=".jpg"}
|
||||||
|
else if (obj.type=="image/png"){filesuffix=".png"}
|
||||||
|
else {filesuffix=""}
|
||||||
|
|
||||||
|
if (helpfilename==""){// check if file has any filename
|
||||||
|
obj.filename=obj["id"]+filesuffix;
|
||||||
|
}
|
||||||
|
else{obj.filename=helpfilename+filesuffix}
|
||||||
|
|
||||||
|
var link="";
|
||||||
|
if(obj["link"][0]){link=obj["link"][0]} else{link=obj["link"]["4"]}
|
||||||
|
xhr.setUrl(Qt.resolvedUrl(link));
|
||||||
|
xhr.setFilename(login.imagestore+'albums/'+obj.album+"/"+obj["filename"]);
|
||||||
|
xhr.setDownloadtype("picture");
|
||||||
|
xhr.download();
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('SELECT * from imageData where id = "'+obj["id"]+'"');
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
result = tx.executeSql('UPDATE imageData SET username ="' +login.username+ '",id="'+obj.id+'", created="'+obj.created+'", edited="'+obj.edited+'", profile="'+obj.profile+'", link="'+obj["link"]["4"]+'", filename="'+obj.filename+'",title="'+obj.title+'", desc="'+obj.desc+'", type="'+obj.type+'", width="'+obj.width+'", height="'+obj.height+'", album="'+obj.album+'", location="file://'+login.imagestore+'albums/'+obj.album+'/" where id="'+obj["id"]+'"');
|
||||||
|
} else {// use insert print('... does not exists, create it')
|
||||||
|
result = tx.executeSql('INSERT INTO imageData VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,obj.id,obj.created,obj.edited, obj.title, obj.desc, obj.album, obj.filename, obj.type, obj.height, obj.width,obj. profile,obj["link"]["4"],'file://'+login.imagestore+'albums/'+obj.album+"/"]);
|
||||||
|
}
|
||||||
|
})}}
|
||||||
|
catch (e){print("Data retrieval failure! "+ e+obj);}
|
||||||
|
})}
|
||||||
|
|
||||||
|
|
||||||
|
function deleteImageData(database,user,field,selection,callback) { // does nothing useful at the moment
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
//print(' delete Image Data() for ' + field +"="+selection)
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
result = tx.executeSql('UPDATE imageData SET data="" where '+ field +'="'+selection+'"');
|
||||||
|
callback(result)})
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestFriendsAlbumPictures(login,friend,rootwindow,callback){
|
||||||
|
// screenscraping of albums page of contact without user and password
|
||||||
|
Helperjs.friendicaWebRequest(friend.url.replace("profile","photos"),rootwindow,function(photohtml){
|
||||||
|
//print(photohtml);
|
||||||
|
var photoarray=[];
|
||||||
|
var arr = photohtml.split("sidebar-photos-albums-li");
|
||||||
|
for (var i=2;i<arr.length;i++){
|
||||||
|
var albumlink = arr[i].substring(arr[i].indexOf('http'),arr[i].indexOf('class')-2);
|
||||||
|
var albumname=arr[i].substring(arr[i].indexOf('/span')+6,arr[i].indexOf('</a>')-1);
|
||||||
|
var album={'link':albumlink,'name':albumname}
|
||||||
|
photoarray.push(album);
|
||||||
|
}
|
||||||
|
callback(photoarray)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestFriendsPictures(link,rootwindow,callback){
|
||||||
|
// screenscraping of pictures page for given album
|
||||||
|
Helperjs.friendicaWebRequest(link,rootwindow,function(photohtml){
|
||||||
|
var photoarray=[];
|
||||||
|
var basehtml=photohtml.substring(photohtml.indexOf('<base')+12,photohtml.indexOf('/>',photohtml.indexOf('<base'))-2);
|
||||||
|
|
||||||
|
// old theme
|
||||||
|
if (photohtml.indexOf("photo-album-image-wrapper-end")>-1){ //theme 1
|
||||||
|
var arr = photohtml.split("photo-album-image-wrapper-end");}
|
||||||
|
|
||||||
|
// other themes
|
||||||
|
if (photohtml.indexOf("photo-album-wrapper")>-1){ //theme 2
|
||||||
|
var photoarea=photohtml.substring(photohtml.indexOf("photo-album-wrapper"),photohtml.indexOf("photo-album-end"))
|
||||||
|
var arr = photoarea.split("</a>");}
|
||||||
|
|
||||||
|
for (var i=0;i<arr.length-1;i++){
|
||||||
|
var photoname=arr[i].substring(arr[i].lastIndexOf('alt')+5,arr[i].lastIndexOf('title')-2);
|
||||||
|
var thumblink=arr[i].substring(arr[i].lastIndexOf('<img')+10,arr[i].lastIndexOf('alt')-2);
|
||||||
|
|
||||||
|
var imagetype=thumblink.substring(thumblink.lastIndexOf("."));
|
||||||
|
var photolink=thumblink.substring(0,thumblink.length-imagetype.length-2)+"-0"+imagetype
|
||||||
|
if(thumblink.substring(0,4)!=="http"){thumblink=basehtml+thumblink}
|
||||||
|
if(photolink.substring(0,4)!=="http"){photolink=basehtml+photolink}
|
||||||
|
var photo={'link':photolink,'name':photoname,'thumb':thumblink}
|
||||||
|
photoarray.push(photo);
|
||||||
|
}
|
||||||
|
callback(photoarray)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// CONFIG FUNCTIONS
|
||||||
|
|
||||||
|
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])
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS imageData(username TEXT,id INT, created TEXT,edited TEXT, title TEXT, desc TEXT, album TEXT,filename TEXT, type TEXT, height INT, width INT, profile INT, link TEXT,location TEXT)');
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS config(server TEXT, username TEXT, password TEXT, imagestore TEXT, maxnews INT, timerInterval INT, newsViewType TEXT,isActive INT, permissions TEXT,maxContactAge INT,APIVersion TEXT)');
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS news(username TEXT, messagetype INT, text TEXT, created_at INT, in_reply_to_status_id INT, source TEXT, status_id INT, in_reply_to_user_id INT, geo TEXT,favorited TEXT, uid INT, statusnet_html TEXT, statusnet_conversation_id TEXT,friendica_activities TEXT, friendica_activities_self TEXT)');
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS contacts(username TEXT, id INT, name TEXT, screen_name TEXT, location TEXT,imageAge INT, profile_image_url TEXT, description TEXT, profile_image BLOB, url TEXT, protected TEXT, followers_count INT, friends_count INT, created_at INT, favourites_count TEXT, utc_offset TEXT, time_zone TEXT, statuses_count INT, following TEXT, verified TEXT, statusnet_blocking TEXT, notifications TEXT, statusnet_profile_url TEXT, cid INT, network TEXT, isFriend INT)');
|
||||||
|
tx.executeSql('CREATE TABLE IF NOT EXISTS groups(username TEXT, groupname TEXT, gid INT, members TEXT)');
|
||||||
|
})}
|
||||||
|
|
||||||
|
function savePermissions(database,obj) { // stores config to DB
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var permissions=JSON.stringify(obj)
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql( 'UPDATE config SET permissions="'+permissions+'" WHERE username="'+obj.username +'"');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function storeConfig(database,obj) { // stores config to DB
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
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+",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, 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);
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
|
||||||
|
function getServerConfig(database,login,rootwindow,callback){
|
||||||
|
// check server with given credentials
|
||||||
|
try {Helperjs.friendicaRequest(login,"/api/statusnet/config",rootwindow, function (obj){
|
||||||
|
var serverconfig = JSON.parse(obj);
|
||||||
|
var serverconfigString="import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:'Server';standardButtons: StandardButton.Ok;text: 'SUCCESS! \nName: "+serverconfig.site.name+"\nLanguage: "+serverconfig.site.language+
|
||||||
|
"\nEmail: "+serverconfig.site.email+"\nTimezone: "+serverconfig.site.timezone+"\nClosed: "+serverconfig.site.closed+
|
||||||
|
"\nText limit: "+serverconfig.site.textlimit+"\nShort Url length: "+serverconfig.site.shorturllength+
|
||||||
|
"\nFriendica version: "+serverconfig.site.friendica.FRIENDICA_VERSION+"\nDFRN version: "+serverconfig.site.friendica.DFRN_PROTOCOL_VERSION +
|
||||||
|
"\nDB Update version: "+serverconfig.site.friendica.DB_UPDATE_VERSION+"'}";
|
||||||
|
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('UPDATE config SET APIVersion="'+ serverconfig.site.friendica.FRIENDICA_VERSION+'" WHERE username="'+login.username +'"')})
|
||||||
|
|
||||||
|
callback(serverconfigString);
|
||||||
|
})}
|
||||||
|
catch (e){callback (e);
|
||||||
|
}}
|
||||||
|
|
||||||
|
function readConfig(database,callback,filter,filtervalue) { // reads config
|
||||||
|
if (filter){var where = " WHERE "+ filter +" = '" + filtervalue+"'"} else { var where=""}
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3],initDatabase(database));
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var tables = tx.executeSql("SELECT * FROM sqlite_master WHERE type='table'");
|
||||||
|
if (tables.rows.length==0){print("no database");callback("")} else {
|
||||||
|
var rs = tx.executeSql('select * from config'+where);
|
||||||
|
var rsArray=[];
|
||||||
|
if (rs.rows.length>0){
|
||||||
|
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};
|
||||||
|
} else {var rsObject=""}
|
||||||
|
callback(rsObject)}}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function readActiveConfig(database){
|
||||||
|
var obj;
|
||||||
|
readConfig(database,function(config){obj=config},"isActive", 0);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteConfig(database,userobj,callback) { // delete user data from DB
|
||||||
|
if (userobj){var where = " WHERE username='"+ userobj.username+"' and server='"+userobj.server+"'";} else { return "no user selected!";}
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
if(!db) { return; }
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
var rs = tx.executeSql('delete from config'+where);
|
||||||
|
callback(rs);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
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 newscountrs = tx.executeSql('SELECT COUNT(*) from news');
|
||||||
|
var newscount = newscountrs.rows.item(0)["COUNT(*)"];
|
||||||
|
if (newscount>maxnews){var lastvalidtimers= tx.executeSql('select created_at from news ORDER BY created_at DESC LIMIT ' +(newscount-maxnews));
|
||||||
|
var lastvalidtime=lastvalidtimers.rows.item(maxnews).created_at;
|
||||||
|
var deleters = tx.executeSql('DELETE from news WHERE created_at<='+lastvalidtime)}
|
||||||
|
callback()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function processNews(callback){
|
||||||
|
Newsjs.getCurrentContacts(login,db,function(contacts){
|
||||||
|
contactlist=contacts});
|
||||||
|
|
||||||
|
if (contactLoadType=="news"){
|
||||||
|
if(root.news.length==0){}
|
||||||
|
else{// show news
|
||||||
|
Newsjs.storeNews(login,db,news,root,function(dbnews){
|
||||||
|
root.newsSignal(dbnews);
|
||||||
|
newstab.newstabstatus=login.newsViewType
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
else if (contactLoadType=="friends"){// show friends
|
||||||
|
root.friendsSignal(login.username);
|
||||||
|
Newsjs.getCurrentContacts(login,db,function(contacts){
|
||||||
|
contactlist=contacts;
|
||||||
|
})}
|
||||||
|
|
||||||
|
else if (contactLoadType=="conversation"){
|
||||||
|
var conversationid=news[0].statusnet_conversation_id
|
||||||
|
if (!isNaN(parseInt(conversationid))){//no directmessage conversation
|
||||||
|
Newsjs.storeNews(root.login,root.db,news,root,function(){
|
||||||
|
Newsjs.conversationfromdb(db,root.login.username,conversationid, function(newsarray){
|
||||||
|
newstab.conversation=newsarray;
|
||||||
|
})
|
||||||
|
})}
|
||||||
|
else {newstab.conversation=news}//only DM conversations from database
|
||||||
|
}
|
||||||
|
else if (contactLoadType=="favorites"){//show favorited news
|
||||||
|
Newsjs.storeNews(root.login,root.db,news,root,function(){
|
||||||
|
Newsjs.favoritesfromdb(db,login.username,function(newsarray){
|
||||||
|
root.newsSignal(newsarray);
|
||||||
|
newstab.newstabstatus="Favorites";
|
||||||
|
})
|
||||||
|
})}
|
||||||
|
callback()
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateContactInDB(login,database,isFriend,contact){// for newstab and friendstab
|
||||||
|
var suffix=contact.profile_image_url.substring(contact.profile_image_url.lastIndexOf("."), contact.profile_image_url.length);
|
||||||
|
var imagename=login.imagestore+"contacts/"+contact.screen_name.trim()+suffix;
|
||||||
|
contacttimer.restart();
|
||||||
|
var currentTime=Date.now();
|
||||||
|
xhr.setUrl(Qt.resolvedUrl(contact.profile_image_url));
|
||||||
|
xhr.setFilename(imagename);
|
||||||
|
xhr.setDownloadtype("contact");
|
||||||
|
xhr.download();
|
||||||
|
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
|
||||||
|
var result;
|
||||||
|
db.transaction( function(tx) {
|
||||||
|
result = tx.executeSql('SELECT * from contacts where username="'+root.login.username+'" AND id = '+contact.id); // check for news id
|
||||||
|
if(result.rows.length === 1) {// use update
|
||||||
|
result = tx.executeSql('UPDATE contacts SET username="'+login.username+'", id='+contact.id+', name="'+Qt.btoa(contact.name)+'", screen_name="'+contact.screen_name+'", location="'+contact.location+'",imageAge='+currentTime+', profile_image_url="'+contact.profile_image_url+'", description="'+Qt.btoa(contact.description)+'", profile_image="'+imagename+'", url="'+contact.url+'" , protected="'+contact.protected+'", followers_count='+contact.followers_count+', friends_count='+contact.friends_count+', created_at="'+ Date.parse(Newsjs.cleanDate(contact.created_at))+'", favourites_count="'+contact.favorites_count+'", utc_offset="'+contact.utc_offset+'", time_zone="'+contact.time_zone+'", statuses_count='+contact.statuses_count+', following="'+contact.following+'", verified ="'+contact.verified+'", statusnet_blocking="'+contact.statusnet_blocking+'", notifications="'+contact.notifictions+'", statusnet_profile_url="'+contact.statusnet_profile_url+'", cid='+contact.cid+', network="'+contact.network+'", isFriend='+isFriend+' where username="'+root.login.username+'" AND id='+contact.id);
|
||||||
|
} else {// use insert
|
||||||
|
result = tx.executeSql('INSERT INTO contacts VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,contact.id,Qt.btoa(contact.name),contact.screen_name,contact.location,currentTime,contact.profile_image_url, Qt.btoa(contact.description),imagename,contact.url,contact.protected,contact.followers_count, contact.friends_count,Date.parse(Newsjs.cleanDate(contact.created_at)),contact.favorites_count,contact.utc_offset,contact.time_zone,contact.statuses_count,contact.following,contact.verfied,contact.statusnet_blocking,contact.notifications,contact.statusnet_profile_url,contact.cid,contact.network,isFriend]);}
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,314 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
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"
|
||||||
|
|
||||||
|
StackView{
|
||||||
|
id: configStack
|
||||||
|
anchors.fill:parent
|
||||||
|
initialItem: Flickable{
|
||||||
|
width:root.width-5*mm
|
||||||
|
height:root.height-12*mm
|
||||||
|
contentHeight: configBackground.height
|
||||||
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
Rectangle{
|
||||||
|
id:configBackground
|
||||||
|
color: "grey"
|
||||||
|
width:parent.width
|
||||||
|
height:Math.max(90*mm,root.height-12*mm)
|
||||||
|
property var users:[]
|
||||||
|
BlueButton{
|
||||||
|
id:userButton
|
||||||
|
text:qsTr("User")
|
||||||
|
y:mm
|
||||||
|
width: root.width/2
|
||||||
|
onClicked:{
|
||||||
|
var useritems="";
|
||||||
|
for (var i=0;i<configBackground.users.length;i++){
|
||||||
|
|
||||||
|
useritems=useritems+"MenuItem{text:'"+configBackground.users[i].username+
|
||||||
|
"'; onTriggered: {Service.readConfig(db,function(obj){
|
||||||
|
userButton.text=obj.username;
|
||||||
|
servername.text=obj.server;
|
||||||
|
username.text= obj.username;
|
||||||
|
password.text=Qt.atob(obj.password);
|
||||||
|
imagestore.text=obj.imagestore;
|
||||||
|
maxNews.value=obj.maxnews;
|
||||||
|
newsTypeField.text=obj.newsViewType;
|
||||||
|
if( obj.isActive==0){isActiveField.text=qsTr('yes')} else {isActiveField.text=qsTr('no')}
|
||||||
|
},'username','"+configBackground.users[i].username+"')}}"
|
||||||
|
}
|
||||||
|
var menuString="import QtQuick.Controls 1.4;import 'qrc:/js/service.js' as Service; Menu {"+useritems+"}";
|
||||||
|
var userlistObject=Qt.createQmlObject(menuString,configBackground,"usermenuOutput")
|
||||||
|
userlistObject.popup() }
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Server"
|
||||||
|
x: 4*mm; y: 10*mm
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "User"
|
||||||
|
x: 4*mm; y: 20*mm
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Password"
|
||||||
|
x: 4*mm; y: 30*mm
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "Image dir."
|
||||||
|
x: 4*mm; y: 40*mm
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
text: "Max. News"
|
||||||
|
x: 4*mm; y: 50*mm
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "News as"
|
||||||
|
x: 4*mm; y: 60*mm
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
text: "is Active"
|
||||||
|
x: 4*mm; y: 70*mm
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{color: "white"; x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;}
|
||||||
|
Flickable {
|
||||||
|
id: servernameFlickable
|
||||||
|
x: 25*mm; y: 10*mm; width: root.width/2; height: 5*mm;
|
||||||
|
contentWidth: servername.paintedWidth
|
||||||
|
contentHeight: servername.paintedHeight
|
||||||
|
clip: true
|
||||||
|
TextEdit {
|
||||||
|
id: servername
|
||||||
|
width: servernameFlickable.width
|
||||||
|
height: servernameFlickable.height
|
||||||
|
focus: true
|
||||||
|
text:"https://..."
|
||||||
|
//wrapMode: TextEdit.NoWrap
|
||||||
|
//validator: RegExpValidator { regExp: /^(((http|https|ftp):\/\/)?([[a-zA-Z0-9]\-\.])+(\.)([[a-zA-Z0-9]]){2,4}([[a-zA-Z0-9]\/+=%&_\.~?\-]*))*$/}
|
||||||
|
// onEditingFinished:{}
|
||||||
|
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,servernameFlickable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
color: "white"
|
||||||
|
x: 25*mm; y: 20*mm; width: root.width/2; height: 5*mm;
|
||||||
|
TextInput {
|
||||||
|
id: username
|
||||||
|
anchors.fill: parent
|
||||||
|
selectByMouse: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
color: "white"
|
||||||
|
x: 25*mm; y: 30*mm; width: root.width/2; height: 5*mm;
|
||||||
|
TextInput {
|
||||||
|
id: password
|
||||||
|
anchors.fill: parent
|
||||||
|
selectByMouse: true
|
||||||
|
echoMode: TextInput.PasswordEchoOnEdit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{color: "white"; x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;}
|
||||||
|
Flickable {
|
||||||
|
id: imagestoreFlickable
|
||||||
|
x: 25*mm; y: 40*mm; width: root.width/2-9*mm; height: 5*mm;
|
||||||
|
clip: true
|
||||||
|
TextInput {
|
||||||
|
id: imagestore
|
||||||
|
width: imagestoreFlickable.width
|
||||||
|
height: imagestoreFlickable.height
|
||||||
|
wrapMode: TextEdit.NoWrap
|
||||||
|
onCursorRectangleChanged: Layoutjs.ensureVisibility(cursorRectangle,imagestoreFlickable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Slider{ id: maxNews
|
||||||
|
x:37*mm; y: 50*mm;width: root.width/3;height:5*mm
|
||||||
|
minimumValue: 0;maximumValue:100000; stepSize: 1000
|
||||||
|
}
|
||||||
|
Rectangle{color: "white"; x: 25*mm; y: 50*mm; width: 9*mm; height: 5*mm;
|
||||||
|
TextEdit{id:maxNewsText;
|
||||||
|
anchors.fill: parent
|
||||||
|
verticalAlignment:TextEdit.AlignRight
|
||||||
|
text:maxNews.value
|
||||||
|
focus: true
|
||||||
|
selectByMouse: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
x: 25*mm; y: 60*mm; width: root.width/2; height: 5*mm;
|
||||||
|
Text{
|
||||||
|
id: newsTypeField
|
||||||
|
anchors.fill: parent
|
||||||
|
text:"Timeline"
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill:parent
|
||||||
|
onClicked:newstypemenu.popup()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
x: 25*mm; y: 70*mm; width: root.width/2; height: 5*mm;
|
||||||
|
Text{
|
||||||
|
id: isActiveField
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
console.log("You chose: " + imagestoreDialog.folder)
|
||||||
|
}
|
||||||
|
onRejected: {console.log("Canceled")}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: root.width/2+18*mm; y: 40*mm; width: 7*mm; height: 5*mm;
|
||||||
|
text: "..."
|
||||||
|
onClicked:
|
||||||
|
{imagestoreDialog.open()}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: 25*mm; y: 80*mm
|
||||||
|
text: "Update"
|
||||||
|
onClicked:{
|
||||||
|
var userconfig={server: servername.text, username: username.text, password:Qt.btoa(password.text), imagestore:imagestore.text,maxnews:maxNewsText.text,newsViewType:newsTypeField.text};
|
||||||
|
var errormessage="";
|
||||||
|
if (servername.text==""){errormessage=qsTr("No server given! ")}
|
||||||
|
//if (!servername.acceptableInput){errormessage+=qsTr("Server name not valid! ")}
|
||||||
|
else if (username.text==""){errormessage+=qsTr("No username 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=="") {
|
||||||
|
filesystem.Directory=userconfig.imagestore;
|
||||||
|
filesystem.makeDir("contacts");
|
||||||
|
filesystem.makeDir("albums");
|
||||||
|
Service.storeConfig(db,userconfig);
|
||||||
|
Service.readConfig(db,function(userconfig){
|
||||||
|
Service.getServerConfig(db,userconfig,configBackground, function(obj){
|
||||||
|
var serverString=obj;
|
||||||
|
var serverconfigObject=Qt.createQmlObject(serverString,configBackground,"serverconfigOutput");
|
||||||
|
Helperjs.readData(db,"config","",function(storedUsers){
|
||||||
|
storedUsers.sort(function(obj1, obj2) {
|
||||||
|
return obj1.isActive - obj2.isActive;
|
||||||
|
});
|
||||||
|
configBackground.users=storedUsers});
|
||||||
|
isActiveField.text="yes"
|
||||||
|
//reset values
|
||||||
|
root.login=userconfig;
|
||||||
|
root.contactlist=[];
|
||||||
|
root.news=[]
|
||||||
|
root.newContacts=[]
|
||||||
|
root.currentContact= 0
|
||||||
|
root.contactLoadType= ""
|
||||||
|
root.currentIndex=0;
|
||||||
|
newstab.active=true;
|
||||||
|
})},"isActive",0);
|
||||||
|
}
|
||||||
|
else {Helperjs.show("Error", errormessage,root)}
|
||||||
|
}}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: root.width/2+2*mm; y: mm; width: 5*mm; height: 5*mm;
|
||||||
|
text: "-"
|
||||||
|
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://...";
|
||||||
|
username.text="";
|
||||||
|
password.text="";
|
||||||
|
imagestore.text="";
|
||||||
|
maxNews.value=0;
|
||||||
|
newsTypeField.text="Timeline";
|
||||||
|
isActiveField.text="";
|
||||||
|
userButton.text=qsTr("User");
|
||||||
|
Helperjs.readData(db,"config","",function(storedUsers){
|
||||||
|
storedUsers.sort(function(obj1, obj2) {
|
||||||
|
return obj1.isActive - obj2.isActive;
|
||||||
|
})
|
||||||
|
configBackground.users=storedUsers;})
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: root.width/2+8*mm; y: mm; width: 5*mm; height: 5*mm;
|
||||||
|
text: "+"
|
||||||
|
onClicked:{
|
||||||
|
servername.text="https://..."
|
||||||
|
username.text=""
|
||||||
|
password.text=""
|
||||||
|
imagestore.text=""
|
||||||
|
maxNews.value=0
|
||||||
|
newsTypeField.text="Timeline"
|
||||||
|
isActiveField.text=""
|
||||||
|
userButton.text=qsTr("User")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
x: root.width/2+14*mm; y: mm; width: 5*mm; height: 5*mm;
|
||||||
|
text: "?"
|
||||||
|
onClicked:{
|
||||||
|
configStack.push({item:"qrc:/qml/configqml/InfoBox.qml"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id:newstypemenu
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Timeline")
|
||||||
|
onTriggered: {newsTypeField.text="Timeline"}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Tree")
|
||||||
|
onTriggered: {newsTypeField.text="Tree"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
try{Helperjs.readData(db,"config","",function(storedUsers){
|
||||||
|
storedUsers.sort(function(obj1, obj2) {
|
||||||
|
return obj1.isActive - obj2.isActive;
|
||||||
|
})
|
||||||
|
configBackground.users=storedUsers;
|
||||||
|
Service.readConfig(db,function(obj){
|
||||||
|
userButton.text=obj.username;
|
||||||
|
servername.text=obj.server;
|
||||||
|
username.text= obj.username;
|
||||||
|
password.text=Qt.atob(obj.password);
|
||||||
|
imagestore.text=obj.imagestore;
|
||||||
|
maxNews.value=obj.maxnews;
|
||||||
|
newsTypeField.text=obj.newsViewType;
|
||||||
|
if( obj.isActive==0){isActiveField.text=qsTr('yes')} else {isActiveField.text=qsTr('no')}},"isActive",0
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
catch (e){print(e)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
Rectangle{
|
||||||
|
color:"white"
|
||||||
|
width:infoBoxText.contentWidth
|
||||||
|
height:infoBoxText.contentHeight
|
||||||
|
Text{id:infoBoxText
|
||||||
|
textFormat: Text.RichText
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
text: "<b>Friendiqa v0.002 </b><br>Licensed under GPL 3<br> "+
|
||||||
|
"Profile <a href='https://freunde.ma-nic.de/profile/friendiqa'>https://freunde.ma-nic.de/profile/friendiqa</a><br>"+
|
||||||
|
"Sourcecode: <a href='https://github.com/LubuWest/Friendiqa'>https://github.com/LubuWest/Friendica</a><br>"+
|
||||||
|
"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>"
|
||||||
|
onLinkActivated:{
|
||||||
|
Qt.openUrlExternally(link)}
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
text:qsTr("Close")
|
||||||
|
onClicked:{configStack.pop()}
|
||||||
|
anchors.top:infoBoxText.bottom
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import "qrc:/js/layout.js" as Layoutjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: contactComponent
|
||||||
|
property var createdAtDate: new Date(contact.created_at)
|
||||||
|
property var linkUrl: contact.network!=="dfrn"?contact.url:contact.url.replace("profile","dfrn_request")
|
||||||
|
Rectangle {
|
||||||
|
id: wrapper
|
||||||
|
width: 16*mm
|
||||||
|
height: 15*mm
|
||||||
|
border.color: "grey"
|
||||||
|
color:"white"
|
||||||
|
Image {
|
||||||
|
id: photoImage
|
||||||
|
x:1
|
||||||
|
y:1
|
||||||
|
width: 10*mm
|
||||||
|
height:10*mm
|
||||||
|
source:(contact.profile_image!="")? "file://"+contact.profile_image : contact.profile_image_url
|
||||||
|
onStatusChanged: if (photoImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id: namelabel
|
||||||
|
x: 1
|
||||||
|
width: wrapper.width-4
|
||||||
|
height: 3*mm
|
||||||
|
text: contact.screen_name
|
||||||
|
elide:Text.ElideRight
|
||||||
|
anchors.topMargin: 0
|
||||||
|
anchors.left: photoImage.left
|
||||||
|
color: "#303030"
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
anchors.top: photoImage.bottom
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
id:infobutton
|
||||||
|
width: 5*mm
|
||||||
|
height: 5*mm
|
||||||
|
color:"transparent"
|
||||||
|
text:"?"
|
||||||
|
anchors.left: photoImage.right
|
||||||
|
anchors.leftMargin: 3
|
||||||
|
anchors.topMargin: 3
|
||||||
|
anchors.top: parent.top
|
||||||
|
onClicked:{
|
||||||
|
contactComponent.state="large";
|
||||||
|
var component = Qt.createComponent("qrc:/qml/contactqml/ContactDetailsComponent.qml");
|
||||||
|
if (component.status== Component.Ready){
|
||||||
|
var contactDetails = component.createObject(wrapper,{"contact": contact})}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "large"
|
||||||
|
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:friendsTabView.width-4*mm; text:Qt.atob(contact.name)+" (@"+contact.screen_name+")"}
|
||||||
|
PropertyChanges { target: contactComponent; z: 2 }
|
||||||
|
PropertyChanges { target: wrapper; width:friendsTabView.width-3*mm;height:friendsTabView.height-10*mm}
|
||||||
|
PropertyChanges { target: photoImage; width:15*mm;height:15*mm }
|
||||||
|
PropertyChanges { target:contactComponent.GridView.view;contentY:contactComponent.y;contentX:contactComponent.x;interactive:false}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id: detailsrectangle
|
||||||
|
anchors.top: namelabel.bottom
|
||||||
|
anchors.topMargin: 2*mm
|
||||||
|
//opacity: 0
|
||||||
|
|
||||||
|
ScrollView{
|
||||||
|
horizontalScrollBarPolicy:Qt.ScrollBarAlwaysOff
|
||||||
|
frameVisible: true
|
||||||
|
//Flickable{
|
||||||
|
id:namelabelflickable
|
||||||
|
width: root.width-10*mm
|
||||||
|
height:friendsTabView.height-45*mm
|
||||||
|
//boundsBehavior:Flickable.StopAtBounds
|
||||||
|
//flickableDirection:Flickable.VerticalFlick
|
||||||
|
//contentWidth:width
|
||||||
|
//contentHeight: namelabeltext.height
|
||||||
|
clip:true
|
||||||
|
Text{
|
||||||
|
id:namelabeltext
|
||||||
|
width: namelabelflickable.width
|
||||||
|
height: implicitHeight
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
textFormat:Text.RichText
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
text:"<b>"+qsTr("Description")+": </b> "+Qt.atob(contact.description)+"<br> <b>"+qsTr("Location")+":</b> "+contact.location+"<br> <b>"+qsTr("Posts")+":</b> "+contact.statuses_count+
|
||||||
|
"<br> <b>"+qsTr("URL")+":</b> <a href='"+ linkUrl+"'>"+linkUrl+"</a><br> <b>"+
|
||||||
|
qsTr("Created at")+":</b> "+createdAtDate.toLocaleString(Qt.locale())
|
||||||
|
onLinkActivated: {
|
||||||
|
Qt.openUrlExternally(link)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row{
|
||||||
|
anchors.top: namelabelflickable.bottom
|
||||||
|
anchors.topMargin: 2*mm
|
||||||
|
spacing:4
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id:photobutton
|
||||||
|
text:"Photos"
|
||||||
|
visible:contact.network=="dfrn"? 1:0
|
||||||
|
onClicked:{contactComponent.state="";detailsrectangle.destroy();
|
||||||
|
root.currentIndex=2;
|
||||||
|
fotostab.active=true;
|
||||||
|
root.fotoSignal(contact) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id:messagebutton
|
||||||
|
text:"Messages"
|
||||||
|
onClicked:{contactComponent.state="";detailsrectangle.destroy();
|
||||||
|
root.currentIndex=0;
|
||||||
|
newstab.active=true;
|
||||||
|
root.messageSignal(contact.id) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id:dmbutton
|
||||||
|
visible: contact.following=="true"?true:false
|
||||||
|
text: "DM"
|
||||||
|
onClicked:{contactComponent.state="";detailsrectangle.destroy();
|
||||||
|
root.currentIndex=0;
|
||||||
|
newstab.active=true;
|
||||||
|
root.directmessageSignal(contact.screen_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id: closeButton
|
||||||
|
text: "close"
|
||||||
|
onClicked:{contactComponent.state="";detailsrectangle.destroy()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,197 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/js/news.js" as Newsjs
|
||||||
|
import "qrc:/qml/contactqml"
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
y:1
|
||||||
|
color: "white"
|
||||||
|
TabView{
|
||||||
|
id:friendsTabView
|
||||||
|
tabPosition: Qt.TopEdge
|
||||||
|
x:mm
|
||||||
|
y:mm
|
||||||
|
width: root.width-2*mm
|
||||||
|
height: root.height-10*mm
|
||||||
|
currentIndex: 0
|
||||||
|
|
||||||
|
signal contactsSignal(var username)
|
||||||
|
signal groupsSignal(var username)
|
||||||
|
onCurrentIndexChanged:{
|
||||||
|
if (currentIndex==0){root.friendsSignal(root.login.username)}
|
||||||
|
else if (currentIndex==1){contactsSignal(root.login.username)}
|
||||||
|
else if (currentIndex==2){groupsSignal(root.login.username)}
|
||||||
|
}
|
||||||
|
style: TabViewStyle {
|
||||||
|
frameOverlap: 1
|
||||||
|
tab: Rectangle {
|
||||||
|
color: "white"
|
||||||
|
//border.color: "light grey"
|
||||||
|
implicitWidth: root.width/3-2*mm
|
||||||
|
implicitHeight: 4*mm
|
||||||
|
Text { id: text
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: styleData.title
|
||||||
|
color: "dark grey"
|
||||||
|
font.pixelSize:2.5*mm
|
||||||
|
font.bold: styleData.selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame: Rectangle { color: "light grey" }
|
||||||
|
tabsAlignment:Qt.AlignHCenter
|
||||||
|
}
|
||||||
|
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Friends")
|
||||||
|
Rectangle{
|
||||||
|
id: friendsGridTab
|
||||||
|
function showFriends(username){
|
||||||
|
try {friendsModel.clear()} catch(e){print(e)};
|
||||||
|
Helperjs.readData(db,"contacts",username,function(friendsobject){
|
||||||
|
for (var i=0;i<friendsobject.length;i++){
|
||||||
|
friendsModel.append({"contact":friendsobject[i]});
|
||||||
|
}},"isFriend",1)
|
||||||
|
}
|
||||||
|
Connections{
|
||||||
|
target:root
|
||||||
|
onLoginChanged:{showFriends()}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
id: updateFriendsButton
|
||||||
|
text: qsTr("Update")
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
onClicked: {
|
||||||
|
try {friendsModel.clear()} catch(e){print(e)};
|
||||||
|
root.contactLoadType="friends";
|
||||||
|
Newsjs.requestFriends(root.login,db,root,function(nc){
|
||||||
|
root.newContacts=nc
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar{
|
||||||
|
id: newContactsProgress
|
||||||
|
width: 15*mm
|
||||||
|
height: updateFriendsButton.height
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right:updateFriendsButton.left
|
||||||
|
anchors.rightMargin:mm
|
||||||
|
visible: (root.currentContact!=root.newContacts.length)?true:false
|
||||||
|
value: root.currentContact/root.newContacts.length
|
||||||
|
}
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: friendsView
|
||||||
|
x:mm
|
||||||
|
y:updateFriendsButton.height+2*mm
|
||||||
|
width:friendsGridTab.width-2*mm
|
||||||
|
height:friendsGridTab.height-updateFriendsButton.height-2*mm
|
||||||
|
clip: true
|
||||||
|
cellHeight: 16*mm
|
||||||
|
cellWidth: 17*mm
|
||||||
|
add: Transition {
|
||||||
|
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
|
||||||
|
}
|
||||||
|
model: friendsModel
|
||||||
|
delegate: ContactComponent { }
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id:friendsModel}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.friendsSignal.connect(showFriends);
|
||||||
|
showFriends(root.login.username)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Other Contacts")
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id: contactsGridTab
|
||||||
|
function showContacts(username){
|
||||||
|
try {contactsModel.clear()} catch(e){print(e)};
|
||||||
|
Helperjs.readData(db, "contacts",root.login.username,function(contactsobject){
|
||||||
|
for (var j=0;j<contactsobject.length;j++){
|
||||||
|
contactsModel.append({"contact":contactsobject[j]});
|
||||||
|
}
|
||||||
|
},"isFriend",0)}
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: contactsView
|
||||||
|
x:mm
|
||||||
|
y:2*mm
|
||||||
|
width:contactsGridTab.width-2*mm
|
||||||
|
height:contactsGridTab.height-2*mm
|
||||||
|
clip: true
|
||||||
|
cellHeight: 16*mm
|
||||||
|
cellWidth: 17*mm
|
||||||
|
add: Transition {
|
||||||
|
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
|
||||||
|
}
|
||||||
|
model: contactsModel
|
||||||
|
delegate: ContactComponent { }
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: contactsModel}
|
||||||
|
Component.onCompleted: {
|
||||||
|
friendsTabView.contactsSignal.connect(showContacts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Groups")
|
||||||
|
Rectangle{
|
||||||
|
id: groupsGridTab
|
||||||
|
function showGroups(username){
|
||||||
|
try {groupsModel.clear()} catch(e){print(e)};
|
||||||
|
Helperjs.readData(db, "groups",root.login.username,function(groupsobject){
|
||||||
|
for (var j=0;j<groupsobject.length;j++){
|
||||||
|
groupsModel.append({"group":groupsobject[j]});
|
||||||
|
}})}
|
||||||
|
BlueButton {
|
||||||
|
id: updateGroupsButton
|
||||||
|
text: qsTr("Update")
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
onClicked: {
|
||||||
|
Newsjs.requestGroups(root.login,root.db,root,function(){
|
||||||
|
showGroups(root.login.username)})}
|
||||||
|
}
|
||||||
|
GridView {
|
||||||
|
id: groupsView
|
||||||
|
x:mm
|
||||||
|
y:updateGroupsButton.height+2*mm
|
||||||
|
width:groupsGridTab.width-2*mm
|
||||||
|
height:groupsGridTab.height-updateGroupsButton.height-2*mm
|
||||||
|
clip: true
|
||||||
|
cellHeight: 16*mm
|
||||||
|
cellWidth: 17*mm
|
||||||
|
add: Transition {
|
||||||
|
NumberAnimation { properties: "x,y"; from: 300; duration: 1000 }
|
||||||
|
}
|
||||||
|
model: groupsModel
|
||||||
|
delegate: GroupComponent { }
|
||||||
|
}
|
||||||
|
ListModel{
|
||||||
|
id: groupsModel
|
||||||
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
friendsTabView.groupsSignal.connect(showGroups);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,121 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: groupComponent
|
||||||
|
Rectangle {
|
||||||
|
id: wrapper
|
||||||
|
width: 16*mm
|
||||||
|
height: 15*mm
|
||||||
|
border.color: "grey"
|
||||||
|
color:"white"
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: photoImage
|
||||||
|
x:1
|
||||||
|
y:1
|
||||||
|
width: 10*mm
|
||||||
|
height:10*mm
|
||||||
|
source:"qrc:/images/defaultcontact.jpg"
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id: namelabel
|
||||||
|
x: 1
|
||||||
|
width: wrapper.width-2
|
||||||
|
height: 3*mm
|
||||||
|
text: group.groupname
|
||||||
|
|
||||||
|
color: "#303030"
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
anchors.top: photoImage.bottom
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
id:infobutton
|
||||||
|
width: 5*mm
|
||||||
|
height: 5*mm
|
||||||
|
color:"transparent"
|
||||||
|
text:"?"
|
||||||
|
anchors.left: photoImage.right
|
||||||
|
anchors.leftMargin: 3
|
||||||
|
anchors.topMargin: 3
|
||||||
|
anchors.top: parent.top
|
||||||
|
onClicked:{
|
||||||
|
Helperjs.readField("members",root.db,"groups",root.login.username,function(groups){
|
||||||
|
try {groupModel.clear()}catch (e){print(e)}
|
||||||
|
var groupmembers=JSON.parse(groups);
|
||||||
|
for (var user in groupmembers){
|
||||||
|
Helperjs.readData(root.db,"contacts",root.login.username,function(userdata){
|
||||||
|
if (userdata[0]){groupModel.append({"groupmember":userdata[0]})}
|
||||||
|
},"id",groupmembers[user])}
|
||||||
|
},"groupname",group.groupname);
|
||||||
|
groupComponent.state="large"}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id: detailsrectangle
|
||||||
|
anchors.top: namelabel.bottom
|
||||||
|
anchors.topMargin: 2*mm
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
Component { id:groupMember
|
||||||
|
Rectangle{
|
||||||
|
border.color: "#EEEEEE"
|
||||||
|
border.width: 1
|
||||||
|
width:parent.width
|
||||||
|
height:6*mm
|
||||||
|
Image {
|
||||||
|
id: memberImage
|
||||||
|
x:1
|
||||||
|
y:1
|
||||||
|
width: 5*mm
|
||||||
|
height:5*mm
|
||||||
|
source:(groupmember.isFriend==1)? "file://"+groupmember.profile_image :groupmember.profile_image_url
|
||||||
|
onStatusChanged: if (photoImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
|
||||||
|
}
|
||||||
|
Text{
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
anchors.left: memberImage.right
|
||||||
|
anchors.margins: 1*mm
|
||||||
|
text:Qt.atob(groupmember.name)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
ListView{
|
||||||
|
id: groupListView
|
||||||
|
x:1
|
||||||
|
//anchors.top: parent.top
|
||||||
|
width: root.width-10*mm
|
||||||
|
height:groupsView.height -28*mm
|
||||||
|
clip: true
|
||||||
|
spacing: 2
|
||||||
|
model: groupModel
|
||||||
|
delegate: groupMember
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: groupModel}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id: closeButton
|
||||||
|
anchors.top: groupListView.bottom
|
||||||
|
x:1
|
||||||
|
text: qsTr("close")
|
||||||
|
onClicked:{groupComponent.state=""}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: "large"
|
||||||
|
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; width:groupsView.width}
|
||||||
|
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 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,149 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.LocalStorage 2.0
|
||||||
|
import QtQuick.Window 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
|
||||||
|
import QtQml.Models 2.1
|
||||||
|
import "qrc:/js/news.js" as Newsjs
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
//import "qrc:/js/layout.js" as Layoutjs
|
||||||
|
//import "qrc:/js/helper.js" as Helperjs
|
||||||
|
//import "qrc:/qml"
|
||||||
|
|
||||||
|
TabView{
|
||||||
|
id:root
|
||||||
|
tabPosition: Qt.BottomEdge
|
||||||
|
width: 500//Screen.desktopAvailableWidth
|
||||||
|
height: 500//Screen.desktopAvailableHeight
|
||||||
|
focus:true
|
||||||
|
property var db: ["Friendiqa", "1.0", "Stores Friendica data", 100000000]
|
||||||
|
property var login: Service.readActiveConfig(db)
|
||||||
|
property var contactlist: []
|
||||||
|
property real mm: Screen.pixelDensity
|
||||||
|
signal messageSignal(var friend)
|
||||||
|
signal fotoSignal(var friend)
|
||||||
|
signal directmessageSignal(var friend)
|
||||||
|
signal newsSignal(var news)
|
||||||
|
signal friendsSignal(var username)
|
||||||
|
|
||||||
|
currentIndex: (login=="")? 3:0
|
||||||
|
|
||||||
|
property var news:[]
|
||||||
|
property var newContacts:[]
|
||||||
|
property int currentContact: 0
|
||||||
|
property string contactLoadType: ""
|
||||||
|
|
||||||
|
onLoginChanged:{
|
||||||
|
Newsjs.getCurrentContacts(login,db,function(contacts){
|
||||||
|
contactlist=contacts});
|
||||||
|
}
|
||||||
|
onNewContactsChanged:{
|
||||||
|
if(newContacts.length>0){// download first contact image and update db
|
||||||
|
Service.updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])}
|
||||||
|
else if (contactLoadType!=""){
|
||||||
|
Service.processNews(function(){
|
||||||
|
root.contactLoadType="";
|
||||||
|
root.news=[];
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCurrentContactChanged:{// download next contact image after photoplaceholder is finished saving and update db
|
||||||
|
if(currentContact<newContacts.length){
|
||||||
|
Service.updateContactInDB(login,db,newContacts[currentContact].isFriend,newContacts[currentContact])}
|
||||||
|
else if (contactLoadType!=""){
|
||||||
|
Service.processNews(function(){
|
||||||
|
root.contactLoadType="";
|
||||||
|
root.news=[];
|
||||||
|
root.newContacts=[];
|
||||||
|
root.currentContact=0;
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target:xhr
|
||||||
|
onDownloaded:{if(data=="contact"){contacttimer.stop();root.currentContact=root.currentContact+1}}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target:xhr
|
||||||
|
onError:{print("Error"+data);
|
||||||
|
if (data=="contact"){
|
||||||
|
var database=LocalStorage.openDatabaseSync(root.db[0],root.db[1],root.db[2],root.db[3]);
|
||||||
|
var result;
|
||||||
|
database.transaction( function(tx) {
|
||||||
|
//print('UPDATE contacts SET profile_image="" where username="'+root.login.username+'" AND id = '+newContacts[currentContact].id);
|
||||||
|
result = tx.executeSql('UPDATE contacts SET profile_image="" where username="'+root.login.username+'" AND id = '+newContacts[currentContact].id);
|
||||||
|
root.currentContact=root.currentContact+1;contacttimer.stop()})}
|
||||||
|
}}
|
||||||
|
|
||||||
|
Timer {id:contacttimer; interval: 5000; running: false; repeat: false
|
||||||
|
onTriggered: {
|
||||||
|
var database=LocalStorage.openDatabaseSync(root.db[0],root.db[1],root.db[2],root.db[3]);
|
||||||
|
database.transaction( function(tx) {
|
||||||
|
var result = tx.executeSql('UPDATE contacts SET profile_image="" where username="'+root.login.username+'" AND id = '+newContacts[currentContact].id);
|
||||||
|
root.currentContact=root.currentContact+1})}
|
||||||
|
}
|
||||||
|
|
||||||
|
Keys.onReleased: {
|
||||||
|
if (event.key === Qt.Key_Escape) {
|
||||||
|
if (currentIndex==0){
|
||||||
|
newstab.active=true;
|
||||||
|
if (newstab.newstabstatus!=login.newsViewType){
|
||||||
|
newstab.newstabstatus=login.newsViewType;
|
||||||
|
if(login.newsViewType=="Timeline"){Newsjs.newsfromdb(db,login.username,function(dbnews){
|
||||||
|
newsSignal(dbnews)
|
||||||
|
})}
|
||||||
|
else{Newsjs.chatsfromdb(db,login.username,function(dbnews){
|
||||||
|
newsSignal(dbnews)
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
else{Service.cleanNews(root.db,function(){Qt.quit()})}
|
||||||
|
}
|
||||||
|
else {currentIndex=0}
|
||||||
|
event.accepted = true
|
||||||
|
}}
|
||||||
|
|
||||||
|
|
||||||
|
style: TabViewStyle {
|
||||||
|
frameOverlap: 1
|
||||||
|
tab: Rectangle {
|
||||||
|
color: styleData.selected?"white":"light blue"
|
||||||
|
border.color: "light grey"
|
||||||
|
implicitWidth: root.width/4-2*mm
|
||||||
|
implicitHeight: 4*mm
|
||||||
|
Text { id: text
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text: styleData.title
|
||||||
|
color: "black"
|
||||||
|
font.pixelSize:3*mm
|
||||||
|
font.bold: styleData.selected
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame: Rectangle { color: "light grey" }
|
||||||
|
tabsAlignment:Qt.AlignHCenter
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("News")
|
||||||
|
id: newstab
|
||||||
|
property string newstabstatus:login.newsViewType
|
||||||
|
property var conversation
|
||||||
|
source:(root.currentIndex==0)? "qrc:/qml/newsqml/NewsTab.qml":""
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Contacts")
|
||||||
|
id: friendstab
|
||||||
|
source: (root.currentIndex==1)?"qrc:/qml/contactqml/FriendsTab.qml":""
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Photos")
|
||||||
|
id: fotostab
|
||||||
|
property string phototabstatus:"Images"
|
||||||
|
source: (root.currentIndex==2)?"qrc:/qml/photoqml/PhotoTab.qml":""
|
||||||
|
}
|
||||||
|
Tab{
|
||||||
|
title: qsTr("Config")
|
||||||
|
source: (root.currentIndex==3)?"qrc:/qml/configqml/ConfigTab.qml":""
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
Rectangle{
|
||||||
|
id: blueButton
|
||||||
|
width: mainText.width+2*mm
|
||||||
|
height: mainText.height+2*mm
|
||||||
|
color:"light blue"
|
||||||
|
|
||||||
|
border.color:"grey"
|
||||||
|
border.width:1
|
||||||
|
radius: mm
|
||||||
|
property alias text: mainText.text
|
||||||
|
signal clicked
|
||||||
|
state:""
|
||||||
|
|
||||||
|
Text{
|
||||||
|
id:mainText
|
||||||
|
color: "black"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
width: contentWidth
|
||||||
|
height: contentHeight
|
||||||
|
font.pixelSize: 3*mm
|
||||||
|
text: ""
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
id:buttonArea
|
||||||
|
anchors.fill:parent
|
||||||
|
onPressed: blueButton.state="Pressed"
|
||||||
|
onReleased: blueButton.state=""
|
||||||
|
onClicked: {parent.clicked()}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State { name: "Pressed"
|
||||||
|
PropertyChanges { target: blueButton; color: "lightsteelblue"} }
|
||||||
|
//State { name: "RELEASED" PropertyChanges { target: button; color: "lightsteelblue"}
|
||||||
|
]
|
||||||
|
transitions: [
|
||||||
|
Transition { to:"*"
|
||||||
|
ColorAnimation { target: blueButton; duration: 100} }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
// ConversationStack with buttons
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
import "qrc:/qml"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id:conversationStack
|
||||||
|
property var news
|
||||||
|
y:1
|
||||||
|
color: "white"
|
||||||
|
width:root.width-2*mm
|
||||||
|
height:root.height-8*mm
|
||||||
|
|
||||||
|
ListView {
|
||||||
|
id: conversationView
|
||||||
|
x:3*mm
|
||||||
|
y:8*mm
|
||||||
|
width: conversationStack.width-4*mm
|
||||||
|
height: conversationStack.height-10*mm
|
||||||
|
clip: true
|
||||||
|
spacing: 0
|
||||||
|
model: conversationModel
|
||||||
|
delegate: Newsitem{}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: conversationModel}
|
||||||
|
|
||||||
|
WorkerScript {
|
||||||
|
id: conversationWorker
|
||||||
|
source: "qrc:/js/newsworker.js"
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
id: closeButton
|
||||||
|
width:10*mm
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 1*mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin: 1*mm
|
||||||
|
text: qsTr("Close")
|
||||||
|
onClicked: {
|
||||||
|
newstab.newstabstatus=login.newsViewType;
|
||||||
|
newsStack.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
var currentTime= new Date();
|
||||||
|
var msg = {'currentTime': currentTime, 'model': conversationModel,'news':news};
|
||||||
|
conversationWorker.sendMessage(msg)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,199 @@
|
||||||
|
// message.qml
|
||||||
|
// message with buttons
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQml 2.2
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Flickable{
|
||||||
|
width:root.width-5*mm
|
||||||
|
height:root.height-12*mm
|
||||||
|
contentHeight: messageColumn.height
|
||||||
|
boundsBehavior: Flickable.StopAtBounds
|
||||||
|
id:messageSend
|
||||||
|
//property var login
|
||||||
|
property string parentId: ""
|
||||||
|
property string reply_to_user:""
|
||||||
|
property string attachImageURL: "";
|
||||||
|
property int directmessage: 0;
|
||||||
|
property var contacts: []
|
||||||
|
property var groups: []
|
||||||
|
property var contact_allow:login.permissions[0]
|
||||||
|
property var contact_deny:login.permissions[1]
|
||||||
|
property var group_allow:login.permissions[2]
|
||||||
|
property var group_deny:login.permissions[3]
|
||||||
|
|
||||||
|
function statusUpdate(title,status,in_reply_to_status_id,attachImageURL) {
|
||||||
|
xhr.url= login.server + "/api/statuses/update.xml";
|
||||||
|
xhr.setLogin(login.username+":"+Qt.atob(login.password));
|
||||||
|
xhr.clearParams();
|
||||||
|
xhr.setParam("source", "Friendiqa");
|
||||||
|
xhr.setParam("status", status);
|
||||||
|
if (parentId!="") {xhr.setParam("in_reply_to_status_id", parentId)};
|
||||||
|
if (title!=="") {xhr.setParam("title", title)};
|
||||||
|
if (group_allow.length>0) {xhr.setParam("group_allow", Helperjs.cleanArray(group_allow))};
|
||||||
|
if (group_deny.length>0) {xhr.setParam("group_deny", Helperjs.cleanArray(group_deny))};
|
||||||
|
if (contact_allow.length>0) {xhr.setParam("contact_allow", Helperjs.cleanArray(contact_allow))};
|
||||||
|
if (contact_deny.length>0) {xhr.setParam("contact_deny", Helperjs.cleanArray(contact_deny))};
|
||||||
|
if (attachImageURL!=="") {xhr.setImageFileParam("media", attachImageURL )};
|
||||||
|
xhr.post();
|
||||||
|
}
|
||||||
|
|
||||||
|
function dmUpdate(title,text,replyto,screen_name,attachImageURL) {
|
||||||
|
xhr.url= login.server + "/api/direct_messages/new.xml";
|
||||||
|
xhr.setLogin(login.username+":"+Qt.atob(login.password));
|
||||||
|
xhr.clearParams();
|
||||||
|
xhr.setParam("text", text);
|
||||||
|
xhr.setParam("screen_name", screen_name);
|
||||||
|
if (parentId!="") {xhr.setParam("replyto", replyto)};
|
||||||
|
if (title!=="") {xhr.setParam("title", title)};
|
||||||
|
xhr.post();
|
||||||
|
}
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id:messageColumn
|
||||||
|
spacing: 2
|
||||||
|
width: parent.width
|
||||||
|
TextField {
|
||||||
|
id: titleField
|
||||||
|
width: parent.width
|
||||||
|
placeholderText: qsTr("Title (optional)")
|
||||||
|
visible: messageSend.parentId === ""
|
||||||
|
}
|
||||||
|
|
||||||
|
TextArea {
|
||||||
|
id: bodyField
|
||||||
|
width: parent.width
|
||||||
|
height: 30*mm
|
||||||
|
wrapMode: TextEdit.Wrap
|
||||||
|
textFormat: TextEdit.PlainText
|
||||||
|
}
|
||||||
|
|
||||||
|
Row{
|
||||||
|
spacing: 2
|
||||||
|
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:qsTr("Url")
|
||||||
|
onClicked: {
|
||||||
|
if(bodyField.selectedText==""){Helperjs.showMessage("Error","No text selected",messageSend)}
|
||||||
|
else{urlTextEdit.text="";
|
||||||
|
urlRectangle.visible=true}}
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
id:urlRectangle
|
||||||
|
height:parent.height
|
||||||
|
width:37*mm
|
||||||
|
visible:false
|
||||||
|
TextField{
|
||||||
|
id:urlTextEdit
|
||||||
|
width:30*mm
|
||||||
|
height:parent.height
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
anchors.left:urlTextEdit.right
|
||||||
|
anchors.leftMargin:mm
|
||||||
|
text:qsTr("\u2713")
|
||||||
|
onClicked: {if(urlTextEdit.text!=""){
|
||||||
|
var start = bodyField.selectionStart;
|
||||||
|
var end = bodyField.selectionEnd;
|
||||||
|
var text = bodyField.getText(start,end);
|
||||||
|
text = "[url="+urlTextEdit.text+"]" + text + "[/url]";
|
||||||
|
bodyField.remove(start,end);
|
||||||
|
bodyField.insert(start,text);}
|
||||||
|
urlRectangle.visible=false}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Row{
|
||||||
|
spacing:2
|
||||||
|
BlueButton{
|
||||||
|
visible: (directmessage==1)?false:true
|
||||||
|
text:qsTr("Permissions")
|
||||||
|
onClicked: {
|
||||||
|
var component = Qt.createComponent("qrc:/qml/newsqml/PermissionDialog.qml");
|
||||||
|
var permissions = component.createObject(messageColumn);
|
||||||
|
}}
|
||||||
|
BlueButton {
|
||||||
|
id: attachButton
|
||||||
|
text: qsTr("Attach")
|
||||||
|
visible:(directmessage==0)
|
||||||
|
onClicked: {
|
||||||
|
if (attachImageURL!=""){
|
||||||
|
Helperjs.showMessage( qsTr("Error"),qsTr("Only one attachment. Remove other attachment first!"), messageColumn)}
|
||||||
|
else{
|
||||||
|
try{imageAttachmentObject.destroy()}catch(e){print(e)}
|
||||||
|
imageAttachmentDialog.open()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
id:contactButton
|
||||||
|
text:qsTr("cc")
|
||||||
|
visible:(directmessage==0)
|
||||||
|
onClicked:{
|
||||||
|
var contactitems="";
|
||||||
|
for (var i=0;i<contacts.length;i++){
|
||||||
|
contactitems=contactitems+"MenuItem{text:'"+contacts[i].screen_name+"'; onTriggered: bodyField.insert(0,' @"+contacts[i].screen_name+" ')}"
|
||||||
|
}
|
||||||
|
var menuString="import QtQuick.Controls 1.4; Menu {"+contactitems+"}";
|
||||||
|
var contactlistObject=Qt.createQmlObject(menuString,messageSend,"contactmenuOutput")
|
||||||
|
contactlistObject.popup() }
|
||||||
|
}
|
||||||
|
BlueButton {
|
||||||
|
id: cancelButton
|
||||||
|
text: qsTr("Cancel")
|
||||||
|
onClicked: {newstab.newstabstatus=login.newsViewType;
|
||||||
|
|
||||||
|
newsStack.pop()}
|
||||||
|
}
|
||||||
|
BlueButton {
|
||||||
|
id: sendButton
|
||||||
|
text: qsTr("Send")
|
||||||
|
onClicked: {
|
||||||
|
//print("login: "+login.server+login.username);
|
||||||
|
var title=titleField.text.replace("\"","\'");
|
||||||
|
var body=bodyField.getText(0,bodyField.length);
|
||||||
|
if (directmessage==0){
|
||||||
|
statusUpdate(title,body,messageSend.parentId,attachImageURL.toString())}
|
||||||
|
else {dmUpdate(title,body,"",messageSend.reply_to_user) }
|
||||||
|
newsStack.pop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FileDialog {
|
||||||
|
id: imageAttachmentDialog
|
||||||
|
title: "Please choose a picture"
|
||||||
|
folder: shortcuts.pictures
|
||||||
|
nameFilters: [ "Image files (*.jpg *.png)", "All files (*)" ]
|
||||||
|
selectedNameFilter:"Image files (*.jpg *.png)"
|
||||||
|
selectFolder: false
|
||||||
|
onAccepted: {
|
||||||
|
if( attachImageURL==""){attachImageURL=imageAttachmentDialog.fileUrl;
|
||||||
|
var imageAttachmentObject=Qt.createQmlObject('import QtQuick 2.0; Image {id:imageAttachment; source:"'+
|
||||||
|
attachImageURL.toString()+'"; width: 15*mm; height: 15*mm;fillMode: Image.PreserveAspectFit;MouseArea{anchors.fill:parent;onClicked:{attachImageURL="";imageAttachment.destroy()}}}',messageColumn,"attachedImage");
|
||||||
|
console.log("You chose: " + attachImageURL)}
|
||||||
|
else{attachImageURL=imageAttachmentDialog.fileUrl;}
|
||||||
|
|
||||||
|
}
|
||||||
|
onRejected: {
|
||||||
|
//console.log("Canceled")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,232 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
//import QtQuick.LocalStorage 2.0 as Sql
|
||||||
|
import "qrc:/qml"
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
import "qrc:/js/news.js" as Newsjs
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Connections{
|
||||||
|
target:newstab
|
||||||
|
onNewstabstatusChanged:{
|
||||||
|
newstabstatusButton.text= qsTr(newstab.newstabstatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Connections{
|
||||||
|
target:newstab
|
||||||
|
onConversationChanged:{
|
||||||
|
newsBusy.running=false;
|
||||||
|
newstab.newstabstatus="Conversation";
|
||||||
|
newsStack.push({item:"qrc:/qml/newsqml/Conversation.qml",properties:{"news": conversation}})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Connections{
|
||||||
|
target:root
|
||||||
|
onCurrentContactChanged:{
|
||||||
|
if (root.newContacts.length>0){
|
||||||
|
print(Qt.atob(root.newContacts[root.currentContact].name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function showNews(newsToShow){
|
||||||
|
if (newsStack.depth>1){newsStack.pop()}
|
||||||
|
newsBusy.running=false;
|
||||||
|
var currentTime= new Date();
|
||||||
|
var msg = {'currentTime': currentTime, 'model': newsModel,'news':newsToShow};
|
||||||
|
newsWorker.sendMessage(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFriendsMessages(friend){
|
||||||
|
newstab.newstabstatus="Contact";
|
||||||
|
Newsjs.newsfromdb(db,root.login.username, function(dbnews){showNews(dbnews)},friend)
|
||||||
|
}
|
||||||
|
|
||||||
|
function onDirectMessage(friend){
|
||||||
|
newstab.newstabstatus="SendMessage"
|
||||||
|
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"reply_to_user": friend,"directmessage":1,"login":root.login}});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
StackView{
|
||||||
|
id: newsStack
|
||||||
|
anchors.fill:parent
|
||||||
|
|
||||||
|
initialItem:Rectangle {
|
||||||
|
y:1
|
||||||
|
color: "white"
|
||||||
|
width:root.width-2*mm
|
||||||
|
height:root.height-8*mm
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id:newstabstatusButton
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 0.5*mm
|
||||||
|
text: qsTr(newstab.newstabstatus)
|
||||||
|
onClicked: {newstabmenu.popup()}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row{
|
||||||
|
spacing: mm
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 0.5*mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
id: newMessageButton
|
||||||
|
width:10*mm
|
||||||
|
text: qsTr("+")
|
||||||
|
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({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"contacts": friends,"login":root.login}})
|
||||||
|
},"isFriend",1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlueButton {
|
||||||
|
id: quitButton
|
||||||
|
width:10*mm
|
||||||
|
text: qsTr("Quit")
|
||||||
|
onClicked: {Service.cleanNews(root.db,function(){Qt.quit() })}
|
||||||
|
}
|
||||||
|
BlueButton {
|
||||||
|
id: update
|
||||||
|
text: "Update"
|
||||||
|
onClicked: {
|
||||||
|
newsBusy.running=true;
|
||||||
|
newstab.newstabstatus=login.newsViewType;
|
||||||
|
root.contactLoadType="news";
|
||||||
|
var onlynew=true;
|
||||||
|
Newsjs.getFriendsTimeline(login,db,contactlist,onlynew,newstab,function(ns,nc){
|
||||||
|
root.news=ns;root.newContacts=nc;root.currentContact=0;
|
||||||
|
if (ns.length==0){// update last 20 existing news for changes and likes
|
||||||
|
onlynew=false;
|
||||||
|
Newsjs.getFriendsTimeline(login,db,contactlist,onlynew,newstab,function(rns,rnc){
|
||||||
|
root.contactLoadType="news";
|
||||||
|
root.news=rns;root.newContacts=rnc;root.currentContact=0})
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Component { id:footerComponent
|
||||||
|
Rectangle{
|
||||||
|
border.color: "#EEEEEE"
|
||||||
|
border.width: 1
|
||||||
|
width:parent.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();
|
||||||
|
if(newstab.newstabstatus=="Timeline"){
|
||||||
|
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
|
||||||
|
Newsjs.newsfromdb(root.db,root.login.username, function(news){
|
||||||
|
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
|
||||||
|
newsWorker.sendMessage(msg);
|
||||||
|
},false,lastnews_id)}
|
||||||
|
if(newstab.newstabstatus=="Tree"){
|
||||||
|
var lastnews_id=newsModel.get(newsModel.count-1).newsitemobject.created_at;
|
||||||
|
Newsjs.chatsfromdb(root.db,root.login.username, function(news){
|
||||||
|
var msg = {'currentTime': currentTime, 'model': newsModel,'news':news,'appendnews':true};
|
||||||
|
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,newsModel.get(newsModel.count-1).newsitemobject.created_at)}
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
id: newsView
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.topMargin: 8*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{}
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id:newstabmenu
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Timeline")
|
||||||
|
onTriggered: {
|
||||||
|
newstab.newstabstatus="Timeline";
|
||||||
|
newsModel.clear();
|
||||||
|
Newsjs.newsfromdb(root.db,root.login.username, function(dbnews){
|
||||||
|
showNews(dbnews)
|
||||||
|
})}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Favorites")
|
||||||
|
onTriggered:{
|
||||||
|
newstab.newstabstatus="Favorites";
|
||||||
|
root.contactLoadType="favorites";
|
||||||
|
newsBusy.running=true;
|
||||||
|
Newsjs.requestFavorites(root.login,db,root.contactlist,root,function(ns,nc){
|
||||||
|
root.news=ns; root.newContacts=nc;root.currentContact=0;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Tree")
|
||||||
|
onTriggered:{
|
||||||
|
newsModel.clear();
|
||||||
|
newstab.newstabstatus="Tree";
|
||||||
|
Newsjs.chatsfromdb(db,root.login.username,function(news){showNews(news)})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Notifications")
|
||||||
|
onTriggered:{
|
||||||
|
newstab.newstabstatus="Notifications";
|
||||||
|
newsBusy.running=true;
|
||||||
|
Newsjs.getNotifications(root.login,db,root,function(news){
|
||||||
|
showNews(news)}
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.messageSignal.connect(onFriendsMessages);
|
||||||
|
root.directmessageSignal.connect(onDirectMessage);
|
||||||
|
root.newsSignal.connect(showNews);
|
||||||
|
try{newsModel.clear()} catch(e){}
|
||||||
|
if(login.newsViewType=="Timeline"){Newsjs.newsfromdb(db,login.username,function(dbnews){showNews(dbnews)})}
|
||||||
|
else{Newsjs.chatsfromdb(db,login.username,function(dbnews){showNews(dbnews)})}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,343 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.LocalStorage 2.0
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQuick.Controls.Styles 1.4
|
||||||
|
import "qrc:/js/news.js" as Newsjs
|
||||||
|
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: newsitem
|
||||||
|
width: newsView.width
|
||||||
|
height:Math.max((itemMessage.height+topFlow.height+friendicaActivities.height+4*mm),profileImage.height+user_name.height+mm)
|
||||||
|
|
||||||
|
property string conversation_id: ""
|
||||||
|
property string attending: ""
|
||||||
|
onAttendingChanged: {attendLabel.visible=true;
|
||||||
|
attendLabel.text= qsTr("attending: ")+ qsTr(attending)}
|
||||||
|
signal replyto(string parent_id)
|
||||||
|
function showConversation(){
|
||||||
|
conversationsymbol.color="black";
|
||||||
|
newsBusy.running=true;
|
||||||
|
root.contactLoadType="conversation";
|
||||||
|
//newstabstatus="Conversation";
|
||||||
|
|
||||||
|
if(newsitemobject.messagetype==0){
|
||||||
|
Newsjs.requestConversation(root.login,db,newsitemobject.status_id,root.contactlist,root,function(ns,nc){
|
||||||
|
root.news=ns;root.newContacts=nc;root.currentContact=0;
|
||||||
|
})}
|
||||||
|
else{Newsjs.conversationfromdb(root.db,root.login.username,newsitemobject.statusnet_conversation_id, function(newsarray){
|
||||||
|
root.news=newsarray;root.newContacts=[];root.currentContact=1;
|
||||||
|
})}}
|
||||||
|
|
||||||
|
Rectangle{width:newsitem.width; height: 1; anchors.bottom: newsitem.bottom; color:"light grey"}
|
||||||
|
//MouseArea{
|
||||||
|
// anchors.fill: parent;
|
||||||
|
// enabled: (newstabstatus=="Chats")
|
||||||
|
// onClicked: {showConversation()}
|
||||||
|
//}
|
||||||
|
Rectangle{
|
||||||
|
width:newsitem.width
|
||||||
|
height:newsitem.height-1
|
||||||
|
color: (newsitemobject.messagetype==1)?"#ffe6e6" : "white"
|
||||||
|
|
||||||
|
Column {
|
||||||
|
id: authorcolumn
|
||||||
|
width: 8*mm
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id:profileImage
|
||||||
|
source: (newsitemobject.user.profile_image!="")? "file://"+newsitemobject.user.profile_image : newsitemobject.user.profile_image_url
|
||||||
|
x:1
|
||||||
|
width: 7*mm
|
||||||
|
height: 7*mm
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill: parent
|
||||||
|
onPressAndHold: { newsmenu.popup()}
|
||||||
|
}
|
||||||
|
onStatusChanged: if (profileImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id:user_name
|
||||||
|
color: "grey"
|
||||||
|
//height:3.5*mm
|
||||||
|
width:parent.width
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
wrapMode: Text.WrapAtWordBoundaryOrAnywhere
|
||||||
|
text: Qt.atob(newsitemobject.user.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Column {
|
||||||
|
id:newscolumn
|
||||||
|
width: newsitem.width-8*mm
|
||||||
|
anchors.left: authorcolumn.right
|
||||||
|
|
||||||
|
Flow{
|
||||||
|
id:topFlow
|
||||||
|
spacing: mm
|
||||||
|
width:parent.width
|
||||||
|
Label {
|
||||||
|
id:messageTypeLabel
|
||||||
|
color: "grey"
|
||||||
|
text: if (newsitemobject.messagetype==0){qsTr("Source: ")+newsitemobject.source
|
||||||
|
} else if (newsitemobject.messagetype==1){ qsTr("Direct Message")} else {" Notification"}
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id:createdAtLabel
|
||||||
|
color: "grey"
|
||||||
|
//height:3.5*mm
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
horizontalAlignment: Label.AlignRight
|
||||||
|
text: dateDiff
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id:replytoLabel
|
||||||
|
color: "grey"
|
||||||
|
//height:3.5*mm
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
horizontalAlignment: Label.AlignRight
|
||||||
|
text: try {qsTr("In reply to ")+newsitemobject.reply_user.screen_name
|
||||||
|
}catch(e){" "}
|
||||||
|
}
|
||||||
|
|
||||||
|
Label {
|
||||||
|
id:newscountLabel
|
||||||
|
visible:((newstabstatus=="Tree")&&(newsitemobject.newscount>1))?true:false
|
||||||
|
color: "grey"
|
||||||
|
height:3.5*mm
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
font.bold: true
|
||||||
|
horizontalAlignment: Label.AlignRight
|
||||||
|
text: try {(newsitemobject.newscount-1)+qsTr(" comments") }catch(e){" "}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill:parent
|
||||||
|
onClicked: showConversation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Text {
|
||||||
|
color: "#404040"
|
||||||
|
linkColor: "light green"
|
||||||
|
id: itemMessage
|
||||||
|
textFormat: Text.RichText
|
||||||
|
text: Qt.atob(newsitemobject.statusnet_html)
|
||||||
|
width: newsitem.width-8*mm-2
|
||||||
|
height: implicitHeight
|
||||||
|
wrapMode: Text.Wrap
|
||||||
|
onLinkActivated:{
|
||||||
|
Qt.openUrlExternally(link)}
|
||||||
|
}
|
||||||
|
|
||||||
|
Row{id:friendicaActivities
|
||||||
|
spacing:mm
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.likeText
|
||||||
|
}
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.dislikeText
|
||||||
|
}
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.attendyesText
|
||||||
|
}
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.attendnoText
|
||||||
|
}
|
||||||
|
Label{color: "grey"
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
text: friendica_activities.attendmaybeText
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Row {
|
||||||
|
CheckBox{id:likeCheckbox
|
||||||
|
height:3*mm
|
||||||
|
width:8*mm
|
||||||
|
visible: (newsitemobject.messagetype==0)? true:false
|
||||||
|
checked:(friendica_activities.self.liked==1)?true:false
|
||||||
|
style: CheckBoxStyle {
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 7*mm
|
||||||
|
implicitHeight: 3*mm
|
||||||
|
color:"white"
|
||||||
|
}
|
||||||
|
indicator:
|
||||||
|
Rectangle{
|
||||||
|
implicitWidth: 3*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
color:control.checked?"yellow":"white"
|
||||||
|
x: 5*mm
|
||||||
|
Text{
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
color:"grey"
|
||||||
|
text:":-)"
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
if(likeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"like",newsitemobject.status_id,root);dislikeCheckbox.checked=false; model.friendica_activities.self.liked=0 }
|
||||||
|
else{Newsjs.like(root.login,root.db,0,"like",newsitemobject.status_id,root); model.friendica_activities.self.liked=1}}
|
||||||
|
}
|
||||||
|
CheckBox{id: dislikeCheckbox
|
||||||
|
height:3*mm
|
||||||
|
width:8*mm
|
||||||
|
visible: (newsitemobject.messagetype==0)? true:false
|
||||||
|
checked: (friendica_activities.self.disliked==1)?true:false
|
||||||
|
style: CheckBoxStyle {
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 7*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
color:"white"
|
||||||
|
}
|
||||||
|
indicator:
|
||||||
|
Rectangle{
|
||||||
|
implicitWidth: 3*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
color:control.checked?"yellow":"white"
|
||||||
|
x:5*mm
|
||||||
|
Text{
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
color:"grey"
|
||||||
|
text:":-("
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
onClicked: {
|
||||||
|
if (dislikeCheckbox.checked==true){Newsjs.like(root.login,root.db,1,"dislike",newsitemobject.status_id,root);likeCheckbox.checked=false; model.friendica_activities.self.disliked=0}
|
||||||
|
else {Newsjs.like(root.login,root.db,0,"dislike",newsitemobject.status_id,root); model.friendica_activities.self.disliked=1}}
|
||||||
|
}
|
||||||
|
CheckBox {
|
||||||
|
id:favoritedCheckbox
|
||||||
|
visible:(newsitemobject.messagetype==0)
|
||||||
|
style: CheckBoxStyle {
|
||||||
|
background: Rectangle {
|
||||||
|
implicitWidth: 6*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
color:"transparent"
|
||||||
|
}
|
||||||
|
indicator:
|
||||||
|
Rectangle{x:3*mm
|
||||||
|
width: 3*mm
|
||||||
|
implicitHeight:3*mm
|
||||||
|
Text{
|
||||||
|
anchors.centerIn: parent
|
||||||
|
color:control.checked?"black":"grey"
|
||||||
|
text:"\u2605"
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
checked:(newsitemobject.favorited>0)
|
||||||
|
onClicked:{
|
||||||
|
if(favoritedCheckbox.checkedState==Qt.Checked)
|
||||||
|
{Newsjs.favorite(login,true,newsitemobject.status_id,root); model.newsitemobject.favorited=1}
|
||||||
|
else if(favoritedCheckbox.checkedState==Qt.Unchecked)
|
||||||
|
{Newsjs.favorite(login,false,newsitemobject.status_id,root);model.newsitemobject.favorited=0}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
width: 4*mm
|
||||||
|
height: 3*mm
|
||||||
|
color:"transparent"
|
||||||
|
Text{
|
||||||
|
id:newsmenusymbol
|
||||||
|
color: "grey"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
font.bold: true
|
||||||
|
text: "\u22EE"
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill:parent
|
||||||
|
onClicked: {newsmenu.popup()}}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
width: 4*mm
|
||||||
|
height: 3*mm
|
||||||
|
color:"transparent"
|
||||||
|
//visible:(newsitemobject.in_reply_to_status_id!="")?true:false
|
||||||
|
Text{
|
||||||
|
id:conversationsymbol
|
||||||
|
color: "grey"
|
||||||
|
anchors.centerIn: parent
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
text: "\u21C4"
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill:parent
|
||||||
|
onClicked: showConversation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Label {
|
||||||
|
id:attendLabel
|
||||||
|
visible: false
|
||||||
|
color: "grey"
|
||||||
|
height:3.5*mm
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
horizontalAlignment: Label.AlignRight
|
||||||
|
text: (friendica_activities.self.attending)?qsTr("attending: ")+ qsTr(attending):""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu {
|
||||||
|
id:newsmenu
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Reply")
|
||||||
|
onTriggered: {
|
||||||
|
var directmessage=0;
|
||||||
|
if (newsitemobject.messagetype==1){ directmessage=1}
|
||||||
|
newsStack.push({item:"qrc:/qml/newsqml/MessageSend.qml",properties:{"reply_to_user": newsitemobject.user.screen_name,"parentId":newsitemobject.status_id,"login":root.login,"directmessage":directmessage}});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("DM")
|
||||||
|
onTriggered: {
|
||||||
|
root.directmessageSignal(newsitemobject.user.screen_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Repost")
|
||||||
|
onTriggered: {
|
||||||
|
Newsjs.retweetNews(root.login,db,newsitemobject.status_id,root,function(reply){
|
||||||
|
print(reply);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Conversation")
|
||||||
|
onTriggered: showConversation()
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu{
|
||||||
|
title: qsTr("Attending")
|
||||||
|
MenuItem{text:qsTr("yes")
|
||||||
|
onTriggered: {Newsjs.attend(root.login,db,"yes",newsitemobject.status_id,root,function(){
|
||||||
|
newsitem.attending="yes";
|
||||||
|
attendLabel.visible=true})}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem{text:qsTr("maybe")
|
||||||
|
onTriggered: {Newsjs.attend(root.login,db,"maybe",newsitemobject.status_id,root,function(){
|
||||||
|
newsitem.attending="maybe"})}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem{text:qsTr("no")
|
||||||
|
onTriggered: {Newsjs.attend(root.login,db,"no",newsitemobject.status_id,root,function(){
|
||||||
|
newsitem.attending="no"})}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Delete")
|
||||||
|
onTriggered: {
|
||||||
|
Newsjs.deleteNews(root.login,root.db,newsitemobject.status_id,newsitemobject.messagetype,root,function(reply){
|
||||||
|
newsModel.remove(index);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,191 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQml.Models 2.1
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
id:permissionDialog
|
||||||
|
x: mm
|
||||||
|
width: messageColumn.width-5*mm
|
||||||
|
height:root.height/3
|
||||||
|
function updatePerms(){
|
||||||
|
for (var i=0;i<groupModel.count;i++)
|
||||||
|
{if (groupModel.get(i).groupstatus=="positive"){
|
||||||
|
group_allow.push(groupModel.get(i).group.gid)
|
||||||
|
}
|
||||||
|
if (groupModel.get(i).groupstatus=="negative"){
|
||||||
|
group_deny.push(groupModel.get(i).group.gid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var j=0;j<contactModel.count;j++)
|
||||||
|
{//print("contact: "+JSON.stringify(contactModel.get(j).contact));
|
||||||
|
if (contactModel.get(j).contactstatus=="positive"){
|
||||||
|
print(JSON.stringify(contact_allow));
|
||||||
|
contact_allow.push(contactModel.get(j).contact.cid)
|
||||||
|
}
|
||||||
|
if (contactModel.get(j).contactstatus=="negative"){
|
||||||
|
contact_deny.push(contactModel.get(j).contact.cid)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
|
||||||
|
Text{
|
||||||
|
x:0.5*mm
|
||||||
|
y:0.5*mm
|
||||||
|
text: "Contacts"
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
id: contactView
|
||||||
|
x:0.5*mm
|
||||||
|
y:5.5*mm
|
||||||
|
width: permissionDialog.width/2-2*mm
|
||||||
|
height: permissionDialog.height-14*mm
|
||||||
|
clip: true
|
||||||
|
spacing: 1
|
||||||
|
model: contactModel
|
||||||
|
delegate: contactItem
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: contactModel}
|
||||||
|
Component{
|
||||||
|
id:contactItem
|
||||||
|
Rectangle{
|
||||||
|
id:contactitemRect
|
||||||
|
width:contactView.width
|
||||||
|
height: 5*mm
|
||||||
|
property string contactstatus
|
||||||
|
onContactstatusChanged:{
|
||||||
|
if(contactstatus=="positive"){contactitemRect.color="light green"}
|
||||||
|
else if (contactstatus=="negative"){contactitemRect.color= "red"}
|
||||||
|
else{contactitemRect.color= "white"}}
|
||||||
|
color: "white"
|
||||||
|
border.color:"grey"
|
||||||
|
Text{
|
||||||
|
color:"grey"
|
||||||
|
text:contact.screen_name
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked:{
|
||||||
|
if(contactModel.get(index).contactstatus=="neutral"){
|
||||||
|
contactModel.set(index,{"contactstatus":"positive"});
|
||||||
|
contactstatus="positive"
|
||||||
|
}
|
||||||
|
else if (contactModel.get(index).contactstatus=="positive"){
|
||||||
|
contactModel.set(index,{"contactstatus":"negative"})
|
||||||
|
contactstatus="negative"
|
||||||
|
}
|
||||||
|
else{contactModel.set(index,{"contactstatus":"neutral"});
|
||||||
|
contactstatus="neutral";
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
Component.onCompleted:{
|
||||||
|
if (contactModel.get(index).contactstatus=="positive"){
|
||||||
|
contactstatus="positive"
|
||||||
|
}
|
||||||
|
else if (contactModel.get(index).contactstatus=="negative"){
|
||||||
|
contactstatus="negative"
|
||||||
|
}
|
||||||
|
else {contactstatus="neutral"} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text{
|
||||||
|
x:contactView.width+2*mm
|
||||||
|
y:0.5*mm
|
||||||
|
text: "Groups"
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
id: groupView
|
||||||
|
x:contactView.width+2*mm
|
||||||
|
y:5.5*mm
|
||||||
|
width: permissionDialog.width/2-2*mm
|
||||||
|
height: permissionDialog.height-14*mm
|
||||||
|
clip: true
|
||||||
|
spacing: 1
|
||||||
|
model: groupModel
|
||||||
|
delegate: groupItem
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{id: groupModel}
|
||||||
|
Component{
|
||||||
|
id:groupItem
|
||||||
|
Rectangle{
|
||||||
|
id:groupitemRect
|
||||||
|
width:groupView.width
|
||||||
|
height: 5*mm
|
||||||
|
property string groupstatus:"neutral"
|
||||||
|
onGroupstatusChanged:
|
||||||
|
{if(groupstatus=="positive"){groupitemRect.color="light green"}
|
||||||
|
else if (groupstatus=="negative"){groupitemRect.color= "red"}
|
||||||
|
else{groupitemRect.color= "white"}}
|
||||||
|
color: "white"
|
||||||
|
border.color:"grey"
|
||||||
|
Text{
|
||||||
|
color:"grey"
|
||||||
|
text:group.groupname
|
||||||
|
}
|
||||||
|
MouseArea{
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked:{
|
||||||
|
if(groupModel.get(index).groupstatus=="neutral"){
|
||||||
|
groupModel.set(index,{"groupstatus":"positive"});
|
||||||
|
groupstatus="positive"}
|
||||||
|
else if (groupModel.get(index).groupstatus=="positive"){
|
||||||
|
groupModel.set(index,{"groupstatus":"negative"});
|
||||||
|
groupstatus="negative"}
|
||||||
|
else{groupModel.set(index,{"groupstatus":"neutral"})
|
||||||
|
groupstatus="neutral"}
|
||||||
|
}}
|
||||||
|
Component.onCompleted:{ if (groupModel.get(index).groupstatus=="positive"){
|
||||||
|
groupstatus="positive"
|
||||||
|
}
|
||||||
|
else if (groupModel.get(index).groupstatus=="negative"){
|
||||||
|
groupstatus="negative"
|
||||||
|
}
|
||||||
|
else {groupstatus="neutral"} }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
x:0.5*mm
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin:1
|
||||||
|
text:qsTr("Save")
|
||||||
|
onClicked:{
|
||||||
|
updatePerms();
|
||||||
|
var perms=[];
|
||||||
|
perms.push(contact_allow,contact_deny,group_allow,group_deny); Service.savePermissions(db,perms)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BlueButton{
|
||||||
|
x:contactView.width+2*mm
|
||||||
|
anchors.bottom: parent.bottom
|
||||||
|
anchors.bottomMargin:1
|
||||||
|
text:qsTr("Done")
|
||||||
|
onClicked:{//var group_allow=[];var group_deny=[];
|
||||||
|
|
||||||
|
//print("contacts: "+Helperjs.cleanArray(contact_allow))
|
||||||
|
permissionDialog.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted:{
|
||||||
|
|
||||||
|
Helperjs.readData(db,"contacts",login.username,function(contacts){
|
||||||
|
for (var name in contacts){
|
||||||
|
var contactstatus="neutral";
|
||||||
|
if (contact_allow.indexOf(contacts[name].cid)>-1){contactstatus="positive";print(contacts[name].cid+" pos")}
|
||||||
|
else if (contact_deny.indexOf(contacts[name].cid)>-1){contactstatus="negative"}
|
||||||
|
contactModel.append({"contact":contacts[name],"contactstatus":contactstatus})
|
||||||
|
}},"isFriend",1);
|
||||||
|
|
||||||
|
Helperjs.readData(db,"groups",login.username,function(owngroups){
|
||||||
|
for (var number in owngroups){
|
||||||
|
var groupstatus= "neutral";
|
||||||
|
if (group_allow.indexOf(owngroups[number].gid)>-1){groupstatus="positive"}
|
||||||
|
else if (group_deny.indexOf(owngroups[number].gid)>-1){groupstatus="negative"}
|
||||||
|
groupModel.append({"group":owngroups[number],"groupstatus":groupstatus})
|
||||||
|
}});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
//import QtQuick.LocalStorage 2.0
|
||||||
|
import QtQuick.Controls 1.2
|
||||||
|
|
||||||
|
Package {
|
||||||
|
Item { id: stackItem; Package.name: 'stack'; z: stackItem.PathView.z;width:16.5*mm;height:16.5*mm}
|
||||||
|
Item { id: listItem; Package.name: 'list'; width: root.width-1*mm; height: root.height-8*mm; }
|
||||||
|
Item { id: gridItem; Package.name: 'grid';}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
id: photoWrapper
|
||||||
|
width: 16.5*mm; height: 16.5*mm
|
||||||
|
z: stackItem.PathView.z
|
||||||
|
property string hqphotolink: photoLink
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: placeHolder
|
||||||
|
color: 'lightblue'; antialiasing: true
|
||||||
|
anchors.fill:parent
|
||||||
|
}
|
||||||
|
|
||||||
|
BusyIndicator { anchors.centerIn: parent; running: realImage.status != Image.Ready }
|
||||||
|
Image {
|
||||||
|
id: realImage;
|
||||||
|
// property string hqphotolink: photoLink
|
||||||
|
width: photoWrapper.width; height: photoWrapper.height
|
||||||
|
antialiasing: true;
|
||||||
|
asynchronous: true
|
||||||
|
cache: false
|
||||||
|
fillMode: Image.PreserveAspectFit;
|
||||||
|
source: imageLocation
|
||||||
|
// onStatusChanged: if (realImage.status == Image.Ready) print(realImage.paintedHeight+"x"+realImage.paintedWidth)
|
||||||
|
}
|
||||||
|
Rectangle{
|
||||||
|
id:phototextRectangle
|
||||||
|
color:"black"
|
||||||
|
z:3
|
||||||
|
opacity: 0.5
|
||||||
|
width:phototext.contentWidth
|
||||||
|
height: phototext.contentHeight
|
||||||
|
anchors.bottom: photoWrapper.bottom
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id:phototext
|
||||||
|
z:4
|
||||||
|
text: photoDescription.trim()
|
||||||
|
width:15*mm
|
||||||
|
anchors.bottom: photoWrapper.bottom
|
||||||
|
color: "white"
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
wrapMode:Text.Wrap
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
width: realImage.paintedWidth; height: realImage.paintedHeight; anchors.centerIn: realImage
|
||||||
|
onClicked: {
|
||||||
|
if (albumWrapper.state == 'inGrid') {
|
||||||
|
gridItem.GridView.view.currentIndex = index;
|
||||||
|
//print("photoLink"+realImage.photoLink)
|
||||||
|
albumWrapper.state = 'fullscreen'
|
||||||
|
} else {
|
||||||
|
gridItem.GridView.view.currentIndex = index;
|
||||||
|
albumWrapper.state = 'inGrid'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: 'stacked'; when: albumWrapper.state == ''
|
||||||
|
ParentChange { target: photoWrapper; parent: stackItem; }//x: 1*mm; y: 1*mm }
|
||||||
|
PropertyChanges { target: photoWrapper; opacity: stackItem.PathView.onPath ? 1.0 : 0.0 }
|
||||||
|
PropertyChanges { target: phototext; opacity: 0.0 }
|
||||||
|
PropertyChanges { target: phototextRectangle; opacity: 0.0 }
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: 'inGrid'; when: albumWrapper.state == 'inGrid'
|
||||||
|
ParentChange { target: photoWrapper; parent: gridItem; x: 1*mm; y: 1*mm;}
|
||||||
|
PropertyChanges { target: phototext; opacity: 1.0 }
|
||||||
|
PropertyChanges { target: phototextRectangle; opacity: 0.5 }
|
||||||
|
PropertyChanges { target: placeHolder; opacity: 1.0 }
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: 'fullscreen'; when: albumWrapper.state == 'fullscreen'
|
||||||
|
ParentChange {
|
||||||
|
target: photoWrapper; parent: listItem; x: 1; y: 1;
|
||||||
|
width: root.width-mm; height: root.height-8*mm
|
||||||
|
}
|
||||||
|
PropertyChanges { target: placeHolder; opacity: 0.0 }
|
||||||
|
PropertyChanges { target: realImage; source: photoWrapper.hqphotolink}
|
||||||
|
PropertyChanges { target: phototext; anchors.bottom: realImage.bottom}
|
||||||
|
PropertyChanges { target: phototext; width:realImage.width }
|
||||||
|
PropertyChanges { target: phototextRectangle; anchors.bottom: realImage.bottom }
|
||||||
|
PropertyChanges { target: realImage; width: Math.min(listItem.width,sourceSize.width);height: Math.min(listItem.height,sourceSize.height) }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,181 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.Dialogs 1.2
|
||||||
|
import QtQuick.Controls 1.4
|
||||||
|
import QtQml.Models 2.1
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
import "qrc:/qml/photoqml"
|
||||||
|
import "qrc:/qml/genericqml"
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id:fotorectangle
|
||||||
|
property string phototabstatus:"Images"
|
||||||
|
onPhototabstatusChanged:{phototabstatusButton.text=qsTr(phototabstatus)}
|
||||||
|
|
||||||
|
y:1
|
||||||
|
width:root.width-mm
|
||||||
|
height:root.height-5*mm
|
||||||
|
color: '#fff'
|
||||||
|
property var newimages:[]
|
||||||
|
property int currentimageno: 0
|
||||||
|
//onLoginChanged:{var msg = {'model': photogroupModel,'albums':[],'firstalbum':0,'foreignPicture':false};
|
||||||
|
// photoWorker.sendMessage(msg);
|
||||||
|
//}
|
||||||
|
onNewimagesChanged:{
|
||||||
|
if(newimages.length>0){
|
||||||
|
Helperjs.readField("album",root.db,"imageData",root.login.username,function(albums){
|
||||||
|
//print("albums"+JSON.stringify(albums)+JSON.stringify(newimages[currentimageno]));
|
||||||
|
for (var i=0;i<newimages.length;i++){
|
||||||
|
if(albums.indexOf(newimages[i].album)==-1){
|
||||||
|
filesystem.Directory=root.login.imagestore+"/albums";
|
||||||
|
filesystem.makeDir(newimages[i].album)}}
|
||||||
|
})
|
||||||
|
//print("Current image number"+currentImageNo)
|
||||||
|
Service.dataRequest(root.login,newimages[currentimageno].id,root.db,fotostab);
|
||||||
|
newImagesProgress.visible=true //download first image
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onCurrentimagenoChanged:{
|
||||||
|
if(currentimageno<newimages.length){Service.dataRequest(root.login,newimages[currentimageno].id,root.db,fotostab)};
|
||||||
|
if(currentimageno==newimages.length){newImagesProgress.visible=false;showOwnFotos();
|
||||||
|
newimages=[];currentimageno=0}
|
||||||
|
// download next image if photoplaceholder is finished saving
|
||||||
|
}
|
||||||
|
|
||||||
|
function showOwnFotos(){
|
||||||
|
try {photogroupModel.clear()}catch (e){print(e)}
|
||||||
|
Helperjs.readField("album",root.db, "imageData",root.login.username,function(albums){
|
||||||
|
if (albums[0]) {
|
||||||
|
var msg = { 'model': photogroupModel,'albums':albums,'firstalbum':0,'foreignPicture': false};
|
||||||
|
photoWorker.sendMessage(msg);
|
||||||
|
};
|
||||||
|
})
|
||||||
|
}
|
||||||
|
Connections{
|
||||||
|
target:root
|
||||||
|
onLoginChanged:{var msg = {'model': photogroupModel,'albums':[],'firstalbum':0,'foreignPicture':false};
|
||||||
|
photoWorker.sendMessage(msg);}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target:xhr
|
||||||
|
onDownloaded:{if(data=="picture"){currentimageno=currentimageno+1}}
|
||||||
|
}
|
||||||
|
|
||||||
|
Connections{
|
||||||
|
target:xhr
|
||||||
|
onError:{if(data=="picture"){print("Error"+data);
|
||||||
|
currentimageno=currentimageno+1}}
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFriendsFotos(friend){
|
||||||
|
fotostab.phototabstatus=friend.screen_name;
|
||||||
|
//print("Friend "+friend.url);
|
||||||
|
try {photogroupModel.clear()}catch (e){print(e)}
|
||||||
|
Service.requestFriendsAlbumPictures(root.login,friend,fotostab,function(albums){
|
||||||
|
var msg = {'model': photogroupModel,'albums':albums,'firstalbum':0,'foreignPicture':true};
|
||||||
|
photoWorker.sendMessage(msg);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ProgressBar{
|
||||||
|
id: newImagesProgress
|
||||||
|
width: 15*mm
|
||||||
|
height: updatePhotolist.height
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.right:updatePhotolist.left
|
||||||
|
anchors.rightMargin:mm
|
||||||
|
visible: false
|
||||||
|
value: currentimageno/newimages.length
|
||||||
|
}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id: updatePhotolist
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 0.5*mm
|
||||||
|
anchors.right:phototabstatusButton.left
|
||||||
|
anchors.rightMargin:mm
|
||||||
|
text: qsTr("Update")
|
||||||
|
onClicked: {
|
||||||
|
Service.requestList(root.login,root.db, fotostab,function(obj){
|
||||||
|
newimages=obj;print("newimages"+JSON.stringify(obj))
|
||||||
|
})}}
|
||||||
|
|
||||||
|
BlueButton{
|
||||||
|
id: phototabstatusButton
|
||||||
|
anchors.top: parent.top
|
||||||
|
anchors.topMargin: 0.5*mm
|
||||||
|
anchors.right: parent.right
|
||||||
|
anchors.rightMargin:2*mm
|
||||||
|
text: qsTr(phototabstatus)
|
||||||
|
onClicked: {phototabmenu.popup()}
|
||||||
|
}
|
||||||
|
Menu {
|
||||||
|
id:phototabmenu
|
||||||
|
MenuItem {
|
||||||
|
text: qsTr("Own Images")
|
||||||
|
onTriggered: {
|
||||||
|
phototabstatus="Images";
|
||||||
|
showOwnFotos()}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DelegateModel{
|
||||||
|
id: visualphotoModel
|
||||||
|
delegate: PhotogroupComponent{}
|
||||||
|
model: photogroupModel
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{
|
||||||
|
id: photogroupModel
|
||||||
|
}
|
||||||
|
|
||||||
|
GridView {
|
||||||
|
id: albumgridview
|
||||||
|
cellWidth: 17*mm
|
||||||
|
cellHeight: 17*mm
|
||||||
|
x: mm;y:8*mm
|
||||||
|
width: parent.width-2*mm; height: parent.height-9*mm
|
||||||
|
clip: true
|
||||||
|
model: visualphotoModel.parts.album
|
||||||
|
footer:
|
||||||
|
Rectangle{
|
||||||
|
border.color: "#EEEEEE"
|
||||||
|
border.width: 1
|
||||||
|
width:12*mm
|
||||||
|
height:6*mm
|
||||||
|
Text{
|
||||||
|
font.pixelSize: 1.5*mm
|
||||||
|
anchors.centerIn: parent
|
||||||
|
text:qsTr("More")
|
||||||
|
}
|
||||||
|
MouseArea{anchors.fill:parent
|
||||||
|
onClicked:{
|
||||||
|
var lastalbum_id=photogroupModel.get(photogroupModel.count-1);
|
||||||
|
if(photogroupModel.get(photogroupModel.count-1).foreignPictures==false){Service.requestFriendsAlbumPictures(friend,fotostab,function(albums){
|
||||||
|
var msg = {'model': photogroupModel,'albums':albums,'firstalbum':lastalbum_id+1,'foreignPicture':true};
|
||||||
|
photoWorker.sendMessage(msg); })}
|
||||||
|
else { Helperjs.readField("album",root.db, "imageData",root.login.username,function(albums){
|
||||||
|
var msg = { 'model': photogroupModel,'albums':albums,'foreignPicture': false,'firstalbum':lastalbum_id+1};
|
||||||
|
photoWorker.sendMessage(msg)})}
|
||||||
|
}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle { id: photoBackground; color: 'light grey'; width: parent.width; height: parent.height; opacity: 0; visible: opacity != 0.0 }
|
||||||
|
|
||||||
|
ListView { anchors.fill: parent; model: visualphotoModel.parts.browser; interactive: false }
|
||||||
|
|
||||||
|
BlueButton {
|
||||||
|
id: backButton
|
||||||
|
text: qsTr("Back")
|
||||||
|
x: parent.width - backButton.width - 3*mm
|
||||||
|
y: -backButton.height - 4*mm
|
||||||
|
onClicked: {photoBackground.opacity=0}
|
||||||
|
}
|
||||||
|
|
||||||
|
ListView {anchors.fill: parent; model: visualphotoModel.parts.fullscreen; interactive: false }
|
||||||
|
WorkerScript{id: photoWorker;source: "qrc:/js/photoworker.js"}
|
||||||
|
|
||||||
|
Component.onCompleted: { root.fotoSignal.connect(onFriendsFotos);}
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
import QtQuick 2.0
|
||||||
|
import QtQuick.LocalStorage 2.0
|
||||||
|
import QtQuick.Controls 1.3
|
||||||
|
import QtQml.Models 2.1
|
||||||
|
import "qrc:/js/service.js" as Service
|
||||||
|
import "qrc:/js/helper.js" as Helperjs
|
||||||
|
|
||||||
|
Package {
|
||||||
|
Item {
|
||||||
|
Package.name: 'browser'
|
||||||
|
GridView {
|
||||||
|
id: photosGridView; model: visualModel.parts.grid; width: albumgridview.width; height: albumgridview.height
|
||||||
|
cellWidth: 16.5*mm; cellHeight: 16.5*mm; interactive: false;anchors.margins:2*mm
|
||||||
|
onCurrentIndexChanged: photosListView.positionViewAtIndex(currentIndex, ListView.Contain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Package.name: 'fullscreen'
|
||||||
|
ListView {
|
||||||
|
id: photosListView; model: visualModel.parts.list; orientation: Qt.Horizontal
|
||||||
|
width: parent.width; height: parent.height; interactive: false
|
||||||
|
onCurrentIndexChanged: photosGridView.positionViewAtIndex(currentIndex, GridView.Contain)
|
||||||
|
highlightRangeMode: ListView.StrictlyEnforceRange; snapMode: ListView.SnapOneItem
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Package.name: 'album'
|
||||||
|
id: albumWrapper; width: 16.5*mm; height: 16.5*mm //-albumtext.contentHeight
|
||||||
|
|
||||||
|
DelegateModel {
|
||||||
|
id: visualModel; delegate: PhotoComponent { }
|
||||||
|
model: photoModel
|
||||||
|
}
|
||||||
|
|
||||||
|
PathView {
|
||||||
|
id: photosPathView;
|
||||||
|
model: visualModel.parts.stack;
|
||||||
|
pathItemCount: 1
|
||||||
|
anchors.centerIn: parent;
|
||||||
|
path: Path {
|
||||||
|
PathAttribute { name: 'z'; value: 9999.0 }
|
||||||
|
PathLine { x: 1; y: 1 }
|
||||||
|
PathAttribute { name: 'z'; value: 0.0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle{
|
||||||
|
color:"black"
|
||||||
|
opacity: 0.5
|
||||||
|
width:albumtext.contentWidth
|
||||||
|
height: albumtext.contentHeight
|
||||||
|
anchors.bottom: albumWrapper.bottom
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
id:albumtext
|
||||||
|
text: albumname //foreignPicture ? album.name.trim() : album
|
||||||
|
width:albumWrapper.width-1*mm
|
||||||
|
height: albumtext.contentHeight
|
||||||
|
wrapMode:Text.Wrap
|
||||||
|
color: "white"
|
||||||
|
font.family: "Monospace"
|
||||||
|
font.pixelSize: 2*mm
|
||||||
|
anchors.bottom: albumWrapper.bottom
|
||||||
|
}
|
||||||
|
|
||||||
|
ListModel{
|
||||||
|
id: photoModel
|
||||||
|
}
|
||||||
|
|
||||||
|
Component.onCompleted:{
|
||||||
|
try {photoModel.clear()}catch (e){print(e)}
|
||||||
|
if(foreignPicture){
|
||||||
|
//print("Albumlink"+album.link);
|
||||||
|
Service.requestFriendsPictures(albumlink,fotostab,function(obj){
|
||||||
|
if (obj) {
|
||||||
|
for (var k=0;k<obj.length;k++){
|
||||||
|
//print("Photomodel:"+obj[k].thumb+obj[k].name+obj[k].link);
|
||||||
|
photoModel.append({"imageLocation": obj[k].thumb,"photoDescription":obj[k].name,"photoLink":obj[k].link})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
})}
|
||||||
|
else{
|
||||||
|
Helperjs.readData(db,"imageData",root.login.username,function(obj){
|
||||||
|
// obj.sort(function(obj1,obj2){return obj1.data-obj2.data});
|
||||||
|
if (obj) {
|
||||||
|
for (var k=0;k<obj.length;k++){
|
||||||
|
// print("Photomodel:"+obj[k].location+obj[k].filename);
|
||||||
|
photoModel.append({"imageLocation": obj[k].location+obj[k].filename,"photoDescription":obj[k].filename,"photoLink":obj[k].location+obj[k].filename})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},"album",albumname)}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: albumWrapper.state = 'inGrid'
|
||||||
|
}
|
||||||
|
|
||||||
|
states: [
|
||||||
|
State {
|
||||||
|
name: 'inGrid'
|
||||||
|
PropertyChanges { target: photosGridView; interactive: true }
|
||||||
|
PropertyChanges { target: photoBackground; opacity: 1 }
|
||||||
|
PropertyChanges { target: backButton; onClicked: albumWrapper.state = ''; y: 6 }
|
||||||
|
},
|
||||||
|
State {
|
||||||
|
name: 'fullscreen'; extend: 'inGrid'
|
||||||
|
PropertyChanges { target: photosGridView; interactive: false }
|
||||||
|
PropertyChanges { target: photosListView; interactive: true }
|
||||||
|
PropertyChanges { target: photoBackground; opacity: 1 }
|
||||||
|
PropertyChanges { target: backButton; y: -backButton.height - 8 }
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
} //album Ende
|
||||||
|
} //Package Ende
|
||||||
|
//item Ende
|