Version 0.002 Release version
19
README.md
|
@ -22,17 +22,20 @@ Currently supported:
|
|||
* Liking, disliking, favoriting
|
||||
* Update fetches new posts since last in 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:
|
||||
* Test new Aspargus features
|
||||
* 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 as attachment (sending and receiving)
|
||||
* Nice symbols for liking, disliking
|
||||
* Videos and other binary data as attachment (sending and receiving)
|
||||
* Rich text editing in Send Dialog
|
||||
* Attachments for Direct messages (currently not supported in API
|
||||
* Better image selection (currently ugly file dialog)
|
||||
|
||||
|
||||
# Friends #
|
||||
Currently supported:
|
||||
* Tabs for friends, other contacts and groups
|
||||
* Grid of all known contacts with locally downloaded pictures
|
||||
* Large friend item for addional information and functionality
|
||||
* Show news of contact from local database
|
||||
|
@ -42,7 +45,6 @@ Currently supported:
|
|||
|
||||
ToDo:
|
||||
* More information for contact from description page, possibly private information for friends
|
||||
* Filter contacts for friends, forums,groups etc.
|
||||
* Groups: create, change, delete
|
||||
|
||||
|
||||
|
@ -53,25 +55,24 @@ Currently supported:
|
|||
* Show albums and images of contacts
|
||||
|
||||
ToDo:
|
||||
* Better download mechanism for own images
|
||||
* Private images of friends
|
||||
* Support for all themes of friends
|
||||
* Delete downloaded own images
|
||||
* Pinch to zoom, swipe to scroll
|
||||
|
||||
|
||||
# Config #
|
||||
Currently supported:
|
||||
* Multiple accounts
|
||||
* Maximum news (deleted after use of Quit button)
|
||||
* View mode for news (tree or timeline)
|
||||
|
||||
ToDo
|
||||
* OAuth?
|
||||
* View mode for news (chronological or tree)
|
||||
|
||||
|
||||
# Other #
|
||||
ToDo
|
||||
* Friendstab and Newstab buggy after account change, restart helps
|
||||
* Calendar tab, video tab
|
||||
* Photo upload to album (needs API change)
|
||||
* Translation
|
||||
|
@ -81,5 +82,5 @@ ToDo
|
|||
## License ##
|
||||
v0.001 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
|
||||
|
||||
|
||||
|
||||
|
||||
|
BIN
v0.002/Release/Friendiqa_v0.002.apk
Normal file
53
v0.002/Release/source-android/android/AndroidManifest.xml
Normal file
|
@ -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>
|
BIN
v0.002/Release/source-android/android/res/drawable/friendiqa.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
v0.002/Release/source-android/android/res/drawable/icon.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
v0.002/Release/source-android/android/res/drawable/splash.png
Normal file
After Width: | Height: | Size: 11 KiB |
25
v0.002/Release/source-android/android/res/values/libs.xml
Normal file
|
@ -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>
|
27
v0.002/Release/source-android/application.qrc
Normal file
|
@ -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>
|
49
v0.002/Release/source-android/common/filesystem.cpp
Normal file
|
@ -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);}
|
||||
}
|
33
v0.002/Release/source-android/common/filesystem.h
Normal file
|
@ -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
|
22
v0.002/Release/source-android/common/friendiqa.cpp
Normal file
|
@ -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();
|
||||
|
||||
}
|
||||
|
90
v0.002/Release/source-android/common/uploadableimage.cpp
Normal file
|
@ -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;
|
||||
}
|
40
v0.002/Release/source-android/common/uploadableimage.h
Normal file
|
@ -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
|
235
v0.002/Release/source-android/common/xhr.cpp
Normal file
|
@ -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);
|
||||
}
|
||||
|
||||
|
73
v0.002/Release/source-android/common/xhr.h
Normal file
|
@ -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
|
55
v0.002/Release/source-android/friendiqa.pro
Normal file
|
@ -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
|
||||
|
||||
|
BIN
v0.002/Release/source-android/images/defaultcontact.jpg
Normal file
After Width: | Height: | Size: 1.1 KiB |
12
v0.002/Release/source-android/js/friendworker.js
Normal file
|
@ -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()
|
||||
};
|
||||
}
|
121
v0.002/Release/source-android/js/helper.js
Normal file
|
@ -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;
|
||||
}
|
44
v0.002/Release/source-android/js/layout.js
Normal file
|
@ -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);
|
||||
}
|
||||
|
399
v0.002/Release/source-android/js/news.js
Normal file
|
@ -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
|
||||
}
|
63
v0.002/Release/source-android/js/newsworker.js
Normal file
|
@ -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()
|
||||
};
|
||||
}
|
15
v0.002/Release/source-android/js/photoworker.js
Normal file
|
@ -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()
|
||||
};
|
||||
}
|
||||
}
|
272
v0.002/Release/source-android/js/service.js
Normal file
|
@ -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]);}
|
||||
});
|
||||
}
|
314
v0.002/Release/source-android/qml/configqml/ConfigTab.qml
Normal file
|
@ -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)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
v0.002/Release/source-android/qml/configqml/InfoBox.qml
Normal file
|
@ -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()}
|
||||
}
|
||||
}
|
||||
}
|
197
v0.002/Release/source-android/qml/contactqml/FriendsTab.qml
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
121
v0.002/Release/source-android/qml/contactqml/GroupComponent.qml
Normal file
|
@ -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 }
|
||||
}
|
||||
]
|
||||
}
|
149
v0.002/Release/source-android/qml/friendiqa.qml
Normal file
|
@ -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":""
|
||||
}
|
||||
}
|
41
v0.002/Release/source-android/qml/genericqml/BlueButton.qml
Normal file
|
@ -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} }
|
||||
]
|
||||
}
|
54
v0.002/Release/source-android/qml/newsqml/Conversation.qml
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
199
v0.002/Release/source-android/qml/newsqml/MessageSend.qml
Normal file
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
232
v0.002/Release/source-android/qml/newsqml/NewsTab.qml
Normal file
|
@ -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)})}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
343
v0.002/Release/source-android/qml/newsqml/Newsitem.qml
Normal file
|
@ -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);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
191
v0.002/Release/source-android/qml/newsqml/PermissionDialog.qml
Normal file
|
@ -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 }});
|
||||
}}}
|
||||
|
181
v0.002/Release/source-android/qml/photoqml/PhotoTab.qml
Normal file
|
@ -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
|
27
v0.002/Release/source-linux/application.qrc
Normal file
|
@ -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>
|
49
v0.002/Release/source-linux/common/filesystem.cpp
Normal file
|
@ -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);}
|
||||
}
|
33
v0.002/Release/source-linux/common/filesystem.h
Normal file
|
@ -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
|
22
v0.002/Release/source-linux/common/friendiqa.cpp
Normal file
|
@ -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();
|
||||
|
||||
}
|
||||
|
90
v0.002/Release/source-linux/common/uploadableimage.cpp
Normal file
|
@ -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;
|
||||
}
|
40
v0.002/Release/source-linux/common/uploadableimage.h
Normal file
|
@ -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
|
235
v0.002/Release/source-linux/common/xhr.cpp
Normal file
|
@ -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);
|
||||
}
|
||||
|
||||
|
73
v0.002/Release/source-linux/common/xhr.h
Normal file
|
@ -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
|
44
v0.002/Release/source-linux/friendiqa.pro
Normal file
|
@ -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
|
||||
|
||||
|
BIN
v0.002/Release/source-linux/images/defaultcontact.jpg
Normal file
After Width: | Height: | Size: 1.1 KiB |
12
v0.002/Release/source-linux/js/friendworker.js
Normal file
|
@ -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()
|
||||
};
|
||||
}
|
121
v0.002/Release/source-linux/js/helper.js
Normal file
|
@ -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;
|
||||
}
|
44
v0.002/Release/source-linux/js/layout.js
Normal file
|
@ -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);
|
||||
}
|
||||
|
399
v0.002/Release/source-linux/js/news.js
Normal file
|
@ -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
|
||||
}
|
63
v0.002/Release/source-linux/js/newsworker.js
Normal file
|
@ -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()
|
||||
};
|
||||
}
|
15
v0.002/Release/source-linux/js/photoworker.js
Normal file
|
@ -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()
|
||||
};
|
||||
}
|
||||
}
|
272
v0.002/Release/source-linux/js/service.js
Normal file
|
@ -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]);}
|
||||
});
|
||||
}
|
314
v0.002/Release/source-linux/qml/configqml/ConfigTab.qml
Normal file
|
@ -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)}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
24
v0.002/Release/source-linux/qml/configqml/InfoBox.qml
Normal file
|
@ -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()}
|
||||
}
|
||||
}
|
||||
}
|
197
v0.002/Release/source-linux/qml/contactqml/FriendsTab.qml
Normal file
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
121
v0.002/Release/source-linux/qml/contactqml/GroupComponent.qml
Normal file
|
@ -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 }
|
||||
}
|
||||
]
|
||||
}
|
149
v0.002/Release/source-linux/qml/friendiqa.qml
Normal file
|
@ -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":""
|
||||
}
|
||||
}
|
41
v0.002/Release/source-linux/qml/genericqml/BlueButton.qml
Normal file
|
@ -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} }
|
||||
]
|
||||
}
|
54
v0.002/Release/source-linux/qml/newsqml/Conversation.qml
Normal file
|
@ -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)
|
||||
}
|
||||
}
|
199
v0.002/Release/source-linux/qml/newsqml/MessageSend.qml
Normal file
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
232
v0.002/Release/source-linux/qml/newsqml/NewsTab.qml
Normal file
|
@ -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)})}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
343
v0.002/Release/source-linux/qml/newsqml/Newsitem.qml
Normal file
|
@ -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);
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
191
v0.002/Release/source-linux/qml/newsqml/PermissionDialog.qml
Normal file
|
@ -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})
|
||||
}});
|
||||
}
|
||||
}
|
99
v0.002/Release/source-linux/qml/photoqml/PhotoComponent.qml
Normal file
|
@ -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) }
|
||||
}
|
||||
]
|
||||
|
||||
}
|
||||
}
|
||||
|
181
v0.002/Release/source-linux/qml/photoqml/PhotoTab.qml
Normal file
|
@ -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);}
|
||||
}
|
119
v0.002/Release/source-linux/qml/photoqml/PhotogroupComponent.qml
Normal file
|
@ -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
|