diff --git a/app/build.gradle b/app/build.gradle
index 334ce38e9..933b35a37 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -191,7 +191,6 @@ dependencies {
implementation "com.github.stateless4j:stateless4j:2.6.0"
// 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"
@@ -229,6 +228,8 @@ dependencies {
androidTestImplementation "androidx.work:work-testing:$work_version"
implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'androidx.core:core-ktx:1.2.0-rc01'
+ implementation 'androidx.sharetarget:sharetarget:1.0.0-rc01'
implementation 'com.google.android.material:material:1.2.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
implementation 'com.github.vanniktech:Emoji:0.6.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 81814b1c6..7251809c5 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -63,9 +63,9 @@
+
+
+
+
+
-
= Build.VERSION_CODES.P) {
- val shortcutService: ShortcutService = get()
- }
+ val shortcutService: ShortcutService = get()
Security.insertProviderAt(Conscrypt.newProvider(), 1)
ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync()
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt
index 0f57d4e10..217b0f774 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt
@@ -664,9 +664,9 @@ class ContactsController : BaseController,
private fun prepareViews() {
layoutManager = SmoothScrollLinearLayoutManager(activity!!)
- recyclerView!!.layoutManager = layoutManager
- recyclerView!!.setHasFixedSize(true)
- recyclerView!!.adapter = adapter
+ recyclerView?.layoutManager = layoutManager
+ recyclerView?.setHasFixedSize(true)
+ recyclerView?.adapter = adapter
adapter!!.setStickyHeaderElevation(5)
.setUnlinkAllItemsOnRemoveHeaders(true)
diff --git a/app/src/main/java/com/nextcloud/talk/jobs/PushRegistrationWorker.kt b/app/src/main/java/com/nextcloud/talk/jobs/PushRegistrationWorker.kt
index 2a8d4fa76..864a388fe 100644
--- a/app/src/main/java/com/nextcloud/talk/jobs/PushRegistrationWorker.kt
+++ b/app/src/main/java/com/nextcloud/talk/jobs/PushRegistrationWorker.kt
@@ -23,7 +23,6 @@ package com.nextcloud.talk.jobs
import android.annotation.SuppressLint
import android.app.Application
import android.content.Context
-import android.text.TextUtils
import android.util.Base64
import androidx.work.CoroutineWorker
import androidx.work.ListenableWorker.Result
@@ -68,8 +67,8 @@ class PushRegistrationWorker(
}
private fun pushRegistrationToServer() {
- val token: String = appPreferences.pushToken
- if (!TextUtils.isEmpty(token)) {
+ val token: String? = appPreferences.pushToken
+ if (!token.isNullOrEmpty()) {
var credentials: String
val pushUtils = PushUtils(usersRepository)
val pushTokenHash = token.hashWithAlgorithm("SHA-512")
diff --git a/app/src/main/java/com/nextcloud/talk/newarch/data/repository/offline/ConversationsRepositoryImpl.kt b/app/src/main/java/com/nextcloud/talk/newarch/data/repository/offline/ConversationsRepositoryImpl.kt
index 765e0ef02..9824e09fe 100644
--- a/app/src/main/java/com/nextcloud/talk/newarch/data/repository/offline/ConversationsRepositoryImpl.kt
+++ b/app/src/main/java/com/nextcloud/talk/newarch/data/repository/offline/ConversationsRepositoryImpl.kt
@@ -65,8 +65,8 @@ class ConversationsRepositoryImpl(val conversationsDao: ConversationsDao) :
}
}
- override fun getLastThreeActiveConversationsForUser(userId: Long): LiveData> {
- return conversationsDao.getLastThreeConversationsForUser(userId).distinctUntilChanged().map { data ->
+ override fun getShortcutTargetConversations(userId: Long): LiveData> {
+ return conversationsDao.getShortcutTargetConversations(userId).distinctUntilChanged().map { data ->
data.map {
it.toConversation()
}
diff --git a/app/src/main/java/com/nextcloud/talk/newarch/di/module/ServiceModule.kt b/app/src/main/java/com/nextcloud/talk/newarch/di/module/ServiceModule.kt
index f921f57ea..d90ad7ca9 100644
--- a/app/src/main/java/com/nextcloud/talk/newarch/di/module/ServiceModule.kt
+++ b/app/src/main/java/com/nextcloud/talk/newarch/di/module/ServiceModule.kt
@@ -6,7 +6,7 @@ import com.nextcloud.talk.newarch.domain.repository.offline.UsersRepository
import com.nextcloud.talk.newarch.domain.usecases.GetConversationUseCase
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
import com.nextcloud.talk.newarch.services.GlobalService
-import com.nextcloud.talk.newarch.utils.ShortcutService
+import com.nextcloud.talk.newarch.services.shortcuts.ShortcutService
import okhttp3.OkHttpClient
import org.koin.dsl.module
import java.net.CookieManager
@@ -14,7 +14,6 @@ import java.net.CookieManager
val ServiceModule = module {
single { createGlobalService(get(), get(), get(), get(), get(), get()) }
single { createShortcutService(get(), get(), get()) }
-
}
fun createGlobalService(usersRepository: UsersRepository, cookieManager: CookieManager,
diff --git a/app/src/main/java/com/nextcloud/talk/newarch/domain/repository/offline/ConversationsRepository.kt b/app/src/main/java/com/nextcloud/talk/newarch/domain/repository/offline/ConversationsRepository.kt
index d965ea25a..b5cdc65ba 100644
--- a/app/src/main/java/com/nextcloud/talk/newarch/domain/repository/offline/ConversationsRepository.kt
+++ b/app/src/main/java/com/nextcloud/talk/newarch/domain/repository/offline/ConversationsRepository.kt
@@ -25,7 +25,7 @@ import com.nextcloud.talk.models.json.conversations.Conversation
interface ConversationsRepository {
fun getConversationsForUser(userId: Long): LiveData>
- fun getLastThreeActiveConversationsForUser(userId: Long): LiveData>
+ fun getShortcutTargetConversations(userId: Long): LiveData>
suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation?
suspend fun clearConversationsForUser(userId: Long)
diff --git a/app/src/main/java/com/nextcloud/talk/newarch/local/dao/ConversationsDao.kt b/app/src/main/java/com/nextcloud/talk/newarch/local/dao/ConversationsDao.kt
index 9999fd942..0bf841a0f 100644
--- a/app/src/main/java/com/nextcloud/talk/newarch/local/dao/ConversationsDao.kt
+++ b/app/src/main/java/com/nextcloud/talk/newarch/local/dao/ConversationsDao.kt
@@ -30,8 +30,8 @@ abstract class ConversationsDao {
@Query("SELECT * FROM conversations WHERE user_id = :userId ORDER BY favorite DESC, last_activity DESC")
abstract fun getConversationsForUser(userId: Long): LiveData>
- @Query("SELECT * FROM conversations WHERE user_id = :userId ORDER BY favorite DESC, last_activity DESC LIMIT 3")
- abstract fun getLastThreeConversationsForUser(userId: Long): LiveData>
+ @Query("SELECT * FROM conversations WHERE user_id = :userId ORDER BY favorite DESC, last_activity DESC LIMIT 4")
+ abstract fun getShortcutTargetConversations(userId: Long): LiveData>
@Query("DELETE FROM conversations WHERE user_id = :userId")
abstract suspend fun clearConversationsForUser(userId: Long)
diff --git a/app/src/main/java/com/nextcloud/talk/newarch/services/shortcuts/ShortcutService.kt b/app/src/main/java/com/nextcloud/talk/newarch/services/shortcuts/ShortcutService.kt
new file mode 100644
index 000000000..15e963f3e
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/newarch/services/shortcuts/ShortcutService.kt
@@ -0,0 +1,149 @@
+/*
+ *
+ * * Nextcloud Talk application
+ * *
+ * * @author Mario Danic
+ * * Copyright (C) 2017-2020 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.newarch.services.shortcuts
+
+import android.content.Context
+import android.content.Intent
+import android.graphics.drawable.BitmapDrawable
+import androidx.core.app.Person
+import androidx.core.content.pm.ShortcutInfoCompat
+import androidx.core.content.pm.ShortcutManagerCompat
+import androidx.core.graphics.drawable.IconCompat
+import androidx.core.graphics.drawable.toBitmap
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.Transformations
+import coil.Coil
+import coil.api.get
+import coil.transform.CircleCropTransformation
+import com.nextcloud.talk.R
+import com.nextcloud.talk.activities.MainActivity
+import com.nextcloud.talk.models.json.conversations.Conversation
+import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
+import com.nextcloud.talk.newarch.local.models.UserNgEntity
+import com.nextcloud.talk.newarch.local.models.getCredentials
+import com.nextcloud.talk.newarch.services.GlobalService
+import com.nextcloud.talk.newarch.utils.Images
+import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.bundle.BundleKeys
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.launch
+import kotlin.math.abs
+
+
+class ShortcutService constructor(private var context: Context,
+ private val conversationsRepository: ConversationsRepository,
+ globalService: GlobalService
+) {
+ private var currentUser: UserNgEntity? = null
+ private var lastFourActiveConversations: LiveData> = Transformations.switchMap(globalService.currentUserLiveData) { user ->
+ currentUser = user
+ var internalUserId: Long = -1
+ currentUser?.let {
+ internalUserId = it.id!!
+ }
+ conversationsRepository.getShortcutTargetConversations(internalUserId)
+ }
+
+ init {
+ lastFourActiveConversations.observeForever {
+ GlobalScope.launch {
+ registerShortcuts(it)
+ }
+ }
+ }
+
+ private suspend fun registerShortcuts(conversations: List) {
+ val openNewConversationIntent = Intent(context, MainActivity::class.java)
+ openNewConversationIntent.action = BundleKeys.KEY_NEW_CONVERSATION
+
+ val shortcuts: MutableList = mutableListOf()
+ val contactCategories: MutableSet = HashSet()
+ contactCategories.add(context.getString(R.string.nc_text_share_target))
+
+ val images = Images()
+
+ currentUser?.let { user ->
+ shortcuts.add(ShortcutInfoCompat.Builder(context, "new")
+ //.setRank(4)
+ .setShortLabel(context.resources.getString(R.string.nc_new_conversation))
+ .setIcon(IconCompat.createWithBitmap(context.resources.getDrawable(R.drawable.new_conversation_shortcut).toBitmap()))
+ .setIntent(openNewConversationIntent)
+ .setAlwaysBadged()
+ .build())
+
+ for ((index, conversation) in conversations.withIndex()) {
+ val intent = Intent(context, MainActivity::class.java)
+ intent.action = BundleKeys.KEY_OPEN_CONVERSATION
+ intent.putExtra(BundleKeys.KEY_INTERNAL_USER_ID, user.id)
+ intent.putExtra(BundleKeys.KEY_ROOM_TOKEN, conversation.token)
+
+ val persons = mutableListOf()
+ conversation.participants?.forEach {
+ val hashMap = it.value as HashMap<*, *>
+ val personBuilder = Person.Builder()
+ personBuilder.setName(hashMap["name"].toString())
+ personBuilder.setBot(false)
+ // we need a key for each of the users
+
+ /*val isGuest = hashMap["type"]?.equals(Participant.ParticipantType.GUEST) == true
+ || hashMap["type"]?.equals(Participant.ParticipantType.GUEST_AS_MODERATOR) == true
+ || hashMap["type"]?.equals(Participant.ParticipantType.USER_FOLLOWING_LINK) == true
+
+ val avatarUrl = if (isGuest) ApiUtils.getUrlForAvatarWithNameForGuests(user.baseUrl, hashMap["name"].toString(), R.dimen.avatar_size_big)
+ else ApiUtils.getUrlForAvatarWithName(user.baseUrl, hashMap["userId"].toString(), R.dimen.avatar_size_big)
+
+ iconImage = Coil.get(avatarUrl) {
+ addHeader("Authorization", user.getCredentials())
+ transformations(CircleCropTransformation())
+ }
+ personBuilder.setIcon(IconCompat.createWithBitmap((iconImage as BitmapDrawable).bitmap))*/
+ persons.add(personBuilder.build())
+ }
+
+ var iconImage = images.getImageForConversation(context, conversation)
+
+ if (iconImage == null) {
+ iconImage = Coil.get(ApiUtils.getUrlForAvatarWithName(user.baseUrl, conversation.name, R.dimen.avatar_size_big)) {
+ addHeader("Authorization", user.getCredentials())
+ transformations(CircleCropTransformation())
+ }
+ }
+
+ shortcuts.add(ShortcutInfoCompat.Builder(context, "current_conversation_" + (index + 1))
+ .setShortLabel(conversation.displayName as String)
+ .setLongLabel(conversation.displayName as String)
+ .setIcon(IconCompat.createWithBitmap((iconImage as BitmapDrawable).bitmap))
+ .setIntent(intent)
+ .setRank(abs(index - 4 + 1))
+ .setRank(0)
+ .setAlwaysBadged()
+ .setCategories(contactCategories)
+ .setPersons(persons.toTypedArray())
+ .build())
+ }
+ }
+
+ ShortcutManagerCompat.removeAllDynamicShortcuts(context)
+ ShortcutManagerCompat.addDynamicShortcuts(context, shortcuts)
+ }
+}
diff --git a/app/src/main/java/com/nextcloud/talk/newarch/utils/ShortcutService.kt b/app/src/main/java/com/nextcloud/talk/newarch/utils/ShortcutService.kt
deleted file mode 100644
index 88ec4d34d..000000000
--- a/app/src/main/java/com/nextcloud/talk/newarch/utils/ShortcutService.kt
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Thomas Ebert
- * @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.newarch.utils
-
-import android.annotation.TargetApi
-import android.content.Context
-import android.content.Intent
-import android.content.pm.ShortcutInfo
-import android.content.pm.ShortcutManager
-import android.graphics.drawable.BitmapDrawable
-import android.graphics.drawable.Icon
-import android.os.Build
-import androidx.annotation.RequiresApi
-import androidx.core.graphics.drawable.toBitmap
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.Transformations
-import coil.Coil
-import coil.api.get
-import coil.transform.CircleCropTransformation
-import com.nextcloud.talk.R
-import com.nextcloud.talk.activities.MainActivity
-import com.nextcloud.talk.models.json.conversations.Conversation
-import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository
-import com.nextcloud.talk.newarch.local.models.UserNgEntity
-import com.nextcloud.talk.newarch.local.models.getCredentials
-import com.nextcloud.talk.newarch.services.GlobalService
-import com.nextcloud.talk.utils.ApiUtils
-import com.nextcloud.talk.utils.bundle.BundleKeys
-import kotlinx.coroutines.GlobalScope
-import kotlinx.coroutines.launch
-
-class ShortcutService constructor(private val context: Context,
- private val conversationsRepository: ConversationsRepository,
- conversationsService: GlobalService
-) {
- private var currentUser: UserNgEntity? = null
- @RequiresApi(Build.VERSION_CODES.N_MR1)
- private val shortcutManager = context.getSystemService(ShortcutManager::class.java)
-
- @RequiresApi(Build.VERSION_CODES.P)
- private var lastThreeActiveConversations: LiveData> = Transformations.switchMap(conversationsService.currentUserLiveData) { user ->
- currentUser = user
- var internalUserId: Long = -1
- currentUser?.let {
- internalUserId = it.id!!
- }
- conversationsRepository.getLastThreeActiveConversationsForUser(internalUserId)
- }
-
- init {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
- lastThreeActiveConversations.observeForever {
- GlobalScope.launch {
- registerShortcuts()
- }
- }
- }
- }
-
- @TargetApi(Build.VERSION_CODES.P)
- private suspend fun registerShortcuts() {
- val openNewConversationIntent = Intent(context, MainActivity::class.java)
- openNewConversationIntent.action = BundleKeys.KEY_NEW_CONVERSATION
-
- val shortcuts: MutableList = mutableListOf()
- val images = Images()
-
- currentUser?.let { user ->
- shortcuts.add(ShortcutInfo.Builder(context, "new")
- .setShortLabel(context.resources.getString(R.string.nc_new_conversation_short))
- .setLongLabel(context.resources.getString(R.string.nc_new_conversation))
- .setIcon(Icon.createWithBitmap(context.resources.getDrawable(R.drawable.new_conversation_shortcut).toBitmap()))
- .setIntent(openNewConversationIntent)
- .build())
-
- lastThreeActiveConversations.value?.let { conversations ->
- for ((index, conversation) in conversations.withIndex()) {
- val intent = Intent(context, MainActivity::class.java)
- intent.action = BundleKeys.KEY_OPEN_CONVERSATION
- intent.putExtra(BundleKeys.KEY_INTERNAL_USER_ID, user.id)
- intent.putExtra(BundleKeys.KEY_ROOM_TOKEN, conversation.token)
-
- var iconImage = images.getImageForConversation(context, conversation)
-
- if (iconImage == null) {
- iconImage = Coil.get(ApiUtils.getUrlForAvatarWithName(user.baseUrl, conversation.name, R.dimen.avatar_size_big)) {
- addHeader("Authorization", user.getCredentials())
- transformations(CircleCropTransformation())
- }
- }
-
- shortcuts.add(ShortcutInfo.Builder(context, "current_conversation_" + (index + 1))
- .setShortLabel(conversation.displayName as String)
- .setLongLabel(conversation.displayName as String)
- .setIcon(Icon.createWithBitmap((iconImage as BitmapDrawable).bitmap))
- .setIntent(intent)
- .build())
- }
- }
- }
-
- shortcutManager?.dynamicShortcuts = shortcuts
- }
-}
diff --git a/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt b/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt
index 1b9f4b26d..ecfb7d923 100644
--- a/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt
+++ b/app/src/main/java/com/nextcloud/talk/utils/bundle/BundleKeys.kt
@@ -60,4 +60,5 @@ object BundleKeys {
val KEY_ACCOUNT = "KEY_ACCOUNT"
val KEY_FILE_ID = "KEY_FILE_ID"
val KEY_NOTIFICATION_ID = "KEY_NOTIFICATION_ID"
+ val KEY_CONVERSATION_ID = "KEY_CONVERSATION_ID"
}
diff --git a/app/src/main/res/values/setup.xml b/app/src/main/res/values/setup.xml
index ddfeb9157..34b172c44 100644
--- a/app/src/main/res/values/setup.xml
+++ b/app/src/main/res/values/setup.xml
@@ -50,4 +50,7 @@
1:829118773643:android:54b65087c544d819
AIzaSyAWIyOcLafaFp8PFL61h64cy1NNZW2cU_s
nextcloud-a7dea.appspot.com
+
+
+ com.nextcloud.talk.newarch.services.shortcuts.category.TEXT_SHARE_TARGET
diff --git a/app/src/main/res/xml/shortcuts.xml b/app/src/main/res/xml/shortcuts.xml
new file mode 100644
index 000000000..f14f6e834
--- /dev/null
+++ b/app/src/main/res/xml/shortcuts.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file