diff --git a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt index b2ca8046b..02826f292 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/MainActivity.kt @@ -37,6 +37,7 @@ import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler import com.google.android.material.appbar.MaterialToolbar import com.nextcloud.talk.R import com.nextcloud.talk.controllers.CallNotificationController +import com.nextcloud.talk.controllers.ContactsController import com.nextcloud.talk.controllers.LockedController import com.nextcloud.talk.controllers.ServerSelectionController import com.nextcloud.talk.controllers.base.providers.ActionBarProvider @@ -152,7 +153,13 @@ class MainActivity : BaseActivity(), ActionBarProvider { override fun onNewIntent(intent: Intent) { super.onNewIntent(intent) - if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) { + if (intent.action == BundleKeys.KEY_NEW_CONVERSATION) { + openNewConversationScreen() + } else if (intent.action == BundleKeys.KEY_OPEN_CONVERSATION) { + ConductorRemapping.remapChatController( + router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1), + intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN)!!, intent.extras!!, false) + } else if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) { if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) { router!!.pushController( RouterTransaction.with(CallNotificationController(intent.extras!!)) @@ -162,7 +169,7 @@ class MainActivity : BaseActivity(), ActionBarProvider { } else { ConductorRemapping.remapChatController( router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1), - intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN), intent.extras!!, false + intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN)!!, intent.extras!!, false ) } } @@ -178,6 +185,17 @@ class MainActivity : BaseActivity(), ActionBarProvider { } } + private fun openNewConversationScreen() { + val bundle = Bundle() + bundle.putBoolean(BundleKeys.KEY_NEW_CONVERSATION, true) + + router?.pushController( + RouterTransaction.with(ContactsController(bundle)) + .pushChangeHandler(HorizontalChangeHandler()) + .popChangeHandler(HorizontalChangeHandler()) + ) + } + companion object { private val TAG = "MainActivity" } diff --git a/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.kt b/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.kt index ca42172af..ba0e607c6 100644 --- a/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.kt +++ b/app/src/main/java/com/nextcloud/talk/application/NextcloudTalkApplication.kt @@ -177,7 +177,7 @@ class NextcloudTalkApplication : Application(), LifecycleObserver { startKoin { androidContext(this@NextcloudTalkApplication) androidLogger() - modules(listOf(CommunicationModule, StorageModule, NetworkModule, ConversationsModule, ConversationsListModule, ManagementModule)) + modules(listOf(CommunicationModule, StorageModule, NetworkModule, ConversationsModule, ConversationsListModule, ServiceModule)) } } 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 c18851c47..765e0ef02 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,6 +65,14 @@ class ConversationsRepositoryImpl(val conversationsDao: ConversationsDao) : } } + override fun getLastThreeActiveConversationsForUser(userId: Long): LiveData> { + return conversationsDao.getLastThreeConversationsForUser(userId).distinctUntilChanged().map { data -> + data.map { + it.toConversation() + } + } + } + override suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation? { val conversationEntity = conversationsDao.getConversationForUserWithToken(userId, token) if (conversationEntity != null) { diff --git a/app/src/main/java/com/nextcloud/talk/newarch/di/module/ManagementModule.kt b/app/src/main/java/com/nextcloud/talk/newarch/di/module/ManagementModule.kt deleted file mode 100644 index a4e5496bb..000000000 --- a/app/src/main/java/com/nextcloud/talk/newarch/di/module/ManagementModule.kt +++ /dev/null @@ -1,38 +0,0 @@ -/* - * 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.newarch.di.module - -import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository -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.utils.ConversationService -import okhttp3.OkHttpClient -import org.koin.dsl.module -import java.net.CookieManager - -val ManagementModule = module { - single { createConversationsManager(get(), get(), get(), get(), get(), get()) } -} - -fun createConversationsManager(usersRepository: UsersRepository, cookieManager: CookieManager, okHttpClient: OkHttpClient, conversationsRepository: ConversationsRepository, getConversationUseCase: GetConversationUseCase, joinConversationUseCase: JoinConversationUseCase): ConversationService { - return ConversationService(usersRepository, cookieManager, okHttpClient, conversationsRepository, joinConversationUseCase, getConversationUseCase) -} \ No newline at end of file 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 new file mode 100644 index 000000000..5de63f1a9 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/newarch/di/module/ServiceModule.kt @@ -0,0 +1,29 @@ +package com.nextcloud.talk.newarch.di.module + +import android.content.Context +import android.content.pm.ShortcutManager +import com.nextcloud.talk.newarch.domain.repository.offline.ConversationsRepository +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.utils.ConversationService +import com.nextcloud.talk.newarch.utils.ShortcutService +import okhttp3.OkHttpClient +import org.koin.dsl.module +import java.net.CookieManager + +val ServiceModule = module { + single { createConversationsService(get(), get(), get(), get(), get(), get()) } + single { createShortcutService(get(), get(), get()) } + +} + +fun createConversationsService(usersRepository: UsersRepository, cookieManager: CookieManager, + okHttpClient: OkHttpClient, conversationsRepository: ConversationsRepository, + getConversationUseCase: GetConversationUseCase, joinConversationUseCase: JoinConversationUseCase): ConversationService { + return ConversationService(usersRepository, cookieManager, okHttpClient, conversationsRepository, joinConversationUseCase, getConversationUseCase) +} + +fun createShortcutService(context: Context, conversationsRepository: ConversationsRepository, conversationsService: ConversationService): ShortcutService { + return ShortcutService(context, conversationsRepository, conversationsService) +} \ No newline at end of file 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 ea15f30c1..d965ea25a 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,6 +25,8 @@ import com.nextcloud.talk.models.json.conversations.Conversation interface ConversationsRepository { fun getConversationsForUser(userId: Long): LiveData> + fun getLastThreeActiveConversationsForUser(userId: Long): LiveData> + suspend fun getConversationForUserWithToken(userId: Long, token: String): Conversation? suspend fun clearConversationsForUser(userId: Long) suspend fun saveConversationsForUser( 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 742dbd32b..253c2bb38 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 @@ -22,6 +22,7 @@ package com.nextcloud.talk.newarch.features.conversationsList import android.app.SearchManager import android.content.Context +import android.content.pm.ShortcutManager import android.graphics.drawable.Drawable import android.os.Build import android.os.Bundle @@ -58,6 +59,7 @@ import com.nextcloud.talk.newarch.utils.Images import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ConductorRemapping import com.nextcloud.talk.utils.DisplayUtils +import com.nextcloud.talk.newarch.utils.ShortcutService import com.nextcloud.talk.utils.animations.SharedElementTransition import com.nextcloud.talk.utils.bundle.BundleKeys import eu.davidea.flexibleadapter.FlexibleAdapter @@ -233,6 +235,7 @@ class ConversationsListView : BaseView(), OnQueryTextListener, ) } +<<<<<<< HEAD recyclerViewAdapter.updateDataSet( newConversations as List>?, false @@ -244,6 +247,18 @@ class ConversationsListView : BaseView(), OnQueryTextListener, recyclerViewAdapter.filterItems(500) }) } +======= + val shortcutService = ShortcutService( + context.getSystemService(ShortcutManager::class.java), + context, + this + //this.offlineRepository + ); + shortcutService.registerShortcuts() + + return super.onCreateView(inflater, container) + } +>>>>>>> feature/app-shortcuts viewState.observe(this@ConversationsListView, Observer { value -> when (value) { 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 61bb0ff97..36d8d518f 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,6 +30,9 @@ 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 last_activity DESC LIMIT 3") + abstract fun getLastThreeConversationsForUser(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/utils/ConversationService.kt b/app/src/main/java/com/nextcloud/talk/newarch/utils/ConversationService.kt index c1ce3f165..8c4d7eda1 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/utils/ConversationService.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/utils/ConversationService.kt @@ -45,7 +45,7 @@ class ConversationService constructor(usersRepository: UsersRepository, private val getConversationUseCase: GetConversationUseCase) : KoinComponent { private val applicationScope = CoroutineScope(Dispatchers.Default) private val previousUser: UserNgEntity? = null - private val currentUserLiveData: LiveData = usersRepository.getActiveUserLiveData() + val currentUserLiveData: LiveData = usersRepository.getActiveUserLiveData() private var currentConversation: Conversation? = null init { 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 new file mode 100644 index 000000000..bd8cf070d --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/newarch/utils/ShortcutService.kt @@ -0,0 +1,107 @@ +/* + * 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.Icon +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +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.utils.bundle.BundleKeys + +class ShortcutService constructor(private val context: Context, + private val conversationsRepository: ConversationsRepository, + conversationsService: ConversationService +) { + private var lastThreeActiveConversations: LiveData> = MutableLiveData() + private var currentUser: UserNgEntity? = null + @RequiresApi(Build.VERSION_CODES.N_MR1) + private val shortcutManager = context.getSystemService(ShortcutManager::class.java) + + init { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + conversationsService.currentUserLiveData.observeForever { + currentUser = it + it?.let { + lastThreeActiveConversations = conversationsRepository.getLastThreeActiveConversationsForUser(it.id!!) + } ?: run { + shortcutManager?.dynamicShortcuts = listOf() + } + } + + lastThreeActiveConversations.observeForever { + registerShortcuts() + } + } + } + + @TargetApi(Build.VERSION_CODES.P) + 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.createWithResource(context, R.drawable.ic_add_grey600_24px)) + .setIntent(openNewConversationIntent) + .build()) + + lastThreeActiveConversations.value?.let { conversations -> + for ((index, conversation) in conversations.withIndex()) { + // Only do this for the first 3 conversations + if (index <= 3) continue + + 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 icon = images.getImageForConversation(context, conversation) + shortcuts.add(ShortcutInfo.Builder(context, "current_conversation_" + (index + 1)) + .setShortLabel(conversation.displayName as String) + .setLongLabel(conversation.displayName as String) + // @TODO: Use avatar as icon + .setIcon(Icon.createWithResource(context, R.drawable.ic_add_grey600_24px)) + .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 840d4bbd5..409acc858 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 @@ -21,6 +21,7 @@ package com.nextcloud.talk.utils.bundle object BundleKeys { + val KEY_OPEN_CONVERSATION: String = "KEY_OPEN_CONVERSATION" val KEY_SELECTED_USERS = "KEY_SELECTED_USERS" val KEY_SELECTED_GROUPS = "KEY_SELECTED_GROUPS" val KEY_USERNAME = "KEY_USERNAME" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d42465d5b..d105947ee 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -167,6 +167,7 @@ If you delete this conversation it will also be deleted for all other participants. + New New conversation Join with a link Join via web