diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/AllFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/AllFragment.kt index 6938aa810..59971e995 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/AllFragment.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/AllFragment.kt @@ -13,7 +13,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.lazy.rememberLazyGridState import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions @@ -214,7 +214,7 @@ class AllFragment : BaseFragmentCompose() { scope.launch { scaffoldState.bottomSheetState.collapse() } } - val state = rememberLazyListState() + val state = rememberLazyGridState() val showButton by remember { derivedStateOf { state.firstVisibleItemIndex > 0 } } val scrollBehaviorTop = remember { TopAppBarDefaults.pinnedScrollBehavior() } Scaffold( @@ -334,7 +334,7 @@ class AllFragment : BaseFragmentCompose() { ) { info.SearchListView( list = searchList, - listState = rememberLazyListState(), + listState = rememberLazyGridState(), favorites = allVm.favoriteList, onLongPress = { item, c -> itemInfo.value = if (c == ComponentState.Pressed) item else null diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/DetailsFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/DetailsFragment.kt index aeaf9a91f..a667af2bf 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/DetailsFragment.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/DetailsFragment.kt @@ -138,6 +138,8 @@ class DetailsFragment : Fragment() { currentDetailsUrl = info.url setContent { + //TODO: Change all this to its own function so we can preview it + val localContext = LocalContext.current val details: DetailViewModel = viewModel(factory = factoryCreate { DetailViewModel(info, localContext) }) @@ -244,7 +246,6 @@ class DetailsFragment : Fragment() { } private fun setup(info: InfoModel) { - viewModelScope.launch(Dispatchers.IO) { combine( itemListener.findItemByUrlFlow(info.url), @@ -261,7 +262,6 @@ class DetailsFragment : Fragment() { .observeOn(AndroidSchedulers.mainThread()) .subscribeBy { chapters = it } .addTo(disposable) - } override fun onCleared() { diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/FavoriteFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/FavoriteFragment.kt index 7b6848969..121a2cc8d 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/FavoriteFragment.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/FavoriteFragment.kt @@ -149,7 +149,6 @@ class FavoriteFragment : Fragment() { val scrollBehavior = remember { TopAppBarDefaults.pinnedScrollBehavior() } - CollapsingToolbarScaffold( modifier = Modifier, state = rememberCollapsingToolbarScaffoldState(), @@ -323,7 +322,7 @@ class FavoriteFragment : Fragment() { contentPadding = p, verticalArrangement = Arrangement.spacedBy(4.dp), horizontalArrangement = Arrangement.spacedBy(4.dp), - state = rememberLazyListState() + state = rememberLazyGridState() ) { items( showing diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/GenericInfo.kt b/UIViews/src/main/java/com/programmersbox/uiviews/GenericInfo.kt index a2b8c016b..0692fe465 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/GenericInfo.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/GenericInfo.kt @@ -1,8 +1,9 @@ package com.programmersbox.uiviews import android.content.Context +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.lazy.LazyGridState import androidx.compose.foundation.lazy.LazyItemScope -import androidx.compose.foundation.lazy.LazyListState import androidx.compose.runtime.Composable import androidx.compose.ui.graphics.Color import androidx.fragment.app.Fragment @@ -31,40 +32,41 @@ interface GenericInfo { fun sourceList(): List<ApiService> fun searchList(): List<ApiService> = sourceList() fun toSource(s: String): ApiService? - fun customPreferences(preferenceScreen: SettingsDsl) = Unit fun composeCustomPreferences(navController: NavController): ComposeSettingsDsl.() -> Unit = {} fun downloadChapter(model: ChapterModel, allChapters: List<ChapterModel>, infoModel: InfoModel, context: Context) @Composable - fun DetailActions(infoModel: InfoModel, tint: Color) { - } + fun DetailActions(infoModel: InfoModel, tint: Color) = Unit @Composable fun ComposeShimmerItem() + @ExperimentalFoundationApi @Composable fun ItemListView( list: List<ItemModel>, favorites: List<DbModel>, - listState: LazyListState, + listState: LazyGridState, onLongPress: (ItemModel, ComponentState) -> Unit, onClick: (ItemModel) -> Unit ) + @ExperimentalFoundationApi @Composable fun AllListView( list: List<ItemModel>, favorites: List<DbModel>, - listState: LazyListState, + listState: LazyGridState, onLongPress: (ItemModel, ComponentState) -> Unit, onClick: (ItemModel) -> Unit ) = ItemListView(list, favorites, listState, onLongPress, onClick) + @ExperimentalFoundationApi @Composable fun SearchListView( list: List<ItemModel>, favorites: List<DbModel>, - listState: LazyListState, + listState: LazyGridState, onLongPress: (ItemModel, ComponentState) -> Unit, onClick: (ItemModel) -> Unit ) = ItemListView(list, favorites, listState, onLongPress, onClick) diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/GlobalSearchFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/GlobalSearchFragment.kt index 89a3a347d..f88bd9209 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/GlobalSearchFragment.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/GlobalSearchFragment.kt @@ -47,8 +47,8 @@ import androidx.lifecycle.lifecycleScope import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.findNavController import androidx.navigation.fragment.navArgs +import coil.compose.rememberImagePainter import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork -import com.google.accompanist.drawablepainter.rememberDrawablePainter import com.google.accompanist.placeholder.material.placeholder import com.google.accompanist.swiperefresh.SwipeRefresh import com.google.accompanist.swiperefresh.rememberSwipeRefreshState @@ -58,7 +58,6 @@ import com.programmersbox.favoritesdatabase.HistoryItem import com.programmersbox.models.ItemModel import com.programmersbox.sharedutils.MainLogo import com.programmersbox.uiviews.utils.* -import com.skydoves.landscapist.glide.GlideImage import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable @@ -442,11 +441,12 @@ class GlobalSearchFragment : Fragment() { } LazyRow( horizontalArrangement = Arrangement.spacedBy(4.dp), - modifier = Modifier.padding(horizontal = 4.dp) + modifier = Modifier + .padding(horizontal = 4.dp) + .padding(bottom = 4.dp) ) { items(i.data) { m -> SearchCoverCard( - modifier = Modifier.padding(bottom = 4.dp), model = m, placeHolder = mainLogo, onLongPress = { c -> @@ -502,22 +502,17 @@ class GlobalSearchFragment : Fragment() { modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center ) { - GlideImage( - imageModel = model.imageUrl, - contentDescription = null, - contentScale = ContentScale.FillBounds, - loading = { - Image( - painter = rememberDrawablePainter(drawable = placeHolder), - contentDescription = model.title - ) + Image( + painter = rememberImagePainter(data = model.imageUrl) { + placeholder(placeHolder) + error(error) + crossfade(true) + lifecycle(LocalLifecycleOwner.current) + size(ComposableUtils.IMAGE_WIDTH_PX, ComposableUtils.IMAGE_HEIGHT_PX) }, - failure = { - Image( - painter = rememberDrawablePainter(drawable = error), - contentDescription = model.title - ) - } + contentDescription = model.title, + contentScale = ContentScale.FillBounds, + modifier = Modifier.matchParentSize() ) Box( diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/HistoryFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/HistoryFragment.kt index 71adcbc71..d9d9bc348 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/HistoryFragment.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/HistoryFragment.kt @@ -4,7 +4,6 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.content.res.AppCompatResources import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.animateFloatAsState import androidx.compose.animation.core.exponentialDecay @@ -33,7 +32,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.input.nestedscroll.nestedScroll import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.platform.ViewCompositionStrategy import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -45,12 +44,11 @@ import androidx.lifecycle.ViewModel import androidx.lifecycle.lifecycleScope import androidx.lifecycle.viewmodel.compose.viewModel import androidx.navigation.fragment.findNavController -import com.google.accompanist.drawablepainter.rememberDrawablePainter +import coil.compose.rememberImagePainter import com.programmersbox.favoritesdatabase.HistoryDatabase import com.programmersbox.favoritesdatabase.RecentModel import com.programmersbox.sharedutils.MainLogo import com.programmersbox.uiviews.utils.* -import com.skydoves.landscapist.glide.GlideImage import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.addTo @@ -322,20 +320,17 @@ class HistoryFragment : Fragment() { secondaryText = { Text(requireContext().getSystemDateTimeFormat().format(item.timestamp)) }, icon = { Surface(shape = MaterialTheme.shapes.medium) { - GlideImage( - imageModel = item.imageUrl, - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier.size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT), - failure = { - Image( - painter = rememberDrawablePainter(AppCompatResources.getDrawable(LocalContext.current, logo.logoId)), - contentDescription = null, - modifier = Modifier - .padding(5.dp) - .size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT) - ) - } + Image( + painter = rememberImagePainter(data = item.imageUrl) { + placeholder(logo.logoId) + error(logo.logoId) + crossfade(true) + lifecycle(LocalLifecycleOwner.current) + size(ComposableUtils.IMAGE_WIDTH_PX, ComposableUtils.IMAGE_HEIGHT_PX) + }, + contentScale = ContentScale.FillBounds, + contentDescription = item.title, + modifier = Modifier.size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT) ) } }, diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/NotificationFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/NotificationFragment.kt index ff9f57fea..1c9fbf48a 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/NotificationFragment.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/NotificationFragment.kt @@ -7,7 +7,6 @@ import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.activity.compose.BackHandler -import androidx.appcompat.content.res.AppCompatResources import androidx.compose.animation.animateColorAsState import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.* @@ -28,10 +27,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.scale import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.platform.* import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastMap @@ -44,9 +40,7 @@ import androidx.work.Data import androidx.work.ExistingWorkPolicy import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager -import com.bumptech.glide.Glide -import com.bumptech.glide.load.resource.bitmap.RoundedCorners -import com.google.accompanist.drawablepainter.rememberDrawablePainter +import coil.compose.rememberImagePainter import com.google.android.material.composethemeadapter.MdcTheme import com.google.android.material.datepicker.CalendarConstraints import com.google.android.material.datepicker.DateValidatorPointForward @@ -59,7 +53,6 @@ import com.programmersbox.gsonutils.toJson import com.programmersbox.helpfulutils.notificationManager import com.programmersbox.sharedutils.MainLogo import com.programmersbox.uiviews.utils.* -import com.skydoves.landscapist.glide.GlideImage import io.reactivex.Completable import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.CompositeDisposable @@ -67,7 +60,6 @@ import io.reactivex.rxkotlin.addTo import io.reactivex.rxkotlin.subscribeBy import io.reactivex.schedulers.Schedulers import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.filter import kotlinx.coroutines.launch import org.koin.android.ext.android.inject @@ -184,27 +176,17 @@ class NotificationFragment : BaseBottomSheetDialogFragment() { ListItem( modifier = Modifier.padding(5.dp), icon = { - GlideImage( - imageModel = item.imageUrl.orEmpty(), - contentDescription = "", - contentScale = ContentScale.Crop, - requestBuilder = { - Glide.with(LocalView.current) - .asDrawable() - .override(360, 480) - .thumbnail(0.5f) - .transform(RoundedCorners(15)) + Image( + painter = rememberImagePainter(data = item.imageUrl.orEmpty()) { + placeholder(logo.logoId) + error(logo.logoId) + crossfade(true) + lifecycle(LocalLifecycleOwner.current) + size(ComposableUtils.IMAGE_WIDTH_PX, ComposableUtils.IMAGE_HEIGHT_PX) }, - modifier = Modifier.size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT), - failure = { - Image( - painter = rememberDrawablePainter(AppCompatResources.getDrawable(LocalContext.current, logo.logoId)), - contentDescription = item.notiTitle, - modifier = Modifier - .padding(5.dp) - .size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT) - ) - } + contentScale = ContentScale.FillBounds, + contentDescription = item.notiTitle, + modifier = Modifier.size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT) ) }, overlineText = { Text(item.source) }, @@ -383,22 +365,18 @@ class NotificationFragment : BaseBottomSheetDialogFragment() { ) { Row { - GlideImage( - imageModel = item.imageUrl.orEmpty(), - contentDescription = "", + Image( + painter = rememberImagePainter(data = item.imageUrl.orEmpty()) { + placeholder(logo.logoId) + error(logo.logoId) + crossfade(true) + lifecycle(LocalLifecycleOwner.current) + }, contentScale = ContentScale.Crop, + contentDescription = item.notiTitle, modifier = Modifier .align(Alignment.CenterVertically) - .size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT), - failure = { - Image( - painter = rememberDrawablePainter(AppCompatResources.getDrawable(LocalContext.current, logo.logoId)), - contentDescription = item.notiTitle, - modifier = Modifier - .padding(5.dp) - .size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT) - ) - } + .size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT) ) Column( diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/RecentFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/RecentFragment.kt index a1c971d84..9f1739c94 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/RecentFragment.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/RecentFragment.kt @@ -10,7 +10,7 @@ import androidx.compose.animation.Crossfade import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.lazy.rememberLazyGridState import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowUpward @@ -160,7 +160,7 @@ class RecentFragment : BaseFragmentCompose() { @Composable private fun RecentView(recentVm: RecentViewModel = viewModel(factory = factoryCreate { RecentViewModel(dao, context) })) { val context = LocalContext.current - val state = rememberLazyListState() + val state = rememberLazyGridState() val scope = rememberCoroutineScope() val source by sourcePublish.subscribeAsState(initial = null) val refresh = rememberSwipeRefreshState(isRefreshing = recentVm.isRefreshing) diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/SettingsFragment.kt b/UIViews/src/main/java/com/programmersbox/uiviews/SettingsFragment.kt index 45e28a5df..fd0ff7743 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/SettingsFragment.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/SettingsFragment.kt @@ -2,7 +2,6 @@ package com.programmersbox.uiviews import android.Manifest import android.content.Context -import android.graphics.drawable.Drawable import android.os.Bundle import android.os.Environment import android.view.LayoutInflater @@ -13,6 +12,7 @@ import androidx.activity.ComponentActivity import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.content.res.AppCompatResources import androidx.compose.animation.ExperimentalAnimationApi +import androidx.compose.animation.core.animateFloatAsState import androidx.compose.foundation.* import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* @@ -34,11 +34,7 @@ import androidx.compose.ui.draw.alpha import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.input.nestedscroll.nestedScroll -import androidx.compose.ui.layout.ContentScale -import androidx.compose.ui.platform.ComposeView -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.platform.LocalView -import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.platform.* import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -55,7 +51,8 @@ import androidx.work.Constraints import androidx.work.ExistingWorkPolicy import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager -import com.bumptech.glide.Glide +import coil.compose.rememberImagePainter +import coil.transform.CircleCropTransformation import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.firebase.auth.FirebaseAuth import com.google.firebase.auth.FirebaseUser @@ -66,7 +63,6 @@ import com.programmersbox.favoritesdatabase.ItemDao import com.programmersbox.favoritesdatabase.ItemDatabase import com.programmersbox.helpfulutils.notificationManager import com.programmersbox.helpfulutils.requestPermissions -import com.programmersbox.helpfulutils.runOnUIThread import com.programmersbox.models.ApiService import com.programmersbox.models.sourcePublish import com.programmersbox.sharedutils.AppUpdate @@ -74,12 +70,8 @@ import com.programmersbox.sharedutils.FirebaseAuthentication import com.programmersbox.sharedutils.MainLogo import com.programmersbox.sharedutils.appUpdateCheck import com.programmersbox.uiviews.utils.* -import com.skydoves.landscapist.glide.GlideImage -import io.reactivex.Single import io.reactivex.android.schedulers.AndroidSchedulers -import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.Observables -import io.reactivex.rxkotlin.addTo import io.reactivex.rxkotlin.subscribeBy import io.reactivex.schedulers.Schedulers import kotlinx.coroutines.* @@ -87,442 +79,8 @@ import kotlinx.coroutines.flow.first import org.koin.android.ext.android.inject import java.io.File import java.util.* -import java.util.concurrent.atomic.AtomicBoolean - -class SettingsFragment1 : PreferenceFragmentCompat() { - - private val disposable: CompositeDisposable = CompositeDisposable() - - private val genericInfo: GenericInfo by inject() - - private val logo: MainLogo by inject() - - override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { - setPreferencesFromResource(R.xml.root_preferences, rootKey) - - accountPreferences() - generalPreferences(genericInfo) - aboutPreferences(genericInfo) - playPreferences() - - val settingsDsl = SettingsDsl() - - genericInfo.customPreferences(settingsDsl) - settingsDsl.navigationSetup(this) - findPreference<PreferenceCategory>("generalCategory")?.let { settingsDsl.generalSettings(this, it) } - findPreference<PreferenceCategory>("viewCategory")?.let { settingsDsl.viewSettings(this, it) } - findPreference<PreferenceCategory>("playCategory")?.let { settingsDsl.playSettings(this, it) } - - findPreference<Preference>("debugMenu")?.let { p -> - p.isVisible = BuildConfig.DEBUG - p.setOnPreferenceClickListener { - findNavController().navigate(SettingsFragmentDirections.actionSettingsFragmentToDebugFragment()) - true - } - } - } - - private fun accountPreferences() { - findPreference<Preference>("user_account")?.let { p -> - - fun accountChanges(user: FirebaseUser?) { - activity?.let { - Glide.with(this@SettingsFragment1) - .load(user?.photoUrl) - .placeholder(logo.logoId) - .error(logo.logoId) - .fallback(logo.logoId) - .circleCrop() - .into<Drawable> { resourceReady { image, _ -> p.icon = image } } - } - p.title = user?.displayName ?: "User" - } - - FirebaseAuthentication.auth.addAuthStateListener { - accountChanges(it.currentUser) - //findPreference<Preference>("upload_favorites")?.isEnabled = it.currentUser != null - //findPreference<Preference>("upload_favorites")?.isVisible = it.currentUser != null - } - - accountChanges(FirebaseAuthentication.currentUser) - - p.setOnPreferenceClickListener { - FirebaseAuthentication.currentUser?.let { - MaterialAlertDialogBuilder(this@SettingsFragment1.requireContext()) - .setTitle(R.string.logOut) - .setMessage(R.string.areYouSureLogOut) - .setPositiveButton(R.string.yes) { d, _ -> - FirebaseAuthentication.signOut() - d.dismiss() - } - .setNegativeButton(R.string.no) { d, _ -> d.dismiss() } - .show() - } ?: FirebaseAuthentication.signIn(requireActivity()) - true - } - } - } - - private fun generalPreferences(genericInfo: GenericInfo) { - - findPreference<PreferenceCategory>("aboutCategory")?.setIcon(logo.logoId) - - findPreference<Preference>("current_source")?.let { p -> - p.setOnPreferenceClickListener { - val list = genericInfo.sourceList().toTypedArray() - val service = requireContext().currentService - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.chooseASource) - .setSingleChoiceItems( - list.map { it.serviceName }.toTypedArray(), - list.indexOfFirst { it.serviceName == service } - ) { d, i -> - sourcePublish.onNext(list[i]) - requireContext().currentService = list[i].serviceName - d.dismiss() - } - .setPositiveButton(R.string.done) { d, _ -> d.dismiss() } - .show() - true - } - sourcePublish.subscribe { p.title = getString(R.string.currentSource, it.serviceName) } - .addTo(disposable) - } - - findPreference<Preference>("view_source")?.let { p -> - p.setOnPreferenceClickListener { - requireContext().openInCustomChromeBrowser(sourcePublish.value!!.baseUrl) { - setStartAnimations(requireContext(), R.anim.slide_in_right, R.anim.slide_out_left) - } - true - } - } - - findPreference<Preference>("view_favorites")?.setOnPreferenceClickListener { - findNavController().navigate(SettingsFragmentDirections.actionSettingsFragmentToFavoriteFragment()) - true - } - - findPreference<Preference>("view_history")?.setOnPreferenceClickListener { - findNavController().navigate(SettingsFragmentDirections.actionSettingsFragmentToHistoryFragment()) - true - } - - findPreference<Preference>("view_global_search")?.setOnPreferenceClickListener { - findNavController().navigate(GlobalNavDirections.showGlobalSearch()) - true - } - - findPreference<ListPreference>("theme_setting")?.let { p -> - p.setDefaultValue("system") - p.setOnPreferenceChangeListener { _, newValue -> - when (newValue) { - "system" -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM - "light" -> AppCompatDelegate.MODE_NIGHT_NO - "dark" -> AppCompatDelegate.MODE_NIGHT_YES - else -> null - }?.let(AppCompatDelegate::setDefaultNightMode) - true - } - - when (p.value) { - "system" -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM - "light" -> AppCompatDelegate.MODE_NIGHT_NO - "dark" -> AppCompatDelegate.MODE_NIGHT_YES - else -> null - }?.let(AppCompatDelegate::setDefaultNightMode) - } - - findPreference<SwitchPreferenceCompat>("share_chapter")?.let { p -> - p.setOnPreferenceChangeListener { _, newValue -> - if (newValue is Boolean) { - lifecycleScope.launch(Dispatchers.IO) { requireContext().updatePref(SHARE_CHAPTER, newValue) } - } - true - } - - lifecycleScope.launch { - requireContext().shareChapter - .flowWithLifecycle(lifecycle) - .collect { runOnUIThread { p.isChecked = it } } - } - } - - val itemDao = ItemDatabase.getInstance(requireContext()).itemDao() - - findPreference<PreferenceCategory>("notification_category")?.let { p -> - itemDao.getAllNotificationCount() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeBy { p.isVisible = it > 0 } - .addTo(disposable) - } - - findPreference<Preference>("saved_notifications")?.let { p -> - itemDao.getAllNotificationCount() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribeBy { p.summary = getString(R.string.pending_saved_notifications, it) } - .addTo(disposable) - - p.setOnPreferenceClickListener { - //SavedNotifications.viewNotificationsFromDb(requireContext()) - findNavController().navigate(SettingsFragmentDirections.actionSettingsFragmentToNotificationFragment()) - true - } - } - - findPreference<Preference>("delete_notifications")?.let { p -> - p.setOnPreferenceClickListener { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(R.string.are_you_sure_delete_notifications) - .setPositiveButton(R.string.yes) { d, _ -> - itemDao - .deleteAllNotifications() - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .map { getString(R.string.deleted_notifications, it) } - .subscribeBy { - Toast.makeText(requireContext(), it, Toast.LENGTH_SHORT).show() - requireContext().notificationManager.cancel(42) - } - .addTo(disposable) - d.dismiss() - } - .setNegativeButton(R.string.no) { d, _ -> d.dismiss() } - .show() - true - } - } - - } - - private fun playPreferences() { - findPreference<SeekBarPreference>("battery_alert")?.let { s -> - s.showSeekBarValue = true - s.setDefaultValue(20) - s.max = 100 - s.setOnPreferenceChangeListener { _, newValue -> - if (newValue is Int) { - lifecycleScope.launch(Dispatchers.IO) { requireContext().updatePref(BATTERY_PERCENT, newValue) } - } - true - } - lifecycleScope.launch { - requireContext().batteryPercent - .flowWithLifecycle(lifecycle) - .collect { runOnUIThread { s.value = it } } - } - } - } - - private fun aboutPreferences(genericInfo: GenericInfo) { - val checker = AtomicBoolean(false) - fun updateSetter() { - if (!checker.get()) { - Single.create<AppUpdate.AppUpdates> { - checker.set(true) - AppUpdate.getUpdate()?.let { d -> it.onSuccess(d) } ?: it.onError(Exception("Something went wrong")) - } - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .doOnError { } - .subscribeBy { - appUpdateCheck.onNext(it) - checker.set(false) - context?.let { c -> Toast.makeText(c, "Done Checking", Toast.LENGTH_SHORT).show() } - } - .addTo(disposable) - } - } - - findPreference<Preference>("about_version")?.let { p -> - p.title = - getString(R.string.currentVersion, context?.packageManager?.getPackageInfo(requireContext().packageName, 0)?.versionName.orEmpty()) - p.setOnPreferenceClickListener { - updateSetter() - true - } - } - - findPreference<Preference>("reset_checker")?.let { p -> - p.setOnPreferenceClickListener { - val work = WorkManager.getInstance(this.requireContext()) - work.cancelUniqueWork("updateChecks") - work.pruneWork() - OtakuApp.updateSetup(requireContext()) - Toast.makeText(requireContext(), R.string.cleared, Toast.LENGTH_SHORT).show() - true - } - } - - findPreference<Preference>("view_on_github")?.setOnPreferenceClickListener { - context?.openInCustomChromeBrowser(otakuWorldGithubUrl) - true - } - - findPreference<Preference>("updateAvailable")?.let { p -> - p.isVisible = false - appUpdateCheck - .subscribe { - p.summary = getString(R.string.currentVersion, it.update_real_version.orEmpty()) - val appVersion = AppUpdate.checkForUpdate( - context?.packageManager?.getPackageInfo(requireContext().packageName, 0)?.versionName.orEmpty(), - it.update_real_version.orEmpty() - ) - p.isVisible = appVersion - } - .addTo(disposable) - - p.setOnPreferenceClickListener { - MaterialAlertDialogBuilder(requireContext()) - .setTitle(getString(R.string.updateTo, p.summary)) - .setMessage(R.string.please_update_for_latest_features) - .setPositiveButton(R.string.update) { d, _ -> - activity?.requestPermissions(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE) { - if (it.isGranted) { - appUpdateCheck.value - ?.let { a -> - val isApkAlreadyThere = File( - context?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)!!.absolutePath + "/", - a.let(genericInfo.apkString).toString() - ) - if (isApkAlreadyThere.exists()) isApkAlreadyThere.delete() - DownloadUpdate(requireContext(), requireContext().packageName).downloadUpdate(a) - } - } - } - d.dismiss() - } - .setNeutralButton(R.string.gotoBrowser) { d, _ -> - context?.openInCustomChromeBrowser("https://github.com/jakepurple13/OtakuWorld/releases/latest") - d.dismiss() - } - .setNegativeButton(R.string.notNow) { d, _ -> d.dismiss() } - .show() - - true - } - } - - findPreference<Preference>("sync_time")?.let { s -> - - listOfNotNull( - requireContext().lastUpdateCheck - ?.let { "Start: ${requireContext().getSystemDateTimeFormat().format(it)}" }, - requireContext().lastUpdateCheckEnd - ?.let { "End: ${requireContext().getSystemDateTimeFormat().format(it)}" } - ) - .joinToString("\n") - .let { s.summary = it } - - Observables.combineLatest( - updateCheckPublish.map { "Start: ${requireContext().getSystemDateTimeFormat().format(it)}" }, - updateCheckPublishEnd.map { "End: ${requireContext().getSystemDateTimeFormat().format(it)}" } - ) - .map { "${it.first}\n${it.second}" } - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe { s.summary = it } - .addTo(disposable) - - s.setOnPreferenceClickListener { - WorkManager.getInstance(this.requireContext()) - .enqueueUniqueWork( - "oneTimeUpdate", - ExistingWorkPolicy.KEEP, - OneTimeWorkRequestBuilder<UpdateWorker>() - .setConstraints( - Constraints.Builder() - .setRequiredNetworkType(androidx.work.NetworkType.CONNECTED) - .setRequiresBatteryNotLow(false) - .setRequiresCharging(false) - .setRequiresDeviceIdle(false) - .setRequiresStorageNotLow(false) - .build() - ) - .build() - ) - true - } - } - - findPreference<SwitchPreferenceCompat>("sync")?.let { s -> - s.setDefaultValue(requireContext().shouldCheck) - s.setOnPreferenceChangeListener { _, newValue -> - if (newValue is Boolean) { - requireContext().shouldCheck = newValue - OtakuApp.updateSetup(requireContext()) - } - true - } - } - - findPreference<Preference>("used_libraries")?.setOnPreferenceClickListener { - findNavController() - .navigate( - SettingsFragmentDirections.actionXToAboutLibs( - LibsBuilder() - .withSortEnabled(true) - .customUtils("loggingutils", "LoggingUtils") - //.customUtils("flowutils", "FlowUtils") - .customUtils("gsonutils", "GsonUtils") - .customUtils("helpfulutils", "HelpfulUtils") - .customUtils("dragswipe", "DragSwipe") - .customUtils("funutils", "FunUtils") - .customUtils("rxutils", "RxUtils") - //.customUtils("thirdpartyutils", "ThirdPartyUtils") - .withShowLoadingProgress(true) - ) - ) - true - } - - } - - private fun LibsBuilder.customUtils(libraryName: String, newName: String) = - withLibraryModification( - libraryName, - Libs.LibraryFields.LIBRARY_REPOSITORY_LINK, - "https://www.github.com/jakepurple13/HelpfulTools" - ) - .withLibraryModification( - libraryName, - Libs.LibraryFields.LIBRARY_NAME, - newName - ) - - override fun onDestroy() { - super.onDestroy() - disposable.dispose() - } -} class SettingsDsl { - internal var generalSettings: (SettingsFragment1, PreferenceCategory) -> Unit = { _, _ -> } - - fun generalSettings(block: (SettingsFragment1, PreferenceCategory) -> Unit) { - generalSettings = block - } - - internal var viewSettings: (SettingsFragment1, PreferenceCategory) -> Unit = { _, _ -> } - - fun viewSettings(block: (SettingsFragment1, PreferenceCategory) -> Unit) { - viewSettings = block - } - - internal var navigationSetup: (SettingsFragment1) -> Unit = {} - - fun navigationSetup(block: (SettingsFragment1) -> Unit) { - navigationSetup = block - } - - internal var playSettings: (SettingsFragment1, PreferenceCategory) -> Unit = { _, _ -> } - - fun playSettings(block: (SettingsFragment1, PreferenceCategory) -> Unit) { - playSettings = block - } - companion object { val customAnimationOptions = navOptions { anim { @@ -690,11 +248,10 @@ fun SettingScreen( scope = scope, activity = activity, genericInfo = genericInfo, - logo = logo, - usedLibraryClick = usedLibraryClick + logo = logo ) - Divider(color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f)) + Divider(color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f), modifier = Modifier.padding(top = 5.dp)) /*Notifications*/ NotificationSettings( @@ -732,6 +289,13 @@ fun SettingScreen( customSettings = customPreferences.playerSettings ) + Divider(color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.12f), modifier = Modifier.padding(top = 5.dp)) + + /*More Info*/ + InfoSettings( + context = context, + usedLibraryClick = usedLibraryClick + ) } } @@ -778,11 +342,14 @@ private fun AccountSettings(context: Context, activity: ComponentActivity, logo: PreferenceSetting( settingTitle = { Text(accountInfo?.displayName ?: "User") }, settingIcon = { - GlideImage( - imageModel = accountInfo?.photoUrl ?: logo.logoId, - contentDescription = null, - contentScale = ContentScale.Fit, - requestBuilder = { Glide.with(LocalView.current).asDrawable().circleCrop() }, + Image( + painter = rememberImagePainter(data = accountInfo?.photoUrl) { + error(logo.logoId) + crossfade(true) + lifecycle(LocalLifecycleOwner.current) + transformations(CircleCropTransformation()) + }, + contentDescription = null ) }, modifier = Modifier.clickable( @@ -809,8 +376,7 @@ private fun AboutSettings( scope: CoroutineScope, activity: ComponentActivity, genericInfo: GenericInfo, - logo: MainLogo, - usedLibraryClick: () -> Unit + logo: MainLogo ) { CategorySetting( settingTitle = { Text(stringResource(R.string.about)) }, @@ -975,34 +541,6 @@ private fun AboutSettings( } ) } - - PreferenceSetting( - settingTitle = { Text(stringResource(R.string.view_libraries_used)) }, - settingIcon = { Icon(Icons.Default.LibraryBooks, null, modifier = Modifier.fillMaxSize()) }, - modifier = Modifier.clickable( - indication = rememberRipple(), - interactionSource = remember { MutableInteractionSource() }, - onClick = usedLibraryClick - ) - ) - - PreferenceSetting( - settingTitle = { Text(stringResource(R.string.view_on_github)) }, - settingIcon = { Icon(painterResource(R.drawable.github_icon), null, modifier = Modifier.fillMaxSize()) }, - modifier = Modifier.clickable( - indication = rememberRipple(), - interactionSource = remember { MutableInteractionSource() } - ) { context.openInCustomChromeBrowser("https://github.com/jakepurple13/OtakuWorld/releases/latest") } - ) - - PreferenceSetting( - settingTitle = { Text(stringResource(R.string.join_discord)) }, - settingIcon = { Icon(painterResource(R.drawable.ic_baseline_discord_24), null, modifier = Modifier.fillMaxSize()) }, - modifier = Modifier.clickable( - indication = rememberRipple(), - interactionSource = remember { MutableInteractionSource() } - ) { context.openInCustomChromeBrowser("https://discord.gg/MhhHMWqryg") } - ) } class NotificationViewModel(dao: ItemDao) : ViewModel() { @@ -1169,11 +707,13 @@ private fun GeneralSettings( } ) - ShowWhen(source != null) { - PreferenceSetting( - settingTitle = { Text(stringResource(R.string.view_source_in_browser)) }, - settingIcon = { Icon(Icons.Default.OpenInBrowser, null, modifier = Modifier.fillMaxSize()) }, - modifier = Modifier.clickable( + PreferenceSetting( + settingTitle = { Text(stringResource(R.string.view_source_in_browser)) }, + settingIcon = { Icon(Icons.Default.OpenInBrowser, null, modifier = Modifier.fillMaxSize()) }, + modifier = Modifier + .alpha(animateFloatAsState(targetValue = if (source != null) 1f else 0f).value) + .clickable( + enabled = source != null, indication = rememberRipple(), interactionSource = remember { MutableInteractionSource() } ) { @@ -1183,8 +723,7 @@ private fun GeneralSettings( } } } - ) - } + ) PreferenceSetting( settingTitle = { Text(stringResource(R.string.global_search)) }, @@ -1262,6 +801,51 @@ private fun PlaySettings(context: Context, scope: CoroutineScope, customSettings customSettings?.invoke() } +@ExperimentalMaterialApi +@Composable +private fun InfoSettings(context: Context, usedLibraryClick: () -> Unit) { + CategorySetting(settingTitle = { Text(stringResource(R.string.more_info_category)) }) + + PreferenceSetting( + settingTitle = { Text(stringResource(R.string.view_libraries_used)) }, + settingIcon = { Icon(Icons.Default.LibraryBooks, null, modifier = Modifier.fillMaxSize()) }, + modifier = Modifier.clickable( + indication = rememberRipple(), + interactionSource = remember { MutableInteractionSource() }, + onClick = usedLibraryClick + ) + ) + + PreferenceSetting( + settingTitle = { Text(stringResource(R.string.view_on_github)) }, + settingIcon = { Icon(painterResource(R.drawable.github_icon), null, modifier = Modifier.fillMaxSize()) }, + modifier = Modifier.clickable( + indication = rememberRipple(), + interactionSource = remember { MutableInteractionSource() } + ) { context.openInCustomChromeBrowser("https://github.com/jakepurple13/OtakuWorld/releases/latest") } + ) + + PreferenceSetting( + settingTitle = { Text(stringResource(R.string.join_discord)) }, + settingIcon = { Icon(painterResource(R.drawable.ic_baseline_discord_24), null, modifier = Modifier.fillMaxSize()) }, + modifier = Modifier.clickable( + indication = rememberRipple(), + interactionSource = remember { MutableInteractionSource() } + ) { context.openInCustomChromeBrowser("https://discord.gg/MhhHMWqryg") } + ) + + PreferenceSetting( + settingTitle = { Text(stringResource(R.string.support)) }, + summaryValue = { Text(stringResource(R.string.support_summary)) }, + settingIcon = { Icon(Icons.Default.AttachMoney, null, modifier = Modifier.fillMaxSize()) }, + modifier = Modifier.clickable( + indication = rememberRipple(), + interactionSource = remember { MutableInteractionSource() } + ) { context.openInCustomChromeBrowser("https://ko-fi.com/V7V3D3JI") } + ) + +} + @ExperimentalComposeUiApi @ExperimentalMaterialApi @Composable diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/UpdateChecker.kt b/UIViews/src/main/java/com/programmersbox/uiviews/UpdateChecker.kt index 5223f87f4..6fd89e272 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/UpdateChecker.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/UpdateChecker.kt @@ -69,8 +69,9 @@ class AppCheckWorker(context: Context, workerParams: WorkerParameters) : RxWorke it.onSuccess(Result.success()) } } - .onErrorReturn { Result.success() } .timeout(1, TimeUnit.MINUTES) + .onErrorReturn { Result.success() } + } @@ -164,12 +165,12 @@ class UpdateWorker(context: Context, workerParams: WorkerParameters) : RxWorker( update.sendFinishedNotification() Result.success() } + .timeout(5, TimeUnit.MINUTES) .onErrorReturn { println(it) update.sendFinishedNotification() Result.success() } - .timeout(5, TimeUnit.MINUTES) } } @@ -363,8 +364,8 @@ class NotifySingleWorker(context: Context, workerParams: WorkerParameters) : RxW it.onSuccess(Result.success()) } - .onErrorReturn { Result.success() } .timeout(1, TimeUnit.MINUTES) + .onErrorReturn { Result.success() } } diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/utils/ComposableUtils.kt b/UIViews/src/main/java/com/programmersbox/uiviews/utils/ComposableUtils.kt index 4e4d67de3..cc6311965 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/utils/ComposableUtils.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/utils/ComposableUtils.kt @@ -547,6 +547,7 @@ private fun <T> DeleteItemView( androidx.compose.material3.Surface( tonalElevation = 5.dp, modifier = Modifier.fillMaxSize(), + shape = MaterialTheme.shapes.medium, indication = rememberRipple(), border = BorderStroke( animateDpAsState(targetValue = if (item in deleteItemList) 5.dp else 1.dp).value, @@ -810,6 +811,31 @@ fun InfiniteListHandler( } } +@ExperimentalFoundationApi +@Composable +fun InfiniteListHandler( + listState: LazyGridState, + buffer: Int = 2, + onLoadMore: () -> Unit +) { + val loadMore = remember { + derivedStateOf { + val layoutInfo = listState.layoutInfo + val totalItemsNumber = layoutInfo.totalItemsCount + val lastVisibleItemIndex = (layoutInfo.visibleItemsInfo.lastOrNull()?.index ?: 0) + 1 + + lastVisibleItemIndex > (totalItemsNumber - buffer) + } + } + + LaunchedEffect(loadMore) { + snapshotFlow { loadMore.value } + .drop(1) + .distinctUntilChanged() + .collect { onLoadMore() } + } +} + class ListBottomSheetItemModel( val primaryText: String, val overlineText: String? = null, @@ -1026,8 +1052,18 @@ fun Coordinator( fun BannerBox( modifier: Modifier = Modifier, showBanner: Boolean = false, - bannerEnter: EnterTransition = slideInVertically { -it }, - bannerExit: ExitTransition = slideOutVertically { -it }, + bannerEnter: EnterTransition = slideInVertically( + animationSpec = tween( + durationMillis = 200, + easing = LinearOutSlowInEasing + ) + ) { -it }, + bannerExit: ExitTransition = slideOutVertically( + animationSpec = tween( + durationMillis = 200, + easing = LinearOutSlowInEasing + ) + ) { -it }, banner: @Composable BoxScope.() -> Unit, content: @Composable BoxScope.() -> Unit ) { diff --git a/UIViews/src/main/java/com/programmersbox/uiviews/utils/OtakuComposableUtils.kt b/UIViews/src/main/java/com/programmersbox/uiviews/utils/OtakuComposableUtils.kt index 87f728d7d..f0b1c07ec 100644 --- a/UIViews/src/main/java/com/programmersbox/uiviews/utils/OtakuComposableUtils.kt +++ b/UIViews/src/main/java/com/programmersbox/uiviews/utils/OtakuComposableUtils.kt @@ -4,6 +4,7 @@ import androidx.appcompat.content.res.AppCompatResources import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.* +import androidx.compose.foundation.shape.CornerSize import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState @@ -36,8 +37,10 @@ import com.skydoves.landscapist.glide.GlideImage import androidx.compose.material3.MaterialTheme as M3MaterialTheme object ComposableUtils { - val IMAGE_WIDTH @Composable get() = with(LocalDensity.current) { 360.toDp() } - val IMAGE_HEIGHT @Composable get() = with(LocalDensity.current) { 480.toDp() } + const val IMAGE_WIDTH_PX = 360 + const val IMAGE_HEIGHT_PX = 480 + val IMAGE_WIDTH @Composable get() = with(LocalDensity.current) { IMAGE_WIDTH_PX.toDp() } + val IMAGE_HEIGHT @Composable get() = with(LocalDensity.current) { IMAGE_HEIGHT_PX.toDp() } } @ExperimentalMaterialApi @@ -290,11 +293,11 @@ fun M3CoverCard( ) { Image( painter = rememberImagePainter(imageUrl) { - placeholder(AppCompatResources.getDrawable(context, placeHolder)!!) - error(AppCompatResources.getDrawable(context, error)!!) + placeholder(placeHolder) + error(error) crossfade(true) lifecycle(LocalLifecycleOwner.current) - size(480, 360) + size(ComposableUtils.IMAGE_WIDTH_PX, ComposableUtils.IMAGE_HEIGHT_PX) }, contentDescription = name, modifier = Modifier.matchParentSize() @@ -419,32 +422,12 @@ fun M3OtakuBannerBox( banner = { androidx.compose.material3.Surface( modifier = Modifier.align(Alignment.TopCenter), - shape = MaterialTheme.shapes.medium, + shape = MaterialTheme.shapes.medium.copy(topStart = CornerSize(0.dp), topEnd = CornerSize(0.dp)), tonalElevation = 5.dp, shadowElevation = 10.dp ) { ListItem( icon = { - /*GlideImage( - imageModel = itemInfo.value?.imageUrl.orEmpty(), - contentDescription = null, - contentScale = ContentScale.Fit, - modifier = Modifier.size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT), - loading = { - Image( - bitmap = placeHolderImage, - contentDescription = null, - modifier = Modifier.size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT) - ) - }, - failure = { - Image( - bitmap = placeHolderImage, - contentDescription = null, - modifier = Modifier.size(ComposableUtils.IMAGE_WIDTH, ComposableUtils.IMAGE_HEIGHT) - ) - } - )*/ val painter = rememberImagePainter(data = itemInfo.value?.imageUrl.orEmpty()) when (painter.state) { diff --git a/UIViews/src/main/res/drawable/ic_baseline_android_24.xml b/UIViews/src/main/res/drawable/ic_baseline_android_24.xml deleted file mode 100644 index 779c034aa..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_android_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M17.6,9.48l1.84,-3.18c0.16,-0.31 0.04,-0.69 -0.26,-0.85c-0.29,-0.15 -0.65,-0.06 -0.83,0.22l-1.88,3.24c-2.86,-1.21 -6.08,-1.21 -8.94,0L5.65,5.67c-0.19,-0.29 -0.58,-0.38 -0.87,-0.2C4.5,5.65 4.41,6.01 4.56,6.3L6.4,9.48C3.3,11.25 1.28,14.44 1,18h22C22.72,14.44 20.7,11.25 17.6,9.48zM7,15.25c-0.69,0 -1.25,-0.56 -1.25,-1.25c0,-0.69 0.56,-1.25 1.25,-1.25S8.25,13.31 8.25,14C8.25,14.69 7.69,15.25 7,15.25zM17,15.25c-0.69,0 -1.25,-0.56 -1.25,-1.25c0,-0.69 0.56,-1.25 1.25,-1.25s1.25,0.56 1.25,1.25C18.25,14.69 17.69,15.25 17,15.25z" /> -</vector> diff --git a/UIViews/src/main/res/drawable/ic_baseline_cached_24.xml b/UIViews/src/main/res/drawable/ic_baseline_cached_24.xml deleted file mode 100644 index 2ed03e008..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_cached_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M19,8l-4,4h3c0,3.31 -2.69,6 -6,6 -1.01,0 -1.97,-0.25 -2.8,-0.7l-1.46,1.46C8.97,19.54 10.43,20 12,20c4.42,0 8,-3.58 8,-8h3l-4,-4zM6,12c0,-3.31 2.69,-6 6,-6 1.01,0 1.97,0.25 2.8,0.7l1.46,-1.46C15.03,4.46 13.57,4 12,4c-4.42,0 -8,3.58 -8,8H1l4,4 4,-4H6z" /> -</vector> diff --git a/UIViews/src/main/res/drawable/ic_baseline_download_24.xml b/UIViews/src/main/res/drawable/ic_baseline_download_24.xml deleted file mode 100644 index 1f61509e8..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_download_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M5,20h14v-2H5V20zM19,9h-4V3H9v6H5l7,7L19,9z"/> -</vector> diff --git a/UIViews/src/main/res/drawable/ic_baseline_library_books_24.xml b/UIViews/src/main/res/drawable/ic_baseline_library_books_24.xml deleted file mode 100644 index 5ac533f50..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_library_books_24.xml +++ /dev/null @@ -1,11 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal" - android:autoMirrored="true"> - <path - android:fillColor="@android:color/white" - android:pathData="M4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6zM20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM19,11L9,11L9,9h10v2zM15,15L9,15v-2h6v2zM19,7L9,7L9,5h10v2z" /> -</vector> diff --git a/UIViews/src/main/res/drawable/ic_baseline_open_in_browser_24.xml b/UIViews/src/main/res/drawable/ic_baseline_open_in_browser_24.xml deleted file mode 100644 index 2b8b999d7..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_open_in_browser_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M19,4L5,4c-1.11,0 -2,0.9 -2,2v12c0,1.1 0.89,2 2,2h4v-2L5,18L5,8h14v10h-4v2h4c1.1,0 2,-0.9 2,-2L21,6c0,-1.1 -0.89,-2 -2,-2zM12,10l-4,4h3v6h2v-6h3l-4,-4z" /> -</vector> diff --git a/UIViews/src/main/res/drawable/ic_baseline_settings_brightness_24.xml b/UIViews/src/main/res/drawable/ic_baseline_settings_brightness_24.xml deleted file mode 100644 index 3c8eb5ea7..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_settings_brightness_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM21,19.01L3,19.01L3,4.99h18v14.02zM8,16h2.5l1.5,1.5 1.5,-1.5L16,16v-2.5l1.5,-1.5 -1.5,-1.5L16,8h-2.5L12,6.5 10.5,8L8,8v2.5L6.5,12 8,13.5L8,16zM12,9c1.66,0 3,1.34 3,3s-1.34,3 -3,3L12,9z"/> -</vector> diff --git a/UIViews/src/main/res/drawable/ic_baseline_share_24.xml b/UIViews/src/main/res/drawable/ic_baseline_share_24.xml deleted file mode 100644 index 5002dcc14..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_share_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z" /> -</vector> diff --git a/UIViews/src/main/res/drawable/ic_baseline_star_24.xml b/UIViews/src/main/res/drawable/ic_baseline_star_24.xml deleted file mode 100644 index 448ae51c5..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_star_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z" /> -</vector> diff --git a/UIViews/src/main/res/drawable/ic_baseline_system_update_alt_24.xml b/UIViews/src/main/res/drawable/ic_baseline_system_update_alt_24.xml deleted file mode 100644 index 020ab2280..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_system_update_alt_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector android:height="24dp" - android:tint="#00E676" - android:viewportHeight="24" - android:viewportWidth="24" - android:width="24dp" - xmlns:android="http://schemas.android.com/apk/res/android"> - <path - android:fillColor="@android:color/white" - android:pathData="M12,16.5l4,-4h-3v-9h-2v9L8,12.5l4,4zM21,3.5h-6v1.99h6v14.03L3,19.52L3,5.49h6L9,3.5L3,3.5c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2v-14c0,-1.1 -0.9,-2 -2,-2z" /> -</vector> diff --git a/UIViews/src/main/res/drawable/ic_baseline_update_24.xml b/UIViews/src/main/res/drawable/ic_baseline_update_24.xml deleted file mode 100644 index 6ccd500f1..000000000 --- a/UIViews/src/main/res/drawable/ic_baseline_update_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M21,10.12h-6.78l2.74,-2.82c-2.73,-2.7 -7.15,-2.8 -9.88,-0.1c-2.73,2.71 -2.73,7.08 0,9.79s7.15,2.71 9.88,0C18.32,15.65 19,14.08 19,12.1h2c0,1.98 -0.88,4.55 -2.64,6.29c-3.51,3.48 -9.21,3.48 -12.72,0c-3.5,-3.47 -3.53,-9.11 -0.02,-12.58s9.14,-3.47 12.65,0L21,3V10.12zM12.5,8v4.25l3.5,2.08l-0.72,1.21L11,13V8H12.5z" /> -</vector> diff --git a/UIViews/src/main/res/raw/heart.json b/UIViews/src/main/res/raw/heart.json deleted file mode 100644 index 20459dd2e..000000000 --- a/UIViews/src/main/res/raw/heart.json +++ /dev/null @@ -1,742 +0,0 @@ -{ - "v": "5.5.2", - "fr": 30, - "ip": 0, - "op": 30, - "w": 24, - "h": 24, - "nm": "heart", - "ddd": 0, - "assets": [], - "layers": [ - { - "ddd": 0, - "ind": 1, - "ty": 4, - "nm": "heart", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 - }, - "r": { - "a": 0, - "k": 0, - "ix": 10 - }, - "p": { - "a": 0, - "k": [ - 12, - 12, - 0 - ], - "ix": 2 - }, - "a": { - "a": 0, - "k": [ - 12, - 12, - 0 - ], - "ix": 1 - }, - "s": { - "a": 0, - "k": [ - 100, - 100, - 100 - ], - "ix": 6 - } - }, - "ao": 0, - "shapes": [ - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [ - 0.001, - 0.001 - ], - [ - 2.148, - -2.148 - ], - [ - 0.001, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 2.149, - -2.148 - ], - [ - -2.148, - -2.148 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 2.147, - 2.148 - ] - ], - "o": [ - [ - -2.147, - -2.148 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - -2.148, - -2.148 - ], - [ - -2.148, - 2.148 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 2.148, - -2.147 - ], - [ - -0.001, - -0.001 - ] - ], - "v": [ - [ - 8.84, - -7.236 - ], - [ - 1.061, - -7.237 - ], - [ - 1.059, - -7.236 - ], - [ - -0.001, - -6.176 - ], - [ - -1.061, - -7.236 - ], - [ - -8.84, - -7.236 - ], - [ - -8.84, - 0.544 - ], - [ - -7.781, - 1.604 - ], - [ - -0.001, - 9.385 - ], - [ - 7.779, - 1.604 - ], - [ - 8.84, - 0.544 - ], - [ - 8.842, - -7.234 - ] - ], - "c": true - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "st", - "c": { - "a": 0, - "k": [ - 0, - 0, - 0, - 1 - ], - "ix": 3 - }, - "o": { - "a": 0, - "k": 100, - "ix": 4 - }, - "w": { - "a": 0, - "k": 2, - "ix": 5 - }, - "lc": 2, - "lj": 2, - "bm": 0, - "nm": "Stroke 1", - "mn": "ADBE Vector Graphic - Stroke", - "hd": false - }, - { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 12, - 11.846 - ], - "ix": 2 - }, - "a": { - "a": 0, - "k": [ - 0, - 0 - ], - "ix": 1 - }, - "s": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.667, - 0.667 - ], - "y": [ - 1, - 1 - ] - }, - "o": { - "x": [ - 0.333, - 0.333 - ], - "y": [ - 0, - 0 - ] - }, - "t": 0, - "s": [ - 100, - 100 - ] - }, - { - "i": { - "x": [ - 0.667, - 0.667 - ], - "y": [ - 1, - 1 - ] - }, - "o": { - "x": [ - 0.333, - 0.333 - ], - "y": [ - 0, - 0 - ] - }, - "t": 5, - "s": [ - 90, - 90 - ] - }, - { - "t": 10, - "s": [ - 100, - 100 - ] - } - ], - "ix": 3 - }, - "r": { - "a": 0, - "k": 0, - "ix": 6 - }, - "o": { - "a": 0, - "k": 100, - "ix": 7 - }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 - }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 - }, - "nm": "Transform" - } - ], - "nm": "Group 1", - "np": 2, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false - } - ], - "ip": 0, - "op": 30, - "st": 0, - "bm": 0 - }, - { - "ddd": 0, - "ind": 2, - "ty": 4, - "nm": "heart Fill", - "sr": 1, - "ks": { - "o": { - "a": 0, - "k": 100, - "ix": 11 - }, - "r": { - "a": 0, - "k": 0, - "ix": 10 - }, - "p": { - "a": 0, - "k": [ - 12, - 12, - 0 - ], - "ix": 2 - }, - "a": { - "a": 0, - "k": [ - 12, - 12, - 0 - ], - "ix": 1 - }, - "s": { - "a": 0, - "k": [ - 100, - 100, - 100 - ], - "ix": 6 - } - }, - "ao": 0, - "shapes": [ - { - "ty": "gr", - "it": [ - { - "ind": 0, - "ty": "sh", - "ix": 1, - "ks": { - "a": 0, - "k": { - "i": [ - [ - 0.001, - 0.001 - ], - [ - 2.148, - -2.148 - ], - [ - 0.001, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 2.149, - -2.148 - ], - [ - -2.148, - -2.148 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 2.147, - 2.148 - ] - ], - "o": [ - [ - -2.147, - -2.148 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - -2.148, - -2.148 - ], - [ - -2.148, - 2.148 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 0, - 0 - ], - [ - 2.148, - -2.147 - ], - [ - -0.001, - -0.001 - ] - ], - "v": [ - [ - 8.84, - -7.236 - ], - [ - 1.061, - -7.237 - ], - [ - 1.059, - -7.236 - ], - [ - -0.001, - -6.176 - ], - [ - -1.061, - -7.236 - ], - [ - -8.84, - -7.236 - ], - [ - -8.84, - 0.544 - ], - [ - -7.781, - 1.604 - ], - [ - -0.001, - 9.385 - ], - [ - 7.779, - 1.604 - ], - [ - 8.84, - 0.544 - ], - [ - 8.842, - -7.234 - ] - ], - "c": true - }, - "ix": 2 - }, - "nm": "Path 1", - "mn": "ADBE Vector Shape - Group", - "hd": false - }, - { - "ty": "fl", - "c": { - "a": 0, - "k": [ - 0, - 0, - 0, - 1 - ], - "ix": 4 - }, - "o": { - "a": 0, - "k": 100, - "ix": 5 - }, - "r": 1, - "bm": 0, - "nm": "Fill 1", - "mn": "ADBE Vector Graphic - Fill", - "hd": false - }, - { - "ty": "tr", - "p": { - "a": 0, - "k": [ - 12, - 11.846 - ], - "ix": 2 - }, - "a": { - "a": 0, - "k": [ - 0, - 0 - ], - "ix": 1 - }, - "s": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.667, - 0.667 - ], - "y": [ - 1, - 1 - ] - }, - "o": { - "x": [ - 0.333, - 0.333 - ], - "y": [ - 0, - 0 - ] - }, - "t": 2, - "s": [ - 50, - 50 - ] - }, - { - "t": 30, - "s": [ - 100, - 100 - ] - } - ], - "ix": 3 - }, - "r": { - "a": 0, - "k": 0, - "ix": 6 - }, - "o": { - "a": 1, - "k": [ - { - "i": { - "x": [ - 0.833 - ], - "y": [ - 0.833 - ] - }, - "o": { - "x": [ - 0.167 - ], - "y": [ - 0.167 - ] - }, - "t": 2, - "s": [ - 0 - ] - }, - { - "t": 7, - "s": [ - 100 - ] - } - ], - "ix": 7 - }, - "sk": { - "a": 0, - "k": 0, - "ix": 4 - }, - "sa": { - "a": 0, - "k": 0, - "ix": 5 - }, - "nm": "Transform" - } - ], - "nm": "fill", - "np": 2, - "cix": 2, - "bm": 0, - "ix": 1, - "mn": "ADBE Vector Group", - "hd": false - } - ], - "ip": 0, - "op": 30, - "st": 0, - "bm": 0 - } - ], - "markers": [] -} \ No newline at end of file diff --git a/UIViews/src/main/res/values/strings.xml b/UIViews/src/main/res/values/strings.xml index 5b3ba8137..0c3dc43b9 100644 --- a/UIViews/src/main/res/values/strings.xml +++ b/UIViews/src/main/res/values/strings.xml @@ -74,6 +74,7 @@ <string name="startingCheck">Starting Check</string> <string name="checking">Checking</string> <string name="about">About</string> + <string name="more_info_category">More Info</string> <string name="account_category_title">Account</string> <string name="last_update_check_time">Last Time Updates Were Checked</string> <string name="check_for_periodic_updates">Check for Updates Periodically</string> @@ -132,6 +133,8 @@ <string name="save_for_later">Save for Later</string> <string name="view_on_github">View on Github</string> <string name="join_discord">Join the Discord</string> + <string name="support">Support the Developer</string> + <string name="support_summary">Support the developer by donating! Buy him a coffee!</string> <string name="get_started">Get Started</string> <string name="get_started_info">Favorite something for it to show up here</string> <string name="add_a_favorite">Add a Favorite</string> diff --git a/UIViews/src/main/res/xml/root_preferences.xml b/UIViews/src/main/res/xml/root_preferences.xml deleted file mode 100644 index 3ea7d4e93..000000000 --- a/UIViews/src/main/res/xml/root_preferences.xml +++ /dev/null @@ -1,146 +0,0 @@ -<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" - xmlns:app="http://schemas.android.com/apk/res-auto"> - - <PreferenceCategory app:title="@string/account_category_title"> - - <Preference - app:key="user_account" - app:title="User" /> - - </PreferenceCategory> - - <PreferenceCategory - app:key="aboutCategory" - app:title="@string/about"> - - <Preference - app:key="about_version" - app:summary="@string/press_to_check_for_updates" - app:title="Version: " /> - - <Preference - app:icon="@drawable/ic_baseline_system_update_alt_24" - app:key="updateAvailable" - app:title="@string/update_available" /> - - <Preference - app:enabled="true" - app:key="sync_time" - app:title="@string/last_update_check_time" /> - - <SwitchPreferenceCompat - app:key="sync" - app:title="@string/check_for_periodic_updates" /> - - <Preference - app:dependency="sync" - app:key="reset_checker" - app:summary="@string/clear_update_queue_summary" - app:title="@string/clear_update_queue" /> - - <Preference - app:icon="@drawable/ic_baseline_library_books_24" - app:key="used_libraries" - app:title="@string/view_libraries_used" /> - - <Preference - app:icon="@drawable/github_icon" - app:key="view_on_github" - app:title="@string/view_on_github" /> - - </PreferenceCategory> - - <PreferenceCategory - app:key="notification_category" - app:title="@string/notifications_category_title"> - - <Preference - app:key="saved_notifications" - app:summary="@string/view_noti_summary" - app:title="@string/view_notifications_title" /> - - <Preference - app:key="delete_notifications" - app:summary="@string/delete_notifications_summary" - app:title="@string/delete_saved_notifications_title" /> - </PreferenceCategory> - - <PreferenceCategory - app:key="viewCategory" - app:title="@string/view_menu_category_title"> - - <Preference - app:icon="@drawable/ic_baseline_android_24" - app:isPreferenceVisible="false" - app:key="debugMenu" - app:title="Debug Menu" /> - - <Preference - app:icon="@drawable/ic_baseline_star_24" - app:key="view_favorites" - app:title="@string/viewFavoritesMenu" /> - - <Preference - app:icon="@drawable/ic_baseline_update_24" - app:key="view_history" - app:title="@string/history" /> - - </PreferenceCategory> - - <PreferenceCategory - app:key="generalCategory" - app:title="@string/general_menu_title"> - - <Preference - app:icon="@android:drawable/ic_menu_preferences" - app:key="current_source" - app:title="Current Source: " /> - - <Preference - app:icon="@drawable/ic_baseline_open_in_browser_24" - app:key="view_source" - app:title="@string/view_source_in_browser" /> - - <Preference - app:icon="@android:drawable/ic_menu_search" - app:key="view_global_search" - app:title="@string/global_search" /> - - <ListPreference - app:defaultValue="system" - app:dialogIcon="@drawable/ic_baseline_settings_brightness_24" - app:dialogTitle="@string/choose_a_theme" - app:entries="@array/theme_items" - app:entryValues="@array/theme_values" - app:icon="@drawable/ic_baseline_settings_brightness_24" - app:key="theme_setting" - app:persistent="true" - app:title="@string/theme_choice_title" - app:useSimpleSummaryProvider="true" /> - - <SwitchPreferenceCompat - app:icon="@drawable/ic_baseline_share_24" - app:key="share_chapter" - app:title="@string/share_chapters" /> - - </PreferenceCategory> - - <PreferenceCategory - app:key="playCategory" - app:title="@string/playSettings"> - - <SeekBarPreference - android:defaultValue="20" - android:max="100" - app:defaultValue="20" - app:icon="@drawable/ic_baseline_battery_alert_24" - app:key="battery_alert" - app:min="1" - app:seekBarIncrement="1" - app:showSeekBarValue="true" - app:summary="@string/battery_default" - app:title="@string/battery_alert_percentage" /> - - </PreferenceCategory> - -</PreferenceScreen> \ No newline at end of file diff --git a/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/Crunchyroll.kt b/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/Crunchyroll.kt index 84a94b19a..64c511d74 100644 --- a/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/Crunchyroll.kt +++ b/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/Crunchyroll.kt @@ -77,7 +77,7 @@ class HttpSession { sessionCookies.putAll( CookieJar( *res.headers - .filter { it.key.toLowerCase() == "set-cookie" } + .filter { it.key.lowercase() == "set-cookie" } .map { Cookie(it.value) } .toTypedArray() ) @@ -116,7 +116,7 @@ class HttpSession { sessionCookies.putAll( CookieJar( *res.headers - .filter { it.key.toLowerCase() == "set-cookie" } + .filter { it.key.lowercase() == "set-cookie" } .map { Cookie(it.value) } .toTypedArray() ) @@ -125,7 +125,7 @@ class HttpSession { } } -private fun String.toAscii() = this.map { it.toInt() }.joinToString() +private fun String.toAscii() = this.map { it.code }.joinToString() class CrunchyrollGeoBypasser { companion object { diff --git a/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/GogoAnimeVC.kt b/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/GogoAnimeVC.kt index 1c95b8ba3..0f09e4ba3 100644 --- a/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/GogoAnimeVC.kt +++ b/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/GogoAnimeVC.kt @@ -17,9 +17,8 @@ import io.reactivex.Single import org.jsoup.Jsoup import org.jsoup.nodes.Document - object GogoAnimeVC : ShowApi( - baseUrl = "https://gogoanime.wiki", + baseUrl = "https://gogoanime.film", recentPath = "", allPath = "" ) { diff --git a/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/Vidstreaming.kt b/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/Vidstreaming.kt index 5bd93a973..5b460619b 100644 --- a/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/Vidstreaming.kt +++ b/anime_sources/src/main/java/com/programmersbox/anime_sources/anime/Vidstreaming.kt @@ -29,7 +29,7 @@ object Vidstreaming : VidstreamingTemplate( } object VidEmbed : VidstreamingTemplate( - "https://vidembed.cc", + "https://vidembed.io", "movies", "series" ) { diff --git a/anime_sources/src/main/java/com/programmersbox/anime_sources/utilities/AnimeUtils.kt b/anime_sources/src/main/java/com/programmersbox/anime_sources/utilities/AnimeUtils.kt index 337723cef..88aba6475 100644 --- a/anime_sources/src/main/java/com/programmersbox/anime_sources/utilities/AnimeUtils.kt +++ b/anime_sources/src/main/java/com/programmersbox/anime_sources/utilities/AnimeUtils.kt @@ -438,7 +438,7 @@ val Response.url: String val Response.cookies: Map<String, String> get() { val cookieList = - this.headers.filter { it.first.toLowerCase(Locale.ROOT) == "set-cookie" }.getOrNull(0)?.second?.split(";") + this.headers.filter { it.first.lowercase(Locale.ROOT) == "set-cookie" }.getOrNull(0)?.second?.split(";") return cookieList?.associate { val split = it.split("=") (split.getOrNull(0)?.trim() ?: "") to (split.getOrNull(1)?.trim() ?: "") diff --git a/anime_sources/src/main/java/com/programmersbox/anime_sources/utilities/Extractors.kt b/anime_sources/src/main/java/com/programmersbox/anime_sources/utilities/Extractors.kt index 0afbff1ad..09f04d2e6 100644 --- a/anime_sources/src/main/java/com/programmersbox/anime_sources/utilities/Extractors.kt +++ b/anime_sources/src/main/java/com/programmersbox/anime_sources/utilities/Extractors.kt @@ -281,7 +281,7 @@ object WcoStreamExtractor : Extractor { val html = get(url, headers = mapOf("Referer" to "https://wcostream.cc/")).text val (Id) = "/e/(.*?)?domain".toRegex().find(url)!!.destructured - val (skey) = """skey\s=\s['"](.*?)['"];""".toRegex().find(html.orEmpty())!!.destructured + val (skey) = """skey\s=\s['"](.*?)['"];""".toRegex().find(html)!!.destructured val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey" val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" diff --git a/animeworld/build.gradle b/animeworld/build.gradle index d8e4ef59a..e48abb72f 100644 --- a/animeworld/build.gradle +++ b/animeworld/build.gradle @@ -128,5 +128,7 @@ dependencies { implementation compose.compose + implementation datastore.datastore + //debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.8' } \ No newline at end of file diff --git a/animeworld/src/main/java/com/programmersbox/animeworld/AnimeUtils.kt b/animeworld/src/main/java/com/programmersbox/animeworld/AnimeUtils.kt index 5c2a66801..07ba7510c 100644 --- a/animeworld/src/main/java/com/programmersbox/animeworld/AnimeUtils.kt +++ b/animeworld/src/main/java/com/programmersbox/animeworld/AnimeUtils.kt @@ -36,10 +36,13 @@ import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.dp +import androidx.datastore.preferences.core.booleanPreferencesKey import com.programmersbox.helpfulutils.sharedPrefNotNullDelegate +import com.programmersbox.uiviews.utils.dataStore import io.reactivex.subjects.PublishSubject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import kotlin.math.roundToInt @@ -47,6 +50,9 @@ var Context.folderLocation: String by sharedPrefNotNullDelegate( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES).toString() + "/AnimeWorld/" ) +val IGNORE_SSL = booleanPreferencesKey("ignore_ssl") +val Context.ignoreSsl get() = dataStore.data.map { it[IGNORE_SSL] ?: true } + data class VideoContent( var videoId: Long = 0, var videoName: String? = null, diff --git a/animeworld/src/main/java/com/programmersbox/animeworld/GenericAnime.kt b/animeworld/src/main/java/com/programmersbox/animeworld/GenericAnime.kt index 788f87ffd..d285f3d77 100644 --- a/animeworld/src/main/java/com/programmersbox/animeworld/GenericAnime.kt +++ b/animeworld/src/main/java/com/programmersbox/animeworld/GenericAnime.kt @@ -11,8 +11,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.clickable import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.* import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.* @@ -29,7 +28,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastAny import androidx.compose.ui.viewinterop.AndroidView -import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModel import androidx.lifecycle.viewmodel.compose.viewModel @@ -37,8 +35,6 @@ import androidx.mediarouter.app.MediaRouteButton import androidx.mediarouter.app.MediaRouteDialogFactory import androidx.navigation.NavController import androidx.navigation.fragment.FragmentNavigator -import androidx.navigation.fragment.findNavController -import androidx.preference.Preference import com.google.accompanist.placeholder.PlaceholderHighlight import com.google.accompanist.placeholder.material.placeholder import com.google.accompanist.placeholder.material.shimmer @@ -51,6 +47,7 @@ import com.programmersbox.anime_sources.utilities.Qualities import com.programmersbox.anime_sources.utilities.getQualityFromName import com.programmersbox.animeworld.cast.ExpandedControlsActivity import com.programmersbox.favoritesdatabase.DbModel +import com.programmersbox.gsonutils.toJson import com.programmersbox.helpfulutils.requestPermissions import com.programmersbox.helpfulutils.runOnUIThread import com.programmersbox.models.* @@ -66,6 +63,7 @@ import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.addTo import io.reactivex.rxkotlin.subscribeBy import io.reactivex.schedulers.Schedulers +import kotlinx.coroutines.launch import org.koin.dsl.module import java.util.concurrent.TimeUnit import kotlin.collections.set @@ -112,6 +110,7 @@ class GenericAnime(val context: Context) : GenericInfo { putExtra("showPath", it.link) putExtra("showName", model.name) putExtra("referer", it.headers["referer"]) + putExtra("chapterModel", it.toJson()) putExtra("downloadOrStream", false) } ) @@ -195,17 +194,17 @@ class GenericAnime(val context: Context) : GenericInfo { .create() model.getChapterInfo() + .doOnSubscribe { runOnUIThread { dialog.show() } } + .onErrorReturnItem(emptyList()) + .subscribeOn(Schedulers.io()) + .observeOn(AndroidSchedulers.mainThread()) + .timeout(15, TimeUnit.SECONDS) .doOnError { runOnUIThread { Toast.makeText(context, R.string.something_went_wrong, Toast.LENGTH_SHORT).show() dialog.dismiss() } } - .doOnSubscribe { runOnUIThread { dialog.show() } } - .onErrorReturnItem(emptyList()) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .timeout(15, TimeUnit.SECONDS) .map { it.filter(filter) } .subscribeBy { c -> dialog.dismiss() @@ -254,117 +253,6 @@ class GenericAnime(val context: Context) : GenericInfo { null } - override fun customPreferences(preferenceScreen: SettingsDsl) { - - preferenceScreen.viewSettings { s, it -> - it.addPreference( - Preference(it.context).apply { - title = context.getString(R.string.video_menu_title) - icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_video_library_24) - setOnPreferenceClickListener { - s.findNavController() - .navigate(ViewVideosFragment::class.java.hashCode(), null, SettingsDsl.customAnimationOptions) - true - } - } - ) - - val casting = Preference(it.context).apply { - title = context.getString(R.string.cast_menu_title) - icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_cast_24) - setOnPreferenceClickListener { - if (MainActivity.cast.isCastActive()) { - context.startActivity(Intent(context, ExpandedControlsActivity::class.java)) - } else { - MediaRouteDialogFactory.getDefault().onCreateChooserDialogFragment() - .also { it.routeSelector = CastContext.getSharedInstance(context).mergedSelector } - .show(MainActivity.activity.supportFragmentManager, "media_chooser") - } - true - } - } - - MainActivity.cast.sessionConnected() - .subscribe(casting::setVisible) - .addTo(disposable) - - MainActivity.cast.sessionStatus() - .map { if (it) R.drawable.ic_baseline_cast_connected_24 else R.drawable.ic_baseline_cast_24 } - .subscribe(casting::setIcon) - .addTo(disposable) - - it.addPreference(casting) - - it.addPreference( - Preference(it.context).apply { - title = context.getString(R.string.downloads_menu_title) - icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_download_24) - setOnPreferenceClickListener { - s.findNavController() - .navigate(DownloadViewerFragment::class.java.hashCode(), null, SettingsDsl.customAnimationOptions) - true - } - } - ) - } - - preferenceScreen.generalSettings { _, it -> - it.addPreference( - Preference(it.context).apply { - title = context.getString(R.string.folder_location) - summary = it.context.folderLocation - icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_folder_24) - setOnPreferenceClickListener { - MainActivity.activity.requestPermissions( - Manifest.permission.READ_EXTERNAL_STORAGE, - Manifest.permission.WRITE_EXTERNAL_STORAGE, - ) { - if (it.isGranted) { - ChooserDialog(context) - .withIcon(R.mipmap.ic_launcher) - .withResources(R.string.choose_a_directory, R.string.chooseText, R.string.cancelText) - .withFilter(true, false) - .withStartFile(context.folderLocation) - .enableOptions(true) - .withChosenListener { dir, _ -> - context.folderLocation = "$dir/" - println(dir) - summary = context.folderLocation - } - .build() - .show() - } - } - true - } - } - ) - } - - preferenceScreen.navigationSetup { - it.findNavController() - .graph - .addDestination( - FragmentNavigator(it.requireContext(), it.childFragmentManager, R.id.setting_nav).createDestination().apply { - id = DownloadViewerFragment::class.java.hashCode() - setClassName(DownloadViewerFragment::class.java.name) - addDeepLink(MainActivity.VIEW_DOWNLOADS) - } - ) - - it.findNavController() - .graph - .addDestination( - FragmentNavigator(it.requireContext(), it.childFragmentManager, R.id.setting_nav).createDestination().apply { - id = ViewVideosFragment::class.java.hashCode() - setClassName(ViewVideosFragment::class.java.name) - addDeepLink(MainActivity.VIEW_VIDEOS) - } - ) - } - - } - @OptIn(ExperimentalAnimationApi::class) @Composable override fun DetailActions(infoModel: InfoModel, tint: Color) { @@ -437,23 +325,16 @@ class GenericAnime(val context: Context) : GenericInfo { override fun ItemListView( list: List<ItemModel>, favorites: List<DbModel>, - listState: LazyListState, + listState: LazyGridState, onLongPress: (ItemModel, ComponentState) -> Unit, onClick: (ItemModel) -> Unit ) { - - //TODO: Add in setting to show grid or list for recent and all screens - - val animated by updateAnimatedItemsState(newList = list) - LazyColumn( + LazyVerticalGrid( + cells = GridCells.Fixed(1), state = listState, verticalArrangement = Arrangement.spacedBy(4.dp) ) { - animatedItems( - animated, - enterTransition = fadeIn(), - exitTransition = fadeOut() - ) { + items(list) { androidx.compose.material3.Surface( modifier = Modifier .fillMaxWidth() @@ -587,6 +468,20 @@ class GenericAnime(val context: Context) : GenericInfo { } + playerSettings { + val context = LocalContext.current + val scope = rememberCoroutineScope() + + val ignoreSsl by context.ignoreSsl.collectAsState(initial = true) + + SwitchSetting( + settingTitle = { androidx.compose.material3.Text(stringResource(id = R.string.ignore_ssl)) }, + settingIcon = { androidx.compose.material3.Icon(Icons.Default.Security, null, modifier = Modifier.fillMaxSize()) }, + value = ignoreSsl + ) { scope.launch { context.updatePref(IGNORE_SSL, it) } } + + } + } override fun settingNavSetup(fragment: Fragment, navController: NavController) { diff --git a/animeworld/src/main/java/com/programmersbox/animeworld/MainActivity.kt b/animeworld/src/main/java/com/programmersbox/animeworld/MainActivity.kt index d48922ddb..159168029 100644 --- a/animeworld/src/main/java/com/programmersbox/animeworld/MainActivity.kt +++ b/animeworld/src/main/java/com/programmersbox/animeworld/MainActivity.kt @@ -33,7 +33,7 @@ class MainActivity : BaseMainActivity() { } if (currentService == null) { - val s = Sources.values().random() + val s = Sources.values().filterNot(Sources::notWorking).random() sourcePublish.onNext(s) currentService = s.serviceName } diff --git a/animeworld/src/main/java/com/programmersbox/animeworld/VideoPlayerActivity.kt b/animeworld/src/main/java/com/programmersbox/animeworld/VideoPlayerActivity.kt index 31c3c3c00..3335fe6d0 100644 --- a/animeworld/src/main/java/com/programmersbox/animeworld/VideoPlayerActivity.kt +++ b/animeworld/src/main/java/com/programmersbox/animeworld/VideoPlayerActivity.kt @@ -19,6 +19,7 @@ import androidx.core.content.ContextCompat import androidx.core.net.toUri import com.github.rubensousa.previewseekbar.PreviewBar import com.google.android.exoplayer2.* +import com.google.android.exoplayer2.source.DefaultMediaSourceFactory import com.google.android.exoplayer2.source.MediaSource import com.google.android.exoplayer2.source.ProgressiveMediaSource import com.google.android.exoplayer2.source.dash.DashMediaSource @@ -32,12 +33,24 @@ import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial import com.mikepenz.iconics.utils.colorInt import com.mikepenz.iconics.utils.sizePx import com.programmersbox.animeworld.databinding.* +import com.programmersbox.gsonutils.fromJson import com.programmersbox.helpfulutils.* +import com.programmersbox.models.ChapterModel import com.programmersbox.rxutils.invoke +import com.programmersbox.uiviews.GenericInfo import com.programmersbox.uiviews.utils.BatteryInformation +import com.programmersbox.uiviews.utils.ChapterModelDeserializer import com.programmersbox.uiviews.utils.toolTipText import io.reactivex.disposables.CompositeDisposable +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.runBlocking +import org.koin.android.ext.android.inject +import java.security.cert.X509Certificate import java.util.* +import javax.net.ssl.HttpsURLConnection +import javax.net.ssl.SSLContext +import javax.net.ssl.SSLSession +import javax.net.ssl.X509TrustManager import kotlin.math.abs import kotlin.math.roundToInt @@ -133,6 +146,13 @@ class VideoPlayerActivity : AppCompatActivity() { private val retriever = MediaMetadataRetriever() private var showPath: String? = null + private val genericInfo: GenericInfo by inject() + + private val chapterModel: ChapterModel? by lazy { + intent.getStringExtra("chapterModel") + ?.fromJson(ChapterModel::class.java to ChapterModelDeserializer(genericInfo)) + } + private lateinit var videoBinding: ActivityVideoPlayerBinding private lateinit var exoBinding: ExoControlsBinding @@ -225,8 +245,17 @@ class VideoPlayerActivity : AppCompatActivity() { //stream //fun buildMediaSource(uri: Uri): MediaSource = //ProgressiveMediaSource.Factory(DefaultHttpDataSourceFactory("exoplayer-codelab")).createMediaSource(uri) - val headers = intent.getStringExtra("referer") - getMediaSource(showPath!!.toUri(), false, headers)!! + + if (runBlocking { ignoreSsl.first() }) { + val sslContext: SSLContext = SSLContext.getInstance("TLS") + sslContext.init(null, arrayOf(SSLTrustManager()), java.security.SecureRandom()) + sslContext.createSSLEngine() + HttpsURLConnection.setDefaultHostnameVerifier { _: String, _: SSLSession -> true } + HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.socketFactory) + } + + val headers = intent.getStringExtra("referer") ?: chapterModel?.url ?: "" + getMediaSource(showPath!!.toUri(), false, headers) } player.setMediaSource(source, true) player.prepare() @@ -521,34 +550,47 @@ class VideoPlayerActivity : AppCompatActivity() { private val bandwidthMeter by lazy { DefaultBandwidthMeter.Builder(this).build() } - private fun getMediaSource(url: Uri, preview: Boolean, header: String?): MediaSource? = + private fun getMediaSource(url: Uri, preview: Boolean, header: String): MediaSource = when (Util.inferContentType(url.lastPathSegment.toString())) { - C.TYPE_SS -> SsMediaSource.Factory( - DefaultDataSourceFactory( - this, null, - getHttpDataSourceFactory(preview, header) - ) - )//.createMediaSource(url) - C.TYPE_DASH -> DashMediaSource.Factory( - DefaultDataSourceFactory( - this, null, - getHttpDataSourceFactory(preview, header) - ) - )//.createMediaSource(url) - C.TYPE_HLS -> HlsMediaSource.Factory(getDataSourceFactory(preview, header))//.createMediaSource(uri) - C.TYPE_OTHER -> ProgressiveMediaSource.Factory(getDataSourceFactory(preview, header))//.createMediaSource(uri) - else -> null - }?.createMediaSource(MediaItem.fromUri(url)) - - private fun getDataSourceFactory(preview: Boolean, header: String?): DataSource.Factory = DefaultDataSourceFactory( + C.TYPE_SS -> SsMediaSource.Factory(getHttpDataSourceFactory(preview, header))//.createMediaSource(url) + C.TYPE_DASH -> DashMediaSource.Factory(getHttpDataSourceFactory(preview, header))//.createMediaSource(url) + C.TYPE_HLS -> HlsMediaSource.Factory(getHttpDataSourceFactory(preview, header))//.createMediaSource(uri) + C.TYPE_OTHER -> ProgressiveMediaSource.Factory(getHttpDataSourceFactory(preview, header))//.createMediaSource(uri) + else -> DefaultMediaSourceFactory(getHttpDataSourceFactory(preview, header)) + }.createMediaSource(MediaItem.fromUri(url)) + + private fun getDataSourceFactory(preview: Boolean, header: String): DataSource.Factory = DefaultDataSourceFactory( this, if (preview) null else bandwidthMeter, getHttpDataSourceFactory(preview, header) ) - private fun getHttpDataSourceFactory(preview: Boolean, header: String?): DataSource.Factory = DefaultHttpDataSource.Factory().apply { + private fun getHttpDataSourceFactory(preview: Boolean, header: String): DataSource.Factory = DefaultHttpDataSource.Factory().apply { setUserAgent(Util.getUserAgent(this@VideoPlayerActivity, "AnimeWorld")) setTransferListener(if (preview) null else bandwidthMeter) - header?.let { setDefaultRequestProperties(hashMapOf("Referer" to it)) } + //header?.let { setDefaultRequestProperties(hashMapOf("Referer" to it)) } + setDefaultRequestProperties( + mapOf( + "referer" to header, + "accept" to "*/*", + "sec-ch-ua" to "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"", + "sec-ch-ua-mobile" to "?0", + "sec-fetch-user" to "?1", + "sec-fetch-mode" to "navigate", + "sec-fetch-dest" to "video" + ) + ) + } + + class SSLTrustManager : X509TrustManager { + override fun checkClientTrusted(p0: Array<out X509Certificate>?, p1: String?) { + } + + override fun checkServerTrusted(p0: Array<out X509Certificate>?, p1: String?) { + } + + override fun getAcceptedIssuers(): Array<X509Certificate> { + return arrayOf() + } } } \ No newline at end of file diff --git a/animeworld/src/main/java/com/programmersbox/animeworld/ViewVideosFragment.kt b/animeworld/src/main/java/com/programmersbox/animeworld/ViewVideosFragment.kt index 8ee9f662a..167a1df23 100644 --- a/animeworld/src/main/java/com/programmersbox/animeworld/ViewVideosFragment.kt +++ b/animeworld/src/main/java/com/programmersbox/animeworld/ViewVideosFragment.kt @@ -437,10 +437,7 @@ class ViewVideosFragment : BaseBottomSheetDialogFragment() { }, modifier = Modifier .align(Alignment.Center) - .size( - with(LocalDensity.current) { 480.toDp() }, - with(LocalDensity.current) { 360.toDp() } - ), + .size(ComposableUtils.IMAGE_HEIGHT, ComposableUtils.IMAGE_WIDTH), failure = { Text(text = "image request failed.") } ) diff --git a/animeworld/src/main/res/drawable/dialog_bg.xml b/animeworld/src/main/res/drawable/dialog_bg.xml deleted file mode 100644 index 736841837..000000000 --- a/animeworld/src/main/res/drawable/dialog_bg.xml +++ /dev/null @@ -1,10 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<shape xmlns:android="http://schemas.android.com/apk/res/android"> - <solid android:color="@android:color/white" /> - <corners android:radius="10dp" /> - <padding - android:left="10dp" - android:top="10dp" - android:right="10dp" - android:bottom="10dp" /> -</shape> \ No newline at end of file diff --git a/animeworld/src/main/res/drawable/ic_baseline_article_24.xml b/animeworld/src/main/res/drawable/ic_baseline_article_24.xml deleted file mode 100644 index 26ca48583..000000000 --- a/animeworld/src/main/res/drawable/ic_baseline_article_24.xml +++ /dev/null @@ -1,11 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal" - android:autoMirrored="true"> - <path - android:fillColor="@android:color/white" - android:pathData="M19,3L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM14,17L7,17v-2h7v2zM17,13L7,13v-2h10v2zM17,9L7,9L7,7h10v2z" /> -</vector> diff --git a/animeworld/src/main/res/drawable/ic_baseline_cast_24.xml b/animeworld/src/main/res/drawable/ic_baseline_cast_24.xml deleted file mode 100644 index 958612973..000000000 --- a/animeworld/src/main/res/drawable/ic_baseline_cast_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2zM1,18v3h3c0,-1.66 -1.34,-3 -3,-3zM1,14v2c2.76,0 5,2.24 5,5h2c0,-3.87 -3.13,-7 -7,-7zM1,10v2c4.97,0 9,4.03 9,9h2c0,-6.08 -4.93,-11 -11,-11z" /> -</vector> diff --git a/animeworld/src/main/res/drawable/ic_baseline_cast_connected_24.xml b/animeworld/src/main/res/drawable/ic_baseline_cast_connected_24.xml deleted file mode 100644 index 9d6df9905..000000000 --- a/animeworld/src/main/res/drawable/ic_baseline_cast_connected_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M1,18v3h3c0,-1.66 -1.34,-3 -3,-3zM1,14v2c2.76,0 5,2.24 5,5h2c0,-3.87 -3.13,-7 -7,-7zM19,7L5,7v1.63c3.96,1.28 7.09,4.41 8.37,8.37L19,17L19,7zM1,10v2c4.97,0 9,4.03 9,9h2c0,-6.08 -4.93,-11 -11,-11zM21,3L3,3c-1.1,0 -2,0.9 -2,2v3h2L3,5h18v14h-7v2h7c1.1,0 2,-0.9 2,-2L23,5c0,-1.1 -0.9,-2 -2,-2z" /> -</vector> diff --git a/animeworld/src/main/res/drawable/ic_baseline_download_24.xml b/animeworld/src/main/res/drawable/ic_baseline_download_24.xml deleted file mode 100644 index 4230ba717..000000000 --- a/animeworld/src/main/res/drawable/ic_baseline_download_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M5,20h14v-2H5V20zM19,9h-4V3H9v6H5l7,7L19,9z" /> -</vector> diff --git a/animeworld/src/main/res/drawable/ic_baseline_folder_24.xml b/animeworld/src/main/res/drawable/ic_baseline_folder_24.xml deleted file mode 100644 index bbfe9c931..000000000 --- a/animeworld/src/main/res/drawable/ic_baseline_folder_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z" /> -</vector> diff --git a/animeworld/src/main/res/drawable/ic_baseline_more_vert_24.xml b/animeworld/src/main/res/drawable/ic_baseline_more_vert_24.xml deleted file mode 100644 index 56a9bd114..000000000 --- a/animeworld/src/main/res/drawable/ic_baseline_more_vert_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2 -2,0.9 -2,2 0.9,2 2,2zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2z" /> -</vector> diff --git a/animeworld/src/main/res/drawable/ic_baseline_refresh_24.xml b/animeworld/src/main/res/drawable/ic_baseline_refresh_24.xml deleted file mode 100644 index 566500b88..000000000 --- a/animeworld/src/main/res/drawable/ic_baseline_refresh_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M17.65,6.35C16.2,4.9 14.21,4 12,4c-4.42,0 -7.99,3.58 -7.99,8s3.57,8 7.99,8c3.73,0 6.84,-2.55 7.73,-6h-2.08c-0.82,2.33 -3.04,4 -5.65,4 -3.31,0 -6,-2.69 -6,-6s2.69,-6 6,-6c1.66,0 3.14,0.69 4.22,1.78L13,11h7V4l-2.35,2.35z" /> -</vector> diff --git a/animeworld/src/main/res/drawable/ic_baseline_video_library_24.xml b/animeworld/src/main/res/drawable/ic_baseline_video_library_24.xml deleted file mode 100644 index 823b24376..000000000 --- a/animeworld/src/main/res/drawable/ic_baseline_video_library_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M4,6L2,6v14c0,1.1 0.9,2 2,2h14v-2L4,20L4,6zM20,2L8,2c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM12,14.5v-9l6,4.5 -6,4.5z" /> -</vector> diff --git a/animeworld/src/main/res/drawable/rounded_corner.xml b/animeworld/src/main/res/drawable/rounded_corner.xml deleted file mode 100644 index d8ad6c1d8..000000000 --- a/animeworld/src/main/res/drawable/rounded_corner.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<inset xmlns:android="http://schemas.android.com/apk/res/android" - android:insetLeft="6dp" - android:insetTop="6dp" - android:insetRight="6dp" - android:insetBottom="6dp"> - <ripple android:color="?attr/colorControlHighlight"> - <item> - <shape - android:shape="rectangle" - android:tint="@color/niceBlue"> - <corners android:radius="10dp" /> - <solid android:color="#1a237e" /> - </shape> - </item> - </ripple> -</inset> \ No newline at end of file diff --git a/animeworld/src/main/res/values/strings.xml b/animeworld/src/main/res/values/strings.xml index 46fceb835..6e2c93914 100644 --- a/animeworld/src/main/res/values/strings.xml +++ b/animeworld/src/main/res/values/strings.xml @@ -98,4 +98,6 @@ <string name="castIntro">Cast!\nStream an episode straight to any Chromecast device!</string> <string name="loading_please_wait">Loading, Please Wait</string> + + <string name="ignore_ssl">Ignore SSL</string> </resources> \ No newline at end of file diff --git a/animeworldtv/src/main/java/com/programmersbox/animeworldtv/DetailsActivity.kt b/animeworldtv/src/main/java/com/programmersbox/animeworldtv/DetailsActivity.kt index 650de08d5..f1d7e68bf 100644 --- a/animeworldtv/src/main/java/com/programmersbox/animeworldtv/DetailsActivity.kt +++ b/animeworldtv/src/main/java/com/programmersbox/animeworldtv/DetailsActivity.kt @@ -14,7 +14,7 @@ class DetailsActivity : FragmentActivity() { if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .replace(R.id.details_fragment, VideoDetailsFragment()) - .commitNow(); + .commitNow() } } diff --git a/animeworldtv/src/main/java/com/programmersbox/animeworldtv/MainActivity.kt b/animeworldtv/src/main/java/com/programmersbox/animeworldtv/MainActivity.kt index 9f5946df6..8e64bdaa3 100644 --- a/animeworldtv/src/main/java/com/programmersbox/animeworldtv/MainActivity.kt +++ b/animeworldtv/src/main/java/com/programmersbox/animeworldtv/MainActivity.kt @@ -23,7 +23,7 @@ class MainActivity : FragmentActivity() { setContentView(R.layout.activity_main) if (currentService == null) { - val s = Sources.values().random() + val s = Sources.values().filterNot(Sources::notWorking).random() sourcePublish.onNext(s) currentService = s.serviceName } else if (currentService != null) { diff --git a/animeworldtv/src/main/java/com/programmersbox/animeworldtv/SettingsActivity.kt b/animeworldtv/src/main/java/com/programmersbox/animeworldtv/SettingsActivity.kt index 2fed1e460..096a58921 100644 --- a/animeworldtv/src/main/java/com/programmersbox/animeworldtv/SettingsActivity.kt +++ b/animeworldtv/src/main/java/com/programmersbox/animeworldtv/SettingsActivity.kt @@ -111,7 +111,7 @@ class SettingsFragment : LeanbackSettingsFragmentCompat(), DialogPreference.Targ .subscribe { val appVersion = context?.packageManager?.getPackageInfo(requireContext().packageName, 0)?.versionName.orEmpty() p.summary = if (AppUpdate.checkForUpdate(appVersion, it.update_real_version.orEmpty())) - getString(R.string.updateVersionAvailable, it.update_real_version?.toString().orEmpty()) + getString(R.string.updateVersionAvailable, it.update_real_version.orEmpty()) else "" } .addTo(disposable) @@ -144,7 +144,7 @@ class SettingsFragment : LeanbackSettingsFragmentCompat(), DialogPreference.Targ findPreference<Preference>("current_source")?.let { p -> p.setOnPreferenceClickListener { - val list = Sources.values() + val list = Sources.values().filterNot(Sources::notWorking) val service = requireContext().currentService MaterialAlertDialogBuilder(requireContext(), R.style.Theme_MaterialComponents) .setTitle(R.string.chooseASource) diff --git a/build.gradle b/build.gradle index 8d8a9a880..64420e1a3 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,6 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = "1.6.0" + ext.kotlin_version = "1.6.10" ext.latestAboutLibsRelease = "8.9.4" ext.coroutinesVersion = "1.6.0" @@ -21,13 +21,13 @@ buildscript { ext.rxbindingKotlin = 'com.jakewharton.rxbinding2:rxbinding-kotlin:2.2.0' ext.androidCore = 'androidx.core:core-ktx:1.7.0' - ext.appCompat = 'androidx.appcompat:appcompat:1.4.0' + ext.appCompat = 'androidx.appcompat:appcompat:1.4.1' ext.material = 'com.google.android.material:material:1.6.0-alpha01' ext.preference = "androidx.preference:preference-ktx:1.1.1" ext.recyclerview = 'androidx.recyclerview:recyclerview:1.2.1' - ext.constraintlayout = 'androidx.constraintlayout:constraintlayout:2.1.2' + ext.constraintlayout = 'androidx.constraintlayout:constraintlayout:2.1.3' ext.swiperefresh = 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' ext.jsoup = 'org.jsoup:jsoup:1.14.3' @@ -37,7 +37,7 @@ buildscript { ext.play_services = 'com.google.android.gms:play-services-auth:20.0.1' ext.exoplayer_version = "2.16.1" - ext.room_version = "2.4.0" + ext.room_version = "2.4.1" ext.nav_version = "2.4.0-rc01" @@ -50,7 +50,7 @@ buildscript { ext.lottieVersion = "4.2.2" - ext.jetpack = "1.1.0-rc01" + ext.jetpack = "1.2.0-alpha01" ext.accompanist = "0.20.3" @@ -61,7 +61,7 @@ buildscript { ext.composeFoundation = "androidx.compose.foundation:foundation:$jetpack" // Material Design ext.composeMaterial = "androidx.compose.material:material:$jetpack" - ext.materialYou = "androidx.compose.material3:material3:1.0.0-alpha02" + ext.materialYou = "androidx.compose.material3:material3:1.0.0-alpha03" // Material design icons ext.composeMaterialIconsCore = "androidx.compose.material:material-icons-core:$jetpack" ext.composeMaterialIconsExtended = "androidx.compose.material:material-icons-extended:$jetpack" @@ -72,10 +72,10 @@ buildscript { // Integration with observables ext.composeRuntimeLivedata = "androidx.compose.runtime:runtime-livedata:$jetpack" ext.composeRuntimeRxjava2 = "androidx.compose.runtime:runtime-rxjava2:$jetpack" - ext.composeMaterialThemeAdapter = "com.google.android.material:compose-theme-adapter:1.1.2" - ext.composeMaterial3ThemeAdapter = "com.google.android.material:compose-theme-adapter-3:1.0.2" + ext.composeMaterialThemeAdapter = "com.google.android.material:compose-theme-adapter:1.1.3" + ext.composeMaterial3ThemeAdapter = "com.google.android.material:compose-theme-adapter-3:1.0.3" ext.landscapistGlide = "com.github.skydoves:landscapist-glide:1.4.5" - ext.composeConstraintLayout = "androidx.constraintlayout:constraintlayout-compose:1.0.0-rc02" + ext.composeConstraintLayout = "androidx.constraintlayout:constraintlayout-compose:1.0.0" ext.composeAnimation = "androidx.compose.animation:animation:$jetpack" ext.materialPlaceholder = "com.google.accompanist:accompanist-placeholder-material:$accompanist" ext.drawablePainter = "com.google.accompanist:accompanist-drawablepainter:$accompanist" @@ -83,6 +83,10 @@ buildscript { ext.uiUtil = "androidx.compose.ui:ui-util:$jetpack" ext.coilCompose = "io.coil-kt:coil-compose:1.4.0" + ext.inset = "com.google.accompanist:accompanist-insets:$accompanist" + // If using insets-ui + ext.insetUi = "com.google.accompanist:accompanist-insets-ui:$accompanist" + ext.datastore = "androidx.datastore:datastore:1.0.0" ext.datastorePref = "androidx.datastore:datastore-preferences:1.0.0" @@ -117,7 +121,8 @@ buildscript { landscapistGlide, coilCompose, composeConstraintLayout, permissions, materialPlaceholder, drawablePainter, uiUtil, - materialYou + materialYou, + inset, insetUi ] ] diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 713c1a02c..206347043 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -1,5 +1,5 @@ object Deps { - const val otakuVersionName = "29.2.5" + const val otakuVersionName = "29.2.6" const val compileVersion = 31 const val minimumSdk = 23 const val targetSdk = 31 diff --git a/mangaworld/src/main/AndroidManifest.xml b/mangaworld/src/main/AndroidManifest.xml index 0dcddcd3b..d9307d950 100644 --- a/mangaworld/src/main/AndroidManifest.xml +++ b/mangaworld/src/main/AndroidManifest.xml @@ -29,7 +29,6 @@ </provider> <activity android:name=".ReadActivity" /> - <activity android:name=".ReadActivityCompose" /> <activity android:exported="true" android:name=".MainActivity"> diff --git a/mangaworld/src/main/java/com/programmersbox/mangaworld/ContextUtils.kt b/mangaworld/src/main/java/com/programmersbox/mangaworld/ContextUtils.kt index 96f059a0d..51567f55e 100644 --- a/mangaworld/src/main/java/com/programmersbox/mangaworld/ContextUtils.kt +++ b/mangaworld/src/main/java/com/programmersbox/mangaworld/ContextUtils.kt @@ -243,7 +243,7 @@ fun BottomNavigationView.show() { drawable.setBounds(left, parent.height, right, parent.height + height) parent.overlay.add(drawable) ValueAnimator.ofInt(parent.height, top).apply { - startDelay = 100L + //startDelay = 100L duration = 300L interpolator = AnimationUtils.loadInterpolator( context, @@ -279,7 +279,7 @@ fun BottomNavigationView.hide() { parent.overlay.add(drawable) visibility = View.GONE ValueAnimator.ofInt(top, parent.height).apply { - startDelay = 100L + startDelay = 200L duration = 200L interpolator = AnimationUtils.loadInterpolator( context, diff --git a/mangaworld/src/main/java/com/programmersbox/mangaworld/GenericManga.kt b/mangaworld/src/main/java/com/programmersbox/mangaworld/GenericManga.kt index 9c83c7c56..905aec2c2 100644 --- a/mangaworld/src/main/java/com/programmersbox/mangaworld/GenericManga.kt +++ b/mangaworld/src/main/java/com/programmersbox/mangaworld/GenericManga.kt @@ -13,7 +13,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.GridCells -import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.LazyGridState import androidx.compose.foundation.lazy.LazyVerticalGrid import androidx.compose.foundation.lazy.items import androidx.compose.material.ExperimentalMaterialApi @@ -31,22 +31,14 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastAny import androidx.compose.ui.util.fastForEach -import androidx.core.content.ContextCompat import androidx.core.net.toUri import androidx.fragment.app.Fragment -import androidx.lifecycle.flowWithLifecycle -import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController import androidx.navigation.fragment.FragmentNavigator -import androidx.navigation.fragment.findNavController -import androidx.preference.Preference -import androidx.preference.SeekBarPreference -import androidx.preference.SwitchPreferenceCompat import com.programmersbox.favoritesdatabase.DbModel import com.programmersbox.gsonutils.toJson import com.programmersbox.helpfulutils.downloadManager import com.programmersbox.helpfulutils.requestPermissions -import com.programmersbox.helpfulutils.runOnUIThread import com.programmersbox.manga_sources.Sources import com.programmersbox.manga_sources.utilities.NetworkHelper import com.programmersbox.models.* @@ -60,7 +52,6 @@ import io.reactivex.disposables.CompositeDisposable import io.reactivex.rxkotlin.addTo import io.reactivex.rxkotlin.subscribeBy import io.reactivex.schedulers.Schedulers -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking @@ -150,89 +141,6 @@ class GenericManga(val context: Context) : GenericInfo { } } - override fun customPreferences(preferenceScreen: SettingsDsl) { - preferenceScreen.generalSettings { _, it -> - it.addPreference( - SwitchPreferenceCompat(it.context).apply { - title = it.context.getString(R.string.showAdultSources) - isChecked = context.showAdult - setOnPreferenceChangeListener { _, newValue -> - context.showAdult = newValue as Boolean - if (!newValue && (sourcePublish.value as? Sources)?.isAdult == true) { - sourcePublish.onNext(Sources.values().random()) - } - true - } - icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_text_format_24) - } - ) - } - - preferenceScreen.viewSettings { s, it -> - it.addPreference( - Preference(it.context).apply { - title = it.context.getString(R.string.downloaded_manga) - setOnPreferenceClickListener { - s.findNavController() - .navigate(DownloadViewerFragment::class.java.hashCode(), null, SettingsDsl.customAnimationOptions) - true - } - icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_library_books_24) - } - ) - } - - preferenceScreen.playSettings { fragment, it -> - it.addPreference( - SeekBarPreference(it.context).apply { - title = it.context.getString(R.string.reader_padding_between_pages) - summary = it.context.getString(R.string.default_padding_summary) - setOnPreferenceChangeListener { _, newValue -> - if (newValue is Int) { - fragment.lifecycleScope.launch(Dispatchers.IO) { it.context.updatePref(PAGE_PADDING, newValue) } - } - true - } - setDefaultValue(4) - showSeekBarValue = true - icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_format_line_spacing_24) - min = 0 - max = 10 - fragment.lifecycleScope.launch { - it.context.pagePadding - .flowWithLifecycle(fragment.lifecycle) - .collect { runOnUIThread { value = it } } - } - } - ) - - it.addPreference( - SwitchPreferenceCompat(it.context).apply { - title = it.context.getString(R.string.useNewReader) - summary = it.context.getString(R.string.reader_summary_setting) - isChecked = context.useNewReader - setOnPreferenceChangeListener { _, newValue -> - context.useNewReader = newValue as Boolean - true - } - icon = ContextCompat.getDrawable(it.context, R.drawable.ic_baseline_chrome_reader_mode_24) - } - ) - - } - - preferenceScreen.navigationSetup { - it.findNavController() - .graph - .addDestination( - FragmentNavigator(it.requireContext(), it.childFragmentManager, R.id.setting_nav).createDestination().apply { - id = DownloadViewerFragment::class.java.hashCode() - setClassName(DownloadViewerFragment::class.java.name) - } - ) - } - } - override fun sourceList(): List<ApiService> = if (runBlocking { context.showAdultFlow.first() }) Sources.values().toList() else Sources.values().filterNot(Sources::isAdult).toList() @@ -264,7 +172,7 @@ class GenericManga(val context: Context) : GenericInfo { override fun ItemListView( list: List<ItemModel>, favorites: List<DbModel>, - listState: LazyListState, + listState: LazyGridState, onLongPress: (ItemModel, ComponentState) -> Unit, onClick: (ItemModel) -> Unit ) { @@ -363,11 +271,11 @@ class GenericManga(val context: Context) : GenericInfo { } - override fun recentNavSetup(fragment: Fragment, navController: NavController) { + private fun readerNavSetup(fragment: Fragment, navController: NavController, navId: Int) { navController .graph .addDestination( - FragmentNavigator(fragment.requireContext(), fragment.childFragmentManager, R.id.recent_nav).createDestination().apply { + FragmentNavigator(fragment.requireContext(), fragment.childFragmentManager, navId).createDestination().apply { id = ReadActivityComposeFragment::class.java.hashCode() setClassName(ReadActivityComposeFragment::class.java.name) } @@ -378,30 +286,16 @@ class GenericManga(val context: Context) : GenericInfo { } } - override fun allNavSetup(fragment: Fragment, navController: NavController) { - navController - .graph - .addDestination( - FragmentNavigator(fragment.requireContext(), fragment.childFragmentManager, R.id.all_nav).createDestination().apply { - id = ReadActivityComposeFragment::class.java.hashCode() - setClassName(ReadActivityComposeFragment::class.java.name) - } - ) + override fun recentNavSetup(fragment: Fragment, navController: NavController) { + readerNavSetup(fragment, navController, R.id.recent_nav) + } - navController.addOnDestinationChangedListener { _, destination, _ -> - showOrHideNav.onNext(destination.id != ReadActivityComposeFragment::class.java.hashCode()) - } + override fun allNavSetup(fragment: Fragment, navController: NavController) { + readerNavSetup(fragment, navController, R.id.all_nav) } override fun settingNavSetup(fragment: Fragment, navController: NavController) { - navController - .graph - .addDestination( - FragmentNavigator(fragment.requireContext(), fragment.childFragmentManager, R.id.setting_nav).createDestination().apply { - id = ReadActivityComposeFragment::class.java.hashCode() - setClassName(ReadActivityComposeFragment::class.java.name) - } - ) + readerNavSetup(fragment, navController, R.id.setting_nav) navController .graph @@ -411,10 +305,6 @@ class GenericManga(val context: Context) : GenericInfo { setClassName(DownloadViewerFragment::class.java.name) } ) - - navController.addOnDestinationChangedListener { _, destination, _ -> - showOrHideNav.onNext(destination.id != ReadActivityComposeFragment::class.java.hashCode()) - } } } \ No newline at end of file diff --git a/mangaworld/src/main/java/com/programmersbox/mangaworld/ReadActivity.kt b/mangaworld/src/main/java/com/programmersbox/mangaworld/ReadActivity.kt index 529bcddba..800d84d75 100644 --- a/mangaworld/src/main/java/com/programmersbox/mangaworld/ReadActivity.kt +++ b/mangaworld/src/main/java/com/programmersbox/mangaworld/ReadActivity.kt @@ -593,10 +593,12 @@ class ReadActivityComposeFragment : BaseBottomSheetDialogFragment() { val delta = available.y val newTopOffset = topBarOffsetHeightPx.value + delta - topBarOffsetHeightPx.value = newTopOffset.coerceIn(-topBarHeightPx, 0f) + if (topBarOffsetHeightPx.value != newTopOffset) + topBarOffsetHeightPx.value = newTopOffset.coerceIn(-topBarHeightPx, 0f) val newOffset = toolbarOffsetHeightPx.value + delta - toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f) + if (toolbarOffsetHeightPx.value != newOffset) + toolbarOffsetHeightPx.value = newOffset.coerceIn(-toolbarHeightPx, 0f) return scrollBehavior.nestedScrollConnection.onPreScroll(available, source)//Offset.Zero } diff --git a/mangaworld/src/main/res/drawable/ic_baseline_chrome_reader_mode_24.xml b/mangaworld/src/main/res/drawable/ic_baseline_chrome_reader_mode_24.xml deleted file mode 100644 index 581eeaa39..000000000 --- a/mangaworld/src/main/res/drawable/ic_baseline_chrome_reader_mode_24.xml +++ /dev/null @@ -1,11 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal" - android:autoMirrored="true"> - <path - android:fillColor="@android:color/white" - android:pathData="M13,12h7v1.5h-7zM13,9.5h7L20,11h-7zM13,14.5h7L20,16h-7zM21,4L3,4c-1.1,0 -2,0.9 -2,2v13c0,1.1 0.9,2 2,2h18c1.1,0 2,-0.9 2,-2L23,6c0,-1.1 -0.9,-2 -2,-2zM21,19h-9L12,6h9v13z" /> -</vector> diff --git a/mangaworld/src/main/res/drawable/ic_baseline_text_format_24.xml b/mangaworld/src/main/res/drawable/ic_baseline_text_format_24.xml deleted file mode 100644 index 903d73b5b..000000000 --- a/mangaworld/src/main/res/drawable/ic_baseline_text_format_24.xml +++ /dev/null @@ -1,10 +0,0 @@ -<vector xmlns:android="http://schemas.android.com/apk/res/android" - android:width="24dp" - android:height="24dp" - android:viewportWidth="24" - android:viewportHeight="24" - android:tint="?attr/colorControlNormal"> - <path - android:fillColor="@android:color/white" - android:pathData="M5,17v2h14v-2L5,17zM9.5,12.8h5l0.9,2.2h2.1L12.75,4h-1.5L6.5,15h2.1l0.9,-2.2zM12,5.98L13.87,11h-3.74L12,5.98z" /> -</vector> diff --git a/novelworld/src/main/java/com/programmersbox/novelworld/GenericNovel.kt b/novelworld/src/main/java/com/programmersbox/novelworld/GenericNovel.kt index c42313602..7b82879b3 100644 --- a/novelworld/src/main/java/com/programmersbox/novelworld/GenericNovel.kt +++ b/novelworld/src/main/java/com/programmersbox/novelworld/GenericNovel.kt @@ -3,14 +3,11 @@ package com.programmersbox.novelworld import android.content.Context import android.content.Intent import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.animation.fadeIn -import androidx.compose.animation.fadeOut import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.lazy.* import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.ListItem import androidx.compose.material.MaterialTheme @@ -19,7 +16,6 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.FavoriteBorder import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.unit.dp @@ -130,20 +126,16 @@ class GenericNovel(val context: Context) : GenericInfo { override fun ItemListView( list: List<ItemModel>, favorites: List<DbModel>, - listState: LazyListState, + listState: LazyGridState, onLongPress: (ItemModel, ComponentState) -> Unit, onClick: (ItemModel) -> Unit ) { - val animated by updateAnimatedItemsState(newList = list) - LazyColumn( + LazyVerticalGrid( + cells = GridCells.Fixed(1), state = listState, verticalArrangement = Arrangement.spacedBy(4.dp) ) { - animatedItems( - animated, - enterTransition = fadeIn(), - exitTransition = fadeOut() - ) { + items(list) { androidx.compose.material3.Surface( modifier = Modifier .fillMaxWidth() diff --git a/otakumanager/src/main/java/com/programmersbox/otakumanager/MainActivity.kt b/otakumanager/src/main/java/com/programmersbox/otakumanager/MainActivity.kt index 116583c7e..563209a34 100644 --- a/otakumanager/src/main/java/com/programmersbox/otakumanager/MainActivity.kt +++ b/otakumanager/src/main/java/com/programmersbox/otakumanager/MainActivity.kt @@ -303,7 +303,7 @@ class MainActivity : ComponentActivity() { LazyVerticalGrid( cells = GridCells.Adaptive(ComposableUtils.IMAGE_WIDTH), contentPadding = it, - state = rememberLazyListState() + //state = rememberLazyListState() ) { items( showing diff --git a/otakumanager/src/main/java/com/programmersbox/otakumanager/OtakuManagerApp.kt b/otakumanager/src/main/java/com/programmersbox/otakumanager/OtakuManagerApp.kt index 694b166ba..11c898b0e 100644 --- a/otakumanager/src/main/java/com/programmersbox/otakumanager/OtakuManagerApp.kt +++ b/otakumanager/src/main/java/com/programmersbox/otakumanager/OtakuManagerApp.kt @@ -1,7 +1,8 @@ package com.programmersbox.otakumanager import android.content.Context -import androidx.compose.foundation.lazy.LazyListState +import androidx.compose.foundation.ExperimentalFoundationApi +import androidx.compose.foundation.lazy.LazyGridState import androidx.compose.runtime.Composable import androidx.navigation.NavController import com.programmersbox.favoritesdatabase.DbModel @@ -38,6 +39,8 @@ class OtakuManagerApp : OtakuApp() { } } + +@OptIn(ExperimentalFoundationApi::class) val appModule = module { single { NetworkHelper(get()) } single { MainLogo(R.mipmap.ic_launcher) } @@ -82,7 +85,7 @@ val appModule = module { override fun ItemListView( list: List<ItemModel>, favorites: List<DbModel>, - listState: LazyListState, + listState: LazyGridState, onLongPress: (ItemModel, ComponentState) -> Unit, onClick: (ItemModel) -> Unit ) { diff --git a/otakumanager/src/main/java/com/programmersbox/otakumanager/OtakuSettings.kt b/otakumanager/src/main/java/com/programmersbox/otakumanager/OtakuSettings.kt index 20a2eaf3e..27a3de07c 100644 --- a/otakumanager/src/main/java/com/programmersbox/otakumanager/OtakuSettings.kt +++ b/otakumanager/src/main/java/com/programmersbox/otakumanager/OtakuSettings.kt @@ -11,7 +11,6 @@ import android.webkit.URLUtil import android.widget.Toast import androidx.activity.ComponentActivity import androidx.appcompat.app.AlertDialog -import androidx.appcompat.app.AppCompatDelegate import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.Image @@ -25,6 +24,8 @@ import androidx.compose.material.Icon import androidx.compose.material.Text import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ChevronRight +import androidx.compose.material.icons.filled.SettingsBrightness +import androidx.compose.material.icons.filled.Update import androidx.compose.runtime.* import androidx.compose.runtime.rxjava2.subscribeAsState import androidx.compose.runtime.saveable.rememberSaveable @@ -38,7 +39,6 @@ import androidx.compose.ui.unit.dp import androidx.core.content.FileProvider import androidx.datastore.core.DataStore import androidx.datastore.preferences.core.Preferences -import androidx.datastore.preferences.core.edit import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore import com.alorma.settings.composables.SettingsGroup @@ -191,7 +191,7 @@ fun OtakuSettings(activity: ComponentActivity, genericInfo: GenericInfo) { } SettingsMenuLink( - icon = { Image(painter = painterResource(id = R.drawable.ic_baseline_system_update_alt_24), contentDescription = null) }, + icon = { Icon(Icons.Default.Update, contentDescription = null) }, title = { Text(text = stringResource(id = R.string.update_available), modifier = Modifier.padding(start = 5.dp)) }, subtitle = { Text( @@ -292,11 +292,11 @@ fun OtakuSettings(activity: ComponentActivity, genericInfo: GenericInfo) { val themeList = arrayOf("System", "Light", "Dark") SettingsMenuLink( - icon = { Image(painter = painterResource(id = R.drawable.ic_baseline_settings_brightness_24), contentDescription = null) }, + icon = { Icon(Icons.Default.SettingsBrightness, contentDescription = null) }, title = { Text(text = stringResource(id = R.string.theme_choice_title), modifier = Modifier.padding(start = 5.dp)) }, subtitle = { Text(text = theme, modifier = Modifier.padding(start = 5.dp)) }, onClick = { - MaterialAlertDialogBuilder(activity) + /*MaterialAlertDialogBuilder(activity) .setTitle(R.string.choose_a_theme) .setIcon(R.drawable.ic_baseline_settings_brightness_24) .setSingleChoiceItems(themeList, themeList.indexOf(theme)) { d, i -> @@ -310,7 +310,7 @@ fun OtakuSettings(activity: ComponentActivity, genericInfo: GenericInfo) { d.dismiss() } .setNegativeButton(R.string.cancel) { d, _ -> d.dismiss() } - .show() + .show()*/ } )