diff --git a/app/src/main/java/com/nextcloud/talk/conversation/CreateConversationDialogFragment.kt b/app/src/main/java/com/nextcloud/talk/conversation/CreateConversationDialogFragment.kt deleted file mode 100644 index ecbd6aa22..000000000 --- a/app/src/main/java/com/nextcloud/talk/conversation/CreateConversationDialogFragment.kt +++ /dev/null @@ -1,307 +0,0 @@ -/* - * Nextcloud Talk - Android Client - * - * SPDX-FileCopyrightText: 2023 Marcel Hibbe - * SPDX-License-Identifier: GPL-3.0-or-later - */ -package com.nextcloud.talk.conversation - -import android.annotation.SuppressLint -import android.app.Dialog -import android.content.Intent -import android.content.res.ColorStateList -import android.os.Bundle -import android.os.Parcelable -import android.text.Editable -import android.text.TextUtils -import android.text.TextWatcher -import android.util.Log -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog -import androidx.core.content.res.ResourcesCompat -import androidx.fragment.app.DialogFragment -import androidx.lifecycle.ViewModelProvider -import androidx.work.Data -import androidx.work.OneTimeWorkRequest -import androidx.work.WorkInfo -import androidx.work.WorkManager -import autodagger.AutoInjector -import com.google.android.material.dialog.MaterialAlertDialogBuilder -import com.google.android.material.snackbar.Snackbar -import com.nextcloud.android.common.ui.theme.utils.ColorRole -import com.nextcloud.talk.R -import com.nextcloud.talk.application.NextcloudTalkApplication -import com.nextcloud.talk.chat.ChatActivity -import com.nextcloud.talk.conversation.viewmodel.ConversationViewModel -import com.nextcloud.talk.databinding.DialogCreateConversationBinding -import com.nextcloud.talk.jobs.AddParticipantsToConversationWorker -import com.nextcloud.talk.models.json.conversations.ConversationEnums -import com.nextcloud.talk.ui.theme.ViewThemeUtils -import com.nextcloud.talk.utils.bundle.BundleKeys -import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew -import com.vanniktech.emoji.EmojiPopup -import org.greenrobot.eventbus.EventBus -import org.parceler.Parcels -import javax.inject.Inject - -@AutoInjector(NextcloudTalkApplication::class) -class CreateConversationDialogFragment : DialogFragment() { - - @Inject - lateinit var viewModelFactory: ViewModelProvider.Factory - - @Inject - lateinit var viewThemeUtils: ViewThemeUtils - - @Inject - lateinit var eventBus: EventBus - - @Inject - lateinit var currentUserProvider: CurrentUserProviderNew - - private lateinit var binding: DialogCreateConversationBinding - private lateinit var viewModel: ConversationViewModel - - private var emojiPopup: EmojiPopup? = null - - private var conversationType: ConversationEnums.ConversationType? = null - private var usersToInvite: ArrayList = ArrayList() - private var groupsToInvite: ArrayList = ArrayList() - private var emailsToInvite: ArrayList = ArrayList() - private var circlesToInvite: ArrayList = ArrayList() - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - - NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) - - viewModel = ViewModelProvider(this, viewModelFactory)[ConversationViewModel::class.java] - - if (arguments?.containsKey(USERS_TO_INVITE) == true) { - usersToInvite = arguments?.getStringArrayList(USERS_TO_INVITE)!! - } - if (arguments?.containsKey(GROUPS_TO_INVITE) == true) { - groupsToInvite = arguments?.getStringArrayList(GROUPS_TO_INVITE)!! - } - if (arguments?.containsKey(EMAILS_TO_INVITE) == true) { - emailsToInvite = arguments?.getStringArrayList(EMAILS_TO_INVITE)!! - } - if (arguments?.containsKey(CIRCLES_TO_INVITE) == true) { - circlesToInvite = arguments?.getStringArrayList(CIRCLES_TO_INVITE)!! - } - if (arguments?.containsKey(KEY_CONVERSATION_TYPE) == true) { - conversationType = Parcels.unwrap(arguments?.getParcelable(KEY_CONVERSATION_TYPE)) - } - } - - @SuppressLint("InflateParams") - override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { - binding = DialogCreateConversationBinding.inflate(layoutInflater) - - val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context) - .setTitle(resources.getString(R.string.create_conversation)) - // listener is null for now to avoid closing after button was clicked. - // listener is set later in onStart - .setPositiveButton(R.string.nc_common_create, null) - .setNegativeButton(R.string.nc_common_dismiss, null) - .setView(binding.root) - viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder) - - return dialogBuilder.create() - } - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - setupListeners() - setupStateObserver() - - setupEmojiPopup() - } - - override fun onStart() { - super.onStart() - - val positiveButton = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE) - positiveButton.isEnabled = false - positiveButton.setOnClickListener { - viewModel.createConversation( - binding.textEdit.text.toString(), - conversationType - ) - } - - themeDialog() - } - - private fun themeDialog() { - viewThemeUtils.platform.themeDialog(binding.root) - viewThemeUtils.platform.colorTextButtons((dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE)) - viewThemeUtils.platform.colorTextButtons((dialog as AlertDialog).getButton(AlertDialog.BUTTON_NEGATIVE)) - viewThemeUtils.material.colorTextInputLayout(binding.textInputLayout) - } - - private fun setupEmojiPopup() { - emojiPopup = binding.let { - EmojiPopup( - rootView = requireView(), - editText = it.textEdit, - onEmojiPopupShownListener = { - viewThemeUtils.platform.colorImageView(it.smileyButton, ColorRole.PRIMARY) - }, - onEmojiPopupDismissListener = { - it.smileyButton.imageTintList = ColorStateList.valueOf( - ResourcesCompat.getColor( - resources, - R.color.medium_emphasis_text, - context?.theme - ) - ) - }, - onEmojiClickListener = { - binding.textEdit.editableText?.append(" ") - } - ) - } - } - - private fun setupListeners() { - binding.smileyButton.setOnClickListener { emojiPopup?.toggle() } - binding.textEdit.addTextChangedListener(object : TextWatcher { - override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { - // unused atm - } - - override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { - // unused atm - } - - override fun afterTextChanged(s: Editable) { - val positiveButton = (dialog as AlertDialog).getButton(AlertDialog.BUTTON_POSITIVE) - - if (!TextUtils.isEmpty(s)) { - if (!positiveButton.isEnabled) { - positiveButton.isEnabled = true - } - } else { - if (positiveButton.isEnabled) { - positiveButton.isEnabled = false - } - } - } - }) - } - - private fun setupStateObserver() { - viewModel.viewState.observe(viewLifecycleOwner) { state -> - when (state) { - is ConversationViewModel.InitialState -> {} - is ConversationViewModel.CreatingState -> {} - is ConversationViewModel.CreatingSuccessState -> addParticipants(state.roomToken) - is ConversationViewModel.CreatingFailedState -> { - Log.e(TAG, "Failed to create conversation") - showError() - } - - else -> {} - } - } - } - - private fun addParticipants(roomToken: String) { - val data = Data.Builder() - data.putLong(BundleKeys.KEY_INTERNAL_USER_ID, currentUserProvider.currentUser.blockingGet().id!!) - data.putString(BundleKeys.KEY_TOKEN, roomToken) - data.putStringArray(BundleKeys.KEY_SELECTED_USERS, usersToInvite.toTypedArray()) - data.putStringArray(BundleKeys.KEY_SELECTED_GROUPS, groupsToInvite.toTypedArray()) - data.putStringArray(BundleKeys.KEY_SELECTED_EMAILS, emailsToInvite.toTypedArray()) - data.putStringArray(BundleKeys.KEY_SELECTED_CIRCLES, circlesToInvite.toTypedArray()) - - val addParticipantsToConversationWorker: OneTimeWorkRequest = OneTimeWorkRequest.Builder( - AddParticipantsToConversationWorker::class.java - ) - .setInputData(data.build()) - .build() - - WorkManager.getInstance(requireContext()).enqueue(addParticipantsToConversationWorker) - - WorkManager.getInstance(requireContext()).getWorkInfoByIdLiveData(addParticipantsToConversationWorker.id) - .observeForever { workInfo: WorkInfo? -> - if (workInfo != null) { - when (workInfo.state) { - WorkInfo.State.RUNNING -> { - Log.d(TAG, "running AddParticipantsToConversation") - } - - WorkInfo.State.SUCCEEDED -> { - Log.d(TAG, "success AddParticipantsToConversation") - initiateConversation(roomToken) - } - - WorkInfo.State.FAILED -> { - Log.e(TAG, "failed to AddParticipantsToConversation") - showError() - } - - else -> { - } - } - } - } - } - - private fun initiateConversation(roomToken: String) { - activity?.let { - val bundle = Bundle() - bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken) - val chatIntent = Intent(it, ChatActivity::class.java) - chatIntent.putExtras(bundle) - chatIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP) - startActivity(chatIntent) - } - - dismiss() - } - - private fun showError() { - dismiss() - Snackbar.make(binding.root, R.string.nc_common_error_sorry, Snackbar.LENGTH_LONG).show() - } - - /** - * Fragment creator - */ - companion object { - private val TAG = CreateConversationDialogFragment::class.java.simpleName - private const val USERS_TO_INVITE = "usersToInvite" - private const val GROUPS_TO_INVITE = "groupsToInvite" - private const val EMAILS_TO_INVITE = "emailsToInvite" - private const val CIRCLES_TO_INVITE = "circlesToInvite" - private const val KEY_CONVERSATION_TYPE = "keyConversationType" - - @JvmStatic - fun newInstance( - usersToInvite: ArrayList?, - groupsToInvite: ArrayList?, - emailsToInvite: ArrayList?, - circlesToInvite: ArrayList?, - conversationType: Parcelable - ): CreateConversationDialogFragment { - val args = Bundle() - args.putStringArrayList(USERS_TO_INVITE, usersToInvite) - args.putStringArrayList(GROUPS_TO_INVITE, groupsToInvite) - args.putStringArrayList(EMAILS_TO_INVITE, emailsToInvite) - args.putStringArrayList(CIRCLES_TO_INVITE, circlesToInvite) - args.putParcelable(KEY_CONVERSATION_TYPE, conversationType) - val fragment = CreateConversationDialogFragment() - fragment.arguments = args - return fragment - } - } -} diff --git a/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepository.kt b/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepository.kt deleted file mode 100644 index 96580c646..000000000 --- a/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepository.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Nextcloud Talk - Android Client - * - * SPDX-FileCopyrightText: 2023 Marcel Hibbe - * SPDX-License-Identifier: GPL-3.0-or-later - */ -package com.nextcloud.talk.conversation.repository - -import com.nextcloud.talk.models.json.conversations.ConversationEnums -import com.nextcloud.talk.models.json.conversations.RoomOverall -import io.reactivex.Observable - -interface ConversationRepository { - - fun createConversation( - roomName: String, - conversationType: ConversationEnums.ConversationType? - ): Observable -} diff --git a/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepositoryImpl.kt b/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepositoryImpl.kt deleted file mode 100644 index d7b3467ef..000000000 --- a/app/src/main/java/com/nextcloud/talk/conversation/repository/ConversationRepositoryImpl.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Nextcloud Talk - Android Client - * - * SPDX-FileCopyrightText: 2023 Marcel Hibbe - * SPDX-License-Identifier: GPL-3.0-or-later - */ -package com.nextcloud.talk.conversation.repository - -import com.nextcloud.talk.api.NcApi -import com.nextcloud.talk.data.user.model.User -import com.nextcloud.talk.models.RetrofitBucket -import com.nextcloud.talk.models.json.conversations.ConversationEnums -import com.nextcloud.talk.models.json.conversations.RoomOverall -import com.nextcloud.talk.utils.ApiUtils -import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew -import io.reactivex.Observable -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.schedulers.Schedulers - -class ConversationRepositoryImpl(private val ncApi: NcApi, currentUserProvider: CurrentUserProviderNew) : - ConversationRepository { - - val currentUser: User = currentUserProvider.currentUser.blockingGet() - val credentials: String = ApiUtils.getCredentials(currentUser.username, currentUser.token)!! - - override fun createConversation( - roomName: String, - conversationType: ConversationEnums.ConversationType? - ): Observable { - val apiVersion = ApiUtils.getConversationApiVersion(currentUser, intArrayOf(ApiUtils.API_V4, ApiUtils.API_V1)) - - val retrofitBucket: RetrofitBucket = - if (conversationType == ConversationEnums.ConversationType.ROOM_PUBLIC_CALL) { - ApiUtils.getRetrofitBucketForCreateRoom( - apiVersion, - currentUser.baseUrl!!, - ROOM_TYPE_PUBLIC, - null, - null, - roomName - ) - } else { - ApiUtils.getRetrofitBucketForCreateRoom( - apiVersion, - currentUser.baseUrl!!, - ROOM_TYPE_GROUP, - null, - null, - roomName - ) - } - return ncApi.createRoom(credentials, retrofitBucket.url, retrofitBucket.queryMap) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .retry(1) - } - - companion object { - private const val ROOM_TYPE_PUBLIC = "3" - private const val ROOM_TYPE_GROUP = "2" - } -} diff --git a/app/src/main/java/com/nextcloud/talk/conversation/viewmodel/ConversationViewModel.kt b/app/src/main/java/com/nextcloud/talk/conversation/viewmodel/ConversationViewModel.kt deleted file mode 100644 index 7783199f1..000000000 --- a/app/src/main/java/com/nextcloud/talk/conversation/viewmodel/ConversationViewModel.kt +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Nextcloud Talk - Android Client - * - * SPDX-FileCopyrightText: 2023 Marcel Hibbe - * SPDX-License-Identifier: GPL-3.0-or-later - */ -package com.nextcloud.talk.conversation.viewmodel - -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import com.nextcloud.talk.conversation.repository.ConversationRepository -import com.nextcloud.talk.models.json.conversations.ConversationEnums -import com.nextcloud.talk.models.json.conversations.RoomOverall -import io.reactivex.Observer -import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.disposables.Disposable -import io.reactivex.schedulers.Schedulers -import javax.inject.Inject - -class ConversationViewModel @Inject constructor(private val repository: ConversationRepository) : ViewModel() { - - sealed class ViewState - object InitialState : ViewState() - - object CreatingState : ViewState() - class CreatingSuccessState(val roomToken: String) : ViewState() - object CreatingFailedState : ViewState() - - private val _viewState: MutableLiveData = MutableLiveData( - InitialState - ) - val viewState: LiveData - get() = _viewState - - private var disposable: Disposable? = null - - override fun onCleared() { - super.onCleared() - disposable?.dispose() - } - - fun createConversation(roomName: String, conversationType: ConversationEnums.ConversationType?) { - _viewState.value = CreatingState - - repository.createConversation( - roomName, - conversationType - ) - .doOnSubscribe { disposable = it } - ?.subscribeOn(Schedulers.io()) - ?.observeOn(AndroidSchedulers.mainThread()) - ?.subscribe(CreateConversationObserver()) - } - - inner class CreateConversationObserver : Observer { - override fun onSubscribe(d: Disposable) { - // unused atm - } - - override fun onNext(roomOverall: RoomOverall) { - val conversation = roomOverall.ocs!!.data - _viewState.value = CreatingSuccessState(conversation?.token!!) - } - - override fun onError(e: Throwable) { - // dispose() - } - - override fun onComplete() { - // dispose() - } - } - - companion object { - private val TAG = ConversationViewModel::class.java.simpleName - } -} diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt index 6243c3198..6eb4d0aa4 100644 --- a/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt +++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/RepositoryModule.kt @@ -17,8 +17,6 @@ import com.nextcloud.talk.chat.data.network.OfflineFirstChatRepository import com.nextcloud.talk.chat.data.network.RetrofitChatNetwork import com.nextcloud.talk.contacts.ContactsRepository import com.nextcloud.talk.contacts.ContactsRepositoryImpl -import com.nextcloud.talk.conversation.repository.ConversationRepository -import com.nextcloud.talk.conversation.repository.ConversationRepositoryImpl import com.nextcloud.talk.conversationcreation.ConversationCreationRepository import com.nextcloud.talk.conversationcreation.ConversationCreationRepositoryImpl import com.nextcloud.talk.conversationinfoedit.data.ConversationInfoEditRepository @@ -142,10 +140,6 @@ class RepositoryModule { return ConversationInfoEditRepositoryImpl(ncApi, ncApiCoroutines, userProvider) } - @Provides - fun provideConversationRepository(ncApi: NcApi, userProvider: CurrentUserProviderNew): ConversationRepository = - ConversationRepositoryImpl(ncApi, userProvider) - @Provides fun provideInvitationsRepository(ncApi: NcApi): InvitationsRepository = InvitationsRepositoryImpl(ncApi) diff --git a/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt b/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt index 823cab6a5..a5626faf2 100644 --- a/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt +++ b/app/src/main/java/com/nextcloud/talk/dagger/modules/ViewModelModule.kt @@ -12,7 +12,6 @@ import androidx.lifecycle.ViewModelProvider import com.nextcloud.talk.chat.viewmodels.ChatViewModel import com.nextcloud.talk.chat.viewmodels.MessageInputViewModel import com.nextcloud.talk.contacts.ContactsViewModel -import com.nextcloud.talk.conversation.viewmodel.ConversationViewModel import com.nextcloud.talk.conversationcreation.ConversationCreationViewModel import com.nextcloud.talk.conversationinfo.viewmodel.ConversationInfoViewModel import com.nextcloud.talk.conversationinfoedit.viewmodel.ConversationInfoEditViewModel @@ -135,11 +134,6 @@ abstract class ViewModelModule { @ViewModelKey(ConversationInfoEditViewModel::class) abstract fun conversationInfoEditViewModel(viewModel: ConversationInfoEditViewModel): ViewModel - @Binds - @IntoMap - @ViewModelKey(ConversationViewModel::class) - abstract fun conversationViewModel(viewModel: ConversationViewModel): ViewModel - @Binds @IntoMap @ViewModelKey(InvitationsViewModel::class)