mirror of
				https://github.com/commons-app/apps-android-commons.git
				synced 2025-10-31 14:53:59 +01:00 
			
		
		
		
	Fix categories searching problem of photo uploading
This commit is contained in:
		
							parent
							
								
									63f1ed8a2d
								
							
						
					
					
						commit
						1e31497f10
					
				
					 1 changed files with 291 additions and 276 deletions
				
			
		|  | @ -1,5 +1,6 @@ | ||||||
| package fr.free.nrw.commons.upload.categories | package fr.free.nrw.commons.upload.categories | ||||||
| 
 | 
 | ||||||
|  | import android.annotation.SuppressLint | ||||||
| import android.text.TextUtils | import android.text.TextUtils | ||||||
| import androidx.lifecycle.LiveData | import androidx.lifecycle.LiveData | ||||||
| import androidx.lifecycle.MutableLiveData | import androidx.lifecycle.MutableLiveData | ||||||
|  | @ -27,288 +28,302 @@ import javax.inject.Singleton | ||||||
|  */ |  */ | ||||||
| @Singleton | @Singleton | ||||||
| class CategoriesPresenter | class CategoriesPresenter | ||||||
|  | @Inject | ||||||
|  | constructor( | ||||||
|  |     private val repository: UploadRepository, | ||||||
|  |     @param:Named(CommonsApplicationModule.IO_THREAD) private val ioScheduler: Scheduler, | ||||||
|  |     @param:Named(CommonsApplicationModule.MAIN_THREAD) private val mainThreadScheduler: Scheduler, | ||||||
|  | ) : CategoriesContract.UserActionListener { | ||||||
|  |     companion object { | ||||||
|  |         private val DUMMY: CategoriesContract.View = proxy() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     var view = DUMMY | ||||||
|  |     private val compositeDisposable = CompositeDisposable() | ||||||
|  |     private val searchTerms = PublishSubject.create<String>() | ||||||
|  |     private var categoryList: MutableLiveData<List<CategoryItem>> = MutableLiveData() | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Current media | ||||||
|  |      */ | ||||||
|  |     private var media: Media? = null | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * helper class for editing categories | ||||||
|  |      */ | ||||||
|     @Inject |     @Inject | ||||||
|     constructor( |     lateinit var categoryEditHelper: CategoryEditHelper | ||||||
|         private val repository: UploadRepository, |  | ||||||
|         @param:Named(CommonsApplicationModule.IO_THREAD) private val ioScheduler: Scheduler, |  | ||||||
|         @param:Named(CommonsApplicationModule.MAIN_THREAD) private val mainThreadScheduler: Scheduler, |  | ||||||
|     ) : CategoriesContract.UserActionListener { |  | ||||||
|         companion object { |  | ||||||
|             private val DUMMY: CategoriesContract.View = proxy() |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         var view = DUMMY |     @SuppressLint("TimberArgCount") | ||||||
|         private val compositeDisposable = CompositeDisposable() |     override fun onAttachView(view: CategoriesContract.View) { | ||||||
|         private val searchTerms = PublishSubject.create<String>() |         this.view = view | ||||||
|         private var categoryList: MutableLiveData<List<CategoryItem>> = MutableLiveData() |         compositeDisposable.add( | ||||||
| 
 |             searchTerms | ||||||
|         /** |                 .observeOn(mainThreadScheduler) | ||||||
|          * Current media |                 .doOnNext { | ||||||
|          */ |                     view.showProgress(true) | ||||||
|         private var media: Media? = null |                 }.switchMap(::searchResults) | ||||||
| 
 |                 .map { repository.selectedCategories + it } | ||||||
|         /** |                 .map { it.distinctBy { categoryItem -> categoryItem.name } } | ||||||
|          * helper class for editing categories |                 .observeOn(mainThreadScheduler) | ||||||
|          */ |                 .subscribe( | ||||||
|         @Inject |                     { | ||||||
|         lateinit var categoryEditHelper: CategoryEditHelper |                         setCategoryListValue(it) | ||||||
| 
 |                         view.showProgress(false) | ||||||
|         override fun onAttachView(view: CategoriesContract.View) { |                         if (it.isEmpty() && !isInitialLoad) { | ||||||
|             this.view = view |  | ||||||
|             compositeDisposable.add( |  | ||||||
|                 searchTerms |  | ||||||
|                     .observeOn(mainThreadScheduler) |  | ||||||
|                     .doOnNext { |  | ||||||
|                         view.showProgress(true) |  | ||||||
|                     }.switchMap(::searchResults) |  | ||||||
|                     .map { repository.selectedCategories + it } |  | ||||||
|                     .map { it.distinctBy { categoryItem -> categoryItem.name } } |  | ||||||
|                     .observeOn(mainThreadScheduler) |  | ||||||
|                     .subscribe( |  | ||||||
|                         { |  | ||||||
|                             setCategoryListValue(it) |  | ||||||
|                             view.showProgress(false) |  | ||||||
|                             if (it.isEmpty()) { |  | ||||||
|                                 view.showError(R.string.no_categories_found) |  | ||||||
|                             } |  | ||||||
|                         }, |  | ||||||
|                         { t: Throwable? -> |  | ||||||
|                             view.showProgress(false) |  | ||||||
|                             view.showError(R.string.no_categories_found) |                             view.showError(R.string.no_categories_found) | ||||||
|                             Timber.e(t) |  | ||||||
|                         }, |  | ||||||
|                     ), |  | ||||||
|             ) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * If media is null : Fetches categories from server according to the term |  | ||||||
|          * Else : Fetches existing categories by their name, fetches categories from server according |  | ||||||
|          * to the term and combines both in a list |  | ||||||
|          */ |  | ||||||
|         private fun searchResults(term: String): Observable<List<CategoryItem>>? { |  | ||||||
|             if (media == null) { |  | ||||||
|                 return repository |  | ||||||
|                     .searchAll(term, getImageTitleList(), repository.selectedDepictions) |  | ||||||
|                     .subscribeOn(ioScheduler) |  | ||||||
|                     .map { |  | ||||||
|                         it.filter { categoryItem -> |  | ||||||
|                             !repository.isSpammyCategory(categoryItem.name) || |  | ||||||
|                                 categoryItem.name == term |  | ||||||
|                         } |                         } | ||||||
|                     } |                     }, | ||||||
|             } else { |                     { t: Throwable? -> | ||||||
|                 return Observable |                         view.showProgress(false) | ||||||
|                     .zip( |                         view.showError(R.string.no_categories_found) | ||||||
|                         repository |                         Timber.e(t) | ||||||
|                             .getCategories(repository.selectedExistingCategories) |                     }, | ||||||
|                             .map { list -> |                 ), | ||||||
|                                 list.map { |         ) | ||||||
|                                     CategoryItem(it.name, it.description, it.thumbnail, true) | 
 | ||||||
|                                 } |         //isInitialLoad = false | ||||||
|                             }, |     } | ||||||
|                         repository.searchAll(term, getImageTitleList(), repository.selectedDepictions), | 
 | ||||||
|                     ) { it1, it2 -> |     private var isInitialLoad = true //avoid initial empty content of edittext lead to showError | ||||||
|                         it1 + it2 | 
 | ||||||
|                     }.subscribeOn(ioScheduler) | 
 | ||||||
|                     .map { |     /** | ||||||
|                         it.filter { categoryItem -> |      * If media is null : Fetches categories from server according to the term | ||||||
|                             !repository.isSpammyCategory(categoryItem.name) || |      * Else : Fetches existing categories by their name, fetches categories from server according | ||||||
|  |      * to the term and combines both in a list | ||||||
|  |      */ | ||||||
|  |     private fun searchResults(term: String): Observable<List<CategoryItem>>? { | ||||||
|  |         if (media == null) { | ||||||
|  |             return repository | ||||||
|  |                 .searchAll(term, getImageTitleList(), repository.selectedDepictions) | ||||||
|  |                 .subscribeOn(ioScheduler) | ||||||
|  |                 .map { | ||||||
|  |                     it.filter { categoryItem -> | ||||||
|  |                         !repository.isSpammyCategory(categoryItem.name) || | ||||||
|                                 categoryItem.name == term |                                 categoryItem.name == term | ||||||
|                         } |  | ||||||
|                     }.map { it.filterNot { categoryItem -> categoryItem.thumbnail == "hidden" } } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         override fun onDetachView() { |  | ||||||
|             view = DUMMY |  | ||||||
|             compositeDisposable.clear() |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * asks the repository to fetch categories for the query |  | ||||||
|          * @param query |  | ||||||
|          */ |  | ||||||
|         override fun searchForCategories(query: String) { |  | ||||||
|             searchTerms.onNext(query) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * Returns image title list from UploadItem |  | ||||||
|          * @return |  | ||||||
|          */ |  | ||||||
|         private fun getImageTitleList(): List<String> = |  | ||||||
|             repository.uploads |  | ||||||
|                 .map { it.uploadMediaDetails[0].captionText } |  | ||||||
|                 .filterNot { TextUtils.isEmpty(it) } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * Verifies the number of categories selected, prompts the user if none selected |  | ||||||
|          */ |  | ||||||
|         override fun verifyCategories() { |  | ||||||
|             val selectedCategories = repository.selectedCategories |  | ||||||
|             if (selectedCategories.isNotEmpty()) { |  | ||||||
|                 repository.setSelectedCategories(selectedCategories.map { it.name }) |  | ||||||
|                 view.goToNextScreen() |  | ||||||
|             } else { |  | ||||||
|                 view.showNoCategorySelected() |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * ask repository to handle category clicked |  | ||||||
|          * |  | ||||||
|          * @param categoryItem |  | ||||||
|          */ |  | ||||||
|         override fun onCategoryItemClicked(categoryItem: CategoryItem) { |  | ||||||
|             repository.onCategoryClicked(categoryItem, media) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * Attaches view and media |  | ||||||
|          */ |  | ||||||
|         override fun onAttachViewWithMedia( |  | ||||||
|             view: CategoriesContract.View, |  | ||||||
|             media: Media, |  | ||||||
|         ) { |  | ||||||
|             this.view = view |  | ||||||
|             this.media = media |  | ||||||
|             repository.selectedExistingCategories = view.existingCategories |  | ||||||
|             compositeDisposable.add( |  | ||||||
|                 searchTerms |  | ||||||
|                     .observeOn(mainThreadScheduler) |  | ||||||
|                     .doOnNext { |  | ||||||
|                         view.showProgress(true) |  | ||||||
|                     }.switchMap(::searchResults) |  | ||||||
|                     .map { repository.selectedCategories + it } |  | ||||||
|                     .map { it.distinctBy { categoryItem -> categoryItem.name } } |  | ||||||
|                     .observeOn(mainThreadScheduler) |  | ||||||
|                     .subscribe( |  | ||||||
|                         { |  | ||||||
|                             setCategoryListValue(it) |  | ||||||
|                             view.showProgress(false) |  | ||||||
|                             if (it.isEmpty()) { |  | ||||||
|                                 view.showError(R.string.no_categories_found) |  | ||||||
|                             } |  | ||||||
|                         }, |  | ||||||
|                         { t: Throwable? -> |  | ||||||
|                             view.showProgress(false) |  | ||||||
|                             view.showError(R.string.no_categories_found) |  | ||||||
|                             Timber.e(t) |  | ||||||
|                         }, |  | ||||||
|                     ), |  | ||||||
|             ) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * Clears previous selections |  | ||||||
|          */ |  | ||||||
|         override fun clearPreviousSelection() { |  | ||||||
|             repository.cleanup() |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * Gets the selected categories and send them for posting to the server |  | ||||||
|          * |  | ||||||
|          * @param media media |  | ||||||
|          * @param wikiText current WikiText from server |  | ||||||
|          */ |  | ||||||
|         override fun updateCategories( |  | ||||||
|             media: Media, |  | ||||||
|             wikiText: String, |  | ||||||
|         ) { |  | ||||||
|             // check if view.existingCategories is null |  | ||||||
|             if (repository.selectedCategories.isNotEmpty() || |  | ||||||
|                 (view.existingCategories != null && repository.selectedExistingCategories.size != view.existingCategories.size) |  | ||||||
|             ) { |  | ||||||
|                 val selectedCategories: MutableList<String> = |  | ||||||
|                     ( |  | ||||||
|                         repository.selectedCategories.map { it.name }.toMutableList() + |  | ||||||
|                             repository.selectedExistingCategories |  | ||||||
|                     ).toMutableList() |  | ||||||
| 
 |  | ||||||
|                 if (selectedCategories.isNotEmpty()) { |  | ||||||
|                     view.showProgressDialog() |  | ||||||
| 
 |  | ||||||
|                     try { |  | ||||||
|                         compositeDisposable.add( |  | ||||||
|                             categoryEditHelper |  | ||||||
|                                 .makeCategoryEdit( |  | ||||||
|                                     view.fragmentContext, |  | ||||||
|                                     media, |  | ||||||
|                                     selectedCategories, |  | ||||||
|                                     wikiText, |  | ||||||
|                                 ).subscribeOn(Schedulers.io()) |  | ||||||
|                                 .observeOn(AndroidSchedulers.mainThread()) |  | ||||||
|                                 .subscribe({ |  | ||||||
|                                     Timber.d("Categories are added.") |  | ||||||
|                                     media.addedCategories = selectedCategories |  | ||||||
|                                     repository.cleanup() |  | ||||||
|                                     view.dismissProgressDialog() |  | ||||||
|                                     view.refreshCategories() |  | ||||||
|                                     view.goBackToPreviousScreen() |  | ||||||
|                                 }, { |  | ||||||
|                                     Timber.e( |  | ||||||
|                                         "Failed to update categories", |  | ||||||
|                                     ) |  | ||||||
|                                 }), |  | ||||||
|                         ) |  | ||||||
|                     } catch (e: InvalidLoginTokenException) { |  | ||||||
|                         view.navigateToLoginScreen() |  | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|             } else { |         } else { | ||||||
|                 repository.cleanup() |             return Observable | ||||||
|                 view.showNoCategorySelected() |                 .zip( | ||||||
|             } |                     repository | ||||||
|         } |                         .getCategories(repository.selectedExistingCategories) | ||||||
| 
 |                         .map { list -> | ||||||
|         /** |                             list.map { | ||||||
|          * Selects each [CategoryItem] in a given list as if they were clicked by the user by calling |                                 CategoryItem(it.name, it.description, it.thumbnail, true) | ||||||
|          * [onCategoryItemClicked] for each category and adding the category to [categoryList] |                             } | ||||||
|          */ |                         }, | ||||||
|         private fun selectNewCategories(toSelect: List<CategoryItem>) { |                     repository.searchAll(term, getImageTitleList(), repository.selectedDepictions), | ||||||
|             toSelect.forEach { |                 ) { it1, it2 -> | ||||||
|                 it.isSelected = true |                     it1 + it2 | ||||||
|                 repository.onCategoryClicked(it, media) |                 }.subscribeOn(ioScheduler) | ||||||
|             } |                 .map { | ||||||
| 
 |                     it.filter { categoryItem -> | ||||||
|             // Add the new selections to the list of category items so that the selections appear |                         !repository.isSpammyCategory(categoryItem.name) || | ||||||
|             // immediately (i.e. without any search term queries) |                                 categoryItem.name == term | ||||||
|             categoryList.value |                     } | ||||||
|                 ?.toMutableList() |                 }.map { it.filterNot { categoryItem -> categoryItem.thumbnail == "hidden" } } | ||||||
|                 ?.let { toSelect + it } |  | ||||||
|                 ?.distinctBy(CategoryItem::name) |  | ||||||
|                 ?.let { setCategoryListValue(it) } |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * Livedata being used to observe category list inside |  | ||||||
|          * @see UploadCategoriesFragment |  | ||||||
|          * Any changes to category list reflect immediately to the adapter list |  | ||||||
|          */ |  | ||||||
|         override fun getCategories(): LiveData<List<CategoryItem>> = categoryList |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * needed for tests |  | ||||||
|          */ |  | ||||||
|         fun setCategoryList(categoryList: MutableLiveData<List<CategoryItem>>) { |  | ||||||
|             this.categoryList = categoryList |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         /** |  | ||||||
|          * needed for tests |  | ||||||
|          */ |  | ||||||
|         fun setCategoryListValue(categoryItems: List<CategoryItem>) { |  | ||||||
|             categoryList.postValue(categoryItems) |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         override fun selectCategories() { |  | ||||||
|             compositeDisposable.add( |  | ||||||
|                 repository.placeCategories |  | ||||||
|                     .subscribeOn(ioScheduler) |  | ||||||
|                     .observeOn(mainThreadScheduler) |  | ||||||
|                     .subscribe(::selectNewCategories), |  | ||||||
|             ) |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     override fun onDetachView() { | ||||||
|  |         view = DUMMY | ||||||
|  |         compositeDisposable.clear() | ||||||
|  |         isInitialLoad = true | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * asks the repository to fetch categories for the query | ||||||
|  |      * @param query | ||||||
|  |      */ | ||||||
|  |     override fun searchForCategories(query: String) { | ||||||
|  |         if (query.isBlank()) { | ||||||
|  |             if (!isInitialLoad) { | ||||||
|  |                 view.showError(R.string.no_categories_found) | ||||||
|  |             } | ||||||
|  |             return | ||||||
|  |         } | ||||||
|  |         isInitialLoad = false | ||||||
|  |         searchTerms.onNext(query) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Returns image title list from UploadItem | ||||||
|  |      * @return | ||||||
|  |      */ | ||||||
|  |     private fun getImageTitleList(): List<String> = | ||||||
|  |         repository.uploads | ||||||
|  |             .map { it.uploadMediaDetails[0].captionText } | ||||||
|  |             .filterNot { TextUtils.isEmpty(it) } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Verifies the number of categories selected, prompts the user if none selected | ||||||
|  |      */ | ||||||
|  |     override fun verifyCategories() { | ||||||
|  |         val selectedCategories = repository.selectedCategories | ||||||
|  |         if (selectedCategories.isNotEmpty()) { | ||||||
|  |             repository.setSelectedCategories(selectedCategories.map { it.name }) | ||||||
|  |             view.goToNextScreen() | ||||||
|  |         } else { | ||||||
|  |             view.showNoCategorySelected() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * ask repository to handle category clicked | ||||||
|  |      * | ||||||
|  |      * @param categoryItem | ||||||
|  |      */ | ||||||
|  |     override fun onCategoryItemClicked(categoryItem: CategoryItem) { | ||||||
|  |         repository.onCategoryClicked(categoryItem, media) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Attaches view and media | ||||||
|  |      */ | ||||||
|  |     override fun onAttachViewWithMedia( | ||||||
|  |         view: CategoriesContract.View, | ||||||
|  |         media: Media, | ||||||
|  |     ) { | ||||||
|  |         this.view = view | ||||||
|  |         this.media = media | ||||||
|  |         repository.selectedExistingCategories = view.existingCategories | ||||||
|  |         compositeDisposable.add( | ||||||
|  |             searchTerms | ||||||
|  |                 .observeOn(mainThreadScheduler) | ||||||
|  |                 .doOnNext { | ||||||
|  |                     view.showProgress(true) | ||||||
|  |                 }.switchMap(::searchResults) | ||||||
|  |                 .map { repository.selectedCategories + it } | ||||||
|  |                 .map { it.distinctBy { categoryItem -> categoryItem.name } } | ||||||
|  |                 .observeOn(mainThreadScheduler) | ||||||
|  |                 .subscribe( | ||||||
|  |                     { | ||||||
|  |                         setCategoryListValue(it) | ||||||
|  |                         view.showProgress(false) | ||||||
|  |                         if (it.isEmpty() && !isInitialLoad) { | ||||||
|  |                             view.showError(R.string.no_categories_found) | ||||||
|  |                         } | ||||||
|  |                     }, | ||||||
|  |                     { t: Throwable? -> | ||||||
|  |                         view.showProgress(false) | ||||||
|  |                         view.showError(R.string.no_categories_found) | ||||||
|  |                         Timber.e(t) | ||||||
|  |                     }, | ||||||
|  |                 ), | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Clears previous selections | ||||||
|  |      */ | ||||||
|  |     override fun clearPreviousSelection() { | ||||||
|  |         repository.cleanup() | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Gets the selected categories and send them for posting to the server | ||||||
|  |      * | ||||||
|  |      * @param media media | ||||||
|  |      * @param wikiText current WikiText from server | ||||||
|  |      */ | ||||||
|  |     override fun updateCategories( | ||||||
|  |         media: Media, | ||||||
|  |         wikiText: String, | ||||||
|  |     ) { | ||||||
|  |         // check if view.existingCategories is null | ||||||
|  |         if (repository.selectedCategories.isNotEmpty() || | ||||||
|  |             (view.existingCategories != null && repository.selectedExistingCategories.size != view.existingCategories.size) | ||||||
|  |         ) { | ||||||
|  |             val selectedCategories: MutableList<String> = | ||||||
|  |                 ( | ||||||
|  |                         repository.selectedCategories.map { it.name }.toMutableList() + | ||||||
|  |                                 repository.selectedExistingCategories | ||||||
|  |                         ).toMutableList() | ||||||
|  | 
 | ||||||
|  |             if (selectedCategories.isNotEmpty()) { | ||||||
|  |                 view.showProgressDialog() | ||||||
|  | 
 | ||||||
|  |                 try { | ||||||
|  |                     compositeDisposable.add( | ||||||
|  |                         categoryEditHelper | ||||||
|  |                             .makeCategoryEdit( | ||||||
|  |                                 view.fragmentContext, | ||||||
|  |                                 media, | ||||||
|  |                                 selectedCategories, | ||||||
|  |                                 wikiText, | ||||||
|  |                             ).subscribeOn(Schedulers.io()) | ||||||
|  |                             .observeOn(AndroidSchedulers.mainThread()) | ||||||
|  |                             .subscribe({ | ||||||
|  |                                 Timber.d("Categories are added.") | ||||||
|  |                                 media.addedCategories = selectedCategories | ||||||
|  |                                 repository.cleanup() | ||||||
|  |                                 view.dismissProgressDialog() | ||||||
|  |                                 view.refreshCategories() | ||||||
|  |                                 view.goBackToPreviousScreen() | ||||||
|  |                             }, { | ||||||
|  |                                 Timber.e( | ||||||
|  |                                     "Failed to update categories", | ||||||
|  |                                 ) | ||||||
|  |                             }), | ||||||
|  |                     ) | ||||||
|  |                 } catch (e: InvalidLoginTokenException) { | ||||||
|  |                     view.navigateToLoginScreen() | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |         } else { | ||||||
|  |             repository.cleanup() | ||||||
|  |             view.showNoCategorySelected() | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Selects each [CategoryItem] in a given list as if they were clicked by the user by calling | ||||||
|  |      * [onCategoryItemClicked] for each category and adding the category to [categoryList] | ||||||
|  |      */ | ||||||
|  |     private fun selectNewCategories(toSelect: List<CategoryItem>) { | ||||||
|  |         toSelect.forEach { | ||||||
|  |             it.isSelected = true | ||||||
|  |             repository.onCategoryClicked(it, media) | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         // Add the new selections to the list of category items so that the selections appear | ||||||
|  |         // immediately (i.e. without any search term queries) | ||||||
|  |         categoryList.value | ||||||
|  |             ?.toMutableList() | ||||||
|  |             ?.let { toSelect + it } | ||||||
|  |             ?.distinctBy(CategoryItem::name) | ||||||
|  |             ?.let { setCategoryListValue(it) } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Livedata being used to observe category list inside | ||||||
|  |      * @see UploadCategoriesFragment | ||||||
|  |      * Any changes to category list reflect immediately to the adapter list | ||||||
|  |      */ | ||||||
|  |     override fun getCategories(): LiveData<List<CategoryItem>> = categoryList | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * needed for tests | ||||||
|  |      */ | ||||||
|  |     fun setCategoryList(categoryList: MutableLiveData<List<CategoryItem>>) { | ||||||
|  |         this.categoryList = categoryList | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * needed for tests | ||||||
|  |      */ | ||||||
|  |     fun setCategoryListValue(categoryItems: List<CategoryItem>) { | ||||||
|  |         categoryList.postValue(categoryItems) | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     override fun selectCategories() { | ||||||
|  |         compositeDisposable.add( | ||||||
|  |             repository.placeCategories | ||||||
|  |                 .subscribeOn(ioScheduler) | ||||||
|  |                 .observeOn(mainThreadScheduler) | ||||||
|  |                 .subscribe(::selectNewCategories), | ||||||
|  |         ) | ||||||
|  |     } | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Zihan Pan
						Zihan Pan