Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Develop #352

Merged
merged 26 commits into from
Dec 23, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
80d9d28
- version update
jakepurple13 Dec 14, 2021
8a4adda
- lib update
jakepurple13 Dec 15, 2021
99543a5
- started to add ViewModel to improve experience and so some things d…
jakepurple13 Dec 15, 2021
5ddd051
- added ViewModel to GlobalSearchFragment.kt
jakepurple13 Dec 15, 2021
cec7d49
- fixed SettingsFragment.kt NotificationViewModel
jakepurple13 Dec 16, 2021
439d919
- added CastingViewModel
jakepurple13 Dec 16, 2021
3b4f6e8
- lib updates
jakepurple13 Dec 17, 2021
de5e914
- moved more variables from FavoriteFragment.kt into the ViewModel
jakepurple13 Dec 17, 2021
949c14e
- added ViewModel to HistoryFragment.kt
jakepurple13 Dec 17, 2021
b08165e
- added ViewModel to MangaWorld's DownloadViewerFragment.kt
jakepurple13 Dec 17, 2021
0412a0d
- added ViewModel to AnimeWorld's ViewVideosFragment.kt
jakepurple13 Dec 17, 2021
f8b7649
- cleanup and more ViewModels
jakepurple13 Dec 17, 2021
13b4e4d
- added the sort presses to the ViewModel in HistoryFragment.kt
jakepurple13 Dec 17, 2021
b952c59
- added page number to page selector
jakepurple13 Dec 20, 2021
9a77381
- lib updates
jakepurple13 Dec 20, 2021
c94a2ba
- added a scrollBuffer variable
jakepurple13 Dec 21, 2021
74a2324
- added ViewModels to AllFragment.kt and RecentFragment.kt
jakepurple13 Dec 21, 2021
2f4ef0d
- cleaned up things a bit
jakepurple13 Dec 21, 2021
210fb55
- lib update
jakepurple13 Dec 22, 2021
e1153ab
- put ViewModel into NovelWorld reader
jakepurple13 Dec 22, 2021
878f3e0
- trying to see if a new layout for landscape and tablets would work …
jakepurple13 Dec 23, 2021
acbc85a
- added a Discord link to SettingsFragment.kt!
jakepurple13 Dec 23, 2021
ae824f9
Merge branch 'master' of https://github.com/jakepurple13/OtakuWorld i…
jakepurple13 Dec 23, 2021
94c0900
- remove unused code
jakepurple13 Dec 23, 2021
a0df34b
- clean up
jakepurple13 Dec 23, 2021
197fb40
Merge pull request #351 from jakepurple13/details-landscape
jakepurple13 Dec 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 5 additions & 6 deletions Models/src/main/java/com/programmersbox/models/Models.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.programmersbox.models

import androidx.lifecycle.ViewModel
import io.reactivex.Single
import io.reactivex.subjects.BehaviorSubject
import java.io.Serializable
Expand All @@ -11,7 +10,7 @@ data class ItemModel(
val url: String,
val imageUrl: String,
val source: ApiService
) : ViewModel(), Serializable {
) : Serializable {
val extras = mutableMapOf<String, Any>()
fun toInfoModel() = source.getItemInfo(this)
}
Expand All @@ -25,15 +24,15 @@ data class InfoModel(
val genres: List<String>,
val alternativeNames: List<String>,
val source: ApiService
) : ViewModel()
)

data class ChapterModel(
val name: String,
val url: String,
val uploaded: String,
val sourceUrl: String,
val source: ApiService
) : ViewModel(), Serializable {
) : Serializable {
var uploadedTime: Long? = null
fun getChapterInfo() = source.getChapterInfo(this)
val extras = mutableMapOf<String, Any>()
Expand All @@ -51,7 +50,7 @@ data class Storage(
val headers = mutableMapOf<String, String>()
}

data class SwatchInfo(val rgb: Int?, val titleColor: Int?, val bodyColor: Int?) : ViewModel()
data class SwatchInfo(val rgb: Int?, val titleColor: Int?, val bodyColor: Int?)

interface ApiService: Serializable {
val baseUrl: String
Expand All @@ -64,7 +63,7 @@ interface ApiService: Serializable {
fun getList(page: Int = 1): Single<List<ItemModel>>
fun getItemInfo(model: ItemModel): Single<InfoModel>
fun searchList(searchText: CharSequence, page: Int = 1, list: List<ItemModel>): Single<List<ItemModel>> =
Single.create { it.onSuccess(list.filter { it.title.contains(searchText, true) }) }
Single.create { e -> e.onSuccess(list.filter { it.title.contains(searchText, true) }) }

fun getChapterInfo(chapterModel: ChapterModel): Single<List<Storage>>

Expand Down
1 change: 1 addition & 0 deletions UIViews/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ dependencies {
implementation material
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation preference
implementation 'androidx.window:window:1.0.0-rc01'
testImplementation Deps.junit
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
Expand Down
190 changes: 105 additions & 85 deletions UIViews/src/main/java/com/programmersbox/uiviews/AllFragment.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.programmersbox.uiviews

import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
Expand Down Expand Up @@ -34,20 +35,23 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.input.nestedscroll.nestedScroll
import androidx.compose.ui.platform.ComposeView
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastMaxBy
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.fragment.findNavController
import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.google.accompanist.swiperefresh.SwipeRefresh
import com.google.accompanist.swiperefresh.SwipeRefreshState
import com.google.accompanist.swiperefresh.rememberSwipeRefreshState
import com.google.android.material.composethemeadapter.MdcTheme
import com.programmersbox.favoritesdatabase.DbModel
import com.programmersbox.favoritesdatabase.ItemDao
import com.programmersbox.favoritesdatabase.ItemDatabase
import com.programmersbox.models.ApiService
import com.programmersbox.models.ItemModel
Expand All @@ -74,20 +78,96 @@ import androidx.compose.material3.contentColorFor as m3ContentColorFor
*/
class AllFragment : BaseFragmentCompose() {

private val disposable: CompositeDisposable = CompositeDisposable()
private var count = 1

private val info: GenericInfo by inject()
private val dao by lazy { ItemDatabase.getInstance(requireContext()).itemDao() }
private val logo: MainLogo by inject()

private val searchPublisher = BehaviorSubject.createDefault<List<ItemModel>>(emptyList())
class AllViewModel(dao: ItemDao, context: Context? = null) : ViewModel() {

private val sourceList = mutableStateListOf<ItemModel>()
private val favoriteList = mutableStateListOf<DbModel>()
val searchPublisher = BehaviorSubject.createDefault<List<ItemModel>>(emptyList())

private val dao by lazy { ItemDatabase.getInstance(requireContext()).itemDao() }
private val itemListener = FirebaseDb.FirebaseListener()
var isSearching by mutableStateOf(false)

private val logo: MainLogo by inject()
var isRefreshing by mutableStateOf(false)
val sourceList = mutableStateListOf<ItemModel>()
val favoriteList = mutableStateListOf<DbModel>()

var count = 1

private val disposable: CompositeDisposable = CompositeDisposable()
private val itemListener = FirebaseDb.FirebaseListener()

private val sub = Flowables.combineLatest(
itemListener.getAllShowsFlowable(),
dao.getAllFavorites()
) { f, d -> (f + d).groupBy(DbModel::url).map { it.value.fastMaxBy(DbModel::numChapters)!! } }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
favoriteList.clear()
favoriteList.addAll(it)
}

init {
sourcePublish
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
count = 1
sourceList.clear()
sourceLoadCompose(context, it)
}
.addTo(disposable)
}

fun reset(context: Context?, sources: ApiService) {
count = 1
sourceList.clear()
sourceLoadCompose(context, sources)
}

fun loadMore(context: Context?, sources: ApiService) {
count++
sourceLoadCompose(context, sources)
}

private fun sourceLoadCompose(context: Context?, sources: ApiService) {
sources
.getList(count)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError { context?.showErrorToast() }
.onErrorReturnItem(emptyList())
.doOnSubscribe { isRefreshing = true }
.subscribeBy {
sourceList.addAll(it)
isRefreshing = false
}
.addTo(disposable)
}

fun search(searchText: String) {
sourcePublish.value
?.searchList(searchText, 1, sourceList)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.doOnSubscribe { isSearching = true }
?.onErrorReturnItem(sourceList)
?.subscribeBy {
searchPublisher.onNext(it)
isSearching = false
}
?.addTo(disposable)
}

override fun onCleared() {
super.onCleared()
itemListener.unregister()
sub.dispose()
disposable.dispose()
}

}

@OptIn(
ExperimentalMaterial3Api::class,
Expand All @@ -102,51 +182,17 @@ class AllFragment : BaseFragmentCompose() {
}

override fun viewCreated(view: View, savedInstanceState: Bundle?) {
sourcePublish
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
count = 1
sourceList.clear()
searchPublisher.onNext(emptyList())
sourceLoadCompose(it)
}
.addTo(disposable)

Flowables.combineLatest(
itemListener.getAllShowsFlowable(),
dao.getAllFavorites()
) { f, d -> (f + d).groupBy(DbModel::url).map { it.value.fastMaxBy(DbModel::numChapters)!! } }
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
favoriteList.clear()
favoriteList.addAll(it)
}
.addTo(disposable)
}

private fun sourceLoadCompose(sources: ApiService, page: Int = 1, refreshState: SwipeRefreshState? = null) {
sources
.getList(page)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.doOnError { context?.showErrorToast() }
.onErrorReturnItem(emptyList())
.doOnSubscribe { refreshState?.isRefreshing = true }
.subscribeBy {
sourceList.addAll(it)
refreshState?.isRefreshing = false
}
.addTo(disposable)
}

@ExperimentalMaterial3Api
@ExperimentalAnimationApi
@ExperimentalMaterialApi
@ExperimentalFoundationApi
@Composable
private fun AllView() {
private fun AllView(allVm: AllViewModel = viewModel(factory = factoryCreate { AllViewModel(dao, context) })) {
val context = LocalContext.current

val isConnected by ReactiveNetwork.observeInternetConnectivity()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
Expand Down Expand Up @@ -203,7 +249,6 @@ class AllFragment : BaseFragmentCompose() {
}
}
else -> {
val refresh = rememberSwipeRefreshState(isRefreshing = false)
BottomSheetScaffold(
modifier = Modifier.padding(p1),
backgroundColor = M3MaterialTheme.colorScheme.background,
Expand All @@ -212,9 +257,8 @@ class AllFragment : BaseFragmentCompose() {
sheetPeekHeight = ButtonDefaults.MinHeight + 4.dp,
sheetContent = {
val focusManager = LocalFocusManager.current
val searchList by searchPublisher.subscribeAsState(initial = emptyList())
val searchList by allVm.searchPublisher.subscribeAsState(initial = emptyList())
var searchText by rememberSaveable { mutableStateOf("") }
var isSearching by remember { mutableStateOf(false) }
val scrollBehavior = remember { TopAppBarDefaults.pinnedScrollBehavior() }
Scaffold(
modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection),
Expand Down Expand Up @@ -266,17 +310,7 @@ class AllFragment : BaseFragmentCompose() {
keyboardOptions = KeyboardOptions(imeAction = ImeAction.Search),
keyboardActions = KeyboardActions(onSearch = {
focusManager.clearFocus()
sourcePublish.value
?.searchList(searchText, 1, sourceList)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.doOnSubscribe { isSearching = true }
?.onErrorReturnItem(sourceList)
?.subscribeBy {
searchPublisher.onNext(it)
isSearching = false
}
?.addTo(disposable)
allVm.search(searchText)
})
)
}
Expand All @@ -285,14 +319,14 @@ class AllFragment : BaseFragmentCompose() {
) { p ->
Box(modifier = Modifier.padding(p)) {
SwipeRefresh(
state = rememberSwipeRefreshState(isRefreshing = isSearching),
state = rememberSwipeRefreshState(isRefreshing = allVm.isSearching),
onRefresh = {},
swipeEnabled = false
) {
info.ItemListView(
list = searchList,
listState = rememberLazyListState(),
favorites = favoriteList,
favorites = allVm.favoriteList,
onLongPress = { item, c ->
itemInfo.value = if (c == ComponentState.Pressed) item else null
showBanner = c == ComponentState.Pressed
Expand All @@ -303,24 +337,19 @@ class AllFragment : BaseFragmentCompose() {
}
}
) { p ->
if (sourceList.isEmpty()) {
if (allVm.sourceList.isEmpty()) {
info.ComposeShimmerItem()
} else {
val refresh = rememberSwipeRefreshState(isRefreshing = allVm.isRefreshing)
SwipeRefresh(
modifier = Modifier.padding(p),
state = refresh,
onRefresh = {
source?.let {
count = 1
sourceList.clear()
sourceLoadCompose(it, count, refresh)
}
}
onRefresh = { source?.let { allVm.reset(context, it) } }
) {
info.ItemListView(
list = sourceList,
list = allVm.sourceList,
listState = state,
favorites = favoriteList,
favorites = allVm.favoriteList,
onLongPress = { item, c ->
itemInfo.value = if (c == ComponentState.Pressed) item else null
showBanner = c == ComponentState.Pressed
Expand All @@ -329,12 +358,9 @@ class AllFragment : BaseFragmentCompose() {
}
}

if (source?.canScrollAll == true && sourceList.isNotEmpty()) {
InfiniteListHandler(listState = state, buffer = 2) {
source?.let {
count++
sourceLoadCompose(it, count, refresh)
}
if (source?.canScrollAll == true && allVm.sourceList.isNotEmpty()) {
InfiniteListHandler(listState = state, buffer = info.scrollBuffer) {
source?.let { allVm.loadMore(context, it) }
}
}
}
Expand All @@ -344,12 +370,6 @@ class AllFragment : BaseFragmentCompose() {
}
}

override fun onDestroy() {
super.onDestroy()
disposable.dispose()
itemListener.unregister()
}

companion object {
@JvmStatic
fun newInstance() = AllFragment()
Expand Down
Loading