Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/talk-android.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
authorMarcel Hibbe <dev@mhibbe.de>2022-09-20 23:28:19 +0300
committerMarcel Hibbe <dev@mhibbe.de>2022-09-21 12:51:59 +0300
commit62777e936dfd3cf746699a66a85de8e5292470c3 (patch)
tree993be3c7949e3de9335030a5f1492d808c57195f /app/src
parent91bc2abfa97566c4864cbbb47ccce028bccab0c2 (diff)
add account switcher for "share to"feature/1353/shareToChooseAccount
fix to avoid share to screen when coming back from conversation to conversation list Signed-off-by: Marcel Hibbe <dev@mhibbe.de>
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt82
-rw-r--r--app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java4
-rw-r--r--app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountShareToDialogFragment.kt195
-rw-r--r--app/src/main/res/layout/dialog_choose_account_share_to.xml51
-rw-r--r--app/src/main/res/menu/menu_conversation_plus_filter.xml30
-rw-r--r--app/src/main/res/values/strings.xml4
6 files changed, 345 insertions, 21 deletions
diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt
index 45dc36750..ed42b9ac4 100644
--- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt
+++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt
@@ -100,6 +100,7 @@ import com.nextcloud.talk.models.json.status.Status
import com.nextcloud.talk.models.json.statuses.StatusesOverall
import com.nextcloud.talk.repositories.unifiedsearch.UnifiedSearchRepository
import com.nextcloud.talk.ui.dialog.ChooseAccountDialogFragment
+import com.nextcloud.talk.ui.dialog.ChooseAccountShareToDialogFragment
import com.nextcloud.talk.ui.dialog.ConversationsListBottomDialog
import com.nextcloud.talk.users.UserManager
import com.nextcloud.talk.utils.ApiUtils
@@ -180,6 +181,7 @@ class ConversationsListController(bundle: Bundle) :
private var conversationItemsWithHeader: MutableList<AbstractFlexibleItem<*>> = ArrayList()
private val searchableConversationItems: MutableList<AbstractFlexibleItem<*>> = ArrayList()
private var searchItem: MenuItem? = null
+ private var chooseAccountItem: MenuItem? = null
private var searchView: SearchView? = null
private var searchQuery: String? = null
private var credentials: String? = null
@@ -250,6 +252,43 @@ class ConversationsListController(bundle: Bundle) :
}
}
+ private fun loadUserAvatar(menuItem: MenuItem) {
+ if (activity != null) {
+ val imageRequest = DisplayUtils.getImageRequestForUrl(
+ ApiUtils.getUrlForAvatar(
+ currentUser!!.baseUrl,
+ currentUser!!.userId,
+ true
+ ),
+ currentUser
+ )
+ val imagePipeline = Fresco.getImagePipeline()
+ val dataSource = imagePipeline.fetchDecodedImage(imageRequest, null)
+ dataSource.subscribe(
+ object : BaseBitmapDataSubscriber() {
+ override fun onNewResultImpl(bitmap: Bitmap?) {
+ if (bitmap != null && resources != null) {
+ val roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(
+ resources!!,
+ bitmap
+ )
+ roundedBitmapDrawable.isCircular = true
+ roundedBitmapDrawable.setAntiAlias(true)
+ menuItem.icon = roundedBitmapDrawable
+ }
+ }
+
+ override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage?>>) {
+ if (resources != null) {
+ menuItem.icon = ResourcesCompat.getDrawable(resources!!, R.drawable.ic_user, null)
+ }
+ }
+ },
+ UiThreadImmediateExecutorService.getInstance()
+ )
+ }
+ }
+
override fun onAttach(view: View) {
Log.d(
TAG,
@@ -257,6 +296,9 @@ class ConversationsListController(bundle: Bundle) :
" Activity: " + System.identityHashCode(activity)
)
super.onAttach(view)
+
+ showShareToScreen = hasActivityActionSendIntent()
+
ClosedInterfaceImpl().setUpPushTokenRegistration()
if (!eventBus.isRegistered(this)) {
eventBus.register(this)
@@ -328,15 +370,32 @@ class ConversationsListController(bundle: Bundle) :
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
super.onCreateOptionsMenu(menu, inflater)
+
inflater.inflate(R.menu.menu_conversation_plus_filter, menu)
searchItem = menu.findItem(R.id.action_search)
+ chooseAccountItem = menu.findItem(R.id.action_choose_account)
+ loadUserAvatar(chooseAccountItem!!)
+
+ chooseAccountItem?.setOnMenuItemClickListener {
+ if (resources != null && resources!!.getBoolean(R.bool.multiaccount_support)) {
+ val newFragment: DialogFragment = ChooseAccountShareToDialogFragment.newInstance()
+ newFragment.show(
+ (activity as MainActivity?)!!.supportFragmentManager,
+ ChooseAccountShareToDialogFragment.TAG
+ )
+ }
+ true
+ }
initSearchView()
}
override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu)
searchView = MenuItemCompat.getActionView(searchItem) as SearchView
- showShareToScreen = !showShareToScreen && hasActivityActionSendIntent()
+
+ val moreAccountsAvailable = userManager.users.blockingGet().size > 1
+ menu.findItem(R.id.action_choose_account).isVisible = showShareToScreen && moreAccountsAvailable
+
if (showShareToScreen) {
hideSearchBar()
actionBar?.setTitle(R.string.send_to_three_dots)
@@ -679,7 +738,7 @@ class ConversationsListController(bundle: Bundle) :
val newFragment: DialogFragment = ChooseAccountDialogFragment.newInstance()
newFragment.show(
(getActivity() as MainActivity?)!!.supportFragmentManager,
- "ChooseAccountDialogFragment"
+ ChooseAccountDialogFragment.TAG
)
} else {
router.pushController(
@@ -858,7 +917,7 @@ class ConversationsListController(bundle: Bundle) :
loadMoreMessages()
}
ConversationItem.VIEW_TYPE -> {
- showConversation((Objects.requireNonNull(item) as ConversationItem).model)
+ handleConversation((Objects.requireNonNull(item) as ConversationItem).model)
}
}
}
@@ -870,21 +929,24 @@ class ConversationsListController(bundle: Bundle) :
val conversationItem = absItem as ConversationItem
if (conversationItem.model.token == conversationToken) {
val conversation = conversationItem.model
- showConversation(conversation)
+ handleConversation(conversation)
}
}
}
- private fun showConversation(conversation: Conversation?) {
+ @Suppress("Detekt.ComplexMethod")
+ private fun handleConversation(conversation: Conversation?) {
selectedConversation = conversation
if (selectedConversation != null && activity != null) {
val hasChatPermission = AttendeePermissionsUtil(selectedConversation!!.permissions).hasChatPermission(
currentUser!!
)
if (showShareToScreen) {
- if (hasChatPermission && !isReadOnlyConversation(selectedConversation!!)) {
+ if (hasChatPermission &&
+ !isReadOnlyConversation(selectedConversation!!) &&
+ !selectedConversation!!.shouldShowLobby(currentUser!!)
+ ) {
handleSharedData()
- showShareToScreen = false
} else {
Toast.makeText(context, R.string.send_to_forbidden, Toast.LENGTH_LONG).show()
}
@@ -947,7 +1009,6 @@ class ConversationsListController(bundle: Bundle) :
}
.setNegativeButton(R.string.nc_no) { _, _ ->
Log.d(TAG, "sharing files aborted, going back to share-to screen")
- showShareToScreen = true
}
viewThemeUtils.dialog
.colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder)
@@ -961,6 +1022,10 @@ class ConversationsListController(bundle: Bundle) :
}
}
+ private fun clearIntentAction() {
+ activity!!.intent.action = ""
+ }
+
override fun onItemLongClick(position: Int) {
if (showShareToScreen) {
Log.d(TAG, "sharing to multiple rooms not yet implemented. onItemLongClick is ignored.")
@@ -1085,6 +1150,7 @@ class ConversationsListController(bundle: Bundle) :
bundle,
false
)
+ clearIntentAction()
}
@Subscribe(sticky = true, threadMode = ThreadMode.BACKGROUND)
diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java
index dc205feb0..f225a680e 100644
--- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java
+++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java
@@ -49,8 +49,8 @@ import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.models.json.status.Status;
import com.nextcloud.talk.models.json.status.StatusOverall;
import com.nextcloud.talk.ui.StatusDrawable;
-import com.nextcloud.talk.users.UserManager;
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
+import com.nextcloud.talk.users.UserManager;
import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.DisplayUtils;
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew;
@@ -74,7 +74,7 @@ import io.reactivex.schedulers.Schedulers;
@AutoInjector(NextcloudTalkApplication.class)
public class ChooseAccountDialogFragment extends DialogFragment {
- private static final String TAG = ChooseAccountDialogFragment.class.getSimpleName();
+ public static final String TAG = ChooseAccountDialogFragment.class.getSimpleName();
private static final float STATUS_SIZE_IN_DP = 9f;
diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountShareToDialogFragment.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountShareToDialogFragment.kt
new file mode 100644
index 000000000..3340f7cb3
--- /dev/null
+++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountShareToDialogFragment.kt
@@ -0,0 +1,195 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Andy Scherzinger
+ * @author Mario Danic
+ * @author Marcel Hibbe
+ * Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
+ * Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
+ * Copyright (C) 2022 Marcel Hibbe (dev@mhibbe.de)
+ *
+ * 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/>.
+ *
+ * Parts related to account import were either copied from or inspired by the great work done by David Luhmer at:
+ * https://github.com/nextcloud/ownCloud-Account-Importer
+ */
+package com.nextcloud.talk.ui.dialog
+
+import android.annotation.SuppressLint
+import android.app.Dialog
+import android.net.Uri
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.DialogFragment
+import androidx.recyclerview.widget.LinearLayoutManager
+import autodagger.AutoInjector
+import com.facebook.drawee.backends.pipeline.Fresco
+import com.facebook.drawee.interfaces.DraweeController
+import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.nextcloud.talk.activities.MainActivity
+import com.nextcloud.talk.adapters.items.AdvancedUserItem
+import com.nextcloud.talk.application.NextcloudTalkApplication
+import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
+import com.nextcloud.talk.data.user.model.User
+import com.nextcloud.talk.databinding.DialogChooseAccountShareToBinding
+import com.nextcloud.talk.models.json.participants.Participant
+import com.nextcloud.talk.ui.theme.ViewThemeUtils
+import com.nextcloud.talk.users.UserManager
+import com.nextcloud.talk.utils.ApiUtils
+import com.nextcloud.talk.utils.DisplayUtils
+import eu.davidea.flexibleadapter.FlexibleAdapter
+import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
+import java.net.CookieManager
+import javax.inject.Inject
+
+@AutoInjector(NextcloudTalkApplication::class)
+class ChooseAccountShareToDialogFragment : DialogFragment() {
+ @JvmField
+ @Inject
+ var userManager: UserManager? = null
+
+ @JvmField
+ @Inject
+ var cookieManager: CookieManager? = null
+
+ @JvmField
+ @Inject
+ var viewThemeUtils: ViewThemeUtils? = null
+ private var binding: DialogChooseAccountShareToBinding? = null
+ private var dialogView: View? = null
+ private var adapter: FlexibleAdapter<AdvancedUserItem>? = null
+ private val userItems: MutableList<AdvancedUserItem> = ArrayList()
+ @SuppressLint("InflateParams")
+ override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+ binding = DialogChooseAccountShareToBinding.inflate(LayoutInflater.from(requireContext()))
+ dialogView = binding!!.root
+ return MaterialAlertDialogBuilder(requireContext()).setView(dialogView).create()
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ sharedApplication!!.componentApplication.inject(this)
+ val user = userManager!!.currentUser.blockingGet()
+ themeViews()
+ setupCurrentUser(user)
+ setupListeners(user)
+ setupAdapter()
+ prepareViews()
+ }
+
+ private fun setupCurrentUser(user: User?) {
+ binding!!.currentAccount.userIcon.tag = ""
+ if (user != null) {
+ binding!!.currentAccount.userName.text = user.displayName
+ binding!!.currentAccount.ticker.visibility = View.GONE
+ binding!!.currentAccount.account.text = Uri.parse(user.baseUrl).host
+ viewThemeUtils!!.platform.colorImageView(binding!!.currentAccount.accountMenu)
+ if (user.baseUrl != null &&
+ (user.baseUrl!!.startsWith("http://") || user.baseUrl!!.startsWith("https://"))
+ ) {
+ binding!!.currentAccount.userIcon.visibility = View.VISIBLE
+ val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
+ .setOldController(binding!!.currentAccount.userIcon.controller)
+ .setAutoPlayAnimations(true)
+ .setImageRequest(
+ DisplayUtils.getImageRequestForUrl(
+ ApiUtils.getUrlForAvatar(
+ user.baseUrl,
+ user.userId,
+ false
+ )
+ )
+ )
+ .build()
+ binding!!.currentAccount.userIcon.controller = draweeController
+ } else {
+ binding!!.currentAccount.userIcon.visibility = View.INVISIBLE
+ }
+ }
+ }
+
+ @Suppress("Detekt.NestedBlockDepth")
+ private fun setupAdapter() {
+ if (adapter == null) {
+ adapter = FlexibleAdapter(userItems, activity, false)
+ var userEntity: User
+ var participant: Participant
+ for (userItem in userManager!!.users.blockingGet()) {
+ userEntity = userItem
+ if (!userEntity.current) {
+ var userId: String?
+ userId = if (userEntity.userId != null) {
+ userEntity.userId
+ } else {
+ userEntity.username
+ }
+ participant = Participant()
+ participant.actorType = Participant.ActorType.USERS
+ participant.actorId = userId
+ participant.displayName = userEntity.displayName
+ userItems.add(AdvancedUserItem(participant, userEntity, null, viewThemeUtils))
+ }
+ }
+ adapter!!.addListener(onSwitchItemClickListener)
+ adapter!!.updateDataSet(userItems, false)
+ }
+ }
+
+ private fun setupListeners(user: User) {
+ binding!!.currentAccount.root.setOnClickListener { v: View? -> dismiss() }
+ }
+
+ private fun themeViews() {
+ viewThemeUtils!!.platform.themeDialog(binding!!.root)
+ }
+
+ private fun prepareViews() {
+ if (activity != null) {
+ val layoutManager: LinearLayoutManager = SmoothScrollLinearLayoutManager(activity)
+ binding!!.accountsList.layoutManager = layoutManager
+ }
+ binding!!.accountsList.setHasFixedSize(true)
+ binding!!.accountsList.adapter = adapter
+ }
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
+ return dialogView
+ }
+
+ override fun onDestroyView() {
+ super.onDestroyView()
+ binding = null
+ }
+
+ private val onSwitchItemClickListener = FlexibleAdapter.OnItemClickListener { view, position ->
+ if (userItems.size > position) {
+ val user = userItems[position].user
+ if (userManager!!.setUserAsActive(user).blockingGet()) {
+ cookieManager!!.cookieStore.removeAll()
+ activity?.runOnUiThread { (activity as MainActivity?)!!.resetConversationsList() }
+ dismiss()
+ }
+ }
+ true
+ }
+
+ companion object {
+ val TAG = ChooseAccountShareToDialogFragment::class.java.simpleName
+ fun newInstance(): ChooseAccountShareToDialogFragment {
+ return ChooseAccountShareToDialogFragment()
+ }
+ }
+}
diff --git a/app/src/main/res/layout/dialog_choose_account_share_to.xml b/app/src/main/res/layout/dialog_choose_account_share_to.xml
new file mode 100644
index 000000000..652f8acf1
--- /dev/null
+++ b/app/src/main/res/layout/dialog_choose_account_share_to.xml
@@ -0,0 +1,51 @@
+<!--
+ ~ Nextcloud Talk application
+ ~
+ ~ @author Marcel Hibbe
+ ~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
+ ~
+ ~ 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/>.
+ -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:background="@color/white"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <include
+ android:id="@+id/current_account"
+ layout="@layout/current_account_item"
+ android:layout_width="match_parent"
+ android:layout_height="72dp"
+ android:layout_margin="4dp"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toTopOf="parent" />
+
+ <androidx.recyclerview.widget.RecyclerView
+ android:id="@+id/accounts_list"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_marginBottom="10dp"
+ app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
+ app:layout_constrainedHeight="true"
+ app:layout_constraintBottom_toTopOf="@+id/add_account"
+ app:layout_constraintEnd_toEndOf="parent"
+ app:layout_constraintStart_toStartOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/divider"
+ tools:listitem="@layout/account_item" />
+
+</LinearLayout>
diff --git a/app/src/main/res/menu/menu_conversation_plus_filter.xml b/app/src/main/res/menu/menu_conversation_plus_filter.xml
index 828b7202a..b46bf45df 100644
--- a/app/src/main/res/menu/menu_conversation_plus_filter.xml
+++ b/app/src/main/res/menu/menu_conversation_plus_filter.xml
@@ -1,8 +1,9 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
+<?xml version="1.0" encoding="utf-8"?><!--
~ Nextcloud Talk application
~
~ @author Mario Danic
+ ~ @author Marcel Hibbe
+ ~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
~ Copyright (C) 2017 Mario Danic
~
~ This program is free software: you can redistribute it and/or modify
@@ -20,14 +21,23 @@
-->
<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ xmlns:tools="http://schemas.android.com/tools">
- <!-- Search, should appear as action button -->
- <item android:id="@+id/action_search"
- android:title="@string/nc_search"
- android:icon="@drawable/ic_search_white_24dp"
- app:showAsAction="collapseActionView|always"
- android:animateLayoutChanges="true"
- app:actionViewClass="androidx.appcompat.widget.SearchView" />
+ <!-- Search, should appear as action button -->
+ <item
+ android:id="@+id/action_search"
+ android:animateLayoutChanges="true"
+ android:icon="@drawable/ic_search_white_24dp"
+ android:title="@string/nc_search"
+ app:actionViewClass="androidx.appcompat.widget.SearchView"
+ app:showAsAction="collapseActionView|always" />
+
+ <item
+ android:id="@+id/action_choose_account"
+ android:animateLayoutChanges="true"
+ android:title="@string/nc_share_to_choose_account"
+ app:showAsAction="collapseActionView|ifRoom"
+ tools:icon="@drawable/account_circle_48dp" />
</menu>
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index d19c8db9e..6d59a36a7 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -455,6 +455,9 @@
<string name="nc_shared_items_location">Location</string>
<string name="nc_shared_items_deck_card">Deck card</string>
+ <!-- share to screen -->
+ <string name="nc_share_to_choose_account">Choose account</string>
+
<!-- voice messages -->
<string name="nc_voice_message_filename">Talk recording from %1$s (%2$s)</string>
<string name="nc_voice_message_hold_to_record_info">Hold to record, release to send.</string>
@@ -599,5 +602,4 @@
<string name="nc_expire_message_one_hour">1 hour</string>
<string name="nc_expire_messages_explanation">Chat messages can be expired after a certain time. Note: Files shared in chat will not be deleted for the owner, but will no longer be shared in the conversation.</string>
-
</resources>