Commit 01dca7e2 authored by armin's avatar armin
Browse files

Merge branch 'master' into 'production'

Master

See merge request !121
parents b64864db ec9aca0c
Pipeline #513 passed with stage
in 1 minute and 51 seconds
Subproject commit 6e640a6600c7168523d688b1b7dccebc65504d97
Subproject commit 22ddc54fa1c6bc6721fa28ffd0a60a0181d2a6f7
<?xml version="1.0"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.osalliance.rocketchatMobile" android:installLocation="auto" android:versionCode="1" android:versionName="0.5">
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="fairchat">
<application android:name="org.qtproject.qt5.android.bindings.QtApplication" android:hardwareAccelerated="true" android:icon="@drawable/icon" android:label="fairchat" android:allowBackup="false">
<activity android:name="com.osalliance.rocketchatMobile.MainActivity" android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation" android:label="fairchat" android:launchMode="singleTop" android:screenOrientation="unspecified">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
......
......@@ -25,7 +25,7 @@ else:unix: PRE_TARGETDEPS += $$OUT_PWD/../engine/libengine.a
TARGET = fairchat
VER_MAJ = 1
VER_MIN = 1
VER_PAT = 8
VER_PAT = 9
VERSION = $$sprintf("%1.%2.%3",$$VER_MAJ,$$VER_MIN,$$VER_PAT)
DEFINES += VERSION=\\\"$$VERSION\\\"
......
......@@ -86,7 +86,7 @@
NSArray *pathComponents = [url pathComponents];
NSString *channel = pathComponents[pathComponents.count-1];
NSLog(@"%@",channel);
DelegateObject *delegateObject = [[DelegateObject alloc] init];
DelegateObject *delegateObject = [[DelegateObject alloc] init];o
[delegateObject initWithCPPInstance];
[delegateObject openChannelByName:channel ];
......@@ -101,6 +101,20 @@
return YES;
}
-(BOOL)application:(UIApplication*)application openURL:(nonnull NSURL *)url options:(nonnull NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
ShareHelperSingelton *instance = ShareHelperSingelton::getInstance();
NSString *fileStr = url.path;
NSLog(@"%@",fileStr);
QString file = QString::fromNSString(fileStr);
instance->setPath(file);
return YES;
}
-(void)application:(UIApplication*)application didRegisterUserNotificationSettings:( UIUserNotificationSettings *)notificationSettings{
[application registerForRemoteNotifications];
}
......
......@@ -18,7 +18,9 @@
* *
********************************************************************************************/
#include <QDesktopServices>
#include <QDebug>
#include <QFileInfo>
#include "ioshelper.h"
IosHelper::IosHelper( QObject *parent ) : QObject( parent )
......@@ -26,11 +28,10 @@ IosHelper::IosHelper( QObject *parent ) : QObject( parent )
mShareHelper = ShareHelperSingelton::getInstance();
mGalleryPicker = new IosGalleryPicker();
connect( mShareHelper, &ShareHelperSingelton::shareLinkReceived, this, &IosHelper::shareLinkReceived, Qt::UniqueConnection );
connect( mShareHelper, &ShareHelperSingelton::shareLinkReceived, this, &IosHelper::checkForFileLink, Qt::UniqueConnection );
connect( mGalleryPicker, &IosGalleryPicker::filePicked, this, &IosHelper::filePicked, Qt::UniqueConnection );
connect( &mNotificationsObject, &Notifications::tokenReceived, this, &IosHelper::pushTokenReceived, Qt::UniqueConnection );
connect( &mNotificationsObject, &Notifications::messageReceived, this, &IosHelper::pushMessageReceived, Qt::UniqueConnection );
}
IosHelper::~IosHelper()
......@@ -47,7 +48,19 @@ void IosHelper::checkForpendingNotification()
void IosHelper::checkForFileLink()
{
QString path = mShareHelper->getPath();
if(path.startsWith("file://")) {
path= path.right(path.length()-7);
qDebug() << "QFile needs this URL: " << path;
}
qDebug()<<"file to upload: "<< path;
QFileInfo fileInfo = QFileInfo(path);
if(fileInfo.exists()) {
qDebug()<<"file exists";
} else {
qDebug() << "setFileUrlReceived: FILE does NOT exist ";
}
if ( !path.isEmpty() ) {
emit shareLinkReceived( path );
}
......
#include "shareheplersingelton.h"
#include <QDebug>
ShareHelperSingelton *ShareHelperSingelton::mInstance = nullptr;
......@@ -18,5 +19,6 @@ QString ShareHelperSingelton::getPath()
void ShareHelperSingelton::setPath(QString pPath)
{
mCurPath = pPath;
qDebug()<<pPath;
emit shareLinkReceived(pPath);
}
......@@ -50,7 +50,8 @@ ServerChoiceModel::ServerChoiceModel()
query.prepare( "CREATE TABLE IF NOT EXISTS server_choice "
"(id integer primary key,"
"hostname varchar(40),"
"description varchar(40))" );
"description varchar(40),"
"unsecure integer)" );
if ( !query.exec() ) {
qWarning() << "db error" << query.lastError();
......@@ -70,26 +71,34 @@ QList<ServerChoice> ServerChoiceModel::getServerList() const
QSqlRecord rec = domainQuery.record();
int hostNameCol = rec.indexOf( "hostname" );
int descCol = rec.indexOf( "description" );
int unsecureCol = rec.indexOf( "unsecure" );
while ( domainQuery.next() ) {
QString domain = domainQuery.value( hostNameCol ).toString();
QString description = domainQuery.value( descCol ).toString();
servers.append( {description, domain} );
bool unsecure = false;
if ( unsecureCol != -1 ) {
unsecure = domainQuery.value( unsecureCol ).toBool();
}
servers.append( {description, domain, unsecure} );
}
}
servers.push_front( {"Rocket.Chat demo", "open.rocket.chat"} );
servers.push_front( {"fairchat", "fairchat.net"} );
servers.push_front( {"Rocket.Chat demo", "open.rocket.chat", false} );
servers.push_front( {"fairchat", "fairchat.net", false} );
return servers;
}
void ServerChoiceModel::addDomain( QString value, QString description )
void ServerChoiceModel::addDomain( QString value, QString description, bool unsecure = false )
{
QSqlQuery domainQuery( mDb );
beginResetModel();
domainQuery.prepare( "INSERT INTO server_choice (hostname, description) VALUES(?,?)" );
domainQuery.prepare( "INSERT INTO server_choice (hostname, description, unsecure) VALUES(?,?,?)" );
domainQuery.addBindValue( value );
domainQuery.addBindValue( description );
domainQuery.addBindValue( unsecure );
if ( !domainQuery.exec() ) {
qWarning() << "db error" << domainQuery.lastError();
......@@ -118,22 +127,27 @@ QVariant ServerChoiceModel::data( const QModelIndex &index, int role ) const
{
auto choice = getServerList()[index.row()];
if ( role == 1 ) {
if ( role == ServerRoles::domain ) {
return choice.domain;
}
if ( role == 2 ) {
if ( role == ServerRoles::description ) {
return choice.description;
}
if ( role == ServerRoles::unsecure ) {
return choice.unsecure;
}
return QVariant();
}
QHash<int, QByteArray> ServerChoiceModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[1] = "domain";
roles[2] = "description";
roles[ServerRoles::domain] = "domain";
roles[ServerRoles::description] = "description";
roles[ServerRoles::unsecure] = "unsecure";
return roles;
}
......@@ -147,6 +161,16 @@ void ServerChoiceModel::setCurrentServerDesc( const QString &value )
currentServerDesc = value;
}
bool ServerChoiceModel::getCurrentServerUnsecure()
{
return currentServerUnsecure;
}
void ServerChoiceModel::setCurrentServerUnsecure( bool pUnsecure )
{
currentServerUnsecure = pUnsecure;
}
QString ServerChoiceModel::getCurrentServer() const
{
return currentServer;
......
......@@ -51,18 +51,26 @@
struct ServerChoice {
QString description;
QString domain;
bool unsecure;
};
class ServerChoiceModel : public QAbstractListModel
{
Q_OBJECT
enum ServerRoles {
domain = Qt::UserRole + 1,
description,
unsecure
};
QSqlDatabase mDb = QSqlDatabase::addDatabase( "QSQLITE", "serverConnection" );
public:
Q_PROPERTY( QString currentServer READ getCurrentServer WRITE setCurrentServer NOTIFY currentServerChanged )
Q_PROPERTY( QString currentServerDesc READ getCurrentServerDesc WRITE setCurrentServerDesc )
Q_PROPERTY( bool currentServerUnsecure READ getCurrentServerUnsecure WRITE setCurrentServerUnsecure )
ServerChoiceModel( void );
QList<ServerChoice> getServerList( void ) const;
Q_INVOKABLE void addDomain( QString, QString );
Q_INVOKABLE void addDomain( QString, QString, bool unsecure );
Q_INVOKABLE void removeDomain( QString );
int rowCount( const QModelIndex &parent = QModelIndex() ) const;
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const;
......@@ -70,6 +78,8 @@ class ServerChoiceModel : public QAbstractListModel
void setCurrentServer( const QString &value );
QString getCurrentServerDesc() const;
void setCurrentServerDesc( const QString &value );
bool getCurrentServerUnsecure();
void setCurrentServerUnsecure( bool pUnsecure );
signals:
void currentServerChanged( void );
......@@ -77,6 +87,7 @@ class ServerChoiceModel : public QAbstractListModel
QHash<int, QByteArray> roleNames() const;
QString currentServer;
QString currentServerDesc;
bool currentServerUnsecure = false;
};
#endif // SERVERCHOICEMODEL_H
......@@ -17,7 +17,6 @@
<file>qml/navigation/TopBar.qml</file>
<file>qml/popups/AddUsersToRoomPopup.qml</file>
<file>qml/popups/WelcomePopup.qml</file>
<file>qml/popups/SharePopUp.qml</file>
<file>qml/popups/LogoutDialog.qml</file>
<file>qml/popups/CreatePrivateChannelPopup.qml</file>
<file>qml/popups/CreatePrivateGroupPopup.qml</file>
......@@ -144,5 +143,11 @@
<file>qml/pages/searchView/MessageResultsList.qml</file>
<file>res/buttons/other/search.svg</file>
<file>qml/pages/channelView/messageTypes/AddedUserMessage.qml</file>
<file>res/images/lock.svg</file>
<file>res/images/lock-open.svg</file>
<file>qml/various/RoomLockImage.qml</file>
<file>qml/pages/channelView/messageTypes/MessageReply.qml</file>
<file>qml/pages/channelView/MessageMenu.qml</file>
<file>qml/pages/channelView/ReplyToMessage.qml</file>
</qresource>
</RCC>
......@@ -82,7 +82,7 @@ StackLayout {
}
populate: Transition {
}
cacheBuffer:0
cacheBuffer:100
}
GridView {
id: emojiNatureGrid
......@@ -109,7 +109,7 @@ StackLayout {
}
populate: Transition {
}
cacheBuffer:0
cacheBuffer:100
}
GridView {
id: emojiFoodGrid
......@@ -136,7 +136,7 @@ StackLayout {
}
populate: Transition {
}
cacheBuffer:0
cacheBuffer:100
}
GridView {
id: emojiCategoryGrid
......@@ -163,7 +163,7 @@ StackLayout {
}
populate: Transition {
}
cacheBuffer:0
cacheBuffer:100
}
GridView {
id: emojiTravelGrid
......@@ -190,7 +190,7 @@ StackLayout {
}
populate: Transition {
}
cacheBuffer:0
cacheBuffer:100
}
GridView {
id: emojiObjectsGrid
......@@ -217,7 +217,7 @@ StackLayout {
}
populate: Transition {
}
cacheBuffer:0
cacheBuffer:100
}
GridView {
id: emojiSymbolsGrid
......@@ -244,7 +244,7 @@ StackLayout {
}
populate: Transition {
}
cacheBuffer:0
cacheBuffer:100
}
GridView {
id: emojiFlagsGrid
......@@ -271,6 +271,6 @@ StackLayout {
}
populate: Transition {
}
cacheBuffer:0
cacheBuffer:100
}
}
......@@ -60,9 +60,6 @@ ApplicationWindow {
fillMode: Image.Stretch
}
WelcomePopup {
id: welcomePopup
}
JitsiMeetMissing{
id: jitsiMeetMissing
}
......@@ -122,6 +119,11 @@ ApplicationWindow {
mainStack.pop()
}
}
function backToLogin(){
while(mainStack.depth > 1){
mainStack.pop();
}
}
}
MessageDialog {
id: messageDialog
......@@ -164,7 +166,7 @@ ApplicationWindow {
Component.onCompleted: {
if(rocketChatController.customEmojisReady){
// Emoji.addEmojisPerCategory()
// Emoji.addEmojisPerCategory()
}
if (rocketChatController.getDdpConnectionEstablished()) {
connectionState = 1
......@@ -177,6 +179,7 @@ ApplicationWindow {
Print.log("error login")
if (mainStack.mainViewPushed) {
mainStack.reset()
mainStack.backToLogin();
}
if (connectionState == 2) {
connectionState = 1
......@@ -196,13 +199,14 @@ ApplicationWindow {
connectionState = 0
}
onError: {
messageDialog.text = text + '<br>Please select a file. <br>We recommend the Amaze App as file manager. Get it from the f-droid.org or Google app store.'
messageDialog.text = text
messageDialog.open()
}
function getUserAvatar(url){
}
//TODO: depricated
onFileRessourceProcessed: {
// if(rocketChatController.isStorageReady()){
// getUserAvatar(url);
......@@ -247,5 +251,10 @@ ApplicationWindow {
onNoJitsiMeetAvailable:{
jitsiMeetMissing.open()
}
onOpenShareDialog:{
while(mainStack.depth>2){
mainStack.navBack()
}
}
}
}
......@@ -75,7 +75,7 @@ Item {
ConnectionIndicator {
// anchors.centerIn: parent
anchors.left: parent.left
anchors.leftMargin: 15
anchors.leftMargin: 130
}
TextField{
anchors.right: parent.right
......
......@@ -53,17 +53,21 @@ Page {
Label {
id: aboutText
text: "<b>fairchat App</b>
text: "<b>fairchat App Version "+version+"</b>
<p>
Questions? Read the <a href=\"https://fairchat.eu/tipps-faqs\" style=\"color: grey;\">FAQs</a> or our <a href=\"https://fairchat.eu/tutorial\" style=\"color: grey;\">Tutorial</a>.
<br>
For GDPR compliance see our <a href=\"https://fairchat.net/privacy-policy\" style=\"color: grey;\"> privacy statement.</a>
</p>
<p>
Provided by osAlliance.com<br>
Contact: info@fairkom.eu</br>
</p>
<p>
Rocket.Chat mobile App Version "+version+"<br>
Get your account at fairchat.net or at any other Rocket.Chat server.<br>
Connects to fairchat.net or any Rocket.Chat server.
</p>
<p>
App features include:
<ul>
<li>browse or start groups</li>
......@@ -71,17 +75,20 @@ App features include:
<li>send text with emojis</li>
<li>photo, video and file upload</li>
<li>start video conference </li>
<li>push notifications (via https://gateway.fairchat.net)</li>
<li>in sync with web interface and multiple devices</li>
<li>mobile push notifications (via https://gateway.fairchat.net)</li>
<li>in sync with web interface and other devices</li>
<li>NEW: search messages and channels</li>
</ul>
Please use the web interface to access even more features and settings. Archived groups or channels are not shown in the app.<br>
Connect with your PC or Laptop to access even more features and settings. Archived groups or channels are not shown in the app.
</p>
<p>
If you found a bug or have a wish, see if somebody else already reported it in our <a href=\"https://git.fairkom.net/chat/fairchat/boards\" style=\"color: grey;\">issue tracker</a> or submit it there.
</p>
<p>
<b>Flag Procedure</b>
</p>
<p>Objectionable content or abusive users may be flagged to the provider of the respective chat server. In case of fairchat.net, report any incident to <a href=\"mailto:support@fairkom.eu?subject=fairchat%20Flag%20Procedure\">support@fairkom.eu</a>.
</p>
<br>
<p>
<b>App License</b>
</p>
......
......@@ -25,6 +25,7 @@ import QtMultimedia 5.8
import QtQuick.Dialogs 1.2
import QtQuick.Window 2.0
import QtQuick.Layouts 1.3
import QtGraphicalEffects 1.0
import "qrc:/qml/navigation"
import "qrc:/qml/various"
......@@ -125,6 +126,13 @@ Page {
height: childrenRect.height
width: messageView.width - 34
onReplyTo:{
replyToMessage.visible = true
replyToMessage.text = model.msg
replyToMessage.author = model.author
replyToMessage.messageId = model.id
replyToMessage.replyUrl = model.replyUrl
}
}
/*delegate: Text {
id: name
......@@ -193,9 +201,67 @@ Page {
footer: Rectangle {
height: 15
}
onVerticalVelocityChanged: {
if(verticalVelocity < 0 && !messageView.atYEnd){
scrollDown.stateVisible = true
}else if (verticalVelocity !== 0){
scrollDown.stateVisible = false
}
}
Rectangle {
id: scrollDown
width: 40
height: width
color: Colors.primary
border.color: "black"
border.width: 0
radius: width*0.5
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 25
property bool stateVisible: false
opacity: 0
Text {
color: Colors.fontColor
text: "V"
anchors.centerIn: parent
}
MouseArea{
anchors.fill: parent
onClicked: {
messageView.positionViewAtEnd();
parent.stateVisible = false;
}
}
states: [
State {
name: "visible";
when: scrollDown.stateVisible;
PropertyChanges { target: scrollDown; opacity: 0.8 }
},
State {
name: "unvisible";
when: !scrollDown.stateVisible;
PropertyChanges { target: scrollDown; opacity: 0.0 }
}
]
transitions: Transition {
NumberAnimation { property: "opacity"; duration: 500}
}
}
}
ReplyToMessage{
id: replyToMessage
anchors.bottom: bottomToolbar.top
anchors.left: parent.left
anchors.right: parent.right
visible: false;
}
ChannelViewFooterToolbar {
visible: !channelView.readOnly
replyUrl: replyToMessage.replyUrl
height:{
if(visible){
return childrenRect.height
......@@ -207,7 +273,11 @@ Page {
anchors.right: parent.right
anchors.bottom: parent.bottom
id: bottomToolbar
onMessageSend:{
replyToMessage.reset()
}
}
}
......@@ -258,6 +328,7 @@ Page {
var readonlyFlag = false
var mutedFlag = false
var blocked = false
var owner = false;
if (details1.hasOwnProperty("ro")) {
readonlyFlag = details1["ro"]
}
......@@ -276,8 +347,11 @@ Page {
if(details1.hasOwnProperty("blocked")){
blocked = details1["blocked"];
}
if(details1.hasOwnProperty("ownerName")){
owner = details["ownerName"] === rocketChatController.getUsername("default");
}
channelView.readOnly = readonlyFlag || archivedFlag || mutedFlag || blocked
channelView.readOnly = (readonlyFlag && !owner) || archivedFlag || mutedFlag || blocked
channelView.archived = archivedFlag
}
}
......@@ -386,4 +460,5 @@ Page {
Component.onDestruction: {
window.activeChannel = ""
}
}
......@@ -53,17 +53,19 @@ Page {
property string previousServer:""
property alias currentServerChoice: currentServer.text
property alias currentServerChoiceDesc: currentServerdesc.text
property bool currentServerUnsecure: false
property int offlineMode: 0;
Component.onCompleted: {
var current = serverChoices.currentServer
if (serverChoices.currentServer) {
currentServerChoice = serverChoices.currentServer
currentServerChoiceDesc = serverChoices.currentServerDesc
currentServerUnsecure = serverChoices.currentServerUnsecure
mainStack.mainViewPushed = false
loginStatus.text = ""
}
previousServer = serverChoices.currentServer
rocketChatController.newServerByDomain(currentServerChoice)
rocketChatController.newServerByDomain(currentServerChoice, currentServerUnsecure)
}
}
Connections {
......@@ -74,8 +76,9 @@ Page {
currentServerSetting.previousServer = serverChoices.currentServer
currentServerSetting.currentServerChoice = serverChoices.currentServer
currentServerSetting.currentServerChoiceDesc = serverChoices.currentServerDesc
currentServerSetting.currentServerUnsecure = serverChoices.currentServerUnsecure
rocketChatController.newServerByDomain(