Version 0.003

This commit is contained in:
LubuWest 2017-03-25 23:36:14 +01:00
commit 10dccdcdbb
572 changed files with 3711 additions and 13631 deletions

View file

@ -0,0 +1,200 @@
<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/newsqml/Conversation.qml</file>
<file>qml/newsqml/ImageDialog.qml</file>
<file>qml/newsqml/FriendicaActivities.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>images/fontawesome-webfont.ttf</file>
<file>images/folder-blue.png</file>
<file>qml/configqml/OSSettingsAndroid.qml</file>
<file>qml/configqml/OSSettingsLinux.qml</file>
<file>qml/newsqml/SmileyDialog.qml</file>
<file>js/smiley.js</file>
<file>images/smileys/animals/bee.gif</file>
<file>images/smileys/animals/bigspider.gif</file>
<file>images/smileys/animals/bunny.gif</file>
<file>images/smileys/animals/bunnyflowers.gif</file>
<file>images/smileys/animals/cat.gif</file>
<file>images/smileys/animals/chick.gif</file>
<file>images/smileys/animals/cow.gif</file>
<file>images/smileys/animals/crab.gif</file>
<file>images/smileys/animals/dog.gif</file>
<file>images/smileys/animals/dolphin.gif</file>
<file>images/smileys/animals/dragonfly.gif</file>
<file>images/smileys/animals/elephant.gif</file>
<file>images/smileys/animals/fish.gif</file>
<file>images/smileys/animals/frog.gif</file>
<file>images/smileys/animals/giraffe.gif</file>
<file>images/smileys/animals/hamster.gif</file>
<file>images/smileys/animals/horse.gif</file>
<file>images/smileys/animals/ladybird.gif</file>
<file>images/smileys/animals/monkey.gif</file>
<file>images/smileys/animals/parrot.gif</file>
<file>images/smileys/animals/pig.gif</file>
<file>images/smileys/animals/sheep.gif</file>
<file>images/smileys/animals/snail.gif</file>
<file>images/smileys/animals/tux.gif</file>
<file>images/smileys/babies/baby.gif</file>
<file>images/smileys/babies/babycot.gif</file>
<file>images/smileys/babies/pregnant.gif</file>
<file>images/smileys/babies/stork.gif</file>
<file>images/smileys/confused/confused.gif</file>
<file>images/smileys/confused/dazed.gif</file>
<file>images/smileys/confused/shrug.gif</file>
<file>images/smileys/confused/stupid.gif</file>
<file>images/smileys/cool/affro.gif</file>
<file>images/smileys/cool/cool.gif</file>
<file>images/smileys/devilangel/angel.gif</file>
<file>images/smileys/devilangel/blondedevil.gif</file>
<file>images/smileys/devilangel/catdevil.gif</file>
<file>images/smileys/devilangel/cherub.gif</file>
<file>images/smileys/devilangel/daseesaw.gif</file>
<file>images/smileys/devilangel/devil.gif</file>
<file>images/smileys/devilangel/graveside.gif</file>
<file>images/smileys/devilangel/saint.gif</file>
<file>images/smileys/devilangel/turnevil.gif</file>
<file>images/smileys/disgust/fartblush.gif</file>
<file>images/smileys/disgust/fartinbed.gif</file>
<file>images/smileys/disgust/toilet.gif</file>
<file>images/smileys/disgust/vomit.gif</file>
<file>images/smileys/drink/tea.gif</file>
<file>images/smileys/drool/drool.gif</file>
<file>images/smileys/fantasy/alienmonster.gif</file>
<file>images/smileys/fantasy/barbarian.gif</file>
<file>images/smileys/fantasy/dinosaur.gif</file>
<file>images/smileys/fantasy/dragon.gif</file>
<file>images/smileys/fantasy/dragonwhelp.gif</file>
<file>images/smileys/fantasy/ghost.gif</file>
<file>images/smileys/fantasy/mummy.gif</file>
<file>images/smileys/fight/2guns.gif</file>
<file>images/smileys/fight/acid.gif</file>
<file>images/smileys/fight/alienfight.gif</file>
<file>images/smileys/fight/alpha.png</file>
<file>images/smileys/fight/army.gif</file>
<file>images/smileys/fight/arrowhead.gif</file>
<file>images/smileys/fight/bfg.gif</file>
<file>images/smileys/fight/bowman.gif</file>
<file>images/smileys/fight/chainsaw.gif</file>
<file>images/smileys/fight/crossbow.gif</file>
<file>images/smileys/fight/crusader.gif</file>
<file>images/smileys/fight/dead.gif</file>
<file>images/smileys/fight/gangs.gif</file>
<file>images/smileys/fight/hammersplat.gif</file>
<file>images/smileys/fight/lasergun.gif</file>
<file>images/smileys/fight/machinegun.gif</file>
<file>images/smileys/fight/marine.gif</file>
<file>images/smileys/fight/sabre.gif</file>
<file>images/smileys/fight/samurai.gif</file>
<file>images/smileys/fight/tank.gif</file>
<file>images/smileys/fight/viking.gif</file>
<file>images/smileys/food/apple.gif</file>
<file>images/smileys/food/banana.gif</file>
<file>images/smileys/food/birthdaycake.gif</file>
<file>images/smileys/food/broccoli.gif</file>
<file>images/smileys/food/cake.gif</file>
<file>images/smileys/food/carrot.gif</file>
<file>images/smileys/food/cooking.gif</file>
<file>images/smileys/food/fryegg.gif</file>
<file>images/smileys/food/popcorn.gif</file>
<file>images/smileys/food/tomato.gif</file>
<file>images/smileys/happy/cloud9.gif</file>
<file>images/smileys/happy/tearsofjoy.gif</file>
<file>images/smileys/laugh/hahaha.gif</file>
<file>images/smileys/laugh/loltv.gif</file>
<file>images/smileys/laugh/rofl.gif</file>
<file>images/smileys/love/iloveyou.gif</file>
<file>images/smileys/love/inlove.gif</file>
<file>images/smileys/love/love.gif</file>
<file>images/smileys/love/lovebear.gif</file>
<file>images/smileys/love/lovebed.gif</file>
<file>images/smileys/love/loveheart.gif</file>
<file>images/smileys/music/dj.gif</file>
<file>images/smileys/music/drums.gif</file>
<file>images/smileys/music/elvis.gif</file>
<file>images/smileys/music/guitar.gif</file>
<file>images/smileys/music/trumpet.gif</file>
<file>images/smileys/music/violin.gif</file>
<file>images/smileys/oldcore/beard.png</file>
<file>images/smileys/oldcore/headbang.gif</file>
<file>images/smileys/oldcore/laughing.gif</file>
<file>images/smileys/oldcore/shaka.gif</file>
<file>images/smileys/oldcore/surprised.gif</file>
<file>images/smileys/oldcore/whitebeard.png</file>
<file>images/smileys/respect/bow.gif</file>
<file>images/smileys/respect/bravo.gif</file>
<file>images/smileys/respect/hailking.gif</file>
<file>images/smileys/respect/number1.gif</file>
<file>images/smileys/sad/crying.png</file>
<file>images/smileys/sad/prisoner.gif</file>
<file>images/smileys/sad/sigh.gif</file>
<file>images/smileys/smoking/smoking.gif</file>
<file>images/smileys/sport/archery.gif</file>
<file>images/smileys/sport/basketball.gif</file>
<file>images/smileys/sport/bowling.gif</file>
<file>images/smileys/sport/cycling.gif</file>
<file>images/smileys/sport/darts.gif</file>
<file>images/smileys/sport/fencing.gif</file>
<file>images/smileys/sport/football.gif</file>
<file>images/smileys/sport/golf.gif</file>
<file>images/smileys/sport/horseriding.gif</file>
<file>images/smileys/sport/juggling.gif</file>
<file>images/smileys/sport/skipping.gif</file>
<file>images/smileys/sport/snooker.gif</file>
<file>images/smileys/sport/surfing.gif</file>
<file>images/smileys/sport/tennis.gif</file>
<file>images/smileys/tired/countsheep.gif</file>
<file>images/smileys/tired/hammock.gif</file>
<file>images/smileys/tired/pillow.gif</file>
<file>images/smileys/tired/yawn.gif</file>
<file>images/smileys/core/beer_mug.gif</file>
<file>images/smileys/core/coffee.gif</file>
<file>images/smileys/core/dislike.gif</file>
<file>images/smileys/core/friendica-16.png</file>
<file>images/smileys/core/like.gif</file>
<file>images/smileys/core/rm-16.png</file>
<file>images/smileys/core/smiley-bangheaddesk.gif</file>
<file>images/smileys/core/smiley-brokenheart.gif</file>
<file>images/smileys/core/smiley-cool.gif</file>
<file>images/smileys/core/smiley-cry.gif</file>
<file>images/smileys/core/smiley-embarassed.gif</file>
<file>images/smileys/core/smiley-facepalm.gif</file>
<file>images/smileys/core/smiley-foot-in-mouth.gif</file>
<file>images/smileys/core/smiley-heart.gif</file>
<file>images/smileys/core/smiley-kiss.gif</file>
<file>images/smileys/core/smiley-laughing.gif</file>
<file>images/smileys/core/smiley-Oo.gif</file>
<file>images/smileys/core/smiley-smile.gif</file>
<file>images/smileys/core/smiley-surprised.gif</file>
<file>images/smileys/core/smiley-thumbsup.gif</file>
<file>images/smileys/core/smiley-tongue-out.gif</file>
<file>images/smileys/core/smiley-undecided.gif</file>
<file>images/smileys/core/smiley-wink.gif</file>
<file>images/smileys/core/smiley-frown.gif</file>
<file>images/smileys/adult/bong.gif</file>
<file>images/smileys/adult/drunk.gif</file>
<file>images/smileys/adult/finger.gif</file>
<file>images/smileys/adult/sperm.gif</file>
<file>images/smileys/adult/tits.gif</file>
</qresource>
</RCC>

View file

@ -0,0 +1,81 @@
#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;
}
QString FILESYSTEM::homePath() const
{
QDir dir(m_Directory);
QString homeDir=dir.homePath();
//qDebug(homeDir);
return homeDir;
}
//QString FILESYSTEM::cameraPath() const
//{
//QAndroidJniObject object = QAndroidJniObject::getStaticObjectField<jstring>("android.os.Environment", "DIRECTORY_DCIM");
//QAndroidJniObject dcim =QAndroidJniObject::callStaticObjectMethod("android.os.Environment","getExternalStoragePublicDirectory", "(Ljava/lang/String;)Ljava/io/File;", object.object<jobject>());
// return dcim.toString;
//}
//bool FILESYSTEM::direxist(QString Directory) const
//{QDir dir(Directory);
// return dir.exists();
//}
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);}
}
QFileInfoList FILESYSTEM::fileList()
{
QDir dir(m_Directory);
QStringList filters;
filters << "*.png" <<"*.PNG" << "*.jpg" << "*.JPG" << "*.JPEG";
dir.setNameFilters(filters);
dir.setSorting(QDir::Time | QDir::Reversed);
//QStringList m_Filelist=dir.entryInfoList();
//qDebug() << "filelist " << m_Filelist;
return dir.entryInfoList();
}

View file

@ -0,0 +1,45 @@
#ifndef FILESYSTEM_H
#define FILESYSTEM_H
#include <QDir>
#include <QObject>
//#include <QtAndroidExtras>
class FILESYSTEM : public QObject
{
Q_OBJECT
Q_PROPERTY(QString Directory READ Directory WRITE setDirectory NOTIFY directoryChanged)
//Q_PROPERTY(bool direxist READ direxist)
Q_PROPERTY(QString homePath READ homePath)
//Q_PROPERTY(QString cameraPath READ cameraPath)
public:
static FILESYSTEM *instance();
explicit FILESYSTEM(QObject *parent = 0);
void setDirectory(QString Directory);
QString Directory() const;
QFileInfoList fileList();
//bool direxist(QString Directory);
QString homePath() const;
QString cameraPath() const;
signals:
void directoryChanged();
//void fileListContent(QList data);
void success(QString data);
void error(QString data, int code);
public slots:
void makeDir(QString name);
void rmDir();
void rmFile(QString name);
//void fileList();
private:
QString m_Directory;
QString homeDir;
//QList m_Filelist;
};
#endif // FILSYSTEM_H

View 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();
}

View 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;
}

View 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

231
source-linux/common/xhr.cpp Normal file
View file

@ -0,0 +1,231 @@
#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);
request.setUrl(requrl);
reply = manager.get(request);
// 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, &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);
buffer.clear();
reply->deleteLater();
}
void XHR::onReplySuccess()
{
qDebug() << "!";
emit this->success( bufferToString() );
buffer.clear();
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();
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
source-linux/common/xhr.h Normal file
View 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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 648 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 696 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 864 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 780 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 951 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 990 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 925 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 184 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,021 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 756 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 119 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 676 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,003 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 301 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 577 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 454 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 810 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 891 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 403 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 664 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 583 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 265 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,010 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1,005 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 652 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 461 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 885 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 306 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 365 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 467 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View 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()
};
}

132
source-linux/js/helper.js Normal file
View file

@ -0,0 +1,132 @@
.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.status=200){ //if (xhrequest.responseText!=""){
callback(xhrequest.responseText)
}else{
showMessage("Error","API:" +api+"\n NO RESPONSE"+xhrequest.statusText,rootwindow);
callback(xhrequest.responseText)
}
}
catch (e){
showMessage("Error", api+" "+e+" "+xhrequest.statusText,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)+Qt.atob(login.password));
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 getCount(database,login,table,field,countvalue){
var db=Sql.LocalStorage.openDatabaseSync(database[0],database[1],database[2],database[3]);
var count=0;
db.transaction( function(tx) {
var countrs = tx.executeSql('SELECT COUNT(*) from '+table+' WHERE username= "'+ login.username +'" AND '+field+' = "'+countvalue+'"');
count = parseInt(countrs.rows.item(0)["COUNT(*)"])
})
return count
}
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, sort) { // 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='';}
if (sort){
var sortparam = " ORDER BY "+ sort;
} else { var sortparam="";}
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+sortparam);
var rsArray=[];
var rs = tx.executeSql('select * from '+table+user+where+sortparam);
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){print("message: "+message);
var cleanmessage=message.replace(/"/g,"-");
var messageString='import QtQuick 2.0; import QtQuick.Dialogs 1.2; MessageDialog{ visible: true; title:"'+header+'";standardButtons: StandardButton.Ok; text:" '+cleanmessage+'"}';
var messageObject=Qt.createQmlObject(messageString,rootwindow,"messageOutput");
}
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
source-linux/js/layout.js Normal file
View 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);
}

398
source-linux/js/news.js Normal file
View file

@ -0,0 +1,398 @@
.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 url 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).url )
//print(result.rows.item(i).url)
}
var lastDate=Date.now()-172800000;// 2 days old
//print('SELECT url from contacts WHERE username="'+login.username+'" AND isFriend=0 AND imageAge>'+lastDate);
var result2 = tx.executeSql('SELECT url 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).url )
}
})
callback(contactlist)
}
function findNewContacts(news,contacts){//print("contacts: "+JSON.stringify(contacts))
var newContacts=[];
for (var i=0;i<news.length;i++){
var url=news[i].user.url;
if(contacts.indexOf(url)==-1 && !(inArray(newContacts,"url",url))){print("new contact "+JSON.stringify(news[i].user));
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_url=news[i].friendica_activities.like[j].url;
if(contacts.indexOf(like_url)==-1 && !(inArray(newContacts,"url",like_url))){print("new like contact "+JSON.stringify(news[i].friendica_activities.like[j]));
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_url=news[i].friendica_activities.dislike[k].url;
if(contacts.indexOf(dislike_url)==-1 && !(inArray(newContacts,"url",dislike_url))){print("new dislike contact "+JSON.stringify(news[i].friendica_activities.dislike[k]));
news[i].friendica_activities.dislike[k].isFriend=0;
newContacts.push(news[i].friendica_activities.dislike[k]);
}
}
}
// var owner_id=parseInt(news[i].friendica_owner.id);
// if(contacts.indexOf(owner_id)==-1 && !(inArray(newContacts,"id",owner_id))){
// news[i].friendica_owner.isFriend=0;
// newContacts.push(news[i].friendica_owner);
// }
}
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(news[i].friendica_activities.like[user].url)}
var dislikearray=[]; for (var user in news[i].friendica_activities.dislike){dislikearray.push(news[i].friendica_activities.dislike[user].url)}
var attendyesarray=[]; for (var user in news[i].friendica_activities.attendyes){attendyesarray.push(news[i].friendica_activities.attendyes[user].url)}
var attendnoarray=[]; for (var user in news[i].friendica_activities.attendno){attendnoarray.push(news[i].friendica_activities.attendno[user].url)}
var attendmaybearray=[]; for (var user in news[i].friendica_activities.attendmaybe){attendmaybearray.push(news[i].friendica_activities.attendmaybe[user].url)}
var friendica_activities=[likearray,dislikearray,attendyesarray,attendnoarray,attendmaybearray]
var attachments="";if (news[i].attachments){attachments=Qt.btoa(JSON.stringify(news[i].attachments))}print(attachments)
db.transaction( function(tx) {
var result = tx.executeSql('SELECT * from news where username="'+login.username+'" AND status_id = "'+news[i].id+'" AND messagetype=0'); // check for news id
if(result.rows.length === 1) {// use update
//print(news[i].id +' news exists, update it'+'UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", created_at="'+Date.parse(cleanDate(news[i].created_at))+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",friendica_activities="'+Qt.btoa(JSON.stringify(friendica_activities))+'",attachments="'+attachments+'",friendica_owner="'+news[i].friendica_owner.url+'" where username="'+login.username+'" AND status_id="'+news[i].status_id+'" AND messagetype=0')
result = tx.executeSql('UPDATE news SET username="'+login.username+'", messagetype=0, text="'+Qt.btoa(news[i].text)+'", created_at="'+Date.parse(cleanDate(news[i].created_at))+'", in_reply_to_status_id="'+news[i].in_reply_to_status_id+'", source="'+news[i].source+'", status_id="'+news[i].id+'", in_reply_to_user_id="'+news[i].in_reply_to_user_id+'", geo="'+news[i].geo+'", favorited="'+news[i].favorited+'", uid="'+news[i].user.id+'", statusnet_html="'+Qt.btoa(news[i].status_html)+'", statusnet_conversation_id="'+news[i].statusnet_conversation_id+'",friendica_activities="'+Qt.btoa(JSON.stringify(friendica_activities))+'",attachments="'+attachments+'",friendica_owner="'+news[i].friendica_owner.url+'" where username="'+login.username+'" AND status_id="'+news[i].status_id+'" AND messagetype=0');
} else {// use insert
result = tx.executeSql('INSERT INTO news (username,messagetype,text,created_at,in_reply_to_status_id,source,status_id,in_reply_to_user_id,geo,favorited,uid,statusnet_html,statusnet_conversation_id,friendica_activities,friendica_activities_self,attachments,friendica_owner) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)', [login.username,0,Qt.btoa(news[i].text),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, Qt.btoa(JSON.stringify(friendica_activities)),"[]",attachments,news[i].friendica_owner.url])}})
}
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,userUrlArray){//print(JSON.stringify(userUrlArray));
var helpArray=[];
for (var i=0;i<userUrlArray.length;i++){
Helperjs.readData(database,"contacts",username,function(userdata){
helpArray.push(userdata[0]);
},"url",userUrlArray[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));
newsArray[i]=fetchUsersForNews(database,username,newsArray[i])
}
callback(newsArray)});
}
function fetchUsersForNews(database,username,news){//print(JSON.stringify(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(Qt.atob(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]);
}
Helperjs.readData(database,"contacts",username,function(friendica_owner_data){
news.friendica_owner_object=friendica_owner_data[0];
//print("Fetch friendica_owner"+JSON.stringify(news.friendica_owner));
},"url",news.friendica_owner);
}
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){
//print("attend: "+attend+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);
if ((attend=="yes")&&(currentActivities.indexOf(3)==-1)){
currentActivities.push(3);
if (currentActivities.indexOf(4)!=-1){currentActivities.splice(currentActivities.indexOf(4),1)}
if (currentActivities.indexOf(5)!=-1){currentActivities.splice(currentActivities.indexOf(5),1)}
//print(JSON.stringify(currentActivities));
}
if ((attend=="no")&&(currentActivities.indexOf(4)==-1)){
currentActivities.push(4);
if (currentActivities.indexOf(3)!=-1){currentActivities.splice(currentActivities.indexOf(3),1)}
if (currentActivities.indexOf(5)!=-1){currentActivities.splice(currentActivities.indexOf(5),1)}
}
if ((attend=="maybe")&&(currentActivities.indexOf(5)==-1)){
currentActivities.push(5);
if (currentActivities.indexOf(3)!=-1){currentActivities.splice(currentActivities.indexOf(3),1)}
if (currentActivities.indexOf(4)!=-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
}

View file

@ -0,0 +1,64 @@
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.friendica_owner+" userid: "+newsitemobject.user.id));
if (newsitemobject.messagetype==2){
newsitemobject.user={};
newsitemobject.user.profile_image="";
newsitemobject.user.profile_image_url="";
newsitemobject.user.name="";
}
//var forumname="";if (newsitemobject.messagetype==0&&(parseInt(newsitemobject.friendica_owner)!=parseInt(newsitemobject.user.id))){forumname=" via "+newsitemobject.friendica_owner_object.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 (newsitemobject.friendica_activities_self.indexOf(3)!=-1){self.attending=qsTr("yes")}
if (newsitemobject.friendica_activities_self.indexOf(4)!=-1){self.attending=qsTr("no")}
if (newsitemobject.friendica_activities_self.indexOf(5)!=-1){self.attending=qsTr("maybe")}
if (newsitemobject.friendica_activities_self.indexOf(1)!=-1){self.liked=1}
if (newsitemobject.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()
};
}

View 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()
};
}
}

279
source-linux/js/service.js Normal file
View file

@ -0,0 +1,279 @@
//.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,layout TEXT, addons 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, attachments TEXT, friendica_owner INT)');
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) {
//print(JSON.stringify(obj));
var result = tx.executeSql('SELECT * from config WHERE username="'+obj.username+'"');
if(result.rows.length === 1) {// use update
var result2 = tx.executeSql('UPDATE config SET server="'+obj.server+'",password="'+obj.password+'", imagestore="'+obj.imagestore+'", maxnews='+obj.maxnews+', timerInterval='+obj.interval+', newsViewType="'+obj.newsViewType+'", isActive=0 WHERE username="'+obj.username +'"');
var result3 = tx.executeSql('UPDATE config SET isActive=1 WHERE username !="'+obj.username +'"');
var result4 = tx.executeSql('UPDATE config SET maxnews='+obj.maxnews);
} else {// use insert print('... does not exists, create it')
var result2 = tx.executeSql('INSERT INTO config VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)', [obj.server, obj.username, obj.password, obj.imagestore, obj.maxnews, obj.interval,obj.newsViewType,0,"[[],[],[],[]]",0,"","",""]);
var 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 +'"')})
Helperjs.friendicaRequest(login,"/friendica/json",rootwindow, function (obj){
var serverData = JSON.parse(obj);var serverAddons=JSON.stringify(serverData.plugins).replace(/"/g,"");
db.transaction( function(tx) {
var result = tx.executeSql('UPDATE config SET addons="'+ serverAddons+'" 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,addons:rsArray[0].addons};
} 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;
var imagename=login.imagestore+"contacts/"+contact.screen_name+"-"+contact.profile_image_url.substring(contact.profile_image_url.lastIndexOf("/")+1, contact.profile_image_url.length);
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="'+login.username+'" AND url = "'+contact.url+'"'); // check for news url
if(result.rows.length === 1) {// use update
result = tx.executeSql('UPDATE contacts SET 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+'", 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="'+login.username+'" AND url="'+contact.url+'"');
} 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]);}
});
}

553
source-linux/js/smiley.js Normal file
View file

@ -0,0 +1,553 @@
var core=[
{name:'&lt;3',url:
'qrc:///images/smileys/core/smiley-heart.gif'},
{name:'&lt;/3',url:
'qrc:///images/smileys/core/smiley-brokenheart.gif'},
{name:':-)',url:
'qrc:///images/smileys/core/smiley-smile.gif'},
{name:';-)',url:
'qrc:///images/smileys/core/smiley-wink.gif'},
{name:':-(',url:
'qrc:///images/smileys/core/smiley-frown.gif'},
{name:':-P',url:
'qrc:///images/smileys/core/smiley-tongue-out.gif'},
{name:':-X',url:
'qrc:///images/smileys/core/smiley-kiss.gif'},
{name:':-D',url:
'qrc:///images/smileys/core/smiley-laughing.gif'},
{name:':-O',url:
'qrc:///images/smileys/core/smiley-surprised.gif'},
{name:'\\o/',url:
'qrc:///images/smileys/core/smiley-thumbsup.gif'},
{name:'o.O',url:
'qrc:///images/smileys/core/smiley-Oo.gif'},
{name:":'(",url:
'qrc:///images/smileys/core/smiley-cry.gif'},
{name:":-!",url:
'qrc:///images/smileys/core/smiley-foot-in-mouth.gif'},
{name:":-/",url:
'qrc:///images/smileys/core/smiley-undecided.gif'},
{name:":-[",url:
'qrc:///images/smileys/core/smiley-embarassed.gif'},
{name:"8-)",url:
'qrc:///images/smileys/core/smiley-cool.gif'},
{name:':beer',url:
'qrc:///images/smileys/core/beer_mug.gif'},
{name:':coffee',url:
'qrc:///images/smileys/core/coffee.gif'},
{name:':facepalm',url:
'qrc:///images/smileys/core/smiley-facepalm.gif'},
{name:':like',url:
'qrc:///images/smileys/core/like.gif'},
{name:':dislike',url:
'qrc:///images/smileys/core/dislike.gif'},
{name:'~friendica',url:
'qrc:///images/smileys/core/friendica-16.png'},
{name:'red#',url:
'qrc:///images/smileys/core/rm-16.png'}
]
var addon=[
{name:':bunnyflowers',url:
'qrc:///images/smileys/animals/bunnyflowers.gif'},
{name:':chick',url:
'qrc:///images/smileys/animals/chick.gif'},
{name:':bumblebee',url:
'qrc:///images/smileys/animals/bee.gif'},
{name:':ladybird',url:
'qrc:///images/smileys/animals/ladybird.gif'},
{name:':bigspider',url:
'qrc:///images/smileys/animals/bigspider.gif' },
{name:':cat',url:
'qrc:///images/smileys/animals/cat.gif'},
{name:':bunny',url:
'qrc:///images/smileys/animals/bunny.gif' },
{name:':cow',url:
'qrc:///images/smileys/animals/cow.gif' },
{name:':crab',url:
'qrc:///images/smileys/animals/crab.gif' },
{name:':dolphin',url:
'qrc:///images/smileys/animals/dolphin.gif' },
{name:':dragonfly',url:
'qrc:///images/smileys/animals/dragonfly.gif' },
{name:':frog',url:
'qrc:///images/smileys/animals/frog.gif'},
{name:':hamster',url:
'qrc:///images/smileys/animals/hamster.gif' },
{name:':monkey',url:
'qrc:///images/smileys/animals/monkey.gif' },
{name:':horse',url:
'qrc:///images/smileys/animals/horse.gif' },
{name:':parrot',url:
'qrc:///images/smileys/animals/parrot.gif' },
{name:':tux',url:
'qrc:///images/smileys/animals/tux.gif' },
{name:':snail',url:
'qrc:///images/smileys/animals/snail.gif' },
{name:':sheep',url:
'qrc:///images/smileys/animals/sheep.gif' },
{name:':dog',url:
'qrc:///images/smileys/animals/dog.gif'},
{name:':elephant',url:
'qrc:///images/smileys/animals/elephant.gif' },
{name:':fish',url:
'qrc:///images/smileys/animals/fish.gif' },
{name:':giraffe',url:
'qrc:///images/smileys/animals/giraffe.gif' },
{name:':pig',url:
'qrc:///images/smileys/animals/pig.gif'},
//Baby
{name:':baby',url:
'qrc:///images/smileys/babies/baby.gif' },
{name:':babycot',url:
'qrc:///images/smileys/babies/babycot.gif' },
{name:':pregnant',url:
'qrc:///images/smileys/babies/pregnant.gif' },
{name:':stork',url:
'qrc:///images/smileys/babies/stork.gif' },
//Confused
{name:':confused',url:
'qrc:///images/smileys/confused/confused.gif' },
{name:':shrug',url:
'qrc:///images/smileys/confused/shrug.gif' },
{name:':stupid',url:
'qrc:///images/smileys/confused/stupid.gif' },
{name:':dazed',url:
'qrc:///images/smileys/confused/dazed.gif' },
//Cool 'qrc:///images/smileys
{name:':affro',url:
'qrc:///images/smileys/cool/affro.gif'},
//Devil/Angel
{name:':angel',url:
'qrc:///images/smileys/devilangel/angel.gif'},
{name:':cherub',url:
'qrc:///images/smileys/devilangel/cherub.gif'},
{name:':devilangel',url:
'qrc:///images/smileys/devilangel/blondedevil.gif' },
{name:':catdevil',url:
'qrc:///images/smileys/devilangel/catdevil.gif'},
{name:':devillish',url:
'qrc:///images/smileys/devilangel/devil.gif'},
{name:':daseesaw',url:
'qrc:///images/smileys/devilangel/daseesaw.gif'},
{name:':turnevil',url:
'qrc:///images/smileys/devilangel/turnevil.gif' },
{name:':saint',url:
'qrc:///images/smileys/devilangel/saint.gif'},
{name:':graveside',url:
'qrc:///images/smileys/devilangel/graveside.gif'},
//Unpleasent
{name:':toilet',url:
'qrc:///images/smileys/disgust/toilet.gif'},
{name:':fartinbed',url:
'qrc:///images/smileys/disgust/fartinbed.gif' },
{name:':fartblush',url:
'qrc:///images/smileys/disgust/fartblush.gif' },
//Drinks
{name:':tea',url:
'qrc:///images/smileys/drink/tea.gif' },
{name:':drool',url:
'qrc:///images/smileys/drool/drool.gif'},
//Sad
{name:':crying',url:
'qrc:///images/smileys/sad/crying.png'},
{name:':prisoner',url:
'qrc:///images/smileys/sad/prisoner.gif' },
{name:':sigh',url:
'qrc:///images/smileys/sad/sigh.gif'},
//Smoking - only one smiley in here, maybe it needs moving elsewhere?
{name:':smoking',url:
'qrc:///images/smileys/smoking/smoking.gif'},
//Sport
{name:':basketball',url:
'qrc:///images/smileys/sport/basketball.gif'},
{name:':bowling',url:
'qrc:///images/smileys/sport/bowling.gif'},
{name:':cycling',url:
'qrc:///images/smileys/sport/cycling.gif'},
{name:':darts',url:
'qrc:///images/smileys/sport/darts.gif'},
{name:':fencing',url:
'qrc:///images/smileys/sport/fencing.gif' },
{name:':juggling',url:
'qrc:///images/smileys/sport/juggling.gif'},
{name:':skipping',url:
'qrc:///images/smileys/sport/skipping.gif'},
{name:':archery',url:
'qrc:///images/smileys/sport/archery.gif'},
{name:':surfing',url:
'qrc:///images/smileys/sport/surfing.gif' },
{name:':snooker',url:
'qrc:///images/smileys/sport/snooker.gif' },
{name:':horseriding',url:
'qrc:///images/smileys/sport/horseriding.gif'},
//Love
{name:':iloveyou',url:
'qrc:///images/smileys/love/iloveyou.gif'},
{name:':inlove',url:
'qrc:///images/smileys/love/inlove.gif'},
{name:':~love',url:
'qrc:///images/smileys/love/love.gif' },
{name:':lovebear',url:
'qrc:///images/smileys/love/lovebear.gif'},
{name:':lovebed',url:
'qrc:///images/smileys/love/lovebed.gif' },
{name:':loveheart',url:
'qrc:///images/smileys/love/loveheart.gif' },
//Tired/Sleep
{name:':countsheep',url:
'qrc:///images/smileys/tired/countsheep.gif' },
{name:':hammock',url:
'qrc:///images/smileys/tired/hammock.gif'},
{name:':pillow',url:
'qrc:///images/smileys/tired/pillow.gif' },
{name:':yawn',url:
'qrc:///images/smileys/tired/yawn.gif'},
//Fight/Flame/Violent
{name:':2guns',url:
'qrc:///images/smileys/fight/2guns.gif' },
{name:':alienfight',url:
'qrc:///images/smileys/fight/alienfight.gif' },
{name:':army',url:
'qrc:///images/smileys/fight/army.gif'},
{name:':arrowhead',url:
'qrc:///images/smileys/fight/arrowhead.gif'},
{name:':bfg',url:
'qrc:///images/smileys/fight/bfg.gif' },
{name:':bowman',url:
'qrc:///images/smileys/fight/bowman.gif' },
{name:':chainsaw',url:
'qrc:///images/smileys/fight/chainsaw.gif'},
{name:':crossbow',url:
'qrc:///images/smileys/fight/crossbow.gif'},
{name:':crusader',url:
'qrc:///images/smileys/fight/crusader.gif' },
{name:':dead',url:
'qrc:///images/smileys/fight/dead.gif' },
{name:':hammersplat',url:
'qrc:///images/smileys/fight/hammersplat.gif' },
{name:':lasergun',url:
'qrc:///images/smileys/fight/lasergun.gif' },
{name:':machinegun',url:
'qrc:///images/smileys/fight/machinegun.gif' },
{name:':acid',url:
'qrc:///images/smileys/fight/acid.gif' },
//Fantasy - monsters and dragons fantasy. The other type of fantasy belongs in adult
{name:':alienmonster',url:
'qrc:///images/smileys/fantasy/alienmonster.gif' },
{name:':barbarian',url:
'qrc:///images/smileys/fantasy/barbarian.gif' },
{name:':dinosaur',url:
'qrc:///images/smileys/fantasy/dinosaur.gif'},
{name:':dragon',url:
'qrc:///images/smileys/fantasy/dragon.gif'},
{name:':draco',url:
'qrc:///images/smileys/fantasy/dragonwhelp.gif'},
{name:':ghost',url:
'qrc:///images/smileys/fantasy/ghost.gif'},
{name:':mummy',url:
'qrc:///images/smileys/fantasy/mummy.gif'},
//Food
{name:':apple',url:
'qrc:///images/smileys/food/apple.gif' },
{name:':broccoli',url:
'qrc:///images/smileys/food/broccoli.gif' },
{name:':cake',url:
'qrc:///images/smileys/food/cake.gif'},
{name:':carrot',url:
'qrc:///images/smileys/food/carrot.gif' },
{name:':popcorn',url:
'qrc:///images/smileys/food/popcorn.gif'},
{name:':tomato',url:
'qrc:///images/smileys/food/tomato.gif'},
{name:':banana',url:
'qrc:///images/smileys/food/banana.gif'},
{name:':cooking',url:
'qrc:///images/smileys/food/cooking.gif'},
{name:':fryegg',url:
'qrc:///images/smileys/food/fryegg.gif'},
{name:':birthdaycake',url:
'qrc:///images/smileys/food/birthdaycake.gif'},
//Happy
{name:':cloud9',url:
'qrc:///images/smileys/happy/cloud9.gif'},
{name:':tearsofjoy',url:
'qrc:///images/smileys/happy/tearsofjoy.gif' },
//Repsect
{name:':bow',url:
'qrc:///images/smileys/respect/bow.gif'},
{name:':bravo',url:
'qrc:///images/smileys/respect/bravo.gif'},
{name:':hailking',url:
'qrc:///images/smileys/respect/hailking.gif'},
{name:':number1',url:
'qrc:///images/smileys/respect/number1.gif' },
//Laugh
{name:':hahaha',url:
'qrc:///images/smileys/laugh/hahaha.gif'},
{name:':loltv',url:
'qrc:///images/smileys/laugh/loltv.gif' },
{name:':rofl',url:
'qrc:///images/smileys/laugh/rofl.gif'},
//Music
{name:':drums',url:
'qrc:///images/smileys/music/drums.gif'},
{name:':guitar',url:
'qrc:///images/smileys/music/guitar.gif'},
{name:':trumpet',url:
'qrc:///images/smileys/music/trumpet.gif' },
//smileys that used to be in core
{name:':headbang',url:
'qrc:///images/smileys/oldcore/headbang.gif'},
{name:':beard',url:
'qrc:///images/smileys/oldcore/beard.png'},
{name:':whitebeard',url:
'qrc:///images/smileys/oldcore/whitebeard.png'},
{name:':shaka',url:
'qrc:///images/smileys/oldcore/shaka.gif'},
{name:':\\.../',url:
'qrc:///images/smileys/oldcore/shaka.gif'},
{name:':\\ooo/',url:
'qrc:///images/smileys/oldcore/shaka.gif' },
{name:':headdesk',url:
'qrc:///images/smileys/oldcore/headbang.gif' },
//These two are still in core, so oldcore isn't strictly right, but we don't want too many directories
{name:':-d',url:
'qrc:///images/smileys/oldcore/laughing.gif'},
{name:':-o',url:
'qrc:///images/smileys/oldcore/surprised.gif' },
// Regex killers - stick these at the bottom so they appear at the end of the English and
// at the start of $OtherLanguage.
{name:':cool',url:
'qrc:///images/smileys/cool/cool.gif' },
{name:':vomit',url:
'qrc:///images/smileys/disgust/vomit.gif' },
{name:':golf',url:
'qrc:///images/smileys/sport/golf.gif' },
{name:':football',url:
'qrc:///images/smileys/sport/football.gif'},
{name:':tennis',url:
'qrc:///images/smileys/sport/tennis.gif' },
{name:':alpha',url:
'qrc:///images/smileys/fight/alpha.png' },
{name:':marine',url:
'qrc:///images/smileys/fight/marine.gif' },
{name:':sabre',url:
'qrc:///images/smileys/fight/sabre.gif' },
{name:':tank',url:
'qrc:///images/smileys/fight/tank.gif' },
{name:':viking',url:
'qrc:///images/smileys/fight/viking.gif' },
{name:':gangs',url:
'qrc:///images/smileys/fight/gangs.gif' },
{name:':dj',url:
'qrc:///images/smileys/music/dj.gif'},
{name:':elvis',url:
'qrc:///images/smileys/music/elvis.gif'},
{name:':violin',url:
'qrc:///images/smileys/music/violin.gif'},
]
var adult=[
{
name:'(o)(o) ',url:
'qrc:///images/smileys/adult/tits.gif'},
{name:'(.)(.) ',url:
'qrc:///images/smileys/adult/tits.gif'},
{name:':bong',url:
'qrc:///images/smileys/adult/bong.gif'},
{name:':sperm',url:
'qrc:///images/smileys/adult/sperm.gif'},
{name:':drunk',url:
'qrc:///images/smileys/adult/drunk.gif'},
{name:':finger',url:
'qrc:///images/smileys/adult/finger.gif'}
]

View file

@ -0,0 +1,327 @@
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: "white"
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){userButton.fontColor='black'} else {userButton.fontColor='grey'}
},'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: "Interval (0=None)"
visible: false
x: 4*mm; y: 70*mm; width:20*mm;wrapMode: Text.Wrap
}
Rectangle{color: "light grey"; 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: "light grey"
x: 25*mm; y: 20*mm; width: root.width/2; height: 5*mm;
TextInput {
id: username
anchors.fill: parent
selectByMouse: true
}
}
Rectangle{
color: "light grey"
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: "light grey"; 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: "light grey"; 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;
color:"light grey"
Text{
id: newsTypeField
anchors.fill: parent
text:"Timeline"
}
MouseArea{
anchors.fill:parent
onClicked:newstypemenu.popup()
}
}
Slider{ id: messageIntervalSlider
visible: false
x:37*mm; y: 70*mm;width: root.width/3;height:5*mm
minimumValue: 0;maximumValue:24; stepSize: 0.5
}
Rectangle{
visible:false
x: 25*mm; y: 70*mm; width: 9*mm; height: 5*mm;
TextEdit{
id: messageIntervalField
anchors.fill: parent
verticalAlignment:TextEdit.AlignRight
text:messageIntervalSlider.value
focus: true
selectByMouse: true
}
}
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
}
}
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: "Confirm"
onClicked:{
var userconfig={server: servername.text, username: username.text, password:Qt.btoa(password.text), imagestore:imagestore.text,maxnews:maxNewsText.text,interval: messageIntervalField.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,root, 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});
userButton.color="black"
//reset values
root.login=userconfig;
// root.contactlist=[];
// root.news=[];
// root.newContacts=[];
// root.currentContact= 0;
// root.contactLoadType= "";
newstab.newstabstatus=userconfig.newsViewType;
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";
messageIntervalSlider.value=0;
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"
messageIntervalSlider.value=0
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;
messageIntervalSlider.value=obj.timerInterval;
if( obj.isActive==0){userButton.fontColor='black'} else {userButton.fontColor='grey'}},"isActive",0
)
})}
catch (e){print(e)}
}
}
}
}

View file

@ -0,0 +1,34 @@
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
anchors.top:closeButton.bottom
anchors.topMargin: mm
textFormat: Text.RichText
wrapMode: Text.Wrap
text: "<b>Friendiqa v0.003 </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><br>"+
"Qt Framework <a href='https://www.qt.io'>www.qt.io</a><br>"+
"Icons by <a href='http://fontawesome.io'>FontAwesome</a><br>"+
"Folder Icon by <a href='https://github.com/KDE/breeze-icons'>KDE Breeze Icons</a>"
onLinkActivated:{
Qt.openUrlExternally(link)}
}
BlueButton{
id:closeButton
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057" //qsTr("Close")
onClicked:{configStack.pop()}
}
}

View file

@ -0,0 +1,8 @@
import QtQuick.Window 2.0
import QtQuick 2.0
QtObject{
property int appWidth: Screen.desktopAvailableWidth
property int appHeight: Screen.desktopAvailableHeight
property int backKey: Qt.Key_Back
property string attachImageDir:filesystem.cameraPath+"/"
}

View file

@ -0,0 +1,7 @@
import QtQuick 2.0
QtObject{
property real appWidth: 500
property real appHeight: 500
property int backKey: Qt.Key_Escape
property string attachImageDir:filesystem.homePath+"/Pictures/"
}

View file

@ -0,0 +1,84 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
import "qrc:/qml/genericqml"
Item {
id: contactComponent
property var createdAtDate: new Date(contact.created_at)
property string connectUrl: (contact.network!=="dfrn")||(contact.isFriend==1)?"":( "<a href='"+contact.url.replace("profile","dfrn_request") +"'>"+qsTr("Connect")+"</a><br>")
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: 0.5*mm
anchors.topMargin: mm
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})}
}
}
}
Timer{id:selectiontimer; //weird behaviour when state set to "large" onCompleted
interval: 200; running: false; repeat: false
onTriggered: {
contactComponent.state="large";
var component = Qt.createComponent("qrc:/qml/contactqml/ContactDetailsComponent.qml");
if (component.status== Component.Ready){
var contactDetails = component.createObject(wrapper,{"contact": contact})}
}
}
Component.onCompleted: {
if(status=="large"){selectiontimer.start()}
else{contactComponent.state=""}
}
states: [
State {
name: "large"
PropertyChanges { target: namelabel; font.pixelSize: 4*mm; x:mm; width:friendsTabView.width-4*mm; text:Qt.atob(contact.name)+" (@"+contact.screen_name+")"}
ParentChange{target:contactComponent;parent:root; x:mm;y:2*mm}
//PropertyChanges { target: contactComponent; z: 2; x:0;y:0}
PropertyChanges { target: wrapper; width:friendsTabView.width;height:friendsTabView.height-15*mm}
PropertyChanges { target: photoImage; width:15*mm;height:15*mm;x:mm;y:mm }
PropertyChanges { target: contactComponent.GridView.view; interactive:false}
}
]
}

View file

@ -0,0 +1,78 @@
import QtQuick 2.0
import QtQuick.Controls 1.3
import "qrc:/qml/genericqml"
Rectangle{
id: detailsrectangle
anchors.top: namelabel.bottom
anchors.topMargin: 2*mm
ScrollView{
horizontalScrollBarPolicy:Qt.ScrollBarAlwaysOff
frameVisible: true
id:namelabelflickable
width: root.width-10*mm
height:friendsTabView.height-45*mm
x: mm
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='"+ contact.url+"'>"+contact.url+"</a><br>"+
connectUrl+ "<b>"+qsTr("Created at")+":</b> "+createdAtDate.toLocaleString(Qt.locale())
onLinkActivated: {
Qt.openUrlExternally(link)}
}
}
Row{
anchors.top: namelabelflickable.bottom
anchors.topMargin: 2*mm
x: mm
spacing:4
BlueButton{
id:photobutton
text: "\uf03e" // "Photos"
visible:(contact.network=="dfrn")
onClicked:{
fotostab.phototabstatus="Contact";
root.currentIndex=2;
fotostab.active=true;
root.fotoSignal(contact) ;
}
}
BlueButton{
id:messagebutton
text: "\uf0e6" //"Messages"
onClicked:{
root.currentIndex=0;
newstab.active=true;
root.messageSignal(contact.id) ;
}
}
BlueButton{
id:dmbutton
visible: (contact.following=="true")
text: "\uf040" //"DM"
onClicked:{
root.currentIndex=0;
newstab.active=true;
root.directmessageSignal(contact.screen_name);
}
}
BlueButton{
id: closeButton
text: "\uf057" //"close"
onClicked:{detailsrectangle.destroy();contactComponent.state="";friendsTabView.contactSignal}
}
}
}

View file

@ -0,0 +1,220 @@
import QtQuick 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
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"
function showContactdetails(contact){
if(contact.isFriend){
friendsTabView.currentIndex=0;
friendsTabView.contactsSignal(contact)
}
else{friendsTabView.currentIndex=1;
friendsTabView.contactsSignal(contact)
}
}
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 contact)
signal groupsSignal(var username)
onCurrentIndexChanged:{
if (currentIndex==0){//print("currentindex 0");
contactsSignal("")
}
else if (currentIndex==1){
contactsSignal("")
}
else if (currentIndex==2){groupsSignal(root.login.username)}
}
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {
color: "white"
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 makebig(friendindex){print("friendindex"+friendindex);if (friendindex){friendsModel.set(friendindex,{"status":"large"})}}
function showFriends(contact,callback){//print("contact"+JSON.stringify(contact));
try {friendsModel.clear()} catch(e){print(e)};
var friendindex;
Helperjs.readData(db,"contacts",root.login.username,function(friendsobject){
for (var i=0;i<friendsobject.length;i++){
var status="";
if(Helperjs.getCount(db,login,"contacts","screen_name",friendsobject[i].screen_name)>1){
friendsobject[i].screen_name=friendsobject[i].screen_name+"+"+friendsobject[i].cid
}
if(contact){if (contact.cid==friendsobject[i].cid){status="large"}}
friendsModel.append({"contact":friendsobject[i],"status":status});
}
},"isFriend",1,"screen_name ASC");
}
BlueButton {
id: updateFriendsButton
text: "\uf021"
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 { }
Component.onCompleted: positionViewAtBeginning()
}
ListModel{id:friendsModel}
Component.onCompleted: {
root.friendsSignal.connect(showFriends);
friendsTabView.contactsSignal.connect(showFriends);
showFriends(root.login.username)
}
}
}
Tab{
title: qsTr("Other Contacts")
Rectangle{
id: contactsGridTab
function showContacts(contact){
try {contactsModel.clear()} catch(e){print(e)};
Helperjs.readData(db, "contacts",root.login.username,function(contactsobject){
for (var j=0;j<contactsobject.length;j++){
var status="";
if(contact){if (contact.id==contactsobject[j].id){status="large"}}
contactsModel.append({"contact":contactsobject[j],"status":status});
}
},"isFriend",0,"screen_name ASC");
}
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 { }
Component.onCompleted: positionViewAtBeginning()
}
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: "\uf021"
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);
}
}
}
}
Component.onCompleted: {
root.contactdetailsSignal.connect(showContactdetails);
}
}

View file

@ -0,0 +1,128 @@
import QtQuick 2.0
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"
}
Text {
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)
}
MouseArea{
anchors.fill: parent
onClicked:{
root.currentIndex=1;
friendstab.active=true;
root.contactdetailsSignal(groupmember)
}
}
}}
ListView{
id: groupListView
x:1
//anchors.top: parent.top
width: root.width-10*mm
height:groupsView.height -29*mm
clip: true
spacing: 2
model: groupModel
delegate: groupMember
}
ListModel{id: groupModel}
BlueButton{
id: closeButton
anchors.top: groupListView.bottom
anchors.topMargin: mm
text: "\uf057"
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 }
}
]
}

View file

@ -0,0 +1,153 @@
import QtQuick 2.0
import QtQuick.LocalStorage 2.0
import QtQuick.Window 2.0
import QtQuick.Controls 1.2
import QtQuick.Controls.Styles 1.4
import "qrc:/js/news.js" as Newsjs
import "qrc:/js/service.js" as Service
TabView{
id:root
property QtObject osSettings: {var tmp=Qt.createComponent("qrc:/qml/configqml/OSSettingsLinux.qml");return tmp.createObject(root)}
tabPosition: Qt.BottomEdge
width: osSettings.appWidth
height:osSettings.appHeight
focus:true
property var db: ["Friendiqa", "1.0", "Stores Friendica data", 100000000]
property var login: Service.readActiveConfig(db)
property var 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)
signal contactdetailsSignal(var contact)
//currentIndex: (login=="")? 3:0
property var news:[]
property var newContacts:[]
property int currentContact: 0
property string contactLoadType: ""
onLoginChanged:{
if(login==""){root.currentIndex=3}
else{
newstab.newstabstatus=login.newsViewType;
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()})}
}}
FontLoader{id: fontAwesome; source: "qrc:/images/fontawesome-webfont.ttf"}
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 === osSettings.backKey) {
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 if (currentIndex==2){fotoSignal("backButton")}
else {currentIndex=0}
event.accepted = true
}}
style: TabViewStyle {
frameOverlap: 1
tab: Rectangle {
color: styleData.selected?"sky blue":"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.family: fontAwesome.name
font.pixelSize: 3*mm
}
}
frame: Rectangle { color: "light grey" }
tabsAlignment:Qt.AlignHCenter
}
Tab{
title: "\uf03a"
id: newstab
property string newstabstatus
property var conversation
source:(root.currentIndex==0)? "qrc:/qml/newsqml/NewsTab.qml":""
}
Tab{
title: "\uf0c0"
id: friendstab
source: (root.currentIndex==1)?"qrc:/qml/contactqml/FriendsTab.qml":""
}
Tab{
title: "\uf03e"
id: fotostab
property string phototabstatus:"Images"
source: (root.currentIndex==2)?"qrc:/qml/photoqml/PhotoTab.qml":""
}
Tab{
title:"\uf085"
id: configtab
source: (root.currentIndex==3)?"qrc:/qml/configqml/ConfigTab.qml":""
}
}

View file

@ -0,0 +1,41 @@
import QtQuick 2.0
Rectangle{
id: blueButton
width: Math.max(mainText.width+2*mm,8*mm)
height: 5*mm
color:"light blue"
property alias fontColor: mainText.color
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.family:fontAwesome.name
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: "sky blue"} }
]
transitions: [
Transition { to:"*"
ColorAnimation { target: blueButton; duration: 100} }
]
}

View file

@ -0,0 +1,74 @@
import QtQuick 2.0
import Qt.labs.folderlistmodel 2.1
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
Rectangle{
id:attachmentDialog
z:2
border.color: "grey"
width: parent.width-4*mm
height:parent.height-12*mm
x:2*mm
y:10*mm
property var parsedAttachments: JSON.parse(attachedobjects)
Text{
x:0.5*mm
y:0.5*mm
width: imageDialog-8*mm
elide:Text.ElideRight
text: "Attachments:"
}
BlueButton{
id:closeButton
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
onClicked:{attachmentDialog.destroy()}
}
ListView {
id: attachmentView
x:0.5*mm
y:5.5*mm
width: attachmentDialog.width-2*mm
height: attachmentDialog.height-14*mm
clip: true
spacing:0
model: attachmentModel
delegate: attachmentItem
}
ListModel{id: attachmentModel}
Component { id:attachmentItem
Rectangle{
border.color: "#EEEEEE"
border.width: 1
width:parent.width
height:6*mm
Text{
font.pixelSize: 3*mm
x: mm
text:attachment.name
}
MouseArea{
anchors.fill: parent
onClicked:{
Qt.openUrlExternally(attachment.url)
}
}
}}
}
Component.onCompleted: {
for (var a in parsedAttachments){
attachmentModel.append({"attachment":parsedAttachments[a]})
}
}
}

View file

@ -0,0 +1,52 @@
// ConversationStack with buttons
import QtQuick 2.0
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
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: "\uf057"// 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)
}
}

View file

@ -0,0 +1,81 @@
// List if people from Friendica Activities
import QtQuick 2.0
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
Rectangle {
id:activitiesRectangle
property var activitymembers
color: "white"
border.color: "light grey"
radius:0.5*mm
width:root.width/2
height:Math.min(root.height/2,(10*mm+6*activitymembers.length*mm))
ListView {
id: contactView
x:mm
y:8*mm
width: activitiesRectangle.width-2*mm
height: activitiesRectangle.height-10*mm
clip: true
spacing: 0
model: activitiesModel
delegate: activitiesContact
}
ListModel{id: activitiesModel}
Component { id:activitiesContact
Rectangle{
border.color: "#EEEEEE"
border.width: 1
radius:0.5*mm
width:parent.width
height:6*mm
Image {
id: contactImage
x:1
y:1
width: 5*mm
height:5*mm
source:(contact.profile_image!="")? "file://"+contact.profile_image : contact.profile_image_url
onStatusChanged: if (contactImage.status == Image.Error) {source="qrc:/images/defaultcontact.jpg"}
}
Text{
font.pixelSize: 3*mm
anchors.left: contactImage.right
anchors.margins: 1*mm
text:Qt.atob(contact.name)
}
MouseArea{
anchors.fill: parent
onClicked:{
try {root.currentIndex=1;
friendstab.active=true;
root.contactdetailsSignal(contact)
} catch(e) {Helperjs.showMessage("Error",e,root)}}
}
}}
BlueButton {
id: closeButton
//width:10*mm
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
color:"white"
text: "\uf057"// qsTr("Close")
onClicked: {
activitiesRectangle.destroy()
}
}
Component.onCompleted: {
for (var user in activitymembers){
activitiesModel.append({"contact":activitymembers[user]})
}
}
}

View file

@ -0,0 +1,121 @@
import QtQuick 2.0
import QtQuick.Controls 1.2
import Qt.labs.folderlistmodel 2.1
import "qrc:/js/service.js" as Service
import "qrc:/js/helper.js" as Helperjs
import "qrc:/qml/genericqml"
Rectangle{
id:imageDialog
z:2
border.color: "grey"
width: parent.width-4*mm
height:parent.height-12*mm
x:2*mm
y:10*mm
property string directory: ""
Text{
id:directoryText
x:0.5*mm
y:0.5*mm
width: imageDialog.width-15*mm
height:contentHeight
wrapMode: Text.Wrap
text: directory
}
BlueButton{
id:closeButton
anchors.top: parent.top
anchors.topMargin: 1*mm
anchors.right: parent.right
anchors.rightMargin: 1*mm
text: "\uf057"
onClicked:{imageDialog.destroy()}
}
ListView {
id: imageView
x:0.5*mm
y:directoryText.height+mm
width: imageDialog.width-2*mm
height: imageDialog.height-directoryText.height-4*mm
clip: true
model: imageModel
delegate: imageItem
}
FolderListModel{
id: imageModel
nameFilters: ["*.png", "*.jpg",".jpeg","*.JPG"]
sortField: FolderListModel.Time
sortReversed:false
showDotAndDotDot: true
showDirs: true
showDirsFirst: true
folder:directory
}
BusyIndicator{
id: imageBusy
anchors.horizontalCenter: imageView.horizontalCenter
anchors.top:imageView.top
anchors.topMargin: 2*mm
width:10*mm
height: 10*mm
running:false
}
Component{
id:imageItem
Item{
width:imageView.width
height:folderImage.height+2*mm
Rectangle{
id:imagetextRectangle
color:"black"
x:mm
z:3
opacity: fileIsDir?0:0.5
width:imagetext.contentWidth
height: imagetext.contentHeight
anchors.bottom: folderImage.bottom
}
Text {
id:imagetext
x:fileIsDir?11*mm:mm
z:4
text: fileName
width: fileIsDir?parent.width - 12*mm :imageView.width-mm
anchors.bottom: folderImage.bottom
color: fileIsDir?"black":"white"
font.pixelSize: 3*mm
wrapMode:Text.Wrap
}
Image{id:folderImage
width: fileIsDir?10*mm: imageView.width-mm
fillMode:Image.PreserveAspectFit
source:fileIsDir?"qrc:/images/folder-blue.png":fileURL
}
MouseArea{
anchors.fill: parent
onClicked:{
if (fileName==".."){
imageModel.folder=imageModel.parentFolder;
directory=imageModel.parentFolder
}
else if (fileIsDir){
imageModel.folder=fileURL;
directory=fileURL
}
else{
attachImageURL=fileURL;
imageDialog.destroy()
}
}
}
}
}
}

View file

@ -0,0 +1,199 @@
// message.qml
// message with buttons
import QtQuick 2.0
import QtQuick.Controls 1.3
import QtQuick.Dialogs 1.2
import "qrc:/js/helper.js" as Helperjs
import "qrc:/js/smiley.js" as Smileyjs
import "qrc:/qml/genericqml"
Flickable{
width:root.width-5*mm
height:root.height-12*mm
contentHeight: messageColumn.height
boundsBehavior: Flickable.StopAtBounds
id:messageSend
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]
onAttachImageURLChanged: {if(attachImageURL!=""){
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)
}}
function statusUpdate(title,status,in_reply_to_status_id,attachImageURL) {
xhr.url= login.server + "/api/statuses/update.json";
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.json";
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:"\uf0c1"
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:"\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{id:permButton
visible: (directmessage==1)?false:true
text: ((contact_allow.length==0)&&(contact_deny.length==0)&&(group_allow.length==0)&&(group_deny.length==0))?"\uf09c":"\uf023"//qsTr("Permissions")
onClicked: {
var component = Qt.createComponent("qrc:/qml/newsqml/PermissionDialog.qml");
var permissions = component.createObject(messageColumn);
}}
BlueButton {
id: attachButton
text: "\uf0c6"
visible:(directmessage==0)
onClicked: {
if (attachImageURL!=""){
Helperjs.showMessage( qsTr("Error"),qsTr("Only one attachment. Remove other attachment first!"), messageColumn)}
else{print(filesystem.homePath);
var defaultDirectory="file://"+osSettings.attachImageDir;//"file:///storage/emif.open()
print(defaultDirectory);
var component = Qt.createComponent("qrc:/qml/newsqml/ImageDialog.qml");
var imagedialog = component.createObject(messageSend,{"directory": defaultDirectory});
}
}
}
BlueButton{
id:contactButton
text:"\uf234"
visible:(directmessage==0)
onClicked:{
var contactitems="";
for (var i=0;i<contacts.length;i++){
if(contacts[i].network=="dfrn"){
if(Helperjs.getCount(db,login,"contacts","screen_name",contacts[i].screen_name)>1){
contacts[i].screen_name=contacts[i].screen_name+"+"+contacts[i].cid
}
contactitems=contactitems+"MenuItem{text:'"+contacts[i].screen_name+"';iconSource:'"+contacts[i].profile_image+"'; onTriggered: bodyField.insert(0,' @"+contacts[i].screen_name+"+"+contacts[i].cid+" ')}"
}}
var menuString="import QtQuick.Controls 1.4; Menu {"+contactitems+"}";
var contactlistObject=Qt.createQmlObject(menuString,messageSend,"contactmenuOutput")
contactlistObject.popup() }
}
BlueButton{
id:smileyButton
text: "\uf118"
onClicked: {
var smileyarray=Smileyjs.smileys
//print(JSON.stringify(smileyarray[0]))
var component = Qt.createComponent("qrc:/qml/newsqml/SmileyDialog.qml");
var smileydialog = component.createObject(messageColumn)
}}
BlueButton {
id: cancelButton
text: "\uf057"
onClicked: {newstab.newstabstatus=login.newsViewType;
newsStack.pop()}
}
BlueButton {
id: sendButton
text: "\uf1d9"
onClicked: {
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) }
newstab.newstabstatus=login.newsViewType; newsStack.pop()
}
}
}
}
}

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