mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-13 15:54:59 +01:00
Move to compat shortcut manager
This commit is contained in:
parent
b265994031
commit
d6935d65d6
@ -191,7 +191,6 @@ dependencies {
|
|||||||
implementation "com.github.stateless4j:stateless4j:2.6.0"
|
implementation "com.github.stateless4j:stateless4j:2.6.0"
|
||||||
|
|
||||||
// ViewModel and LiveData
|
// ViewModel and LiveData
|
||||||
implementation "androidx.core:core-ktx:1.1.0"
|
|
||||||
implementation "androidx.sqlite:sqlite-ktx:2.0.1"
|
implementation "androidx.sqlite:sqlite-ktx:2.0.1"
|
||||||
implementation "androidx.collection:collection-ktx:1.1.0"
|
implementation "androidx.collection:collection-ktx:1.1.0"
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"
|
||||||
@ -229,6 +228,8 @@ dependencies {
|
|||||||
androidTestImplementation "androidx.work:work-testing:$work_version"
|
androidTestImplementation "androidx.work:work-testing:$work_version"
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0'
|
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 'com.google.android.material:material:1.2.0-alpha03'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta4'
|
||||||
implementation 'com.github.vanniktech:Emoji:0.6.0'
|
implementation 'com.github.vanniktech:Emoji:0.6.0'
|
||||||
|
@ -63,9 +63,9 @@
|
|||||||
<application
|
<application
|
||||||
android:name=".application.NextcloudTalkApplication"
|
android:name=".application.NextcloudTalkApplication"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:fullBackupContent="@xml/backup_config"
|
|
||||||
android:allowClearUserData="false"
|
android:allowClearUserData="false"
|
||||||
android:allowClearUserDataOnFailedRestore="true"
|
android:allowClearUserDataOnFailedRestore="true"
|
||||||
|
android:fullBackupContent="@xml/backup_config"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/nc_app_name"
|
android:label="@string/nc_app_name"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
@ -79,15 +79,34 @@
|
|||||||
android:name="android.max_aspect"
|
android:name="android.max_aspect"
|
||||||
android:value="10" />
|
android:value="10" />
|
||||||
|
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.MainActivity"
|
android:name=".activities.MainActivity"
|
||||||
android:label="@string/nc_app_label"
|
android:label="@string/nc_app_label"
|
||||||
android:launchMode="singleTask"
|
android:launchMode="singleTask"
|
||||||
android:windowSoftInputMode="adjustPan">
|
android:windowSoftInputMode="adjustPan">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.SEND" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data android:name="android.app.shortcuts"
|
||||||
|
android:resource="@xml/shortcuts" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="android.service.chooser.chooser_target_service"
|
||||||
|
android:value="androidx.sharetarget.ChooserTargetServiceCompat"
|
||||||
|
/>
|
||||||
|
-->
|
||||||
|
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
@ -104,7 +123,6 @@
|
|||||||
<service
|
<service
|
||||||
android:name="com.novoda.merlin.MerlinService"
|
android:name="com.novoda.merlin.MerlinService"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<provider
|
<provider
|
||||||
android:name="androidx.core.content.FileProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="${applicationId}"
|
android:authorities="${applicationId}"
|
||||||
|
@ -51,7 +51,7 @@ import com.nextcloud.talk.newarch.features.conversationsList.di.module.Conversat
|
|||||||
import com.nextcloud.talk.newarch.local.dao.UsersDao
|
import com.nextcloud.talk.newarch.local.dao.UsersDao
|
||||||
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
import com.nextcloud.talk.newarch.local.models.UserNgEntity
|
||||||
import com.nextcloud.talk.newarch.local.models.other.UserStatus.*
|
import com.nextcloud.talk.newarch.local.models.other.UserStatus.*
|
||||||
import com.nextcloud.talk.newarch.utils.ShortcutService
|
import com.nextcloud.talk.newarch.services.shortcuts.ShortcutService
|
||||||
import com.nextcloud.talk.utils.ClosedInterfaceImpl
|
import com.nextcloud.talk.utils.ClosedInterfaceImpl
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||||
@ -133,10 +133,7 @@ class NextcloudTalkApplication : Application(), LifecycleObserver {
|
|||||||
setAppTheme(appPreferences.theme)
|
setAppTheme(appPreferences.theme)
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
|
val shortcutService: ShortcutService = get()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
||||||
val shortcutService: ShortcutService = get()
|
|
||||||
}
|
|
||||||
|
|
||||||
Security.insertProviderAt(Conscrypt.newProvider(), 1)
|
Security.insertProviderAt(Conscrypt.newProvider(), 1)
|
||||||
ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync()
|
ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync()
|
||||||
|
@ -664,9 +664,9 @@ class ContactsController : BaseController,
|
|||||||
|
|
||||||
private fun prepareViews() {
|
private fun prepareViews() {
|
||||||
layoutManager = SmoothScrollLinearLayoutManager(activity!!)
|
layoutManager = SmoothScrollLinearLayoutManager(activity!!)
|
||||||
recyclerView!!.layoutManager = layoutManager
|
recyclerView?.layoutManager = layoutManager
|
||||||
recyclerView!!.setHasFixedSize(true)
|
recyclerView?.setHasFixedSize(true)
|
||||||
recyclerView!!.adapter = adapter
|
recyclerView?.adapter = adapter
|
||||||
|
|
||||||
adapter!!.setStickyHeaderElevation(5)
|
adapter!!.setStickyHeaderElevation(5)
|
||||||
.setUnlinkAllItemsOnRemoveHeaders(true)
|
.setUnlinkAllItemsOnRemoveHeaders(true)
|
||||||
|
@ -23,7 +23,6 @@ package com.nextcloud.talk.jobs
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.text.TextUtils
|
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import androidx.work.CoroutineWorker
|
import androidx.work.CoroutineWorker
|
||||||
import androidx.work.ListenableWorker.Result
|
import androidx.work.ListenableWorker.Result
|
||||||
@ -68,8 +67,8 @@ class PushRegistrationWorker(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun pushRegistrationToServer() {
|
private fun pushRegistrationToServer() {
|
||||||
val token: String = appPreferences.pushToken
|
val token: String? = appPreferences.pushToken
|
||||||
if (!TextUtils.isEmpty(token)) {
|
if (!token.isNullOrEmpty()) {
|
||||||
var credentials: String
|
var credentials: String
|
||||||
val pushUtils = PushUtils(usersRepository)
|
val pushUtils = PushUtils(usersRepository)
|
||||||
val pushTokenHash = token.hashWithAlgorithm("SHA-512")
|
val pushTokenHash = token.hashWithAlgorithm("SHA-512")
|
||||||
|
@ -65,8 +65,8 @@ class ConversationsRepositoryImpl(val conversationsDao: ConversationsDao) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getLastThreeActiveConversationsForUser(userId: Long): LiveData<List<Conversation>> {
|
override fun getShortcutTargetConversations(userId: Long): LiveData<List<Conversation>> {
|
||||||
return conversationsDao.getLastThreeConversationsForUser(userId).distinctUntilChanged().map { data ->
|
return conversationsDao.getShortcutTargetConversations(userId).distinctUntilChanged().map { data ->
|
||||||
data.map {
|
data.map {
|
||||||
it.toConversation()
|
it.toConversation()
|
||||||
}
|
}
|
||||||
|
@ -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.GetConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
import com.nextcloud.talk.newarch.domain.usecases.JoinConversationUseCase
|
||||||
import com.nextcloud.talk.newarch.services.GlobalService
|
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 okhttp3.OkHttpClient
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
@ -14,7 +14,6 @@ import java.net.CookieManager
|
|||||||
val ServiceModule = module {
|
val ServiceModule = module {
|
||||||
single { createGlobalService(get(), get(), get(), get(), get(), get()) }
|
single { createGlobalService(get(), get(), get(), get(), get(), get()) }
|
||||||
single { createShortcutService(get(), get(), get()) }
|
single { createShortcutService(get(), get(), get()) }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createGlobalService(usersRepository: UsersRepository, cookieManager: CookieManager,
|
fun createGlobalService(usersRepository: UsersRepository, cookieManager: CookieManager,
|
||||||
|
@ -25,7 +25,7 @@ import com.nextcloud.talk.models.json.conversations.Conversation
|
|||||||
|
|
||||||
interface ConversationsRepository {
|
interface ConversationsRepository {
|
||||||
fun getConversationsForUser(userId: Long): LiveData<List<Conversation>>
|
fun getConversationsForUser(userId: Long): LiveData<List<Conversation>>
|
||||||
fun getLastThreeActiveConversationsForUser(userId: Long): LiveData<List<Conversation>>
|
fun getShortcutTargetConversations(userId: Long): LiveData<List<Conversation>>
|
||||||
|
|
||||||
suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation?
|
suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation?
|
||||||
suspend fun clearConversationsForUser(userId: Long)
|
suspend fun clearConversationsForUser(userId: Long)
|
||||||
|
@ -30,8 +30,8 @@ abstract class ConversationsDao {
|
|||||||
@Query("SELECT * FROM conversations WHERE user_id = :userId ORDER BY favorite DESC, last_activity DESC")
|
@Query("SELECT * FROM conversations WHERE user_id = :userId ORDER BY favorite DESC, last_activity DESC")
|
||||||
abstract fun getConversationsForUser(userId: Long): LiveData<List<ConversationEntity>>
|
abstract fun getConversationsForUser(userId: Long): LiveData<List<ConversationEntity>>
|
||||||
|
|
||||||
@Query("SELECT * FROM conversations WHERE user_id = :userId ORDER BY favorite DESC, last_activity DESC LIMIT 3")
|
@Query("SELECT * FROM conversations WHERE user_id = :userId ORDER BY favorite DESC, last_activity DESC LIMIT 4")
|
||||||
abstract fun getLastThreeConversationsForUser(userId: Long): LiveData<List<ConversationEntity>>
|
abstract fun getShortcutTargetConversations(userId: Long): LiveData<List<ConversationEntity>>
|
||||||
|
|
||||||
@Query("DELETE FROM conversations WHERE user_id = :userId")
|
@Query("DELETE FROM conversations WHERE user_id = :userId")
|
||||||
abstract suspend fun clearConversationsForUser(userId: Long)
|
abstract suspend fun clearConversationsForUser(userId: Long)
|
||||||
|
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * Nextcloud Talk application
|
||||||
|
* *
|
||||||
|
* * @author Mario Danic
|
||||||
|
* * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||||
|
* *
|
||||||
|
* * 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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<List<Conversation>> = 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<Conversation>) {
|
||||||
|
val openNewConversationIntent = Intent(context, MainActivity::class.java)
|
||||||
|
openNewConversationIntent.action = BundleKeys.KEY_NEW_CONVERSATION
|
||||||
|
|
||||||
|
val shortcuts: MutableList<ShortcutInfoCompat> = mutableListOf()
|
||||||
|
val contactCategories: MutableSet<String> = 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<Person>()
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
@ -1,123 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Thomas Ebert<thomas@thomasebert.net>
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
|
||||||
*
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<List<Conversation>> = 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<ShortcutInfo> = 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
|
|
||||||
}
|
|
||||||
}
|
|
@ -60,4 +60,5 @@ object BundleKeys {
|
|||||||
val KEY_ACCOUNT = "KEY_ACCOUNT"
|
val KEY_ACCOUNT = "KEY_ACCOUNT"
|
||||||
val KEY_FILE_ID = "KEY_FILE_ID"
|
val KEY_FILE_ID = "KEY_FILE_ID"
|
||||||
val KEY_NOTIFICATION_ID = "KEY_NOTIFICATION_ID"
|
val KEY_NOTIFICATION_ID = "KEY_NOTIFICATION_ID"
|
||||||
|
val KEY_CONVERSATION_ID = "KEY_CONVERSATION_ID"
|
||||||
}
|
}
|
||||||
|
@ -50,4 +50,7 @@
|
|||||||
<string name="google_app_id" translatable="false">1:829118773643:android:54b65087c544d819</string>
|
<string name="google_app_id" translatable="false">1:829118773643:android:54b65087c544d819</string>
|
||||||
<string name="google_crash_reporting_api_key" translatable="false">AIzaSyAWIyOcLafaFp8PFL61h64cy1NNZW2cU_s</string>
|
<string name="google_crash_reporting_api_key" translatable="false">AIzaSyAWIyOcLafaFp8PFL61h64cy1NNZW2cU_s</string>
|
||||||
<string name="google_storage_bucket" translatable="false">nextcloud-a7dea.appspot.com</string>
|
<string name="google_storage_bucket" translatable="false">nextcloud-a7dea.appspot.com</string>
|
||||||
|
|
||||||
|
<!-- Other things -->
|
||||||
|
<string name="nc_text_share_target">com.nextcloud.talk.newarch.services.shortcuts.category.TEXT_SHARE_TARGET</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
29
app/src/main/res/xml/shortcuts.xml
Normal file
29
app/src/main/res/xml/shortcuts.xml
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ /*
|
||||||
|
~ * Nextcloud Talk application
|
||||||
|
~ *
|
||||||
|
~ * @author Mario Danic
|
||||||
|
~ * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||||
|
~ *
|
||||||
|
~ * 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 <http://www.gnu.org/licenses/>.
|
||||||
|
~ */
|
||||||
|
-->
|
||||||
|
|
||||||
|
<shortcuts xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<share-target android:targetClass="com.nextcloud.talk.activities.MainActivity" >
|
||||||
|
<data android:mimeType="text/plain" />
|
||||||
|
<category android:name="@string/nc_text_share_target" android:label="@string/nc_app_label"/>
|
||||||
|
</share-target>
|
||||||
|
</shortcuts>
|
Loading…
Reference in New Issue
Block a user