diff --git a/app/src/main/java/com/nextcloud/talk/controllers/CallController.kt b/app/src/main/java/com/nextcloud/talk/controllers/CallController.kt index 910ac78f3..daf691c8c 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/CallController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/CallController.kt @@ -353,7 +353,7 @@ class CallController(args: Bundle) : BaseController() { } override fun onNext(roomsOverall: RoomsOverall) { - for (conversation in roomsOverall?.ocs?.data!!) { + for (conversation in roomsOverall.ocs?.data!!) { if (roomId == conversation.conversationId) { roomToken = conversation.token.toString() break diff --git a/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.kt b/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.kt index 4044a6c2f..ad47bf22d 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/CallNotificationController.kt @@ -241,7 +241,7 @@ class CallNotificationController(private val originalBundle: Bundle) : BaseContr override fun onSubscribe(d: Disposable) {} override fun onNext(roomsOverall: RoomsOverall) { - for (conversation in roomsOverall.ocs.data!!) { + for (conversation in roomsOverall.ocs.data) { if (roomId == conversation.conversationId) { currentConversation = conversation runAllThings() diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt index 20b6cb13a..68fe7f279 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt @@ -260,7 +260,7 @@ class ChatController(args: Bundle) : BaseController(), MessagesListAdapter } override fun onNext(roomsOverall: RoomsOverall) { - for (conversation in roomsOverall.ocs.data!!) { + for (conversation in roomsOverall.ocs.data) { if (roomId == conversation.conversationId) { roomToken = conversation.token currentConversation = conversation diff --git a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt index 34cf9a36b..18e991a58 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt @@ -31,6 +31,7 @@ import android.view.ViewGroup import android.view.inputmethod.EditorInfo import android.view.inputmethod.InputMethodManager import android.widget.EditText +import android.widget.ProgressBar import androidx.annotation.RequiresApi import androidx.appcompat.app.ActionBar import androidx.core.view.isVisible @@ -87,6 +88,17 @@ abstract class BaseController : ButterKnifeController(), ComponentCallbacks { return view } + protected val toolbarProgressBar: View? + get() { + var view: ProgressBar? = null + activity?.let { + if (it is MainActivity) { + view = it.toolbarProgressBar + } + } + return view + } + protected val floatingActionButton: FloatingActionButton? get() { @@ -127,6 +139,7 @@ abstract class BaseController : ButterKnifeController(), ComponentCallbacks { actionBar?.setIcon(null) setOptionsMenuHidden(true) if (changeType == ControllerChangeType.POP_EXIT || changeType == ControllerChangeType.PUSH_EXIT) { + toolbarProgressBar?.isVisible = false activity?.inputEditText?.text = null searchLayout?.searchProgressBar?.isVisible = false floatingActionButton?.isVisible = false diff --git a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt index 4aa9fd144..08536b6f7 100644 --- a/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt +++ b/app/src/main/java/com/nextcloud/talk/models/json/chat/ChatMessage.kt @@ -158,8 +158,8 @@ class ChatMessage : IMessage, MessageContentType, MessageContentType.Image { } return ApiUtils.getUrlForFilePreviewWithFileId(activeUser!!.baseUrl, individualHashMap["id"], sharedApplication - !!.resources - !!.getDimensionPixelSize(R.dimen.maximum_file_preview_size)) + !!.resources + !!.getDimensionPixelSize(R.dimen.maximum_file_preview_size)) } } } @@ -197,27 +197,27 @@ class ChatMessage : IMessage, MessageContentType, MessageContentType.Image { sharedApplication!!.getString(R.string.nc_sent_a_gif_you) } else { String.format(sharedApplication - !!.getResources() + !!.resources .getString(R.string.nc_sent_a_gif), if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication - !!.getString(R.string.nc_guest)) + !!.getString(R.string.nc_guest)) } } else if (messageType == MessageType.SINGLE_NC_ATTACHMENT_MESSAGE) { return if (actorId.equals(activeUser!!.userId)) { sharedApplication!!.resources.getString(R.string.nc_sent_an_attachment_you) } else { String.format(sharedApplication - !!.resources + !!.resources .getString(R.string.nc_sent_an_attachment), if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication - !!.getString(R.string.nc_guest)) + !!.getString(R.string.nc_guest)) } } else if (messageType == MessageType.SINGLE_LINK_MESSAGE) { return if (actorId.equals(activeUser!!.userId)) { sharedApplication!!.resources.getString(R.string.nc_sent_a_link_you) } else { String.format(sharedApplication - !! .getResources() + !!.resources .getString(R.string.nc_sent_a_link), if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication!!.getString(R.string.nc_guest)) } @@ -226,30 +226,30 @@ class ChatMessage : IMessage, MessageContentType, MessageContentType.Image { sharedApplication!!.resources.getString(R.string.nc_sent_an_audio_you) } else { String.format(sharedApplication - !!.getResources() + !!.resources .getString(R.string.nc_sent_an_audio), if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication - !!.getString(R.string.nc_guest)) + !!.getString(R.string.nc_guest)) } } else if (messageType == MessageType.SINGLE_LINK_VIDEO_MESSAGE) { return if (actorId.equals(activeUser!!.userId)) { sharedApplication!!.resources.getString(R.string.nc_sent_a_video_you) } else { String.format(sharedApplication - !!.resources + !!.resources .getString(R.string.nc_sent_a_video), if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication - !!.getString(R.string.nc_guest)) + !!.getString(R.string.nc_guest)) } } else if (messageType == MessageType.SINGLE_LINK_IMAGE_MESSAGE) { return if (actorId.equals(activeUser!!.userId)) { sharedApplication!!.getString(R.string.nc_sent_an_image_you) } else { String.format(sharedApplication - !!.getResources() + !!.resources .getString(R.string.nc_sent_an_image), if (!TextUtils.isEmpty(actorDisplayName)) actorDisplayName else sharedApplication - !!.getString(R.string.nc_guest)) + !!.getString(R.string.nc_guest)) } } } diff --git a/app/src/main/java/com/nextcloud/talk/newarch/data/repository/online/NextcloudTalkRepositoryImpl.kt b/app/src/main/java/com/nextcloud/talk/newarch/data/repository/online/NextcloudTalkRepositoryImpl.kt index 98e9b8fff..8a58329b9 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/data/repository/online/NextcloudTalkRepositoryImpl.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/data/repository/online/NextcloudTalkRepositoryImpl.kt @@ -93,6 +93,10 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou } } + override suspend fun setPasswordForConversation(user: UserNgEntity, conversationToken: String, password: String): GenericOverall { + return apiService.setPasswordForConversation(user.getCredentials(), ApiUtils.getUrlForPassword(user.baseUrl, conversationToken), password) + } + override suspend fun addParticipantToConversation(user: UserNgEntity, conversationToken: String, participantId: String, source: String): AddParticipantOverall { return apiService.addParticipant(user.getCredentials(), ApiUtils.getUrlForParticipants(user.baseUrl, conversationToken), participantId, source) } @@ -102,7 +106,7 @@ class NextcloudTalkRepositoryImpl(private val apiService: ApiService) : Nextclou } override suspend fun getContactsForUser(user: UserNgEntity, groupConversation: Boolean, searchQuery: String?, conversationToken: String?): List { - return apiService.getContacts(authorization = user.getCredentials(), url = ApiUtils.getUrlForContactsSearch(user.baseUrl), shareTypes = ApiUtils.getShareTypesForContactsSearch(groupConversation), options = ApiUtils.getQueryMapForContactsSearch(searchQuery, conversationToken)).ocs.data.map { + return apiService.getContacts(authorization = user.getCredentials(), url = ApiUtils.getUrlForContactsSearch(user.baseUrl), shareTypes = ApiUtils.getShareTypesForContactsSearch(user, groupConversation), options = ApiUtils.getQueryMapForContactsSearch(searchQuery, conversationToken)).ocs.data.map { val participant = Participant() participant.userId = it.id participant.displayName = it.label diff --git a/app/src/main/java/com/nextcloud/talk/newarch/data/source/remote/ApiService.kt b/app/src/main/java/com/nextcloud/talk/newarch/data/source/remote/ApiService.kt index 921f90786..85876de23 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/data/source/remote/ApiService.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/data/source/remote/ApiService.kt @@ -34,6 +34,12 @@ import com.nextcloud.talk.models.json.userprofile.UserProfileOverall import retrofit2.http.* interface ApiService { + @FormUrlEncoded + @PUT + suspend fun setPasswordForConversation(@Header("Authorization") authorization: String, + @Url url: String?, + @Field("password") password: String): GenericOverall + @POST suspend fun addParticipant(@Header("Authorization") authorization: String, @Url url: String, diff --git a/app/src/main/java/com/nextcloud/talk/newarch/domain/di/module/UseCasesModule.kt b/app/src/main/java/com/nextcloud/talk/newarch/domain/di/module/UseCasesModule.kt index bde53026b..7792e1187 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/domain/di/module/UseCasesModule.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/domain/di/module/UseCasesModule.kt @@ -50,9 +50,15 @@ val UseCasesModule = module { single { createGetContactsUseCase(get(), get()) } single { createCreateConversationUseCase(get(), get()) } single { createAddParticipantToConversationUseCase(get(), get()) } + single { setConversationPasswordUseCase(get(), get()) } factory { createChatViewModelFactory(get(), get(), get(), get(), get(), get()) } } +fun setConversationPasswordUseCase(nextcloudTalkRepository: NextcloudTalkRepository, + apiErrorHandler: ApiErrorHandler): SetConversationPasswordUseCase { + return SetConversationPasswordUseCase(nextcloudTalkRepository, apiErrorHandler) +} + fun createAddParticipantToConversationUseCase(nextcloudTalkRepository: NextcloudTalkRepository, apiErrorHandler: ApiErrorHandler): AddParticipantToConversationUseCase { return AddParticipantToConversationUseCase(nextcloudTalkRepository, apiErrorHandler) diff --git a/app/src/main/java/com/nextcloud/talk/newarch/domain/repository/online/NextcloudTalkRepository.kt b/app/src/main/java/com/nextcloud/talk/newarch/domain/repository/online/NextcloudTalkRepository.kt index adf3d7a2b..87671a5ee 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/domain/repository/online/NextcloudTalkRepository.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/domain/repository/online/NextcloudTalkRepository.kt @@ -34,6 +34,7 @@ import com.nextcloud.talk.models.json.userprofile.UserProfileOverall import com.nextcloud.talk.newarch.local.models.UserNgEntity interface NextcloudTalkRepository { + suspend fun setPasswordForConversation(user: UserNgEntity, conversationToken: String, password: String): GenericOverall suspend fun addParticipantToConversation(user: UserNgEntity, conversationToken: String, participantId: String, source: String): AddParticipantOverall suspend fun createConversationForUser(user: UserNgEntity, conversationType: Int, invite: String?, source: String?, conversationName: String?): ConversationOverall suspend fun getContactsForUser(user: UserNgEntity, groupConversation: Boolean, searchQuery: String?, conversationToken: String?): List diff --git a/app/src/main/java/com/nextcloud/talk/newarch/domain/usecases/SetConversationPasswordUseCase.kt b/app/src/main/java/com/nextcloud/talk/newarch/domain/usecases/SetConversationPasswordUseCase.kt new file mode 100644 index 000000000..5e25d9c3d --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/newarch/domain/usecases/SetConversationPasswordUseCase.kt @@ -0,0 +1,44 @@ +/* + * + * * 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.domain.usecases + +import com.nextcloud.talk.models.json.generic.GenericOverall +import com.nextcloud.talk.newarch.data.source.remote.ApiErrorHandler +import com.nextcloud.talk.newarch.domain.repository.online.NextcloudTalkRepository +import com.nextcloud.talk.newarch.domain.usecases.base.UseCase +import org.koin.core.parameter.DefinitionParameters + +class SetConversationPasswordUseCase constructor( + private val nextcloudTalkRepository: NextcloudTalkRepository, + apiErrorHandler: ApiErrorHandler? +) : UseCase(apiErrorHandler) { + + override suspend fun run(params: Any?): GenericOverall { + val definitionParameters = params as DefinitionParameters + return nextcloudTalkRepository.setPasswordForConversation( + definitionParameters[0], + definitionParameters[1], + definitionParameters[2] + ) + } +} diff --git a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsViewOperationState.kt b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/ContactsFlowOperationState.kt similarity index 85% rename from app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsViewOperationState.kt rename to app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/ContactsFlowOperationState.kt index 9d2de4b94..207692aa0 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsViewOperationState.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/ContactsFlowOperationState.kt @@ -20,7 +20,7 @@ * */ -package com.nextcloud.talk.newarch.features.contactsflow.contacts +package com.nextcloud.talk.newarch.features.contactsflow import kotlinx.serialization.Serializable @@ -28,7 +28,9 @@ enum class ContactsViewOperationState { WAITING, PROCESSING, OK, - CONVERSATION_CREATION_FAILED + CONVERSATION_CREATION_FAILED, + CONVERSATION_CREATED_WITH_MISSING_TOKEN, + CONVERSATION_PASSWORD_NOT_SET } @Serializable diff --git a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsView.kt b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsView.kt index 90ea4cfae..602b87bea 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsView.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsView.kt @@ -37,6 +37,8 @@ import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler import com.nextcloud.talk.R import com.nextcloud.talk.controllers.ChatController import com.nextcloud.talk.models.json.participants.Participant +import com.nextcloud.talk.newarch.features.contactsflow.ContactsViewOperationState +import com.nextcloud.talk.newarch.features.contactsflow.groupconversation.GroupConversationView import com.nextcloud.talk.newarch.features.contactsflow.source.FixedListSource import com.nextcloud.talk.newarch.features.search.DebouncingTextWatcher import com.nextcloud.talk.newarch.mvvm.BaseView @@ -224,7 +226,9 @@ class ContactsView(private val bundle: Bundle? = null) : BaseView() { } } } else if (element.type == ParticipantElementType.PARTICIPANT_NEW_GROUP.ordinal) { - + router.replaceTopController(RouterTransaction.with(GroupConversationView()) + .popChangeHandler(HorizontalChangeHandler()) + .pushChangeHandler(HorizontalChangeHandler())) } else if (element.type == ParticipantElementType.PARTICIPANT_JOIN_VIA_LINK.ordinal) { } diff --git a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsViewModel.kt b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsViewModel.kt index 31e661f70..86a3b9bf3 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsViewModel.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/contacts/ContactsViewModel.kt @@ -37,6 +37,8 @@ import com.nextcloud.talk.newarch.domain.usecases.AddParticipantToConversationUs import com.nextcloud.talk.newarch.domain.usecases.CreateConversationUseCase import com.nextcloud.talk.newarch.domain.usecases.GetContactsUseCase import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse +import com.nextcloud.talk.newarch.features.contactsflow.ContactsViewOperationState +import com.nextcloud.talk.newarch.features.contactsflow.ContactsViewOperationStateWrapper import com.nextcloud.talk.newarch.features.conversationslist.ConversationsListView import com.nextcloud.talk.newarch.services.GlobalService import kotlinx.coroutines.runBlocking diff --git a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/di/module/ContactsFlowModule.kt b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/di/module/ContactsFlowModule.kt index 12ae65090..6d81604cd 100644 --- a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/di/module/ContactsFlowModule.kt +++ b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/di/module/ContactsFlowModule.kt @@ -26,7 +26,9 @@ import android.app.Application import com.nextcloud.talk.newarch.domain.usecases.AddParticipantToConversationUseCase import com.nextcloud.talk.newarch.domain.usecases.CreateConversationUseCase import com.nextcloud.talk.newarch.domain.usecases.GetContactsUseCase +import com.nextcloud.talk.newarch.domain.usecases.SetConversationPasswordUseCase import com.nextcloud.talk.newarch.features.contactsflow.contacts.ContactsViewModelFactory +import com.nextcloud.talk.newarch.features.contactsflow.groupconversation.GroupConversationViewModelFactory import com.nextcloud.talk.newarch.services.GlobalService import org.koin.android.ext.koin.androidApplication import org.koin.dsl.module @@ -37,6 +39,20 @@ val ContactsFlowModule = module { androidApplication(), get(), get(), get(), get() ) } + factory { + createGroupConversationViewModelFactory( + androidApplication(), get(), get(), get() + ) + } +} + +fun createGroupConversationViewModelFactory( + application: Application, + createConversationUseCase: CreateConversationUseCase, + setConversationPasswordUseCase: SetConversationPasswordUseCase, + globalService: GlobalService +): GroupConversationViewModelFactory { + return GroupConversationViewModelFactory(application, createConversationUseCase, setConversationPasswordUseCase, globalService) } fun createContactsViewModelFactory( diff --git a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/groupconversation/GroupConversationView.kt b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/groupconversation/GroupConversationView.kt new file mode 100644 index 000000000..9d6830c08 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/groupconversation/GroupConversationView.kt @@ -0,0 +1,117 @@ +/* + * + * * 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.features.contactsflow.groupconversation + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.core.view.isVisible +import androidx.core.widget.doOnTextChanged +import androidx.lifecycle.Observer +import com.bluelinelabs.conductor.RouterTransaction +import com.bluelinelabs.conductor.autodispose.ControllerScopeProvider +import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler +import com.nextcloud.talk.R +import com.nextcloud.talk.newarch.features.contactsflow.ContactsViewOperationState +import com.nextcloud.talk.newarch.features.contactsflow.contacts.ContactsView +import com.nextcloud.talk.newarch.mvvm.BaseView +import com.nextcloud.talk.utils.bundle.BundleKeys +import com.uber.autodispose.lifecycle.LifecycleScopeProvider +import kotlinx.android.synthetic.main.new_group_conversation_view.view.* +import org.koin.android.ext.android.inject + +class GroupConversationView : BaseView() { + override val scopeProvider: LifecycleScopeProvider<*> = ControllerScopeProvider.from(this) + + private lateinit var viewModel: GroupConversationViewModel + val factory: GroupConversationViewModelFactory by inject() + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup): View { + setHasOptionsMenu(true) + viewModel = viewModelProvider(factory).get(GroupConversationViewModel::class.java) + val view = super.onCreateView(inflater, container) + + view.apply { + conversationNameInputEditText.doOnTextChanged { text, start, count, after -> + floatingActionButton?.isVisible = !text.isNullOrBlank() + } + + allowGuestsSwitchMaterial.setOnCheckedChangeListener { buttonView, isChecked -> + passwordTextInputLayout.isVisible = isChecked + } + } + + viewModel.operationState.observe(this, Observer { operationState -> + when (operationState.operationState) { + ContactsViewOperationState.WAITING -> { + // do nothing, just sit there and wait + } + ContactsViewOperationState.PROCESSING -> { + view.passwordInputEditText.isEnabled = false + view.conversationNameInputEditText.isEnabled = false + view.allowGuestsSwitchMaterial.isEnabled = false + toolbarProgressBar?.isVisible = true + + } + ContactsViewOperationState.OK -> { + val bundle = Bundle() + bundle.putString(BundleKeys.KEY_CONVERSATION_TOKEN, operationState.conversationToken) + bundle.putBoolean(BundleKeys.KEY_NEW_GROUP_CONVERSATION, true) + router.replaceTopController(RouterTransaction.with(ContactsView(bundle)) + .popChangeHandler(HorizontalChangeHandler()) + .pushChangeHandler(HorizontalChangeHandler())) + } + else -> { + // we should do something else as well, but this will do for now + // we failed, I'm afraid :( + toolbarProgressBar?.isVisible = false + view.passwordInputEditText.isEnabled = true + view.conversationNameInputEditText.isEnabled = true + view.allowGuestsSwitchMaterial.isEnabled = true + } + } + }) + + return view + } + + override fun getLayoutId(): Int { + return R.layout.new_group_conversation_view + } + + override fun getTitle(): String? { + return context.getString(R.string.nc_new_group) + } + + override fun onFloatingActionButtonClick() { + view?.conversationNameInputEditText?.text?.let { conversationName -> + val conversationType = if (view?.allowGuestsSwitchMaterial?.isChecked == true) 2 else 3 + viewModel.createConversation(conversationType, conversationName.toString(), view?.passwordInputEditText?.text?.toString()) + } + } + + override fun getFloatingActionButtonDrawableRes(): Int { + return R.drawable.ic_arrow_forward_white_24px + } +} diff --git a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/groupconversation/GroupConversationViewModel.kt b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/groupconversation/GroupConversationViewModel.kt new file mode 100644 index 000000000..82d6241ac --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/groupconversation/GroupConversationViewModel.kt @@ -0,0 +1,84 @@ +/* + * + * * 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.features.contactsflow.groupconversation + +import android.app.Application +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.distinctUntilChanged +import androidx.lifecycle.viewModelScope +import com.nextcloud.talk.models.json.conversations.ConversationOverall +import com.nextcloud.talk.models.json.generic.GenericOverall +import com.nextcloud.talk.newarch.conversationsList.mvp.BaseViewModel +import com.nextcloud.talk.newarch.data.model.ErrorModel +import com.nextcloud.talk.newarch.domain.usecases.CreateConversationUseCase +import com.nextcloud.talk.newarch.domain.usecases.SetConversationPasswordUseCase +import com.nextcloud.talk.newarch.domain.usecases.base.UseCaseResponse +import com.nextcloud.talk.newarch.features.contactsflow.ContactsViewOperationState +import com.nextcloud.talk.newarch.features.contactsflow.ContactsViewOperationStateWrapper +import com.nextcloud.talk.newarch.features.conversationslist.ConversationsListView +import com.nextcloud.talk.newarch.services.GlobalService +import org.koin.core.parameter.parametersOf + +class GroupConversationViewModel constructor( + application: Application, + private val createConversationUseCase: CreateConversationUseCase, + private val setPasswordUseCase: SetConversationPasswordUseCase, + val globalService: GlobalService +) : BaseViewModel(application) { + private val _operationState = MutableLiveData(ContactsViewOperationStateWrapper(ContactsViewOperationState.WAITING, null, null)) + val operationState: LiveData = _operationState.distinctUntilChanged() + + fun createConversation(conversationType: Int, conversationName: String, conversationPassword: String? = null) { + _operationState.postValue(ContactsViewOperationStateWrapper(ContactsViewOperationState.PROCESSING, null, null)) + createConversationUseCase.invoke(viewModelScope, parametersOf(globalService.currentUserLiveData.value, conversationType, null, null, conversationName), object : UseCaseResponse { + override suspend fun onSuccess(result: ConversationOverall) { + result.ocs.data.token?.let { token -> + if (conversationPassword != null) { + setPasswordForConversation(token, conversationPassword) + } else { + _operationState.postValue(ContactsViewOperationStateWrapper(ContactsViewOperationState.OK, null, token)) + } + } ?: run { + _operationState.postValue(ContactsViewOperationStateWrapper(ContactsViewOperationState.CONVERSATION_CREATED_WITH_MISSING_TOKEN, null, null)) + } + } + + override suspend fun onError(errorModel: ErrorModel?) { + _operationState.postValue(ContactsViewOperationStateWrapper(ContactsViewOperationState.CONVERSATION_CREATION_FAILED, errorModel?.getErrorMessage(), null)) + } + }) + } + + private fun setPasswordForConversation(conversationToken: String, conversationPassword: String) { + setPasswordUseCase.invoke(viewModelScope, parametersOf(globalService.currentUserLiveData.value, conversationToken, conversationPassword), object : UseCaseResponse { + override suspend fun onSuccess(result: GenericOverall) { + _operationState.postValue(ContactsViewOperationStateWrapper(ContactsViewOperationState.OK, null, conversationToken)) + } + + override suspend fun onError(errorModel: ErrorModel?) { + _operationState.postValue(ContactsViewOperationStateWrapper(ContactsViewOperationState.CONVERSATION_PASSWORD_NOT_SET, errorModel?.getErrorMessage(), conversationToken)) + } + }) + } +} \ No newline at end of file diff --git a/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/groupconversation/GroupConversationViewModelFactory.kt b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/groupconversation/GroupConversationViewModelFactory.kt new file mode 100644 index 000000000..3fbfae280 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/newarch/features/contactsflow/groupconversation/GroupConversationViewModelFactory.kt @@ -0,0 +1,41 @@ +/* + * + * * 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.features.contactsflow.groupconversation + +import android.app.Application +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.nextcloud.talk.newarch.domain.usecases.CreateConversationUseCase +import com.nextcloud.talk.newarch.domain.usecases.SetConversationPasswordUseCase +import com.nextcloud.talk.newarch.services.GlobalService + +class GroupConversationViewModelFactory constructor( + private val application: Application, + private val createConversationUseCase: CreateConversationUseCase, + private val setConversationPasswordUseCase: SetConversationPasswordUseCase, + private val globalService: GlobalService +) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + return GroupConversationViewModel(application, createConversationUseCase, setConversationPasswordUseCase, globalService) as T + } +} diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index c4e6dbf34..37d9a8c76 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -27,7 +27,6 @@ android:animateLayoutChanges="true" tools:context=".activities.MainActivity"> - + app:popupTheme="@style/appActionBarPopupMenu"> + + + + @@ -58,7 +68,7 @@ android:id="@+id/controller_container" android:layout_width="match_parent" android:layout_height="match_parent" - app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/> + app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" /> -