Commit d05342db authored by armin's avatar armin

Merge branch 'master' into responsiveLoginPage

parents 426f5bae 67bf77bc
Pipeline #798 passed with stage
in 4 minutes and 17 seconds
......@@ -5,11 +5,11 @@ stages:
- build
- deploy
docker:build:Qt:5.9:
docker:build:Qt:5.12.1:
stage: build
script:
- ls
- docker create --name ci-$CI_COMMIT_SHA-qt-android-docker -v ~/.gradle:/root/.gradle -v ~/.ccache:/root/.ccache afelder/qt-android-docker /bin/bash -c "mkdir -p /src/build && cd /src/build && ls /src && /opt/Qt/5.9.7/android_armv7/bin/qmake -spec android-g++ ../RocketChatMobileModular.pro && make -j9 && make install INSTALL_ROOT=/src/build/android-build/ &&/opt/Qt/5.9.7/android_armv7/bin/androiddeployqt --input fairchat/android-libfairchat.so-deployment-settings.json --output android-build --deployment bundled --android-platform android-28 --jdk /usr/lib/jvm/java-8-oracle --gradle"
- docker create --name ci-$CI_COMMIT_SHA-qt-android-docker -v ~/.gradle:/root/.gradle -v ~/.ccache:/root/.ccache afelder/qt-android-docker /bin/bash -c "mkdir -p /src/build && cd /src/build && ls /src && /opt/Qt/5.12.1/android_armv7/bin/qmake -spec android-clang ../RocketChatMobileModular.pro && make -j9 && make install INSTALL_ROOT=/src/build/android-build/ &&/opt/Qt/5.12.1/android_armv7/bin/androiddeployqt --input fairchat/android-libfairchat.so-deployment-settings.json --output android-build --deployment bundled --android-platform android-28 --jdk /usr/lib/jvm/java-8-oracle --gradle"
- docker cp ./ ci-$CI_COMMIT_SHA-qt-android-docker:/src/
- docker start ci-$CI_COMMIT_SHA-qt-android-docker -a
after_script:
......
......@@ -2,7 +2,7 @@
## fairchat App
Qt based mobile app for Android, iOS, Windows Phone.
Qt based mobile app for Android, iOS, ~~Windows Phone~~(dropped), with partial support for Desktop (Windows, MacOS, Linux)
Customized version for fairchat.net
Provided by osAlliance.com
......@@ -30,33 +30,30 @@ GPLv3
* Add users to groups
## Build instructions
Install Qt5.8 Creator for Android on Linux
Install Qt5.12 for Android on Linux
Add Android SDK and add with SDK Manager your target SDK (e.g. 25 for Android 7)
Add in Qt5 path to NDK and SDK Android Kit
Install Android NDK
sudo apt-get install libgl-dev libpulse-dev
Start qt5 Creator and pull git
Start QtCreator and pull git
build and run on your Linux desktop for testing
### Deploy on Android
Build for Android 4.1 - 7.1:
Build for Android 4.2 - 9:
Connect your Android device with USB, get it into developer mode and switch USB debugging on.
In Qt creator on left menu bar select "Projects" and at Build settings for Android select "Use Gradle".
In Projects->android-arm...->Build Android APK->Additional Libraries->
You may need to add manually openssl/android/libopenssl.so + openssl/android/libcrypto.so
### Deploy on iOS
Needs OS X as build environment
Install Qt Creator as described above
Code has to be built as Objective-C++ (-> Build Settings -> LLVM... -> Compile As)
App dev cert has to be installed in OS X certmanager, download here: https://developer.apple.com/account/ios/certificate/development
To have Push Notifications work correctly, the App needs to be signed and bundle identifier must be set
### Deploy on Windows Phone
how-to pending
dropped
## Issues & Feature requests
......
......@@ -7,15 +7,20 @@ contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
$$PWD/openssl/android-arm/libcrypto.so \
$$PWD/openssl/android-arm/libssl.so
}
contains(ANDROID_TARGET_ARCH,armeabi-v8a) {
contains(ANDROID_TARGET_ARCH,arm64-v8a) {
ANDROID_EXTRA_LIBS = \
$$PWD/../openssl/android-arm64/libssl.so \
$$PWD/../openssl/android-arm64/libcrypto.so
}
contains(ANDROID_TARGET_ARCH,) {
contains(ANDROID_TARGET_ARCH,x86) {
ANDROID_EXTRA_LIBS = \
$$PWD/../openssl/android-arm64/libssl.so \
$$PWD/../openssl/android-arm64/libcrypto.so
$$PWD/../openssl/android-x86/libssl.so \
$$PWD/../openssl/android-x86/libcrypto.so
}
contains(ANDROID_TARGET_ARCH,x86_64) {
ANDROID_EXTRA_LIBS = \
$$PWD/../openssl/android-x86_64/libssl.so \
$$PWD/../openssl/android-x86_64/libcrypto.so
}
win32{
!contains(QMAKE_TARGET.arch, x86_64) {
......
Subproject commit 5a15fd3b891f3d4a25cc02b686ebefaa9a456050
Subproject commit 9ab892de72db4d211e6ad93e21f6e07cef3b412f
......@@ -105,25 +105,41 @@ android {
defaultConfig {
int archCode = 0
project.logger.lifecycle(android_armv7.toString())
project.logger.lifecycle(android_armv8.toString())
project.logger.lifecycle(android_x86.toString())
if (android_armv7 == 1) {
ndk {
abiFilters 'armeabi-v7a'
}
archCode = 0
project.logger.lifecycle("arm 32")
} else if (android_armv8 == 1){
ndk {
abiFilters 'arm64-v8a'
}
archCode = 1
project.logger.lifecycle("arm 64")
} else if(android_x86 == 1){
ndk {
abiFilters 'x86'
}
archCode = 2
}else if(android_x86_64 == 1){
ndk {
abiFilters 'x86_64'
}
archCode = 3
}
versionCode versionMajor * (100000 + versionMinor * 1000)+1 + versionPatch * 100
versionCode versionMajor * 100000 + versionMinor * 1000 + versionPatch * 10 + archCode
project.logger.lifecycle(versionCode.toString())
versionName QtApp.VERSION
}
......
......@@ -128,8 +128,8 @@ public class MainActivity extends QtActivity {
e.printStackTrace();
}*/
Fabric fabric = new Fabric.Builder(this).debuggable(true).kits(new Crashlytics(), new CrashlyticsNdk()).build();
Fabric.with(fabric);
// Fabric fabric = new Fabric.Builder(this).debuggable(true).kits(new Crashlytics(), new CrashlyticsNdk()).build();
Fabric.with(this, new Crashlytics(), new CrashlyticsNdk());
//Fabric.with(this, new Crashlytics(), new CrashlyticsNdk());
//Fabric.with(this, new Crashlytics(), new CrashlyticsNdk());
......
......@@ -43,7 +43,7 @@ message($$PRE_TARGETDEPS)
TARGET = fairchat
VER_MAJ = 1
VER_MIN = 2
VER_PAT = 0
VER_PAT = 1
VERSION = $$sprintf("%1.%2.%3",$$VER_MAJ,$$VER_MIN,$$VER_PAT)
ANDROID_ARM64 = 0
......@@ -51,18 +51,29 @@ ANDROID_ARMv7 = 0
ANDROID_x86 = 0
ANDROID_x86_64 = 0
contains(ANDROID_TARGET_ARCH,armeabi-v8a) {
ANDROID_ARM64 = 1
}
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
ANDROID_ARMv7 = 1
ANDROID_EXTRA_LIBS = \
$$PWD/../openssl/android-arm/libcrypto.so \
$$PWD/../openssl/android-arm/libssl.so
}
contains(ANDROID_TARGET_ARCH,arm64-v8a) {
ANDROID_ARM64 = 1
ANDROID_EXTRA_LIBS = \
$$PWD/../openssl/android-arm64/libssl.so \
$$PWD/../openssl/android-arm64/libcrypto.so
}
contains(ANDROID_TARGET_ARCH,x86) {
ANDROID_x86 = 1
ANDROID_EXTRA_LIBS = \
$$PWD/../openssl/android-x86/libssl.so \
$$PWD/../openssl/android-x86/libcrypto.so
}
contains(ANDROID_TARGET_ARCH,x86_64) {
ANDROID_x86_64 = 1
ANDROID_EXTRA_LIBS = \
$$PWD/../openssl/android-x86_64/libssl.so \
$$PWD/../openssl/android-x86_64/libcrypto.so
}
DEFINES += VERSION=\\\"$$VERSION\\\"
......@@ -102,17 +113,6 @@ android{
QMAKE_POST_LINK = $$QMAKE_COPY $$shell_path($$[QT_INSTALL_TRANSLATIONS]/qt*_de.qm) $$TRDESTDIR
}
contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
ANDROID_EXTRA_LIBS = \
$$PWD/../openssl/android-arm/libssl.so \
$$PWD/../openssl/android-arm/libcrypto.so
}
contains(ANDROID_TARGET_ARCH,armeabi-v8a) {
ANDROID_EXTRA_LIBS = \
$$PWD/../openssl/android-arm64/libssl.so \
$$PWD/../openssl/android-arm64/libcrypto.so
}
ios{
QT += gui-private
......@@ -163,7 +163,7 @@ ios{
QMAKE_ASSET_CATALOGS = $$PWD/ios/Images.xcassets
QMAKE_ASSET_CATALOGS_APP_ICON = "Appicon"
QMAKE_IOS_DEPLOYMENT_TARGET = 10.0
QMAKE_IOS_DEPLOYMENT_TARGET = 11.0
QMAKE_APPLE_TARGETED_DEVICE_FAMILY = 1
PRODUCT_NAME = fairchat
#PRODUCT_BUNDLE_IDENTIFIER = com.osalliance.RocketChatMobile
......
......@@ -42,6 +42,7 @@ class IosGalleryPicker: public QObject
void receiveFile( QString pFileUrl );
private:
void openGalleryPicker();
QString mImagePath;
void *mDelegate;
......
......@@ -43,16 +43,22 @@
UIImage *orig = [info valueForKey:UIImagePickerControllerOriginalImage];
PHAsset *asset = [info valueForKey:UIImagePickerControllerPHAsset];
NSString *filename = [asset valueForKey:@"filename"];
QString qFilename = QString::fromNSString(filename);
auto assetRes = [PHAssetResource assetResourcesForAsset:asset];
auto assetObj = [assetRes firstObject];
QStringList fileParts = qFilename.split(".");
QString fileExt = fileParts[fileParts.length()-1];
if(assetObj){
NSString * filename = [assetObj originalFilename ];
NSString *assetUti = [assetObj valueForKey:@"uniformTypeIdentifier"];
QString assetUtiStr = QString::fromNSString(assetUti);
QString qFilename = QString::fromNSString(filename);
NSData *imgData = nil;
if(!fileExt.compare("png",Qt::CaseInsensitive)){
if(assetUtiStr == "public.png"){
imgData = UIImagePNGRepresentation(orig);
}else{
imgData = UIImageJPEGRepresentation(orig, 1.0);
......@@ -60,12 +66,16 @@
QByteArray qImgData = QByteArray::fromNSData(imgData);
QString path = QStandardPaths::writableLocation( QStandardPaths::DocumentsLocation );
path += "/"+QString::fromNSString(filename);
path += "/"+qFilename;
QFile destFile(path);
destFile.open(QFile::WriteOnly);
if(destFile.write(qImgData)>0){
mIosPicker->receiveFile(path);
}
}else{
qWarning()<<"failed to pick file";
}
[picker dismissViewControllerAnimated:YES completion:NULL];
[picker release];
}
......@@ -83,6 +93,28 @@ void IosGalleryPicker::receiveFile(QString pFileUrl){
void IosGalleryPicker::open()
{
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
if(status != PHAuthorizationStatusAuthorized){
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status){
switch (status) {
case PHAuthorizationStatusAuthorized:
openGalleryPicker();
break;
case PHAuthorizationStatusRestricted:
break;
case PHAuthorizationStatusDenied:
break;
default:
break;
}
}];
}else{
openGalleryPicker();
}
}
void IosGalleryPicker::openGalleryPicker(){
UIViewController *qtController = [[UIApplication sharedApplication].keyWindow rootViewController];
UIImagePickerController *imageController = [[UIImagePickerController alloc] init];
......
......@@ -21,46 +21,24 @@
statusBar.backgroundColor = color;
}
if( SYSTEM_VERSION_LESS_THAN( @"9.0" ) ){
if ([application respondsToSelector:@selector(isRegisteredForRemoteNotifications)])
{
// for iOS 8
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[application registerForRemoteNotifications];
}else{
UIUserNotificationType myTypes = UIUserNotificationTypeBadge|UIRemoteNotificationTypeAlert|UIRemoteNotificationTypeSound;
[application registerForRemoteNotificationTypes:myTypes];
}
}else if( SYSTEM_VERSION_LESS_THAN( @"10.0" ) )
{
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]];
[[UIApplication sharedApplication] registerForRemoteNotifications];
if( launchOptions != nil )
{
NSLog( @"registerForPushWithOptions:" );
}
}
else
{
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error)
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
center.delegate = self;
[center requestAuthorizationWithOptions:(UNAuthorizationOptionSound | UNAuthorizationOptionAlert | UNAuthorizationOptionBadge) completionHandler:^(BOOL granted, NSError * _Nullable error)
{
if( !error && granted )
{
if( !error )
{
[[UIApplication sharedApplication] registerForRemoteNotifications]; // required to get the app to do anything at all about push notifications
NSLog( @"Push registration success." );
}
else
{
NSLog( @"Push registration FAILED" );
NSLog( @"ERROR: %@ - %@", error.localizedFailureReason, error.localizedDescription );
NSLog( @"SUGGESTIONS: %@ - %@", error.localizedRecoveryOptions, error.localizedRecoverySuggestion );
}
}];
}
[[UIApplication sharedApplication] registerForRemoteNotifications]; // required to get the app to do anything at all about push notifications
NSLog( @"Push registration success." );
}
else
{
NSLog( @"Push registration FAILED" );
NSLog( @"ERROR: %@ - %@", error.localizedFailureReason, error.localizedDescription );
NSLog( @"SUGGESTIONS: %@ - %@", error.localizedRecoveryOptions, error.localizedRecoverySuggestion );
}
}];
volatile NSDictionary *remoteNotif = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
......
......@@ -171,5 +171,6 @@
<file>qml/pages/channelView/messageTypes/RoomNameChangedMessage.qml</file>
<file>qml/pages/channelView/messageTypes/PrivacyMessage.qml</file>
<file>res/logos/fairchat_logo_400x400.svg</file>
<file>qml/various/DownloadButton.qml</file>
</qresource>
</RCC>
......@@ -305,6 +305,7 @@ Item {
prevText = text
hideSearchField()
messageSearchModel.clear()
roomSearchModel.clear()
focus = false
}
......@@ -359,9 +360,9 @@ Item {
onActiveFocusChanged: {
if(activeFocus){
showSearchField()
}else if(text == ""){
}/*else if(text == ""){
resetSearchField()
}
}*/
}
onAccepted: {
......
......@@ -212,9 +212,9 @@ Page {
}
height: {
if(loginPage.height>500){
return 40;
return 50;
}else{
return 20
return 40
}
}
model: loginMethodsModel
......@@ -236,7 +236,13 @@ Page {
background: Rectangle {
clip:true
implicitWidth: 100
implicitHeight: 40
implicitHeight: {
if(loginPage.height>500){
return 50;
}else{
return 40
}
}
opacity: enabled ? 1 : 0.3
color: "transparent"
......
import QtQuick 2.9
import QtQuick.Controls 2.2
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtGraphicalEffects 1.0
import "qrc:/qml/style"
StyledMenu{
......@@ -7,42 +7,48 @@ StyledMenu{
signal replyTo(string messageId)
signal blockUser()
signal reportContent()
implicitWidth: 110
implicitWidth: 50
//implicitWidth: 110
StyledMenuItem{
id: copyItem
text: qsTr("copy")
onPressed: {
Action {
text: qsTr("copy");
checkable: false;
onTriggered: {
rocketChatController.copyToClipboard(messageText.text)
}
}
StyledMenuItem{
id: reply
text: qsTr("reply")
onPressed: {
Action {
text: qsTr("reply");
checkable: false
onTriggered: {
replyTo(model.id);
}
background: Item{}
}
StyledMenuItem{
id: deleteMessage
text: qsTr("delete")
onPressed: {
Action {
text: qsTr("delete");
checkable: false
onTriggered: {
rocketChatController.deleteMessage(channelView.currentChannel,model.id)
}
}
StyledMenuItem{
id: blockUserItem
text: qsTr("blockUser")
onPressed: {
Action {
text: qsTr("blockUser");
checkable: false
onTriggered: {
textBackground.blockUser();
}
}
StyledMenuItem{
id: reportContent
text: qsTr("report abuse")
onPressed: {
Action {
text: qsTr("report abuse");
checkable: false
onTriggered: {
textBackground.reportContent();
}
}
delegate: StyledMenuItem{
}
}
......@@ -94,7 +94,7 @@ Rectangle {
}
}else{
rocketChatController.getFileRessource(model.linkurl)
rocketChatController.getFileRessource(model.linkurl,"temp")
}
}
background: StdImageHighDPI {
......@@ -122,28 +122,16 @@ Rectangle {
source: "qrc:/res/stop.png"
}
}
Button {
id: downloadButton
font.family: Fonts.fontello.name
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
height: 15
onPressed: {
rocketChatController.getFileRessource(model.linkurl,"audio")
}
StdImageHighDPI{
anchors.centerIn: parent
source: "qrc:/res/download.svg";
height: 15
fillMode: Image.PreserveAspectFit
}
background: Rectangle {
anchors.leftMargin: 10
implicitWidth: 15
implicitHeight: 15
color: Colors.white
}
}
DownloadButton{
id: downloadButton
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 10
width: 15
height: 15
url: model.linkurl
backgroundColor: Colors.white
}
StyledText{
anchors.left: audioStop.right
anchors.verticalCenter: parent.verticalCenter
......@@ -237,6 +225,7 @@ Rectangle {
player.source = pathPrefix+path;
player.play()
}else if(url === model.linkurl){
downloadButton.state = "default"
if(Qt.platform.os == "ios"){
rocketChatController.openFileExternally(pathPrefix + path)
}else{
......
......@@ -25,6 +25,7 @@ import QtQuick.Controls 2.2
import "qrc:/qml/style"
import "qrc:/javascript/print.js" as Print
import "qrc:/qml/various"
import "qrc:/qml/pages/channelView/messageTypes"
Item {
anchors.left: parent.left
......@@ -37,41 +38,28 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
spacing: 5
height: 20
StyledText {
width: parent.width-30
text: model.msg
wrapMode: Text.WrapAnywhere
color: Colors.fontColor
}
Button {
DownloadButton{
id: downloadButton
font.family: Fonts.fontello.name
width: 15
height: 15
onPressed: {
console.log(model.linkurl);
rocketChatController.getFileRessource(model.linkurl,"cache")
}
StdImageHighDPI{
anchors.centerIn: parent
source: "qrc:/res/download.svg";
height: 15
fillMode: Image.PreserveAspectFit
}
background: Rectangle {
anchors.leftMargin: 10
implicitWidth: 15
implicitHeight: 15
color: model.ownMessage?Colors.ownMessage:Colors.white
}
url: model.linkurl
backgroundColor: model.ownMessage?Colors.ownMessage:Colors.white
}
}
Connections {
target: rocketChatController
onFileRessourceProcessed: {
if (url === model.linkurl) {
console.log("document"+pathPrefix + path)
downloadButton.state = "default"
if(Qt.platform.os == "ios"){
rocketChatController.openFileExternally(pathPrefix + path)
}else{
......
......@@ -50,26 +50,13 @@ Item {
wrapMode: Text.WrapAnywhere
color: Colors.fontColor
}
Button {
id: downloadButton
font.family: Fonts.fontello.name
height: 15
onPressed: {
rocketChatController.getFileRessource(model.linkurl,"cache")
}
StdImageHighDPI{
anchors.centerIn: parent
source: "qrc:/res/download.svg";
height: 15
fillMode: Image.PreserveAspectFit
}
background: Rectangle {
anchors.leftMargin: 10
implicitWidth: 15
implicitHeight: 15
color: model.ownMessage?Colors.ownMessage:Colors.white
}
}
DownloadButton{
id: downloadButton
width: 15
height: 15
url: model.linkurl
backgroundColor: model.ownMessage?Colors.ownMessage:Colors.white
}
}
Rectangle {
......@@ -157,6 +144,7 @@ Item {
if (url === model.linkurl) {
Print.log("file match")
var linkurl = model.linkurl
downloadButton.state = "default"
if (showInline) {
if(path !== ""){
window.fileCache[model.linkurl] = pathPrefix + path
......
......@@ -120,7 +120,7 @@ Item {
}else{
imageBackground.visible=true
rocketChatController.getFileRessource(model.linkurl)
rocketChatController.getFileRessource(model.linkurl,"temp")
}
}
......@@ -148,30 +148,17 @@ Item {
source: "qrc:/res/stop.png"
}
}
Button {
id: downloadButton
font.family: Fonts.fontello.name
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
height: 15
onPressed: {
rocketChatController.getFileRessource(model.linkurl,"cache")
}
StdImageHighDPI{
anchors.centerIn: parent
source: "qrc:/res/download.svg";
height: 15
fillMode: Image.PreserveAspectFit
}
DownloadButton{
id: downloadButton
anchors.verticalCenter: parent.verticalCenter
anchors.right: parent.right
anchors.rightMargin: 10
width: 15
height: 15
url: model.linkurl
backgroundColor: Colors.white
}
background: Rectangle {
anchors.leftMargin: 10
implicitWidth: 15
implicitHeight: 15
color: Colors.white
}
}
StyledText{
anchors.left: audioStop.right
anchors.verticalCenter: parent.verticalCenter
......@@ -238,6 +225,7 @@ Item {
busyIndicator.visible = false
player.play()
}else if(url === model.linkurl){
downloadButton.state = "default"
if(Qt.platform.os == "ios"){
rocketChatController.openFileExternally(pathPrefix + path)
}else{
......
......@@ -43,6 +43,14 @@ Item {
color: Colors.tertiary
textColor: Colors.white
font.pointSize: Fonts.baseFontSize
height: {
if(loginPage.height>500){
return 50;
}else{
return 40
}
}