From bf3d5c2c656b0ae4c5b42e03159d261aa3fa5fe0 Mon Sep 17 00:00:00 2001 From: Mario Danic Date: Sun, 20 Oct 2019 01:54:28 +0200 Subject: [PATCH] Bug fixes, improvements, and significant changes to the conversation menu & info Signed-off-by: Mario Danic --- app/build.gradle | 518 +++++++++--------- app/gplay.gradle | 1 + app/ic_public_black_24px.xml | 29 + .../controllers/ConversationInfoController.kt | 231 +++++++- .../interfaces/ConversationInfoInterface.java | 26 + .../talk/jobs/NotificationWorker.java | 1 + .../ConversationsListView.kt | 2 +- .../ConversationsListViewModel.kt | 2 +- .../talk/receivers/PackageReplacedReceiver.kt | 46 +- .../com/nextcloud/talk/utils/ShareUtils.java | 53 -- .../DatabaseStorageFactory.java | 8 +- .../DatabaseStorageModule.java | 159 +++++- .../main/res/drawable/ic_link_black_24px.xml | 17 +- .../res/drawable/ic_link_grey600_24px.xml | 29 - .../res/drawable/ic_message_black_24dp.xml | 25 + .../res/drawable/ic_public_black_24px.xml | 25 - .../main/res/drawable/ic_share_black_24dp.xml | 26 + .../res/drawable/ic_whatshot_black_24dp.xml | 25 + app/src/main/res/drawable/link_variant.xml | 29 + .../layout/controller_conversation_info.xml | 24 +- .../layout/conversation_privacy_toggle.xml | 2 +- app/src/main/res/layout/general_info_item.xml | 93 ++++ .../res/layout/join_conversation_via_link.xml | 2 +- .../res/layout/notification_settings_item.xml | 6 + app/src/main/res/layout/rv_item_contact.xml | 1 - .../main/res/layout/view_message_input.xml | 4 +- app/src/main/res/values/strings.xml | 7 + app/src/main/res/values/styles.xml | 4 - 28 files changed, 932 insertions(+), 463 deletions(-) create mode 100644 app/ic_public_black_24px.xml create mode 100644 app/src/main/java/com/nextcloud/talk/interfaces/ConversationInfoInterface.java delete mode 100644 app/src/main/res/drawable/ic_link_grey600_24px.xml create mode 100644 app/src/main/res/drawable/ic_message_black_24dp.xml delete mode 100644 app/src/main/res/drawable/ic_public_black_24px.xml create mode 100644 app/src/main/res/drawable/ic_share_black_24dp.xml create mode 100644 app/src/main/res/drawable/ic_whatshot_black_24dp.xml create mode 100644 app/src/main/res/drawable/link_variant.xml create mode 100644 app/src/main/res/layout/general_info_item.xml diff --git a/app/build.gradle b/app/build.gradle index 302f9d27e..3cbd78b9d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -23,285 +23,305 @@ apply plugin: 'findbugs' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' apply plugin: 'kotlin-kapt' -apply plugin: 'realm-android' def taskRequest = getGradle().getStartParameter().getTaskRequests().toString() -if (taskRequest.contains("Gplay") || taskRequest.contains("findbugs") || taskRequest.contains("lint")) { - apply from: 'gplay.gradle' +if (taskRequest.contains("Gplay") || taskRequest.contains("findbugs") || + taskRequest.contains("lint")) { + apply from: 'gplay.gradle' } android { - compileSdkVersion 29 - buildToolsVersion '29.0.2' - defaultConfig { - applicationId "com.nextcloud.talk2" - versionName version - minSdkVersion 21 - targetSdkVersion 29 - testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + compileSdkVersion 29 + buildToolsVersion '29.0.2' + defaultConfig { + applicationId "com.nextcloud.talk2" + versionName version + minSdkVersion 21 + targetSdkVersion 29 + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - versionCode 119 - versionName "7.0.5" + versionCode 120 + versionName "8.0.0alpha1" - flavorDimensions "default" - renderscriptTargetApi 19 - renderscriptSupportModeEnabled true + flavorDimensions "default" + renderscriptTargetApi 19 + renderscriptSupportModeEnabled true - productFlavors { - dev { - resConfigs "en", "xxxhdpi" - } - // used for f-droid - generic - gplay - - } - - // Enabling multidex support. - multiDexEnabled true - - vectorDrawables.useSupportLibrary = true - - lintOptions { - disable 'InvalidPackage' - disable 'MissingTranslation' - disable "ValidController" - disable "ValidControllerChangeHandler" - } - - javaCompileOptions { - annotationProcessorOptions { - arguments = [ - parcelerStacktrace: "true" - ] - } - } - - dataBinding { - enabled = true - } + productFlavors { + dev { + resConfigs "en", "xxxhdpi" + } + // used for f-droid + generic + gplay } - dexOptions { - javaMaxHeapSize "4g" - } + // Enabling multidex support. + multiDexEnabled true - buildTypes { - debug { - applicationIdSuffix '.debug' - splits.abi.enable = false - splits.density.enable = false - } - - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } - - packagingOptions { - exclude 'META-INF/LICENSE' - exclude 'META-INF/NOTICE' - exclude 'META-INF/rxjava.properties' - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 - } + vectorDrawables.useSupportLibrary = true lintOptions { - abortOnError false - htmlReport true - htmlOutput file("$project.buildDir/reports/lint/lint.html") - disable 'MissingTranslation' + disable 'InvalidPackage' + disable 'MissingTranslation' + disable "ValidController" + disable "ValidControllerChangeHandler" } - task findbugs(type: FindBugs) { - ignoreFailures = false - effort = "max" - reportLevel = "medium" - classes = fileTree("$project.buildDir/intermediates/classes/gplay/debug/com/nextcloud") - excludeFilter = file("${project.rootDir}/findbugs-filter.xml") - source = fileTree('src/main/java') - pluginClasspath = project.configurations.findbugsPlugins - classpath = files() - include '**/*.java' - exclude '**/gen/**' - - reports { - xml.enabled = false - html.enabled = true - html { - destination = file("$project.buildDir/reports/findbugs/findbugs.html") - } - } + javaCompileOptions { + annotationProcessorOptions { + arguments = [ + parcelerStacktrace: "true" + ] + } } + + dataBinding { + enabled = true + } + } + + dexOptions { + javaMaxHeapSize "4g" + } + + buildTypes { + debug { + applicationIdSuffix '.debug' + splits.abi.enable = false + splits.density.enable = false + } + + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + } + } + + packagingOptions { + exclude 'META-INF/LICENSE' + exclude 'META-INF/NOTICE' + exclude 'META-INF/rxjava.properties' + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + lintOptions { + abortOnError false + htmlReport true + htmlOutput file("$project.buildDir/reports/lint/lint.html") + disable 'MissingTranslation' + } + + task findbugs(type: FindBugs) { + ignoreFailures = false + effort = "max" + reportLevel = "medium" + classes = fileTree("$project.buildDir/intermediates/classes/gplay/debug/com/nextcloud") + excludeFilter = file("${project.rootDir}/findbugs-filter.xml") + source = fileTree('src/main/java') + pluginClasspath = project.configurations.findbugsPlugins + classpath = files() + include '**/*.java' + exclude '**/gen/**' + + reports { + xml.enabled = false + html.enabled = true + html { + destination = file("$project.buildDir/reports/findbugs/findbugs.html") + } + } + } } ext { - work_version = "1.0.1" - koin_version = "2.1.0-alpha-1" - lifecycle_version = "2.1.0" - coil_version = "0.7.0" + work_version = "2.3.0-alpha02" + koin_version = "2.1.0-alpha-1" + lifecycle_version = "2.2.0-beta01" + coil_version = "0.7.0" + room_version = "2.2.0" } - configurations.all { - exclude group: 'com.google.firebase', module: 'firebase-core' - exclude group: 'com.google.firebase', module: 'firebase-analytics' - exclude group: 'com.google.firebase', module: 'firebase-measurement-connector' + exclude group: 'com.google.firebase', module: 'firebase-core' + exclude group: 'com.google.firebase', module: 'firebase-analytics' + exclude group: 'com.google.firebase', module: 'firebase-measurement-connector' } - dependencies { - implementation fileTree(include: ['*'], dir: 'libs') + implementation fileTree(include: ['*'], dir: 'libs') - // Koin for Android - implementation "org.koin:koin-android:$koin_version" - // Koin AndroidX Scope features - implementation "org.koin:koin-androidx-scope:$koin_version" - // Koin AndroidX ViewModel features - implementation "org.koin:koin-androidx-viewmodel:$koin_version" - // Koin AndroidX Experimental features - implementation "org.koin:koin-androidx-ext:$koin_version" + // Koin for Android + implementation "org.koin:koin-android:$koin_version" + // Koin AndroidX Scope features + implementation "org.koin:koin-androidx-scope:$koin_version" + // Koin AndroidX ViewModel features + implementation "org.koin:koin-androidx-viewmodel:$koin_version" + // Koin AndroidX Experimental features + implementation "org.koin:koin-androidx-ext:$koin_version" - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2' - implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2' - implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.2' + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.2' + implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" - implementation "com.github.stateless4j:stateless4j:2.6.0" + implementation "com.github.stateless4j:stateless4j:2.6.0" - // ViewModel and LiveData - implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" + // ViewModel and LiveData + implementation "androidx.core:core-ktx:1.1.0" + implementation "androidx.sqlite:sqlite-ktx:2.0.1" + implementation "androidx.collection:collection-ktx:1.1.0" + implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-livedata:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" - implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0-beta01" - implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.2.0-beta01" - implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0-beta01" - - // optional - ReactiveStreams support for LiveData - implementation "androidx.lifecycle:lifecycle-reactivestreams:$lifecycle_version" // For Kotlin use lifecycle-reactivestreams-ktx - - // optional - Test helpers for LiveData - testImplementation "androidx.arch.core:core-testing:$lifecycle_version" - - implementation 'androidx.appcompat:appcompat:1.1.0' - implementation 'com.google.android.material:material:1.1.0-beta01' - implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2' - implementation 'com.github.vanniktech:Emoji:0.6.0' - implementation group: 'androidx.emoji', name: 'emoji-bundled', version: '1.0.0' - implementation 'org.michaelevans.colorart:library:0.0.3' - implementation "android.arch.work:work-runtime:${work_version}" - implementation "android.arch.work:work-rxjava2:${work_version}" - implementation 'com.google.android:flexbox:1.1.0' - androidTestImplementation "android.arch.work:work-testing:${work_version}" - implementation 'com.gitlab.bitfireAT:dav4jvm:ee66e8e5' - implementation 'org.conscrypt:conscrypt-android:2.2.1' - - implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' - - implementation 'androidx.biometric:biometric:1.0.0-rc01' - implementation "androidx.lifecycle:lifecycle-extensions:2.1.0" - - implementation 'androidx.multidex:multidex:2.0.1' - - implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' - implementation "io.reactivex.rxjava2:rxjava:2.2.11" - - implementation 'com.bluelinelabs:conductor:3.0.0-rc2' - implementation 'com.bluelinelabs:conductor-support:3.0.0-rc2' - implementation 'com.bluelinelabs:conductor-archlifecycle:3.0.0-rc2' - implementation 'com.bluelinelabs:conductor-rxlifecycle2:3.0.0-rc2' - implementation 'com.bluelinelabs:conductor-autodispose:3.0.0-rc2' - implementation "com.github.miquelbeltran:conductor-viewmodel:1.0.3" - - implementation 'com.squareup.okhttp3:okhttp:3.14.4' - implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.14.4' - implementation 'com.squareup.okhttp3:logging-interceptor:3.14.4' - - implementation 'com.squareup.retrofit2:retrofit:2.6.2' - implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.2' - implementation 'com.github.aurae.retrofit2:converter-logansquare:1.4.1' - implementation group: 'joda-time', name: 'joda-time', version: '2.10.3' - implementation 'com.bluelinelabs:logansquare:1.3.7' - implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.10.0.pr1' - kapt 'com.bluelinelabs:logansquare-compiler:1.3.7' - - implementation 'com.google.dagger:dagger:2.24' - kapt 'com.google.dagger:dagger-compiler:2.24' - implementation 'com.github.lukaspili.autodagger2:autodagger2:1.1' - kapt 'com.github.lukaspili.autodagger2:autodagger2-compiler:1.1' - compileOnly 'javax.annotation:jsr250-api:1.0' - // Android only - implementation 'org.greenrobot:eventbus:3.1.1' - implementation 'io.requery:requery:1.5.1' - implementation 'io.requery:requery-android:1.5.1' - implementation 'net.zetetic:android-database-sqlcipher:3.5.9' - kapt 'io.requery:requery-processor:1.5.1' - implementation 'net.orange-box.storebox:storebox-lib:1.4.0' - compileOnly 'org.projectlombok:lombok:1.18.10' - annotationProcessor 'org.projectlombok:lombok:1.18.10' - kapt "org.projectlombok:lombok:1.18.10" - - implementation 'com.jakewharton:butterknife:10.2.0' - kapt 'com.jakewharton:butterknife-compiler:10.2.0' - implementation 'com.github.HITGIF:TextFieldBoxes:1.4.5' - implementation 'eu.davidea:flexible-adapter:5.1.0' - implementation 'eu.davidea:flexible-adapter-ui:1.0.0' - implementation 'eu.davidea:flexible-adapter-livedata:1.0.0-b3' - implementation 'org.webrtc:google-webrtc:1.0.23295' - implementation 'com.yarolegovich:lovely-dialog:1.1.0' - implementation 'com.yarolegovich:lovelyinput:1.0.9' - implementation 'com.yarolegovich:mp:1.0.9' - implementation 'me.zhanghai.android.effortlesspermissions:library:1.1.0' - implementation 'org.apache.commons:commons-lang3:3.9' - implementation 'com.github.wooplr:Spotlight:1.3' - implementation('com.github.mario:chatkit:a183142049', { - exclude group: 'com.facebook.fresco' - }) - - implementation 'com.github.mario.fresco:fresco:111' - implementation 'com.github.mario.fresco:animated-webp:111' - implementation 'com.github.mario.fresco:webpsupport:111' - implementation 'com.github.mario.fresco:animated-gif:111' - implementation 'com.github.mario.fresco:imagepipeline-okhttp3:111' - - implementation "io.coil-kt:coil:${coil_version}" - implementation "io.coil-kt:coil-gif:${coil_version}" - implementation "io.coil-kt:coil-svg:${coil_version}" - - implementation 'com.github.natario1:Autocomplete:v1.1.0' - - implementation 'com.github.cotechde.hwsecurity:hwsecurity-fido:2.4.5' - - implementation 'com.novoda:merlin:1.2.1' - - implementation 'com.github.Kennyc1012:BottomSheet:2.4.1' - implementation 'com.github.mario:PopupBubble:a365177d96' - implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' - implementation 'eu.medsea.mimeutil:mime-util:2.1.3' - - implementation 'com.afollestad.material-dialogs:core:3.1.0' - implementation 'com.afollestad.material-dialogs:datetime:3.1.0' - implementation 'com.afollestad.material-dialogs:bottomsheets:3.1.0' - implementation 'com.afollestad.material-dialogs:lifecycle:3.1.0' - - implementation 'org.parceler:parceler-api:1.1.12' - kapt 'org.parceler:parceler:1.1.12' - - testImplementation 'junit:junit:4.12' - testImplementation 'org.mockito:mockito-core:3.0.0' - testImplementation 'org.powermock:powermock-core:2.0.2' - testImplementation 'org.powermock:powermock-module-junit4:2.0.2' - testImplementation 'org.powermock:powermock-api-mockito2:2.0.2' + implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycle_version" + implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" - androidTestImplementation ('androidx.test.espresso:espresso-core:3.3.0-alpha02', { - exclude group: 'com.android.support', module: 'support-annotations' - }) - findbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.9.0' - findbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.4.6' - implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0' + + // optional - ReactiveStreams support for LiveData + implementation "androidx.lifecycle:lifecycle-reactivestreams-ktx:$lifecycle_version" + + // optional - Test helpers for LiveData + testImplementation "androidx.arch.core:core-testing:2.1.0" + + implementation "androidx.room:room-runtime:$room_version" + kapt "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of + // annotationProcessor + + // optional - Kotlin Extensions and Coroutines support for Room + implementation "androidx.room:room-ktx:$room_version" + + // optional - RxJava support for Room + implementation "androidx.room:room-rxjava2:$room_version" + + // optional - Guava support for Room, including Optional and ListenableFuture + //implementation "androidx.room:room-guava:$room_version" + + // Test helpers + testImplementation "androidx.room:room-testing:$room_version" + + implementation "androidx.work:work-runtime-ktx:$work_version" + implementation "androidx.work:work-rxjava2:$work_version" + androidTestImplementation "androidx.work:work-testing:$work_version" + + implementation 'androidx.appcompat:appcompat:1.1.0' + implementation 'com.google.android.material:material:1.1.0-beta01' + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2' + implementation 'com.github.vanniktech:Emoji:0.6.0' + implementation group: 'androidx.emoji', name: 'emoji-bundled', version: '1.0.0' + implementation 'org.michaelevans.colorart:library:0.0.3' + implementation 'com.google.android:flexbox:1.1.0' + implementation 'com.gitlab.bitfireAT:dav4jvm:ee66e8e5' + implementation 'org.conscrypt:conscrypt-android:2.2.1' + + implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0' + + implementation 'androidx.biometric:biometric:1.0.0-rc01' + implementation "androidx.lifecycle:lifecycle-extensions:2.1.0" + + implementation 'androidx.multidex:multidex:2.0.1' + + implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' + implementation "io.reactivex.rxjava2:rxjava:2.2.11" + + implementation 'com.bluelinelabs:conductor:3.0.0-rc2' + implementation 'com.bluelinelabs:conductor-support:3.0.0-rc2' + implementation 'com.bluelinelabs:conductor-archlifecycle:3.0.0-rc2' + implementation 'com.bluelinelabs:conductor-rxlifecycle2:3.0.0-rc2' + implementation 'com.bluelinelabs:conductor-autodispose:3.0.0-rc2' + implementation "com.github.miquelbeltran:conductor-viewmodel:1.0.3" + + implementation 'com.squareup.okhttp3:okhttp:3.14.4' + implementation 'com.squareup.okhttp3:okhttp-urlconnection:3.14.4' + implementation 'com.squareup.okhttp3:logging-interceptor:3.14.4' + + implementation 'com.squareup.retrofit2:retrofit:2.6.2' + implementation 'com.squareup.retrofit2:adapter-rxjava2:2.6.2' + implementation 'com.github.aurae.retrofit2:converter-logansquare:1.4.1' + implementation group: 'joda-time', name: 'joda-time', version: '2.10.3' + implementation 'com.bluelinelabs:logansquare:1.3.7' + implementation group: 'com.fasterxml.jackson.core', name: 'jackson-core', version: '2.10.0.pr1' + kapt 'com.bluelinelabs:logansquare-compiler:1.3.7' + + implementation 'com.google.dagger:dagger:2.24' + kapt 'com.google.dagger:dagger-compiler:2.24' + kapt 'com.google.dagger:dagger-android-processor:2.24' + implementation 'com.github.lukaspili.autodagger2:autodagger2:1.1' + kapt 'com.github.lukaspili.autodagger2:autodagger2-compiler:1.1' + compileOnly 'javax.annotation:jsr250-api:1.0' + // Android only + implementation 'org.greenrobot:eventbus:3.1.1' + implementation 'io.requery:requery:1.5.1' + implementation 'io.requery:requery-android:1.5.1' + implementation 'net.zetetic:android-database-sqlcipher:3.5.9' + kapt 'io.requery:requery-processor:1.5.1' + implementation 'net.orange-box.storebox:storebox-lib:1.4.0' + compileOnly 'org.projectlombok:lombok:1.18.10' + annotationProcessor 'org.projectlombok:lombok:1.18.10' + kapt "org.projectlombok:lombok:1.18.10" + + implementation 'com.jakewharton:butterknife:10.2.0' + kapt 'com.jakewharton:butterknife-compiler:10.2.0' + implementation 'com.github.HITGIF:TextFieldBoxes:1.4.5' + implementation 'eu.davidea:flexible-adapter:5.1.0' + implementation 'eu.davidea:flexible-adapter-ui:1.0.0' + implementation 'eu.davidea:flexible-adapter-livedata:1.0.0-b3' + implementation 'org.webrtc:google-webrtc:1.0.23295' + implementation 'com.yarolegovich:lovely-dialog:1.1.0' + implementation 'com.yarolegovich:lovelyinput:1.0.9' + implementation 'com.yarolegovich:mp:1.0.9' + implementation 'me.zhanghai.android.effortlesspermissions:library:1.1.0' + implementation 'org.apache.commons:commons-lang3:3.9' + implementation 'com.github.wooplr:Spotlight:1.3' + implementation('com.github.mario:chatkit:c6a6176729', { + exclude group: 'com.facebook.fresco' + }) + + implementation 'com.github.mario.fresco:fresco:111' + implementation 'com.github.mario.fresco:animated-webp:111' + implementation 'com.github.mario.fresco:webpsupport:111' + implementation 'com.github.mario.fresco:animated-gif:111' + implementation 'com.github.mario.fresco:imagepipeline-okhttp3:111' + + implementation "io.coil-kt:coil:${coil_version}" + implementation "io.coil-kt:coil-gif:${coil_version}" + implementation "io.coil-kt:coil-svg:${coil_version}" + + implementation 'com.github.natario1:Autocomplete:v1.1.0' + + implementation 'com.github.cotechde.hwsecurity:hwsecurity-fido:2.4.5' + + implementation 'com.novoda:merlin:1.2.1' + + implementation 'com.github.mario:PopupBubble:a365177d96' + implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' + implementation 'eu.medsea.mimeutil:mime-util:2.1.3' + + implementation 'com.afollestad.material-dialogs:core:3.1.0' + implementation 'com.afollestad.material-dialogs:datetime:3.1.0' + implementation 'com.afollestad.material-dialogs:bottomsheets:3.1.0' + implementation 'com.afollestad.material-dialogs:lifecycle:3.1.0' + + implementation 'org.parceler:parceler-api:1.1.12' + kapt 'org.parceler:parceler:1.1.12' + + testImplementation 'junit:junit:4.12' + testImplementation 'org.mockito:mockito-core:3.0.0' + testImplementation 'org.powermock:powermock-core:2.0.2' + testImplementation 'org.powermock:powermock-module-junit4:2.0.2' + testImplementation 'org.powermock:powermock-api-mockito2:2.0.2' + + androidTestImplementation('androidx.test.espresso:espresso-core:3.3.0-alpha02', { + exclude group: 'com.android.support', module: 'support-annotations' + }) + findbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.9.0' + findbugsPlugins 'com.mebigfatguy.fb-contrib:fb-contrib:7.4.6' + implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0' + implementation 'com.github.Kennyc1012:BottomSheet:2.4.1' } diff --git a/app/gplay.gradle b/app/gplay.gradle index 10b22760d..076f6bf84 100644 --- a/app/gplay.gradle +++ b/app/gplay.gradle @@ -19,5 +19,6 @@ */ dependencies { + implementation "androidx.work:work-gcm:$work_version" implementation "com.google.firebase:firebase-messaging:20.0.0" } diff --git a/app/ic_public_black_24px.xml b/app/ic_public_black_24px.xml new file mode 100644 index 000000000..87359106b --- /dev/null +++ b/app/ic_public_black_24px.xml @@ -0,0 +1,29 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt index 3b3ea5912..148e2de59 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt @@ -20,6 +20,7 @@ package com.nextcloud.talk.controllers +import android.content.Intent import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.os.Bundle @@ -48,6 +49,7 @@ import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler import com.facebook.drawee.backends.pipeline.Fresco import com.facebook.drawee.view.SimpleDraweeView import com.nextcloud.talk.R +import com.nextcloud.talk.R.string import com.nextcloud.talk.adapters.items.UserItem import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.application.NextcloudTalkApplication @@ -55,24 +57,30 @@ import com.nextcloud.talk.controllers.base.BaseController import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage import com.nextcloud.talk.events.EventStatus +import com.nextcloud.talk.interfaces.ConversationInfoInterface import com.nextcloud.talk.jobs.DeleteConversationWorker import com.nextcloud.talk.jobs.LeaveConversationWorker import com.nextcloud.talk.models.database.UserEntity import com.nextcloud.talk.models.json.conversations.Conversation +import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType.ROOM_PUBLIC_CALL import com.nextcloud.talk.models.json.conversations.RoomOverall import com.nextcloud.talk.models.json.converters.EnumNotificationLevelConverter import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.models.json.participants.ParticipantsOverall +import com.nextcloud.talk.newarch.utils.getCredentials import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DisplayUtils +import com.nextcloud.talk.utils.ShareUtils import com.nextcloud.talk.utils.bundle.BundleKeys +import com.nextcloud.talk.utils.database.user.UserUtils import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule import com.nextcloud.talk.utils.ui.MaterialPreferenceCategoryWithRightLink import com.yarolegovich.lovelydialog.LovelySaveStateHandler import com.yarolegovich.lovelydialog.LovelyStandardDialog import com.yarolegovich.mp.MaterialChoicePreference +import com.yarolegovich.mp.MaterialEditTextPreference import com.yarolegovich.mp.MaterialPreferenceCategory import com.yarolegovich.mp.MaterialPreferenceScreen import com.yarolegovich.mp.MaterialStandardPreference @@ -92,7 +100,24 @@ import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) class ConversationInfoController(args: Bundle) : BaseController(), - FlexibleAdapter.OnItemClickListener { + FlexibleAdapter.OnItemClickListener, ConversationInfoInterface { + + override fun conversationNameSet(name: String?) { + conversationDisplayName.post { + conversationDisplayName.text = name + } + } + + override fun passwordSet(isCleared: Boolean) { + passwordAction.post { + if (!isCleared) { + passwordAction.setSummary(context.getString(string.nc_password_redacted)) + } else { + passwordAction.setSummary(context.getString(string.nc_manual)) + } + } + } + @BindView(R.id.notification_settings) lateinit var notificationsPreferenceScreen: MaterialPreferenceScreen @BindView(R.id.progressBar) @@ -125,9 +150,23 @@ class ConversationInfoController(args: Bundle) : BaseController(), lateinit var muteCalls: MaterialSwitchPreference @BindView(R.id.mpc_action) lateinit var actionTextView: TextView + @BindView(R.id.generalConversationOptions) + lateinit var generalConversationOptions: MaterialPreferenceScreen + @BindView(R.id.changeConversationName) + lateinit var changeConversationName: MaterialEditTextPreference + @BindView(R.id.favoriteConversationAction) + lateinit var favoriteConversationAction: MaterialSwitchPreference + @BindView(R.id.allowGuestsAction) + lateinit var allowGuestsAction: MaterialSwitchPreference + @BindView(R.id.passwordAction) + lateinit var passwordAction: MaterialEditTextPreference + @BindView(R.id.shareAction) + lateinit var shareAction: MaterialStandardPreference @set:Inject lateinit var ncApi: NcApi + @set:Inject + lateinit var userUtils: UserUtils private val conversationToken: String? private val conversationUser: UserEntity? @@ -189,13 +228,6 @@ class ConversationInfoController(args: Bundle) : BaseController(), super.onAttach(view) eventBus.register(this) - if (databaseStorageModule == null) { - databaseStorageModule = DatabaseStorageModule(conversationUser!!, conversationToken) - } - - notificationsPreferenceScreen.setStorageModule(databaseStorageModule) - conversationInfoWebinar.setStorageModule(databaseStorageModule) - fetchRoomInfo() } @@ -206,6 +238,15 @@ class ConversationInfoController(args: Bundle) : BaseController(), saveStateHandler = LovelySaveStateHandler() } + if (databaseStorageModule == null) { + databaseStorageModule = DatabaseStorageModule( + conversationUser, conversationToken, this) + } + + notificationsPreferenceScreen.setStorageModule(databaseStorageModule) + conversationInfoWebinar.setStorageModule(databaseStorageModule) + generalConversationOptions.setStorageModule(databaseStorageModule) + actionTextView.visibility = View.GONE } @@ -280,6 +321,91 @@ class ConversationInfoController(args: Bundle) : BaseController(), } } + fun submitGuestChange() { + if (databaseStorageModule != null && conversationUser != null && conversation != null) { + if ((allowGuestsAction.findViewById(R.id.mp_checkable) as SwitchCompat).isChecked) { + ncApi.makeRoomPublic(conversationUser.getCredentials(), ApiUtils.getUrlForRoomVisibility + (conversationUser.baseUrl, conversation!!.token)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Observer { + override fun onComplete() { + } + + override fun onSubscribe(d: Disposable) { + } + + override fun onNext(t: GenericOverall) { + } + + override fun onError(e: Throwable) { + } + }) + } else { + ncApi.makeRoomPrivate(conversationUser.getCredentials(), ApiUtils.getUrlForRoomVisibility + (conversationUser.baseUrl, conversation!!.token)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Observer { + override fun onComplete() { + } + + override fun onSubscribe(d: Disposable) { + } + + override fun onNext(t: GenericOverall) { + } + + override fun onError(e: Throwable) { + } + }) + } + } + } + + fun submitFavoriteChange() { + if (databaseStorageModule != null && conversationUser != null && conversation != null) { + if ((favoriteConversationAction.findViewById(R.id.mp_checkable) as SwitchCompat).isChecked) { + ncApi.addConversationToFavorites(conversationUser.getCredentials(), ApiUtils + .getUrlForConversationFavorites(conversationUser.baseUrl, conversation!!.token)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Observer { + override fun onComplete() { + } + + override fun onSubscribe(d: Disposable) { + } + + override fun onNext(t: GenericOverall) { + } + + override fun onError(e: Throwable) { + } + + }) + } else { + ncApi.removeConversationFromFavorites(conversationUser.getCredentials(), ApiUtils + .getUrlForConversationFavorites(conversationUser.baseUrl, conversation!!.token)) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(object : Observer { + override fun onComplete() { + } + + override fun onSubscribe(d: Disposable) { + } + + override fun onNext(t: GenericOverall) { + } + + override fun onError(e: Throwable) { + } + + }) + } + } + } fun submitLobbyChanges() { val state = if ((conversationInfoLobby.findViewById( R.id @@ -518,15 +644,17 @@ class ConversationInfoController(args: Bundle) : BaseController(), val conversationCopy = conversation - if (conversationCopy!!.canModerate(conversationUser)) { - actionTextView.visibility = View.VISIBLE - } else { - actionTextView.visibility = View.GONE - } if (isAttached && (!isBeingDestroyed || !isDestroyed)) { + if (conversationCopy!!.canModerate(conversationUser)) { + actionTextView.visibility = View.VISIBLE + } else { + actionTextView.visibility = View.GONE + } + ownOptionsCategory.visibility = View.VISIBLE + setupGeneralSettings() setupWebinaryView() if (!conversation!!.canLeave(conversationUser)) { @@ -571,6 +699,83 @@ class ConversationInfoController(args: Bundle) : BaseController(), }) } + private fun setupGeneralSettings() { + if (conversation != null) { + changeConversationName.value = conversation!!.displayName + + if (conversation!!.isNameEditable(conversationUser)) { + changeConversationName.visibility = View.VISIBLE + } else { + changeConversationName.visibility = View.GONE + } + + favoriteConversationAction.value = conversation!!.isFavorite + allowGuestsAction.value = conversation!!.type == ROOM_PUBLIC_CALL + + (allowGuestsAction.findViewById(R.id.mp_checkable) as SwitchCompat) + .isChecked = allowGuestsAction.value + (favoriteConversationAction.findViewById(R.id.mp_checkable) as SwitchCompat) + .isChecked = favoriteConversationAction.value + + (favoriteConversationAction.findViewById(R.id.mp_checkable) as SwitchCompat).setOnCheckedChangeListener { buttonView, isChecked -> + submitFavoriteChange() + } + + (allowGuestsAction.findViewById(R.id.mp_checkable) as SwitchCompat).setOnCheckedChangeListener { buttonView, isChecked -> + if (isChecked) { + passwordAction.visibility = View.VISIBLE + shareAction.visibility = View.VISIBLE + } else { + passwordAction.visibility = View.GONE + shareAction.visibility = View.GONE + } + + submitGuestChange() + } + + shareAction.setOnClickListener { + val sendIntent: Intent = Intent().apply { + action = Intent.ACTION_SEND + putExtra( + Intent.EXTRA_SUBJECT, + String.format( + context.getString(R.string.nc_share_subject), + context.getString(R.string.nc_app_name) + ) + ) + + putExtra( + Intent.EXTRA_TEXT, ShareUtils.getStringForIntent( + context, conversation!!.password, + userUtils, conversation + ) + ) + + type = "text/plain" + } + + val intent = Intent.createChooser(sendIntent, context.getString(string.nc_share_link)) + startActivity(intent) + } + + if (allowGuestsAction.value) { + passwordAction.visibility = View.VISIBLE + shareAction.visibility = View.VISIBLE + + passwordAction.value = conversation!!.hasPassword.toString() + if (conversation!!.hasPassword) { + passwordAction.setSummary(context.getString(string.nc_password_redacted)) + } else { + passwordAction.setSummary(context.getString(string.nc_manual)) + } + } else { + passwordAction.visibility = View.GONE + shareAction.visibility = View.GONE + } + + } + } + private fun adjustNotificationLevelUI() { if (conversation != null) { if (conversationUser != null && conversationUser.hasSpreedFeatureCapability( diff --git a/app/src/main/java/com/nextcloud/talk/interfaces/ConversationInfoInterface.java b/app/src/main/java/com/nextcloud/talk/interfaces/ConversationInfoInterface.java new file mode 100644 index 000000000..7e7fde230 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/interfaces/ConversationInfoInterface.java @@ -0,0 +1,26 @@ +/* + * Nextcloud Talk application + * + * @author Mario Danic + * Copyright (C) 2017-2019 Mario Danic + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.nextcloud.talk.interfaces; + +public interface ConversationInfoInterface { + void conversationNameSet(String name); + void passwordSet(boolean isCleared); +} diff --git a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java index 11143fb69..aed265a9c 100644 --- a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java +++ b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.graphics.drawable.Drawable; import android.media.AudioAttributes; import android.media.MediaPlayer; import android.net.Uri; diff --git a/app/src/main/java/com/nextcloud/talk/newarch/features/conversationsList/ConversationsListView.kt b/app/src/main/java/com/nextcloud/talk/newarch/features/conversationsList/ConversationsListView.kt index 71e21da08..73a6bdd06 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/features/conversationsList/ConversationsListView.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/features/conversationsList/ConversationsListView.kt @@ -345,7 +345,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener, drawable.ic_star_black_24dp -> { viewModel.changeFavoriteValueForConversation(conversation, true) } - drawable.ic_link_grey600_24px -> { + drawable.ic_share_black_24dp -> { startActivity(viewModel.getShareIntentForConversation(conversation)) } drawable.ic_exit_to_app_black_24dp -> { diff --git a/app/src/main/java/com/nextcloud/talk/newarch/features/conversationsList/ConversationsListViewModel.kt b/app/src/main/java/com/nextcloud/talk/newarch/features/conversationsList/ConversationsListViewModel.kt index 601c50b37..b763efe2d 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/features/conversationsList/ConversationsListViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/features/conversationsList/ConversationsListViewModel.kt @@ -276,7 +276,7 @@ class ConversationsListViewModel constructor( items.add( (BasicListItemWithImage( drawable - .ic_link_grey600_24px, context.getString(string.nc_share_link) + .ic_share_black_24dp, context.getString(string.nc_share_link) )) ) } diff --git a/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.kt b/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.kt index 396439ef8..d32dffd72 100644 --- a/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.kt +++ b/app/src/main/java/com/nextcloud/talk/receivers/PackageReplacedReceiver.kt @@ -60,32 +60,30 @@ class PackageReplacedReceiver : BroadcastReceiver() { .NOTIFICATION_SERVICE ) as NotificationManager - if (notificationManager != null) { - if (!appPreferences.isNotificationChannelUpgradedToV2) { - for (notificationChannelGroup in notificationManager - .notificationChannelGroups) { - notificationManager.deleteNotificationChannelGroup(notificationChannelGroup.id) - } - - notificationManager.deleteNotificationChannel( - NotificationUtils.NOTIFICATION_CHANNEL_CALLS - ) - notificationManager.deleteNotificationChannel( - NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES - ) - - appPreferences.setNotificationChannelIsUpgradedToV2(true) + if (!appPreferences.isNotificationChannelUpgradedToV2) { + for (notificationChannelGroup in notificationManager + .notificationChannelGroups) { + notificationManager.deleteNotificationChannelGroup(notificationChannelGroup.id) } - if (!appPreferences.isNotificationChannelUpgradedToV3 && packageInfo.versionCode > 51) { - notificationManager.deleteNotificationChannel( - NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES_V2 - ) - notificationManager.deleteNotificationChannel( - NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V2 - ) - appPreferences.setNotificationChannelIsUpgradedToV3(true) - } + notificationManager.deleteNotificationChannel( + NotificationUtils.NOTIFICATION_CHANNEL_CALLS + ) + notificationManager.deleteNotificationChannel( + NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES + ) + + appPreferences.setNotificationChannelIsUpgradedToV2(true) + } + + if (!appPreferences.isNotificationChannelUpgradedToV3 && packageInfo.versionCode > 51) { + notificationManager.deleteNotificationChannel( + NotificationUtils.NOTIFICATION_CHANNEL_MESSAGES_V2 + ) + notificationManager.deleteNotificationChannel( + NotificationUtils.NOTIFICATION_CHANNEL_CALLS_V2 + ) + appPreferences.setNotificationChannelIsUpgradedToV3(true) } } diff --git a/app/src/main/java/com/nextcloud/talk/utils/ShareUtils.java b/app/src/main/java/com/nextcloud/talk/utils/ShareUtils.java index e2c551a18..0c42c8ceb 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/ShareUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/ShareUtils.java @@ -17,27 +17,17 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . * - * Part of the code in ShareUtils was inspired by BottomSheet under the Apache licence - * located here: https://github.com/Kennyc1012/BottomSheet/blob/master/library/src/main/java/com/kennyc/bottomsheet/BottomSheet.java#L425 */ package com.nextcloud.talk.utils; import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.content.pm.ResolveInfo; -import android.graphics.drawable.Drawable; import android.text.TextUtils; import androidx.annotation.Nullable; -import com.kennyc.bottomsheet.adapters.AppAdapter; import com.nextcloud.talk.R; import com.nextcloud.talk.models.database.UserEntity; import com.nextcloud.talk.models.json.conversations.Conversation; import com.nextcloud.talk.utils.database.user.UserUtils; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; public class ShareUtils { @@ -58,47 +48,4 @@ public class ShareUtils { return shareString; } - - public static List getShareApps(Context context, Intent intent, - @Nullable Set appsFilter, @Nullable Set toExclude) { - - if (context == null || intent == null) return null; - - PackageManager manager = context.getPackageManager(); - List apps = manager.queryIntentActivities(intent, 0); - - if (apps != null && !apps.isEmpty()) { - List appResources = new ArrayList<>(apps.size()); - boolean shouldCheckPackages = appsFilter != null && !appsFilter.isEmpty(); - - for (ResolveInfo resolveInfo : apps) { - String packageName = resolveInfo.activityInfo.packageName; - - if (shouldCheckPackages && !appsFilter.contains(packageName)) { - continue; - } - - String title = resolveInfo.loadLabel(manager).toString(); - String name = resolveInfo.activityInfo.name; - Drawable drawable = resolveInfo.loadIcon(manager); - appResources.add(new AppAdapter.AppInfo(title, packageName, name, drawable)); - } - - if (toExclude != null && !toExclude.isEmpty()) { - List toRemove = new ArrayList<>(); - - for (AppAdapter.AppInfo appInfo : appResources) { - if (toExclude.contains(appInfo.packageName)) { - toRemove.add(appInfo); - } - } - - if (!toRemove.isEmpty()) appResources.removeAll(toRemove); - } - - return appResources; - } - - return null; - } } diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageFactory.java b/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageFactory.java index c2769c655..5f56e863d 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageFactory.java +++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageFactory.java @@ -21,20 +21,24 @@ package com.nextcloud.talk.utils.preferences.preferencestorage; import android.content.Context; +import com.nextcloud.talk.interfaces.ConversationInfoInterface; import com.nextcloud.talk.models.database.UserEntity; import com.yarolegovich.mp.io.StorageModule; public class DatabaseStorageFactory implements StorageModule.Factory { private UserEntity conversationUser; private String conversationToken; + private ConversationInfoInterface conversationInfoInterface; - public DatabaseStorageFactory(UserEntity conversationUser, String conversationToken) { + public DatabaseStorageFactory(UserEntity conversationUser, String conversationToken, + ConversationInfoInterface conversationInfoInterface) { this.conversationUser = conversationUser; this.conversationToken = conversationToken; + this.conversationInfoInterface = conversationInfoInterface; } @Override public StorageModule create(Context context) { - return new DatabaseStorageModule(conversationUser, conversationToken); + return new DatabaseStorageModule(conversationUser, conversationToken, conversationInfoInterface); } } diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.java b/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.java index 86ea8b28c..67f45ee13 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.java +++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/preferencestorage/DatabaseStorageModule.java @@ -25,6 +25,7 @@ import android.text.TextUtils; import autodagger.AutoInjector; import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.interfaces.ConversationInfoInterface; import com.nextcloud.talk.models.database.ArbitraryStorageEntity; import com.nextcloud.talk.models.database.UserEntity; import com.nextcloud.talk.models.json.generic.GenericOverall; @@ -50,10 +51,17 @@ public class DatabaseStorageModule implements StorageModule { private long accountIdentifier; private boolean lobbyValue; + private boolean favoriteConversationValue; + private boolean allowGuestsValue; + + private Boolean hasPassword; + private String conversationNameValue; private String messageNotificationLevel; + private ConversationInfoInterface conversationInfoInterface; - public DatabaseStorageModule(UserEntity conversationUser, String conversationToken) { + public DatabaseStorageModule(UserEntity conversationUser, String conversationToken, + ConversationInfoInterface conversationInfoInterface) { NextcloudTalkApplication.Companion.getSharedApplication() .getComponentApplication() .inject(this); @@ -61,46 +69,94 @@ public class DatabaseStorageModule implements StorageModule { this.conversationUser = conversationUser; this.accountIdentifier = conversationUser.getId(); this.conversationToken = conversationToken; + this.conversationInfoInterface = conversationInfoInterface; } @Override public void saveBoolean(String key, boolean value) { - if (!key.equals("conversation_lobby")) { + if (!key.equals("conversation_lobby") && !key.equals("allow_guests") && !key.equals( + "favorite_conversation")) { arbitraryStorageUtils.storeStorageSetting(accountIdentifier, key, Boolean.toString(value), conversationToken); } else { - lobbyValue = value; + switch (key) { + case "conversation_lobby": + lobbyValue = value; + break; + case "allow_guests": + allowGuestsValue = value; + break; + case "favorite_conversation": + favoriteConversationValue = value; + break; + default: + } } } @Override public void saveString(String key, String value) { - if (!key.equals("message_notification_level")) { + if (!key.equals("message_notification_level") + && !key.equals("conversation_name") + && !key.equals("conversation_password")) { arbitraryStorageUtils.storeStorageSetting(accountIdentifier, key, value, conversationToken); } else { - if (conversationUser.hasSpreedFeatureCapability("notification-levels")) { - if (!TextUtils.isEmpty(messageNotificationLevel) && !messageNotificationLevel.equals( - value)) { - int intValue; - switch (value) { - case "never": - intValue = 3; - break; - case "mention": - intValue = 2; - break; - case "always": - intValue = 1; - break; - default: - intValue = 0; - } + if (key.equals("message_notification_level")) { + if (conversationUser.hasSpreedFeatureCapability("notification-levels")) { + if (!TextUtils.isEmpty(messageNotificationLevel) && !messageNotificationLevel.equals( + value)) { + int intValue; + switch (value) { + case "never": + intValue = 3; + break; + case "mention": + intValue = 2; + break; + case "always": + intValue = 1; + break; + default: + intValue = 0; + } - ncApi.setNotificationLevel( - ApiUtils.getCredentials(conversationUser.getUsername(), conversationUser.getToken()), - ApiUtils.getUrlForSettingNotificationlevel(conversationUser.getBaseUrl(), - conversationToken), - intValue) + ncApi.setNotificationLevel( + ApiUtils.getCredentials(conversationUser.getUsername(), + conversationUser.getToken()), + ApiUtils.getUrlForSettingNotificationlevel(conversationUser.getBaseUrl(), + conversationToken), + intValue) + .subscribeOn(Schedulers.io()) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onNext(GenericOverall genericOverall) { + messageNotificationLevel = value; + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onComplete() { + } + }); + } else { + messageNotificationLevel = value; + } + } + } else if (key.equals("conversation_password")) { + if (hasPassword != null) { + ncApi.setPassword(ApiUtils.getCredentials(conversationUser.getUsername(), + conversationUser.getToken()), + ApiUtils.getUrlForPassword(conversationUser.getBaseUrl(), + conversationToken), value) .subscribeOn(Schedulers.io()) .subscribe(new Observer() { @Override @@ -110,7 +166,8 @@ public class DatabaseStorageModule implements StorageModule { @Override public void onNext(GenericOverall genericOverall) { - messageNotificationLevel = value; + hasPassword = !TextUtils.isEmpty(value); + conversationInfoInterface.passwordSet(TextUtils.isEmpty(value)); } @Override @@ -123,7 +180,37 @@ public class DatabaseStorageModule implements StorageModule { } }); } else { - messageNotificationLevel = value; + hasPassword = Boolean.parseBoolean(value); + } + } else if (key.equals("conversation_name")) { + if (!TextUtils.isEmpty(conversationNameValue) && !conversationNameValue.equals(value)) { + ncApi.renameRoom(ApiUtils.getCredentials(conversationUser.getUsername(), + conversationUser.getToken()), ApiUtils.getRoom(conversationUser.getBaseUrl(), + conversationToken), value) + .subscribeOn(Schedulers.io()) + .subscribe(new Observer() { + @Override + public void onSubscribe(Disposable d) { + + } + + @Override + public void onNext(GenericOverall genericOverall) { + conversationNameValue = value; + conversationInfoInterface.conversationNameSet(value); + } + + @Override + public void onError(Throwable e) { + + } + + @Override + public void onComplete() { + } + }); + } else { + conversationNameValue = value; } } } @@ -144,6 +231,10 @@ public class DatabaseStorageModule implements StorageModule { public boolean getBoolean(String key, boolean defaultVal) { if (key.equals("conversation_lobby")) { return lobbyValue; + } else if (key.equals("allow_guests")) { + return allowGuestsValue; + } else if (key.equals("favorite_conversation")) { + return favoriteConversationValue; } else { ArbitraryStorageEntity valueFromDb = arbitraryStorageUtils.getStorageSetting(accountIdentifier, key, conversationToken); @@ -157,7 +248,9 @@ public class DatabaseStorageModule implements StorageModule { @Override public String getString(String key, String defaultVal) { - if (!key.equals("message_notification_level")) { + if (!key.equals("message_notification_level") + && !key.equals("conversation_name") + && !key.equals("conversation_password")) { ArbitraryStorageEntity valueFromDb = arbitraryStorageUtils.getStorageSetting(accountIdentifier, key, conversationToken); if (valueFromDb == null) { @@ -165,9 +258,15 @@ public class DatabaseStorageModule implements StorageModule { } else { return valueFromDb.getValue(); } - } else { + } else if (key.equals("message_notification_level")) { return messageNotificationLevel; + } else if (key.equals("conversation_name")) { + return conversationNameValue; + } else if (key.equals("conversation_password")) { + return ""; } + + return ""; } @Override diff --git a/app/src/main/res/drawable/ic_link_black_24px.xml b/app/src/main/res/drawable/ic_link_black_24px.xml index d1e8a70fa..7a66a5dcd 100644 --- a/app/src/main/res/drawable/ic_link_black_24px.xml +++ b/app/src/main/res/drawable/ic_link_black_24px.xml @@ -18,12 +18,11 @@ ~ along with this program. If not, see . --> - - - + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_link_grey600_24px.xml b/app/src/main/res/drawable/ic_link_grey600_24px.xml deleted file mode 100644 index 2c15eb899..000000000 --- a/app/src/main/res/drawable/ic_link_grey600_24px.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_message_black_24dp.xml b/app/src/main/res/drawable/ic_message_black_24dp.xml new file mode 100644 index 000000000..66bdd411c --- /dev/null +++ b/app/src/main/res/drawable/ic_message_black_24dp.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_public_black_24px.xml b/app/src/main/res/drawable/ic_public_black_24px.xml deleted file mode 100644 index 49c84ae88..000000000 --- a/app/src/main/res/drawable/ic_public_black_24px.xml +++ /dev/null @@ -1,25 +0,0 @@ - - - - - diff --git a/app/src/main/res/drawable/ic_share_black_24dp.xml b/app/src/main/res/drawable/ic_share_black_24dp.xml new file mode 100644 index 000000000..b138986d7 --- /dev/null +++ b/app/src/main/res/drawable/ic_share_black_24dp.xml @@ -0,0 +1,26 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_whatshot_black_24dp.xml b/app/src/main/res/drawable/ic_whatshot_black_24dp.xml new file mode 100644 index 000000000..4624e58d8 --- /dev/null +++ b/app/src/main/res/drawable/ic_whatshot_black_24dp.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/app/src/main/res/drawable/link_variant.xml b/app/src/main/res/drawable/link_variant.xml new file mode 100644 index 000000000..99b109d33 --- /dev/null +++ b/app/src/main/res/drawable/link_variant.xml @@ -0,0 +1,29 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/controller_conversation_info.xml b/app/src/main/res/layout/controller_conversation_info.xml index f544b65c0..0578f7f50 100644 --- a/app/src/main/res/layout/controller_conversation_info.xml +++ b/app/src/main/res/layout/controller_conversation_info.xml @@ -75,24 +75,12 @@ - - - - - - - + android:layout_height="wrap_content" + android:layout_width="match_parent" + /> + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/join_conversation_via_link.xml b/app/src/main/res/layout/join_conversation_via_link.xml index 5ed10adfb..059339f7f 100644 --- a/app/src/main/res/layout/join_conversation_via_link.xml +++ b/app/src/main/res/layout/join_conversation_via_link.xml @@ -33,7 +33,7 @@ android:layout_centerVertical="true" android:layout_marginEnd="8dp" android:contentDescription="@null" - android:src="@drawable/ic_public_black_24px" + android:src="@drawable/link_variant" android:tint="@color/colorPrimary" /> @@ -45,6 +47,8 @@ android:id="@+id/conversation_info_message_notifications" android:layout_width="match_parent" android:layout_height="wrap_content" + apc:mp_icon="@drawable/ic_message_black_24dp" + apc:mp_icon_tint="@color/grey_600" apc:mp_entry_descriptions="@array/message_notification_levels" apc:mp_entry_values="@array/message_notification_levels_entry_values" apc:mp_key="message_notification_level" @@ -57,6 +61,8 @@ android:layout_height="wrap_content" apc:mp_default_value="false" apc:mp_key="mute_calls" + apc:mp_icon="@drawable/ic_volume_mute_white_24dp" + apc:mp_icon_tint="@color/grey_600" apc:mp_title="@string/nc_mute_calls" apc:mp_summary="@string/nc_mute_calls_desc"/> diff --git a/app/src/main/res/layout/rv_item_contact.xml b/app/src/main/res/layout/rv_item_contact.xml index 476aebed1..7205245e4 100644 --- a/app/src/main/res/layout/rv_item_contact.xml +++ b/app/src/main/res/layout/rv_item_contact.xml @@ -46,7 +46,6 @@ android:layout_toStartOf="@id/checkedImageView" android:layout_toEndOf="@id/simple_drawee_view" android:ellipsize="end" - android:textAppearance="@style/ListItem" tools:text="Contact item text" /> - - No proxy Username Password + Redacted for privacy reasons Conversation link New password Wrong password @@ -169,8 +170,11 @@ New conversation Join with a link Join via web + Favorite conversation Add to favorites Remove from favorites + Conversation will be pinned to the top of the + conversations list Select contacts @@ -311,4 +315,7 @@ Unknown error No Unauthorized + General + Allow guests + diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 5122e4efe..8cb5b6341 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -39,10 +39,6 @@ 12sp - -