BlackZerg

Untitled

Aug 2nd, 2021
769
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /// ViewModel
  2.  
  3. @ExperimentalCoroutinesApi
  4. @SuppressLint("NullSafeMutableLiveData")
  5. class GroupEditViewModel
  6. @Inject
  7. constructor(
  8.     userRepository: UserRepository,
  9.     private val groupsRepository: GroupsRepository,
  10.     private val contactRepository: ContactRepository,
  11.     private val filtersRepository: FiltersRepository,
  12.     private val dbRepository: DatabaseRepository
  13. ) : ViewModel() {
  14.  
  15.     val progress: Flow<Int>
  16.         get() = _progress
  17.     val errors: Flow<Exception>
  18.         get() = _errors
  19.  
  20.     val watchMembersByGroup: Flow<List<MemberModel>>
  21.         get() = _membersByGroup
  22.     val watchParticipantsByGroup: Flow<List<Participants>>
  23.         get() = _participantsByGroup
  24.     val watchGroup: StateFlow<Groups?>
  25.         get() = _group
  26.     val startTime: StateFlow<String>
  27.         get() = _startTime
  28.     val endTime: StateFlow<String>
  29.         get() = _endTime
  30.     val filterId: StateFlow<Int>
  31.         get() = _filterId
  32.     val photoUri: StateFlow<String?>
  33.         get() = _photoUri
  34.     val saveButtonState: StateFlow<SaveButtonState>
  35.         get() = _saveButtonState
  36.     val editGroupState: StateFlow<GroupEditState>
  37.         get() = _editGroupState
  38.  
  39.     private val _onUploadFilter = MutableSharedFlow<Boolean>()
  40.     private val _onSave = MutableSharedFlow<Unit>()
  41.  
  42.     private val _groupId = MutableSharedFlow<Int>()
  43.     private val _groupName = MutableSharedFlow<String>()
  44.     private val _group = MutableStateFlow<Groups?>(null)
  45.     private val _startTime = MutableStateFlow("00:00")
  46.     private val _endTime = MutableStateFlow("23:59")
  47.     private val _period = MutableSharedFlow<FilterModelData>()
  48.     private val _filterType = MutableSharedFlow<Int>()
  49.     private val _isCallEnabled = MutableSharedFlow<Boolean>()
  50.     private val _filterId = MutableStateFlow(0)
  51.     private val _photoUri = MutableStateFlow<String?>(null)
  52.     private val _participants = MutableStateFlow<List<Participants>>(listOf())
  53.     private val _saveButtonState = MutableStateFlow<SaveButtonState>(SaveButtonState.NeutralState)
  54.     private val _editGroupState = MutableStateFlow<GroupEditState>(GroupEditState.EditStarted)
  55.     private val _isCreateFilter = MutableSharedFlow<Boolean>()
  56.     private val _groupModel = MutableSharedFlow<GroupsModel>()
  57.     private val _filters = MutableSharedFlow<List<FilterModel>>()
  58.     private val _avatarUri = MutableSharedFlow<String>()
  59.     private val _participantsByGroup = MutableSharedFlow<List<Participants>>()
  60.     private val _membersByGroup = MutableSharedFlow<List<MemberModel>>()
  61.  
  62.     private val userId = userRepository.userId ?: 0
  63.  
  64.     private val _errors = MutableSharedFlow<Exception>()
  65.     private val _progress = MutableSharedFlow<Int>()
  66.     private var counter = 0
  67.  
  68.     private var groupName: String = NO_GROUP
  69.     private var filterType: Int = 0
  70.     private var period: FilterModelData = FilterModelData(daily = null, table = null)
  71.  
  72.     init {
  73.         viewModelScope.launch {
  74.             launch {
  75.                 _groupId
  76.                     .filter { id -> id > 0 }
  77.                     .collect { fetchGroupInfo(it) }
  78.             }
  79.             launch {
  80.                 _groupId
  81.                     .filter { id -> id > 0 }
  82.                     .flatMapLatest { dbRepository.watchGroup(it) }
  83.                     .collect { g ->
  84.                         _group.value = g
  85.                         _membersByGroup.emit(g.groupMembers as List<MemberModel>)
  86.                     }
  87.             }
  88.             launch {
  89.                 _groupId
  90.                     .filter { id -> id > 0 }
  91.                     .flatMapLatest { dbRepository.watchParticipantsByGroup(it) }
  92.                     .collect { _participantsByGroup.emit(it) }
  93.             }
  94.             launch {
  95.                 _groupId
  96.                     .filter { id -> id > 0 }
  97.                     .combine(_groupModel) { id, gm -> id to gm }
  98.                     .collect { (id, gm) ->
  99.                         doUpdateGroupInfo(id, gm)
  100.                     }
  101.             }
  102.             launch {
  103.                 _groupName.collect { groupName = it.ifBlank { NO_GROUP } }
  104.             }
  105.             launch {
  106.                 _filterType
  107.                     .filter { id -> id > 0 }
  108.                     .distinctUntilChanged()
  109.                     .collect { filterType = it }
  110.             }
  111.             launch {
  112.                 _period
  113.                     .filterNotNull()
  114.                     .distinctUntilChanged()
  115.                     .collect { period = it }
  116.             }
  117.             launch {
  118.                 _isCreateFilter
  119.                     .filter { it }
  120.                     .combine(_isCallEnabled) { _, ic -> ic }
  121.                     .collect { ic ->
  122.                         doCreateFilter(groupName, ic, filterType, period)
  123.                     }
  124.             }
  125.             launch {
  126.                 _filters.collect { doUpdateFilters(it, groupName) }
  127.             }
  128.             launch {
  129.                 _onUploadFilter
  130.                     .collect { isE ->
  131.                         _saveButtonState.value =
  132.                             if (isE) SaveButtonState.EmptyParticipants else SaveButtonState.NeutralState
  133.                     }
  134.             }
  135.             launch {
  136.                 _groupId
  137.                     .filter { id -> id > 0 }
  138.                     .combine(_avatarUri) { id, a -> id to a }
  139.                     .collect { (id, a) -> doUploadGroupAvatar(id, a) }
  140.             }
  141.             launch {
  142.                 _onSave
  143.                     .zip(_groupId) { _, id -> id }
  144.                     .filter { id -> id > 0 }
  145.                     .combine(_filterId.filter { fId -> fId > 0 }) { id, fId -> id to fId }
  146.                     .combine(_isCallEnabled) { (id, fId), ic -> Triple(id, fId, ic) }
  147.                     .collect { (id, fId, ic) ->
  148.                         GlobalScope.launch {
  149.                             doUpdateUserFilters(
  150.                                 groupId = id,
  151.                                 filterId = fId,
  152.                                 groupName = groupName,
  153.                                 filterType = filterType,
  154.                                 period = period,
  155.                                 isCallEnabled = ic
  156.                             )
  157.                         }
  158.                     }
  159.             }
  160.             launch {
  161.                 _onSave.collect { _saveButtonState.value = SaveButtonState.PositiveState }
  162.             }
  163.             /**
  164.              batch update
  165.              */
  166.             launch {
  167.                 _onSave
  168.                     .zip(_groupId) { _, id -> id }
  169.                     .filter { id -> id > 0 }
  170.                     .combine(_participants) { id, ps -> id to ps }
  171.                     .combine(_filterId.filter { fId -> fId > 0 }) { (id, ps), fId -> Triple(id, ps, fId) }
  172.                     .collect { (id, ps, fId) ->
  173.                         GlobalScope.launch {
  174.                             dbRepository.updateGroupFilterInfo(GroupsUpdate(id, fId))
  175.                             dbRepository.updateListContactsGroupInfo(
  176.                                 ps.map { ContactsUpdate(it.userId, id) }
  177.                             )
  178.                             doUpdateUserGroupInfo(id, ps, fId, groupName)
  179.                         }
  180.                     }
  181.             }
  182.         }
  183.     }
  184.  
  185.     fun onSetGroupId(groupId: Int) {
  186.         viewModelScope.launch { _groupId.emit(groupId) }
  187.     }
  188.  
  189.     fun onSetEditGroupState(state: GroupEditState) {
  190.         _editGroupState.value = state
  191.     }
  192.  
  193.     fun onTimeSelected(time: String, filter: Filter) {
  194.         when (filter) {
  195.             Filter.DailyStartTime -> _startTime.value = time
  196.             Filter.DailyEndTime -> _endTime.value = time
  197.         }
  198.     }
  199.  
  200.     fun onSetPhotoUri(photoUri: String?) {
  201.         _photoUri.value = photoUri
  202.     }
  203.  
  204.     fun onSetListParticipants(participants: List<Participants>) {
  205.         _participants.value = _participants.value + participants
  206.     }
  207.  
  208.     fun onSetGroupName(groupName: String) {
  209.         viewModelScope.launch { _groupName.emit(groupName) }
  210.     }
  211.  
  212.     fun onSetFilterType(type: Int) {
  213.         viewModelScope.launch { _filterType.emit(type) }
  214.     }
  215.  
  216.     fun onSetPeriodData(data: FilterModelData) {
  217.         viewModelScope.launch { _period.emit(data) }
  218.     }
  219.  
  220.     fun onSetCanCall(isCallEnabled: Boolean) {
  221.         viewModelScope.launch { _isCallEnabled.emit(isCallEnabled) }
  222.     }
  223.  
  224.     fun onSetAvatarUri(uri: String) {
  225.         viewModelScope.launch { _avatarUri.emit(uri) }
  226.     }
  227.  
  228.     fun onSetSaveButtonState(state: SaveButtonState) {
  229.         _saveButtonState.value = state
  230.     }
  231.  
  232.     fun resetSaveButtonState() {
  233.         _saveButtonState.value = SaveButtonState.NeutralState
  234.     }
  235.  
  236.     fun onSave(isParticipantsEmpty: Boolean) {
  237.         viewModelScope.launch {
  238.             _onSave.emit(Unit)
  239.             _onUploadFilter.emit(isParticipantsEmpty)
  240.         }
  241.     }
  242.  
  243.     private suspend fun doCreateFilter(
  244.         groupName: String,
  245.         isCallEnabled: Boolean,
  246.         type: Int,
  247.         period: FilterModelData
  248.     ) {
  249.         counter += 1
  250.         _progress.emit(counter)
  251.  
  252.         when (val r = filtersRepository.setUserFilter(
  253.             FilterData(
  254.                 groupIds = null,
  255.                 eventIds = null,
  256.                 type = type,
  257.                 filterName = groupName,
  258.                 period = period,
  259.                 canCall = isCallEnabled
  260.             )
  261.         )) {
  262.             is Left -> _errors.emit(r.value)
  263.             is Right -> {
  264.                 _filterId.value = r.value.data.id
  265.                 _filters.emit(listOf(r.value.data))
  266.             }
  267.         }
  268.  
  269.         counter -= 1
  270.         _progress.emit(counter)
  271.     }
  272.  
  273.     private suspend fun doUpdateFilters(filters: List<FilterModel>, groupName: String) {
  274.         counter += 1
  275.         _progress.emit(counter)
  276.  
  277.         when (val r = dbRepository.updateFilters(
  278.             filters.map {
  279.                 Filters(
  280.                     filterId = it.id,
  281.                     userId = it.userId,
  282.                     filterName = it.filterName,
  283.                     type = it.type,
  284.                     data = it.period,
  285.                     isCanCall = it.canCall,
  286.                     //TODO remove later
  287.                     photoUri = null, //photoUri.value,
  288.                     eventIds = it.eventIds,
  289.                     groupIds = it.groupIds,
  290.                     group_name = groupName
  291.                 )
  292.             }
  293.         )) {
  294.             is Left -> _errors.emit(r.value)
  295.             is Right -> Unit
  296.         }
  297.  
  298.         counter -= 1
  299.         _progress.emit(counter)
  300.     }
  301.  
  302.     private suspend fun doUpdateUserFilters(
  303.         groupId: Int,
  304.         filterId: Int,
  305.         groupName: String,
  306.         filterType: Int,
  307.         period: FilterModelData,
  308.         isCallEnabled: Boolean
  309.     ) {
  310.         counter += 1
  311.         _progress.emit(counter)
  312.  
  313.         when (val r = filtersRepository.updateUserFilter(
  314.             filterId, FilterData(
  315.                 groupIds = listOf(IdData(groupId)),
  316.                 eventIds = null,
  317.                 type = filterType,
  318.                 filterName = groupName,
  319.                 period = period,
  320.                 canCall = isCallEnabled
  321.             )
  322.         )) {
  323.             is Left -> _errors.emit(r.value)
  324.             is Right -> doUpdateFiltersTable(
  325.                 FiltersPartialUpdate(
  326.                     filterId = filterId,
  327.                     type = filterType,
  328.                     filterName = groupName,
  329.                     data = period,
  330.                     canCall = isCallEnabled,
  331.                     groupIds = listOf(IdData(groupId)),
  332.                     eventIds = null
  333.                 )
  334.             )
  335.         }
  336.  
  337.         counter -= 1
  338.         _progress.emit(counter)
  339.     }
  340.  
  341.     private suspend fun doUpdateFiltersTable(filter: FiltersPartialUpdate) {
  342.         when (val r = dbRepository.partialUpdateFilters(filter)) {
  343.             is Left -> _errors.emit(r.value)
  344.             is Right -> Unit
  345.         }
  346.     }
  347.  
  348.     private suspend fun doUpdateUserGroupInfo(
  349.         groupId: Int,
  350.         participants: List<Participants>,
  351.         filterId: Int,
  352.         groupName: String
  353.     ) {
  354.         counter += 1
  355.         _progress.emit(counter)
  356.         val members: List<String?> = participants.map { it.phoneNumber }
  357.  
  358.         when (val r = groupsRepository.updateUserGroupInfo(
  359.             groupId,
  360.             GroupBody(filterId, groupName, members)
  361.         )) {
  362.             is Left -> _errors.emit(r.value)
  363.             is Right -> _editGroupState.value = GroupEditState.EditFinished
  364.         }
  365.  
  366.         counter -= 1
  367.         _progress.emit(counter)
  368.     }
  369.  
  370.     private suspend fun doUploadGroupAvatar(groupId: Int, image: String) {
  371.         counter += 1
  372.         _progress.emit(counter)
  373.  
  374.         when (val r = groupsRepository.uploadGroupAvatar(
  375.             groupId, getResizedRequestBody(image, MULTIPART_AVATAR_NAME),
  376.         )) {
  377.             is Left -> _errors.emit(r.value)
  378.             is Right -> r.value.data.let { doUpdateGroupAvatar(groupId, it.url) }
  379.         }
  380.  
  381.         counter -= 1
  382.         _progress.emit(counter)
  383.     }
  384.  
  385.     private suspend fun doUpdateGroupAvatar(groupId: Int, avatar: String?) {
  386.         counter += 1
  387.         _progress.emit(counter)
  388.  
  389.         dbRepository.updateGroupAvatarInfo(GroupsAvatarUpdate(groupId, avatar))
  390.  
  391.         counter -= 1
  392.         _progress.emit(counter)
  393.     }
  394.  
  395.     private suspend fun fetchGroupInfo(groupId: Int) {
  396.         counter += 1
  397.         _progress.emit(counter)
  398.  
  399.         when (val r = groupsRepository.getUserGroupInfo(groupId)) {
  400.             is Left -> _errors.emit(r.value)
  401.             is Right -> {
  402.                 val fId = r.value.data.filterId
  403.                 _isCreateFilter.emit(fId <= 0)
  404.                 _filterId.emit(fId)
  405.                 _groupModel.emit(r.value.data)
  406.             }
  407.         }
  408.  
  409.         counter -= 1
  410.         _progress.emit(counter)
  411.     }
  412.  
  413.     private suspend fun doUpdateGroupInfo(groupId: Int, group: GroupsModel) {
  414.         counter += 1
  415.         _progress.emit(counter)
  416.  
  417.         when (val r = dbRepository.insertGroup(
  418.             Groups(
  419.                 groupId = groupId,
  420.                 userId = userId,
  421.                 groupName = group.groupName,
  422.                 filterId = group.filterId,
  423.                 type = group.type,
  424.                 subscriptionStatus = group.subscriptionStatus,
  425.                 groupMembers = group.groupMembers,
  426.                 avatarUrl = group.avatar_url,
  427.                 isDefault = group.isDefault,
  428.             )
  429.         )) {
  430.             is Left -> _errors.emit(r.value)
  431.             is Right -> Unit
  432.         }
  433.  
  434.         counter -= 1
  435.         _progress.emit(counter)
  436.     }
  437.  
  438.     fun updateContactsGroupInfo(contactsGroupBody: ContactsGroupBodyM) {
  439.         GlobalScope.launch {
  440.             counter += 1
  441.             _progress.emit(counter)
  442.  
  443.             when (val r = contactRepository.updateContactsGroup(contactsGroupBody)) {
  444.                 is Left -> _errors.emit(r.value)
  445.                 is Right -> Unit
  446.             }
  447.  
  448.             counter -= 1
  449.             _progress.emit(counter)
  450.         }
  451.     }
  452.  
  453.     companion object {
  454.         private const val NO_GROUP = "Нет группы"
  455.     }
  456. }
  457.  
  458.  
  459. /// Fragment
  460.  
  461. @ExperimentalCoroutinesApi
  462. class GroupEditFragment : BaseFragment(R.layout.fragment_group) {
  463.  
  464.     private val contextPhotoMenu: ContextPhotoMenuDialog by lazy { ContextPhotoMenuDialog { camera ->
  465.         requireContext().imagePicker(
  466.             fragment = this,
  467.             requestCode = when (camera) {
  468.                 CameraState.CameraSelected -> 148
  469.                 CameraState.GallerySelected -> 146
  470.             },
  471.             isProfile = true,
  472.             isGallery = when (camera) {
  473.                 CameraState.CameraSelected -> false
  474.                 CameraState.GallerySelected -> true
  475.             }
  476.         )
  477.     } }
  478.     private val timeDialog: TimeDialog by lazy { TimeDialog { groupEditViewModel.onTimeSelected(it, filter) } }
  479.  
  480.     private val groupEditViewModel: GroupEditViewModel by lazy { injectViewModel() }
  481.     private val groupEditFiltersVM: GEFiltersVM by lazy { injectViewModel() }
  482.     private val settingsViewModel: SettingsViewModel by lazy { injectViewModel() }
  483.     private val listContactsVM: ListContactsVM by lazy { injectViewModel() }
  484.     private val imageLoader: ImageLoaderViewModel by lazy { injectViewModel() }
  485.     private val stateListContactsVM: StateListContactsVM by lazy { injectOneViewModelForFewFragment() }
  486.  
  487.     private var binding: FragmentGroupBinding? = null
  488.     private var bfBinding: ButtonFiltersBinding? = null
  489.     private var bindingCFDB: ContainerFiltersDailyBinding? = null
  490.  
  491.     private lateinit var filter: Filter
  492.  
  493.     private var groupId: Int? = null
  494.     private var groupName: String = EMPTY_STRING
  495.  
  496.     private var isEnable = true
  497.  
  498.     private var listParticipants: List<Participants>? = null
  499.  
  500.     override fun onCreate(savedInstanceState: Bundle?) {
  501.         super.onCreate(savedInstanceState)
  502.         groupId = arguments?.getInt(KEY_GROUP_ID)
  503.         groupName = arguments?.getString(KEY_GROUP_NAME).orEmpty()
  504.     }
  505.  
  506.     override fun setupUI(v: View) {
  507.         val pBind = ContainerParticipantsBinding.bind(v)
  508.  
  509.         val bindingImage = ContainerImageBlockBinding.bind(v)
  510.  
  511.         binding = FragmentGroupBinding.bind(v).apply {
  512.  
  513.             ContainerHeaderBlockBinding.bind(v).apply {
  514.                 headerTitleTV.text = groupName
  515.                 backButtonIV.apply {
  516.                     setImageDrawable(drawable(R.drawable.ic_close))
  517.                     setOnClickListener { navigateUp() }
  518.                 }
  519.                 saveButtonIV.setOnClickListener { onSaveButtonListener() }
  520.             }
  521.  
  522.             with(listContactsVM) {
  523.                 progress.observe(viewLifecycleOwner) { progressBar.showProgressBar(it) }
  524.                 errors.observe(viewLifecycleOwner) {
  525.                     processingServerError(it, requireActivity()) { state ->
  526.                         when (state) {
  527.                             ServerErrorState.LogoutState -> settingsViewModel.sendLogoutRequest(requireActivity())
  528.                             else -> Unit
  529.                         }
  530.                     }
  531.                 }
  532.             }
  533.  
  534.             lifecycleScope.launch {
  535.                 launch { imageLoader.progress.collect { progressBar.showProgressBar(it) } }
  536.                 launch {
  537.                     imageLoader.errors.collect {
  538.                         processingServerError(it, requireActivity()) { state ->
  539.                             when (state) {
  540.                                 ServerErrorState.LogoutState -> settingsViewModel.sendLogoutRequest(requireActivity())
  541.                                 else -> Unit
  542.                             }
  543.                         }
  544.                     }
  545.                 }
  546.                 launch { groupEditViewModel.progress.collect { progressBar.showProgressBar(it) } }
  547.                 launch {
  548.                     groupEditViewModel.errors.collect {
  549.                         processingServerError(it, requireActivity()) { state ->
  550.                             when (state) {
  551.                                 ServerErrorState.LogoutState -> settingsViewModel.sendLogoutRequest(requireActivity())
  552.                                 else -> Unit
  553.                             }
  554.                         }
  555.                     }
  556.                 }
  557.                 launch { groupEditFiltersVM.progress.collect { progressBar.showProgressBar(it) } }
  558.                 launch {
  559.                     groupEditFiltersVM.errors.collect {
  560.                         processingServerError(it, requireActivity()) { state ->
  561.                             when (state) {
  562.                                 ServerErrorState.LogoutState -> settingsViewModel.sendLogoutRequest(requireActivity())
  563.                                 else -> Unit
  564.                             }
  565.                         }
  566.                     }
  567.                 }
  568.             }
  569.         }
  570.  
  571.         bindingImage.apply {
  572.             showImage(contactAvatar, R.drawable.ic_avatar_group)
  573.             addPhotoContainer.setAllOnClickListener { checkPhotoPermission() }
  574.             replacePhotoContainer.setAllOnClickListener { checkPhotoPermission() }
  575.             deletePhotoContainer.setAllOnClickListener { removeProfilePhoto() }
  576.         }
  577.  
  578.         pBind.apply {
  579.             addParticipantsView.setOnClickListener {
  580.                 groupEditViewModel.resetSaveButtonState()
  581.                 stateListContactsVM.onSetNavEventState(LCNavState.LCAddGroupContacts)
  582.                 navigateTo(
  583.                     R.id.action_groupEditFragment_to_listContactsFragment,
  584.                     bundleOf(
  585.                         KEY_GROUP_ID to groupId
  586.                     )
  587.                 )
  588.             }
  589.         }
  590.  
  591.         bfBinding = ButtonFiltersBinding.bind(v).apply {
  592.             filterCallsView.setOnClickListener { animateButton(isEnable) }
  593.  
  594.             fAllDayView.setOnClickListener { setFilterRuleListener(FilterRule.ALWAYS, it) }
  595.             fTemplateView.setOnClickListener { setFilterRuleListener(FilterRule.TEMPLATE, it) }
  596. //            fDailyView.setOnClickListener { setFilterRuleListener(FilterRule.DAILY, it) }
  597. //            fTableView.setOnClickListener { setFilterRuleListener(FilterRule.SCHEDULE, it) }
  598.  
  599.             tableDetails.apply {
  600.                 setDayCell(mondayHeader, mondayDetails, R.string.day_1_full)
  601.                 setDayCell(tuesdayHeader, tuesdayDetails, R.string.day_2_full)
  602.                 setDayCell(wednesdayHeader, wednesdayDetails, R.string.day_3_full)
  603.                 setDayCell(thursdayHeader, thursdayDetails, R.string.day_4_full)
  604.                 setDayCell(fridayHeader, fridayDetails, R.string.day_5_full)
  605.                 setDayCell(saturdayHeader, saturdayDetails, R.string.day_6_full)
  606.                 setDayCell(sundayHeader, sundayDetails, R.string.day_7_full)
  607.             }
  608.  
  609.             lifecycleScope.launch {
  610.                 launch { groupEditFiltersVM.isCanCallForView.collect { animateButton(it) } }
  611.                 launch { groupEditFiltersVM.filterRule.collect { animateDailyDetails(it) } }
  612.             }
  613.         }
  614.  
  615.         bindingCFDB = ContainerFiltersDailyBinding.bind(v).apply {
  616.             dailyStartTimeV.setOnClickListener { setDailyTimeListener(Filter.DailyStartTime) }
  617.             dailyEndTimeV.setOnClickListener { setDailyTimeListener(Filter.DailyEndTime) }
  618.  
  619.             lifecycleScope.launch {
  620.                 launch { groupEditFiltersVM.fromTime.collect { setTime(this@apply.dailyStartTimeTV, it) } }
  621.                 launch { groupEditFiltersVM.toTime.collect { setTime(this@apply.dailyEndTimeTV, it) } }
  622.                 launch { groupEditViewModel.startTime.collect { dailyStartTimeTV.text = it } }
  623.                 launch { groupEditViewModel.endTime.collect { dailyEndTimeTV.text = it } }
  624.             }
  625.         }
  626.  
  627.         lifecycleScope.launch {
  628.             launch { groupEditViewModel.photoUri.collect { renderProfilePhoto(bindingImage, it) } }
  629.             launch { groupEditViewModel.watchParticipantsByGroup.collect { listParticipants = it } }
  630.             launch {
  631.                 groupEditViewModel
  632.                     .watchGroup
  633.                     .combine(groupEditViewModel.watchMembersByGroup) { g, ps -> g to ps }
  634.                     .collect { (g, ps) -> renderGroupInfo(bindingImage, pBind, g, ps) }
  635.             }
  636.         }
  637.     }
  638.  
  639.     override fun setupObserver() {
  640.         groupId?.let {
  641.             groupEditViewModel.onSetGroupId(it)
  642.             listContactsVM.onSetGroupId(it)
  643.         }
  644.         groupEditViewModel.onSetGroupName(groupName)
  645.         groupEditFiltersVM.onSetGroupName(groupName)
  646.  
  647.         lifecycleScope.launch {
  648.             launch { imageLoader.watchAvatarUrl.collect { setAvatarUrl(it) } }
  649.             launch { listContactsVM.othersGroupId.collect { showGroupEditField(it) } }
  650.  
  651.             launch { groupEditViewModel.editGroupState.collect { onEditGroupState(it) } }
  652.             launch { groupEditViewModel.saveButtonState.collect { saveButtonStateListener(it) } }
  653.             launch { groupEditFiltersVM.watchFilterType.collect { groupEditViewModel.onSetFilterType(it) } }
  654.             launch { groupEditFiltersVM.watchPeriod.collect { groupEditViewModel.onSetPeriodData(it) } }
  655.             launch { groupEditFiltersVM.watchIsCallEnabled.collect { groupEditViewModel.onSetCanCall(it) } }
  656.         }
  657.     }
  658.  
  659.     override fun onDestroy() {
  660.         super.onDestroy()
  661.         binding = null
  662.         bfBinding = null
  663.         bindingCFDB = null
  664.     }
  665.  
  666.     override fun onRequestPermissionsResult(
  667.         requestCode: Int,
  668.         permissions: Array<out String>,
  669.         grantResults: IntArray
  670.     ) {
  671.         when (requestCode) {
  672.             REQUEST_CODE_PHOTO -> if (grantResults.size == 3 &&
  673.                 grantResults[0] == PackageManager.PERMISSION_GRANTED &&
  674.                 grantResults[1] == PackageManager.PERMISSION_GRANTED &&
  675.                 grantResults[2] == PackageManager.PERMISSION_GRANTED
  676.             ) contextPhotoMenu.show(requireActivity().supportFragmentManager, DIALOG_MENU_TAG)
  677.             else processingPermissionError(requireActivity(), requireActivity().getString(R.string.photo_gallery_permission_not_granted))
  678.         }
  679.     }
  680.  
  681.     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  682.         super.onActivityResult(requestCode, resultCode, data)
  683.         if (resultCode == Activity.RESULT_OK) when (requestCode) {
  684.             REQUEST_CODE_GALLERY -> processingImage(data)
  685.             REQUEST_CODE_CAMERA -> processingImage(data)
  686.         }
  687.     }
  688.  
  689.     private fun showGroupEditField(id: Int) {
  690.         groupId?.let {
  691.             binding?.apply {
  692.                 groupNameET.isEnabled = id < it
  693.                 groupNameEditView.isVisible = id < it
  694.                 groupNameETV.isVisible = id < it
  695.             }
  696.         }
  697.     }
  698.  
  699.     private fun showReplacePhotoButtons(binding: ContainerImageBlockBinding) {
  700.         binding.apply {
  701.             replacePhotoContainer.visibility = View.VISIBLE
  702.             deletePhotoContainer.visibility = View.VISIBLE
  703.             addPhotoContainer.visibility = View.GONE
  704.         }
  705.     }
  706.  
  707.     private fun showNewPhotoButton(binding: ContainerImageBlockBinding) {
  708.         binding.apply {
  709.             replacePhotoContainer.visibility = View.GONE
  710.             deletePhotoContainer.visibility = View.INVISIBLE
  711.             addPhotoContainer.visibility = View.VISIBLE
  712.         }
  713.     }
  714.  
  715.     private fun removeProfilePhoto() {
  716.         groupEditViewModel.onSetPhotoUri(null)
  717.     }
  718.  
  719.     private fun renderProfilePhoto(binding: ContainerImageBlockBinding, photoUri: String?) {
  720.         binding.apply {
  721.             photoUri?.let {
  722.                 showReplacePhotoButtons(binding)
  723.                 showImage(contactAvatar, it)
  724.             } ?: run {
  725.                 showNewPhotoButton(binding)
  726.                 showImage(contactAvatar, R.drawable.ic_avatar_group)
  727.             }
  728.         }
  729.     }
  730.  
  731.     private fun checkPhotoPermission() {
  732.         binding?.apply {
  733.             if (checkSelfPhotoPermission(root.context))
  734.                 requestPhotoPermission()
  735.             else
  736.                 contextPhotoMenu.show(requireActivity().supportFragmentManager, DIALOG_MENU_TAG)
  737.         }
  738.     }
  739.  
  740.     private fun requestPhotoPermission() {
  741.         if (getPhotoPermissionStatus(requireActivity()))
  742.             requireActivity().requestPermissions(permissionPhoto(), REQUEST_CODE_PHOTO)
  743.         else
  744.             requireActivity().requestPermissions(permissionPhoto(), REQUEST_CODE_PHOTO)
  745.     }
  746.  
  747.     private fun processingImage(data: Intent?) {
  748.         data?.data?.let {
  749.             groupEditViewModel.onSetPhotoUri(it.toString())
  750.             uploadImage(it)
  751.         }
  752.     }
  753.  
  754.     private fun uploadImage(image: Uri) {
  755.         image.path?.let { groupEditViewModel.onSetAvatarUri(it) }
  756.     }
  757.  
  758.     private fun setAvatarUrl(url: String?) {
  759.         groupEditViewModel.onSetPhotoUri(url)
  760.     }
  761.  
  762.     private fun renderGroupInfo(
  763.         b1: ContainerImageBlockBinding,
  764.         b2: ContainerParticipantsBinding,
  765.         group: Groups?,
  766.         participants: List<MemberModel>
  767.     ) {
  768.         renderParticipantsSize(b2, participants.size)
  769.         group?.also { g ->
  770.             g.avatarUrl?.also { avatar -> if (avatar.isNotBlank()) renderProfilePhoto(b1, avatar) }
  771.             g.filterId?.also { groupEditFiltersVM.onSetFilterId(it) }
  772.         }
  773.     }
  774.  
  775.     private fun renderParticipantsSize(bind: ContainerParticipantsBinding, size: Int) {
  776.         bind.apply {
  777.             participantsTitleTV.text = if (size != 0)
  778.                 resources.getQuantityString(R.plurals.participants_group_size, size, size)
  779.             else resources.getString(R.string.fragment_group_size_zero)
  780.         }
  781.     }
  782.  
  783.     private fun setDayCell(b1: ContainerFiltersDayBinding, b2: ContainerFiltersDailyBinding, @StringRes day: Int) {
  784.         b1.apply {
  785.             dayTV.text = getString(day)
  786.             dayView.setOnClickListener {
  787.                 dayCB.isChecked = !dayCB.isChecked
  788.                 b2.root.visibility = setViewVisibility(dayCB.isChecked)
  789.             }
  790.         }
  791.     }
  792.  
  793.     private fun setTime(field: TextView, time: String) {
  794.         bindingCFDB?.apply {
  795.             when (field) {
  796.                 dailyStartTimeTV -> dailyStartTimeTV.text = time
  797.                 dailyEndTimeTV -> dailyEndTimeTV.text = time
  798.             }
  799.         }
  800.     }
  801.  
  802.     private fun animateButton(isCanCall: Boolean) {
  803.         isEnable = !isCanCall
  804.         bfBinding?.apply {
  805.             val direction = (resources.displayMetrics.widthPixels / 2) - requireContext().dpToPx(20)
  806.             buttonView.animateSlide(if (isCanCall) -0f else direction.toFloat(), onAnimationEnd {
  807.                 bfBinding?.root?.context?.apply {
  808.                     setStateColorTV(enableTV, isCanCall)
  809.                     setStateColorTV(disableTV, !isCanCall)
  810.                 }
  811.             })
  812.         }
  813.         setFilterStateListener(if (isCanCall) FilterState.ENABLE else FilterState.DISABLE)
  814.     }
  815.  
  816.     private fun animateDailyDetails(filterRule: FilterRule) {
  817.         groupEditFiltersVM.onCreateFilterData(filterRule)
  818.         bindingCFDB?.apply {
  819.             groupEditFiltersVM.onSetStartTime(dailyStartTimeTV.text.toString())
  820.             groupEditFiltersVM.onSetEndTime(dailyEndTimeTV.text.toString())
  821.         }
  822.         bfBinding?.apply {
  823.             val button: View = when (filterRule) {
  824.                 FilterRule.ALWAYS -> fAllDayView
  825.                 FilterRule.DAILY -> fDailyView
  826.                 FilterRule.SCHEDULE -> fTableView
  827.                 else -> fAllDayView
  828.             }
  829.             setFilterRuleListener(filterRule, button)
  830.         }
  831.     }
  832.  
  833.     private fun setDailyTimeListener(filter: Filter) {
  834.         this.filter = filter
  835.         timeDialog.show(requireActivity().supportFragmentManager, DIALOG_MENU_TAG)
  836.     }
  837.  
  838.     private fun setFilterStateListener(state: FilterState) {
  839.         groupEditFiltersVM.onSetFilterState(state)
  840.     }
  841.  
  842.     private fun setFilterRuleListener(filter: FilterRule, button: View) {
  843.         groupEditFiltersVM.onCreateFilterData(filter)
  844.         buttonPressedListener(button)
  845.         bfBinding?.apply {
  846.             when (filter) {
  847.                 FilterRule.ALWAYS -> Unit
  848.                 FilterRule.DAILY -> dailyDetails.root.isVisible = true
  849.                 FilterRule.SCHEDULE -> tableDetails.root.isVisible = true
  850.                 FilterRule.TEMPLATE -> Unit
  851.             }
  852.         }
  853.     }
  854.  
  855.     private fun buttonPressedListener(button: View) {
  856.         bfBinding?.apply {
  857.             resetButton(this)
  858.             resetAdditionalFields(this)
  859.             val templatesButton = listOf(fAllDayView, fTemplateView, fDailyView, fTableView)
  860.             val templatesButtonIV = listOf(fAllDayIV, fTemplateIV, fDailyIV, fTableIV)
  861.             val templatesButtonTV = listOf(fAllDayTV, fTemplateTV, fDailyTV, fTableTV)
  862.  
  863.             setButtonState(templatesButtonIV[templatesButton.indexOf(button)], FilterButtonState.CheckedState)
  864.             root.context.setButtonTitle(templatesButtonTV[templatesButton.indexOf(button)], FilterButtonState.CheckedState)
  865.         }
  866.     }
  867.  
  868.     private fun resetButton(binding: ButtonFiltersBinding) {
  869.         binding.apply {
  870.             root.context.apply {
  871.                 setButtonState(fAllDayIV, FilterButtonState.NeutralState)
  872.                 setButtonTitle(fAllDayTV, FilterButtonState.NeutralState)
  873.                 setButtonState(fDailyIV, FilterButtonState.DisabledState)
  874.                 setButtonTitle(fDailyTV, FilterButtonState.DisabledState)
  875.                 setButtonState(fTableIV, FilterButtonState.DisabledState)
  876.                 setButtonTitle(fTableTV, FilterButtonState.DisabledState)
  877.                 setButtonState(fTemplateIV, FilterButtonState.NeutralState)
  878.                 setButtonTitle(fTemplateTV, FilterButtonState.NeutralState)
  879.             }
  880.         }
  881.     }
  882.  
  883.     private fun resetAdditionalFields(binding: ButtonFiltersBinding) {
  884.         binding.apply {
  885.             dailyDetails.root.isVisible = false
  886.             tableDetails.root.isVisible = false
  887.         }
  888.     }
  889.  
  890.     private fun onSaveButtonListener() {
  891.         groupEditViewModel.onSave((listParticipants?.size ?: 0) < 1)
  892.     }
  893.  
  894.     private fun saveButtonStateListener(buttonState: SaveButtonState) {
  895.         when (buttonState) {
  896.             SaveButtonState.NeutralState -> Unit
  897.             SaveButtonState.EmptyParticipants -> requireView().showToast(getString(R.string.fragment_filter_participants_empty_error))
  898.             SaveButtonState.PositiveState -> {
  899.                 listParticipants?.let { participants ->
  900.                     val contactsIds = mutableListOf<GroupIdModel>()
  901.                     participants.map {
  902.                         it.userId?.let { id ->
  903.                             contactsIds.add(GroupIdModel(id))
  904.                         }
  905.                     }
  906.                     groupEditViewModel.onSetListParticipants(participants.toList())
  907.                     groupEditViewModel.updateContactsGroupInfo(ContactsGroupBodyM(groupId, contactsIds))
  908.                 }
  909.             }
  910.         }
  911.         groupEditViewModel.resetSaveButtonState()
  912.     }
  913.  
  914.     private fun onEditGroupState(editGroupState: GroupEditState) {
  915.         if (editGroupState == GroupEditState.EditFinished) navigateUp()
  916.     }
  917.  
  918.     companion object {
  919.         private val TAG = GroupEditFragment::class.java.simpleName
  920.     }
  921. }
RAW Paste Data