mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-17 19:35:36 -04:00
Fixed: Clicking on "Plus button" in tab switcher crashes the application.
* Refactored the "FullScreen Video" functionality according to compose UI. * Refactored the functionality where custom app is configured to show search placeholder in toolbar, and created the search placeholder in compose. * Refactored the functionality where custom app is configured to show app icon in place of humbuger icon.
This commit is contained in:
parent
234e9169f6
commit
2608694442
@ -85,7 +85,7 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
toolbar?.let { activity.setupDrawerToggle(it, true) }
|
activity.setupDrawerToggle(true)
|
||||||
openPageInBookFromNavigationArguments()
|
openPageInBookFromNavigationArguments()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,7 +180,7 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
|||||||
* @see closeAllTabs
|
* @see closeAllTabs
|
||||||
*/
|
*/
|
||||||
override fun hideTabSwitcher(shouldCloseZimBook: Boolean) {
|
override fun hideTabSwitcher(shouldCloseZimBook: Boolean) {
|
||||||
toolbar?.let { activity?.setupDrawerToggle(it, true) }
|
activity?.setupDrawerToggle(true)
|
||||||
setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||||
if (webViewList.isEmpty()) {
|
if (webViewList.isEmpty()) {
|
||||||
readerMenuState?.hideTabSwitcher()
|
readerMenuState?.hideTabSwitcher()
|
||||||
@ -302,14 +302,12 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
|||||||
|
|
||||||
@Throws(IllegalArgumentException::class)
|
@Throws(IllegalArgumentException::class)
|
||||||
override fun createWebView(attrs: AttributeSet?): ToolbarScrollingKiwixWebView? {
|
override fun createWebView(attrs: AttributeSet?): ToolbarScrollingKiwixWebView? {
|
||||||
// requireNotNull(activityMainRoot)
|
|
||||||
return ToolbarScrollingKiwixWebView(
|
return ToolbarScrollingKiwixWebView(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
this,
|
this,
|
||||||
attrs ?: throw IllegalArgumentException("AttributeSet must not be null"),
|
attrs ?: throw IllegalArgumentException("AttributeSet must not be null"),
|
||||||
null,
|
null,
|
||||||
// requireNotNull(videoView),
|
requireNotNull(readerScreenState.value.fullScreenItem.second),
|
||||||
null,
|
|
||||||
CoreWebViewClient(this, requireNotNull(zimReaderContainer)),
|
CoreWebViewClient(this, requireNotNull(zimReaderContainer)),
|
||||||
// requireNotNull(toolbarContainer),
|
// requireNotNull(toolbarContainer),
|
||||||
// requireNotNull(bottomToolbar),
|
// requireNotNull(bottomToolbar),
|
||||||
|
@ -33,7 +33,6 @@ import android.view.MenuItem
|
|||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.view.ActionMode
|
import androidx.appcompat.view.ActionMode
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.FragmentActivity
|
import androidx.fragment.app.FragmentActivity
|
||||||
@ -101,8 +100,8 @@ object ActivityExtensions {
|
|||||||
val Activity.cachedComponent: CoreActivityComponent
|
val Activity.cachedComponent: CoreActivityComponent
|
||||||
get() = coreMainActivity.cachedComponent
|
get() = coreMainActivity.cachedComponent
|
||||||
|
|
||||||
fun Activity.setupDrawerToggle(toolbar: Toolbar, shouldEnableRightDrawer: Boolean = false) =
|
fun Activity.setupDrawerToggle(shouldEnableRightDrawer: Boolean = false) =
|
||||||
coreMainActivity.setupDrawerToggle(toolbar, shouldEnableRightDrawer)
|
coreMainActivity.setupDrawerToggle(shouldEnableRightDrawer)
|
||||||
|
|
||||||
fun Activity.navigate(fragmentId: Int) {
|
fun Activity.navigate(fragmentId: Int) {
|
||||||
coreMainActivity.navigate(fragmentId)
|
coreMainActivity.navigate(fragmentId)
|
||||||
|
@ -27,7 +27,6 @@ import android.view.MenuItem
|
|||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.appcompat.app.ActionBarDrawerToggle
|
import androidx.appcompat.app.ActionBarDrawerToggle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.os.bundleOf
|
import androidx.core.os.bundleOf
|
||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
@ -59,9 +58,7 @@ import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadMonitorServ
|
|||||||
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadMonitorService.Companion.STOP_DOWNLOAD_SERVICE
|
import org.kiwix.kiwixmobile.core.downloader.downloadManager.DownloadMonitorService.Companion.STOP_DOWNLOAD_SERVICE
|
||||||
import org.kiwix.kiwixmobile.core.error.ErrorActivity
|
import org.kiwix.kiwixmobile.core.error.ErrorActivity
|
||||||
import org.kiwix.kiwixmobile.core.extensions.browserIntent
|
import org.kiwix.kiwixmobile.core.extensions.browserIntent
|
||||||
import org.kiwix.kiwixmobile.core.extensions.getToolbarNavigationIcon
|
|
||||||
import org.kiwix.kiwixmobile.core.extensions.isServiceRunning
|
import org.kiwix.kiwixmobile.core.extensions.isServiceRunning
|
||||||
import org.kiwix.kiwixmobile.core.extensions.setToolTipWithContentDescription
|
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||||
import org.kiwix.kiwixmobile.core.search.NAV_ARG_SEARCH_STRING
|
import org.kiwix.kiwixmobile.core.search.NAV_ARG_SEARCH_STRING
|
||||||
@ -271,15 +268,16 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
|
|||||||
override fun onSupportNavigateUp(): Boolean =
|
override fun onSupportNavigateUp(): Boolean =
|
||||||
navController.navigateUp() || super.onSupportNavigateUp()
|
navController.navigateUp() || super.onSupportNavigateUp()
|
||||||
|
|
||||||
open fun setupDrawerToggle(toolbar: Toolbar, shouldEnableRightDrawer: Boolean = false) {
|
open fun setupDrawerToggle(shouldEnableRightDrawer: Boolean = false) {
|
||||||
// Set the initial contentDescription to the hamburger icon.
|
// Set the initial contentDescription to the hamburger icon.
|
||||||
// This method is called from various locations after modifying the navigationIcon.
|
// This method is called from various locations after modifying the navigationIcon.
|
||||||
// For example, we previously changed this icon/contentDescription to the "+" button
|
// For example, we previously changed this icon/contentDescription to the "+" button
|
||||||
// when opening the tabSwitcher. After closing the tabSwitcher, we reset the
|
// when opening the tabSwitcher. After closing the tabSwitcher, we reset the
|
||||||
// contentDescription to the default hamburger icon.
|
// contentDescription to the default hamburger icon.
|
||||||
toolbar.getToolbarNavigationIcon()?.setToolTipWithContentDescription(
|
// Todo we will refactore this when migrating the CoreMainActivity.
|
||||||
getString(R.string.open_drawer)
|
// toolbar.getToolbarNavigationIcon()?.setToolTipWithContentDescription(
|
||||||
)
|
// getString(R.string.open_drawer)
|
||||||
|
// )
|
||||||
drawerToggle =
|
drawerToggle =
|
||||||
ActionBarDrawerToggle(
|
ActionBarDrawerToggle(
|
||||||
this,
|
this,
|
||||||
|
@ -75,7 +75,6 @@ import androidx.compose.runtime.mutableStateOf
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.runtime.snapshotFlow
|
import androidx.compose.runtime.snapshotFlow
|
||||||
import androidx.compose.ui.platform.ComposeView
|
import androidx.compose.ui.platform.ComposeView
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
@ -174,6 +173,7 @@ import org.kiwix.kiwixmobile.core.search.viewmodel.effects.SearchItemToOpen
|
|||||||
import org.kiwix.kiwixmobile.core.ui.components.NavigationIcon
|
import org.kiwix.kiwixmobile.core.ui.components.NavigationIcon
|
||||||
import org.kiwix.kiwixmobile.core.ui.components.rememberBottomNavigationVisibility
|
import org.kiwix.kiwixmobile.core.ui.components.rememberBottomNavigationVisibility
|
||||||
import org.kiwix.kiwixmobile.core.ui.models.IconItem
|
import org.kiwix.kiwixmobile.core.ui.models.IconItem
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.theme.White
|
||||||
import org.kiwix.kiwixmobile.core.utils.DimenUtils.getWindowWidth
|
import org.kiwix.kiwixmobile.core.utils.DimenUtils.getWindowWidth
|
||||||
import org.kiwix.kiwixmobile.core.utils.DonationDialogHandler
|
import org.kiwix.kiwixmobile.core.utils.DonationDialogHandler
|
||||||
import org.kiwix.kiwixmobile.core.utils.DonationDialogHandler.ShowDonationDialogCallback
|
import org.kiwix.kiwixmobile.core.utils.DonationDialogHandler.ShowDonationDialogCallback
|
||||||
@ -233,8 +233,6 @@ abstract class CoreReaderFragment :
|
|||||||
|
|
||||||
var tabSwitcherRoot: View? = null
|
var tabSwitcherRoot: View? = null
|
||||||
|
|
||||||
var videoView: ViewGroup? = null
|
|
||||||
|
|
||||||
var activityMainRoot: View? = null
|
var activityMainRoot: View? = null
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
@ -273,8 +271,6 @@ abstract class CoreReaderFragment :
|
|||||||
protected var actionBar: ActionBar? = null
|
protected var actionBar: ActionBar? = null
|
||||||
protected var mainMenu: MainMenu? = null
|
protected var mainMenu: MainMenu? = null
|
||||||
|
|
||||||
var toolbarWithSearchPlaceholder: ConstraintLayout? = null
|
|
||||||
|
|
||||||
private var tabRecyclerView: RecyclerView? = null
|
private var tabRecyclerView: RecyclerView? = null
|
||||||
private var isFirstTimeMainPageLoaded = true
|
private var isFirstTimeMainPageLoaded = true
|
||||||
private var isFromManageExternalLaunch = false
|
private var isFromManageExternalLaunch = false
|
||||||
@ -374,7 +370,10 @@ abstract class CoreReaderFragment :
|
|||||||
closeTab(position)
|
closeTab(position)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
shouldShowFullScreenMode = false
|
shouldShowFullScreenMode = false,
|
||||||
|
searchPlaceHolderItemForCustomApps = false to {
|
||||||
|
openSearch(searchString = "", isOpenedFromTabView = false, false)
|
||||||
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
private var readerLifeCycleScope: CoroutineScope? = null
|
private var readerLifeCycleScope: CoroutineScope? = null
|
||||||
@ -486,12 +485,19 @@ abstract class CoreReaderFragment :
|
|||||||
updateTabIcon(size)
|
updateTabIcon(size)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LaunchedEffect(currentWebViewIndex, readerMenuState?.isInTabSwitcher) {
|
LaunchedEffect(Unit) {
|
||||||
readerScreenState.update {
|
readerScreenState.update {
|
||||||
copy(
|
copy(
|
||||||
bottomNavigationHeight = getBottomNavigationHeight(),
|
bottomNavigationHeight = getBottomNavigationHeight(),
|
||||||
readerScreenTitle = context.getString(R.string.reader),
|
readerScreenTitle = context.getString(R.string.reader),
|
||||||
darkModeViewPainter = darkModeViewPainter,
|
darkModeViewPainter = darkModeViewPainter,
|
||||||
|
fullScreenItem = fullScreenItem.first to getVideoView()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LaunchedEffect(currentWebViewIndex, readerMenuState?.isInTabSwitcher) {
|
||||||
|
readerScreenState.update {
|
||||||
|
copy(
|
||||||
currentWebViewPosition = currentWebViewIndex,
|
currentWebViewPosition = currentWebViewIndex,
|
||||||
showTabSwitcher = readerMenuState?.isInTabSwitcher == true
|
showTabSwitcher = readerMenuState?.isInTabSwitcher == true
|
||||||
)
|
)
|
||||||
@ -504,7 +510,8 @@ abstract class CoreReaderFragment :
|
|||||||
NavigationIcon(
|
NavigationIcon(
|
||||||
iconItem = navigationIcon(),
|
iconItem = navigationIcon(),
|
||||||
contentDescription = navigationIconContentDescription(),
|
contentDescription = navigationIconContentDescription(),
|
||||||
onClick = { navigationIconClick() }
|
onClick = { navigationIconClick() },
|
||||||
|
iconTint = navigationIconTint()
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
listState = lazyListState
|
listState = lazyListState
|
||||||
@ -609,7 +616,15 @@ abstract class CoreReaderFragment :
|
|||||||
viewLifecycleOwner,
|
viewLifecycleOwner,
|
||||||
Observer(::storeSearchItem)
|
Observer(::storeSearchItem)
|
||||||
)
|
)
|
||||||
handleClicks()
|
}
|
||||||
|
|
||||||
|
private fun getVideoView() = context?.let {
|
||||||
|
FrameLayout(it).apply {
|
||||||
|
layoutParams = ViewGroup.LayoutParams(
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT,
|
||||||
|
ViewGroup.LayoutParams.MATCH_PARENT
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getBottomNavigationHeight(): Int = getBottomNavigationView()?.measuredHeight ?: ZERO
|
private fun getBottomNavigationHeight(): Int = getBottomNavigationView()?.measuredHeight ?: ZERO
|
||||||
@ -639,7 +654,25 @@ abstract class CoreReaderFragment :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun navigationIcon() = if (readerMenuState?.isInTabSwitcher == true) {
|
/**
|
||||||
|
* Returns the tint color to be applied to the navigation icon.
|
||||||
|
*
|
||||||
|
* Subclasses (e.g., CustomReaderFragment) can override this method to provide custom behavior,
|
||||||
|
* such as setting a colored app icon in place of the default hamburger icon when configured.
|
||||||
|
*
|
||||||
|
* By default, this returns [White], which is appropriate for vector icons that rely on tinting.
|
||||||
|
*/
|
||||||
|
open fun navigationIconTint() = White
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides the navigationIcon based on condition.
|
||||||
|
* Subclasses like CustomReaderFragment override this method to provide custom
|
||||||
|
* behavior, such as set the app icon on hamburger when configure to not show the title.
|
||||||
|
*
|
||||||
|
* WARNING: If modifying this method, ensure thorough testing with custom apps
|
||||||
|
* to verify proper functionality.
|
||||||
|
*/
|
||||||
|
open fun navigationIcon() = if (readerMenuState?.isInTabSwitcher == true) {
|
||||||
IconItem.Drawable(R.drawable.ic_round_add_white_36dp)
|
IconItem.Drawable(R.drawable.ic_round_add_white_36dp)
|
||||||
} else {
|
} else {
|
||||||
IconItem.Vector(Icons.Filled.Menu)
|
IconItem.Vector(Icons.Filled.Menu)
|
||||||
@ -652,25 +685,17 @@ abstract class CoreReaderFragment :
|
|||||||
|
|
||||||
private fun prepareViews() {
|
private fun prepareViews() {
|
||||||
fragmentReaderBinding?.let { readerBinding ->
|
fragmentReaderBinding?.let { readerBinding ->
|
||||||
videoView = readerBinding.fullscreenVideoContainer
|
|
||||||
with(readerBinding.root) {
|
with(readerBinding.root) {
|
||||||
activityMainRoot = findViewById(R.id.activity_main_root)
|
activityMainRoot = findViewById(R.id.activity_main_root)
|
||||||
contentFrame = findViewById(R.id.activity_main_content_frame)
|
contentFrame = findViewById(R.id.activity_main_content_frame)
|
||||||
toolbar = findViewById(R.id.toolbar)
|
toolbar = findViewById(R.id.toolbar)
|
||||||
tabSwitcherRoot = findViewById(R.id.activity_main_tab_switcher)
|
tabSwitcherRoot = findViewById(R.id.activity_main_tab_switcher)
|
||||||
toolbarWithSearchPlaceholder = findViewById(R.id.toolbarWithSearchPlaceholder)
|
|
||||||
tabRecyclerView = findViewById(R.id.tab_switcher_recycler_view)
|
tabRecyclerView = findViewById(R.id.tab_switcher_recycler_view)
|
||||||
donationLayout = findViewById(R.id.donation_layout)
|
donationLayout = findViewById(R.id.donation_layout)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun handleClicks() {
|
|
||||||
toolbarWithSearchPlaceholder?.setOnClickListener {
|
|
||||||
openSearch(searchString = "", isOpenedFromTabView = false, false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initTabCallback() {
|
private fun initTabCallback() {
|
||||||
tabCallback = object : ItemTouchHelper.Callback() {
|
tabCallback = object : ItemTouchHelper.Callback() {
|
||||||
override fun getMovementFlags(
|
override fun getMovementFlags(
|
||||||
@ -859,34 +884,30 @@ abstract class CoreReaderFragment :
|
|||||||
showBackToTopButton = false
|
showBackToTopButton = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
showSearchPlaceHolderInToolbar(true)
|
||||||
startAnimation(tabSwitcherRoot, R.anim.slide_down)
|
startAnimation(tabSwitcherRoot, R.anim.slide_down)
|
||||||
tabsAdapter?.let { tabsAdapter ->
|
|
||||||
tabRecyclerView?.let { recyclerView ->
|
|
||||||
if (tabsAdapter.selected < webViewList.size &&
|
|
||||||
recyclerView.layoutManager != null
|
|
||||||
) {
|
|
||||||
recyclerView.layoutManager?.scrollToPosition(tabsAdapter.selected)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Notify the tabs adapter to update the UI when the tab switcher is shown
|
|
||||||
// This ensures that any changes made to the adapter's data or views are
|
|
||||||
// reflected correctly.
|
|
||||||
tabsAdapter.notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
readerMenuState?.showTabSwitcherOptions()
|
readerMenuState?.showTabSwitcherOptions()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the tabs switcher visibility, controlling the visibility of the tab.
|
* Controls the visibility of the search placeholder in the toolbar.
|
||||||
* Subclasses, like CustomReaderFragment, override this method to provide custom
|
|
||||||
* behavior, such as hiding the placeholder in the toolbar when a custom app is configured
|
|
||||||
* not to show the title. This is necessary because the same toolbar is used for displaying tabs.
|
|
||||||
*
|
*
|
||||||
* WARNING: If modifying this method, ensure thorough testing with custom apps
|
* Subclasses (e.g., CustomReaderFragment) can override this method to customize behavior,
|
||||||
* to verify proper functionality.
|
* such as showing a search placeholder instead of the title when the app is configured to
|
||||||
|
* hide the title. This is important because the same toolbar is shared with the tab display.
|
||||||
|
*
|
||||||
|
* NOTE: This method sets `showSearchPlaceHolderForCustomApps` to `false` by default.
|
||||||
|
* Subclasses must explicitly handle the `true` case if needed.
|
||||||
|
*
|
||||||
|
* ⚠️ When modifying this method, thoroughly test with custom app configurations to
|
||||||
|
* ensure correct toolbar behavior.
|
||||||
*/
|
*/
|
||||||
open fun setTabSwitcherVisibility(visibility: Int) {
|
open fun showSearchPlaceHolderInToolbar(isTabSwitcherShowing: Boolean) {
|
||||||
tabSwitcherRoot?.visibility = visibility
|
readerScreenState.update {
|
||||||
|
copy(
|
||||||
|
searchPlaceHolderItemForCustomApps = searchPlaceHolderItemForCustomApps.copy(first = false)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -926,7 +947,7 @@ abstract class CoreReaderFragment :
|
|||||||
* as closing the ZIM book would require reloading the ZIM file, which can be a resource-intensive operation.
|
* as closing the ZIM book would require reloading the ZIM file, which can be a resource-intensive operation.
|
||||||
*/
|
*/
|
||||||
protected open fun hideTabSwitcher(shouldCloseZimBook: Boolean = true) {
|
protected open fun hideTabSwitcher(shouldCloseZimBook: Boolean = true) {
|
||||||
toolbar?.let(::setUpDrawerToggle)
|
setUpDrawerToggle()
|
||||||
setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||||
selectTab(currentWebViewIndex)
|
selectTab(currentWebViewIndex)
|
||||||
readerScreenState.update {
|
readerScreenState.update {
|
||||||
@ -935,24 +956,15 @@ abstract class CoreReaderFragment :
|
|||||||
pageLoadingItem = false to ZERO,
|
pageLoadingItem = false to ZERO,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
showSearchPlaceHolderInToolbar(false)
|
||||||
readerMenuState?.showWebViewOptions(urlIsValid())
|
readerMenuState?.showWebViewOptions(urlIsValid())
|
||||||
// Reset the top margin of web views to 0 to remove any previously set margin
|
// Reset the top margin of web views to 0 to remove any previously set margin
|
||||||
// This ensures that the web views are displayed without any additional top margin for kiwix custom apps.
|
// This ensures that the web views are displayed without any additional top margin for kiwix custom apps.
|
||||||
// setTopMarginToWebViews(0)
|
// setTopMarginToWebViews(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
open fun setUpDrawerToggle() {
|
||||||
* Sets the drawer toggle, controlling the toolbar.
|
(requireActivity() as CoreMainActivity).setupDrawerToggle(true)
|
||||||
* Subclasses like CustomReaderFragment override this method to provide custom
|
|
||||||
* behavior, such as set the app icon on hamburger when configure to not show the title.
|
|
||||||
*
|
|
||||||
* WARNING: If modifying this method, ensure thorough testing with custom apps
|
|
||||||
* to verify proper functionality.
|
|
||||||
*/
|
|
||||||
open fun setUpDrawerToggle(toolbar: Toolbar) {
|
|
||||||
toolbar.let {
|
|
||||||
(requireActivity() as CoreMainActivity).setupDrawerToggle(it, true)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1335,10 +1347,8 @@ abstract class CoreReaderFragment :
|
|||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
private fun unBindViewsAndBinding() {
|
private fun unBindViewsAndBinding() {
|
||||||
activityMainRoot = null
|
activityMainRoot = null
|
||||||
toolbarWithSearchPlaceholder = null
|
|
||||||
tabRecyclerView = null
|
tabRecyclerView = null
|
||||||
tabSwitcherRoot = null
|
tabSwitcherRoot = null
|
||||||
videoView = null
|
|
||||||
contentFrame = null
|
contentFrame = null
|
||||||
compatCallback?.finish()
|
compatCallback?.finish()
|
||||||
compatCallback = null
|
compatCallback = null
|
||||||
@ -1402,14 +1412,12 @@ abstract class CoreReaderFragment :
|
|||||||
|
|
||||||
@Throws(IllegalArgumentException::class)
|
@Throws(IllegalArgumentException::class)
|
||||||
protected open fun createWebView(attrs: AttributeSet?): ToolbarScrollingKiwixWebView? {
|
protected open fun createWebView(attrs: AttributeSet?): ToolbarScrollingKiwixWebView? {
|
||||||
// requireNotNull(activityMainRoot)
|
|
||||||
return ToolbarScrollingKiwixWebView(
|
return ToolbarScrollingKiwixWebView(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
this,
|
this,
|
||||||
attrs ?: throw IllegalArgumentException("AttributeSet must not be null"),
|
attrs ?: throw IllegalArgumentException("AttributeSet must not be null"),
|
||||||
null,
|
null,
|
||||||
// requireNotNull(readerScreenState.value.fullScreenItem.second),
|
requireNotNull(readerScreenState.value.fullScreenItem.second),
|
||||||
null,
|
|
||||||
CoreWebViewClient(this, requireNotNull(zimReaderContainer)),
|
CoreWebViewClient(this, requireNotNull(zimReaderContainer)),
|
||||||
// requireNotNull(toolbarContainer),
|
// requireNotNull(toolbarContainer),
|
||||||
// requireNotNull(bottomToolbar),
|
// requireNotNull(bottomToolbar),
|
||||||
@ -1446,7 +1454,6 @@ abstract class CoreReaderFragment :
|
|||||||
if (selectTab) {
|
if (selectTab) {
|
||||||
selectTab(webViewList.size - 1)
|
selectTab(webViewList.size - 1)
|
||||||
}
|
}
|
||||||
tabsAdapter?.notifyDataSetChanged()
|
|
||||||
}
|
}
|
||||||
return webView
|
return webView
|
||||||
}
|
}
|
||||||
@ -1739,10 +1746,18 @@ abstract class CoreReaderFragment :
|
|||||||
*/
|
*/
|
||||||
override fun onFullscreenVideoToggled(isFullScreen: Boolean) {
|
override fun onFullscreenVideoToggled(isFullScreen: Boolean) {
|
||||||
if (isFullScreen) {
|
if (isFullScreen) {
|
||||||
|
readerScreenState.update {
|
||||||
|
copy(
|
||||||
|
fullScreenItem = fullScreenItem.copy(first = true),
|
||||||
|
shouldShowBottomAppBar = false
|
||||||
|
)
|
||||||
|
}
|
||||||
(requireActivity() as CoreMainActivity).disableDrawer(false)
|
(requireActivity() as CoreMainActivity).disableDrawer(false)
|
||||||
} else {
|
} else {
|
||||||
|
readerScreenState.update { copy(fullScreenItem = fullScreenItem.copy(first = false)) }
|
||||||
if (!isInFullScreenMode()) {
|
if (!isInFullScreenMode()) {
|
||||||
toolbar?.let(::setUpDrawerToggle)
|
readerScreenState.update { copy(shouldShowBottomAppBar = true) }
|
||||||
|
setUpDrawerToggle()
|
||||||
setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1768,7 +1783,7 @@ abstract class CoreReaderFragment :
|
|||||||
|
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
open fun closeFullScreen() {
|
open fun closeFullScreen() {
|
||||||
toolbar?.let(::setUpDrawerToggle)
|
setUpDrawerToggle()
|
||||||
setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
|
||||||
sharedPreferenceUtil?.putPrefFullScreen(false)
|
sharedPreferenceUtil?.putPrefFullScreen(false)
|
||||||
readerScreenState.update {
|
readerScreenState.update {
|
||||||
@ -2187,10 +2202,8 @@ abstract class CoreReaderFragment :
|
|||||||
protected fun isInFullScreenMode(): Boolean = sharedPreferenceUtil?.prefFullScreen == true
|
protected fun isInFullScreenMode(): Boolean = sharedPreferenceUtil?.prefFullScreen == true
|
||||||
|
|
||||||
private fun updateBottomToolbarVisibility() {
|
private fun updateBottomToolbarVisibility() {
|
||||||
// TODO refactroe this code once we integrate the tabSwitcher
|
|
||||||
// tabSwitcherRoot?.visibility != VISIBLE && !isInFullScreenMode()
|
|
||||||
readerScreenState.update {
|
readerScreenState.update {
|
||||||
copy(shouldShowBottomAppBar = !isInFullScreenMode())
|
copy(shouldShowBottomAppBar = !showTabSwitcher && !isInFullScreenMode())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2861,11 +2874,7 @@ abstract class CoreReaderFragment :
|
|||||||
try {
|
try {
|
||||||
isFromManageExternalLaunch = true
|
isFromManageExternalLaunch = true
|
||||||
currentWebViewIndex = 0
|
currentWebViewIndex = 0
|
||||||
tabsAdapter?.apply {
|
webViewList.removeFirstOrNull()
|
||||||
webViewList.removeAt(0)
|
|
||||||
notifyItemRemoved(0)
|
|
||||||
notifyDataSetChanged()
|
|
||||||
}
|
|
||||||
webViewHistoryItemList.forEach { webViewHistoryItem ->
|
webViewHistoryItemList.forEach { webViewHistoryItem ->
|
||||||
newTab("", shouldLoadUrl = false)?.let {
|
newTab("", shouldLoadUrl = false)?.let {
|
||||||
restoreTabState(it, webViewHistoryItem)
|
restoreTabState(it, webViewHistoryItem)
|
||||||
|
@ -167,6 +167,7 @@ class ReaderMenuState(
|
|||||||
|
|
||||||
fun hideTabSwitcher() {
|
fun hideTabSwitcher() {
|
||||||
isInTabSwitcher = false
|
isInTabSwitcher = false
|
||||||
|
updateMenuItems()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateMenuItems() {
|
private fun updateMenuItems() {
|
||||||
|
@ -26,6 +26,7 @@ import androidx.compose.animation.core.animateFloatAsState
|
|||||||
import androidx.compose.animation.core.tween
|
import androidx.compose.animation.core.tween
|
||||||
import androidx.compose.foundation.BorderStroke
|
import androidx.compose.foundation.BorderStroke
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.border
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.combinedClickable
|
import androidx.compose.foundation.combinedClickable
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
@ -48,6 +49,7 @@ import androidx.compose.foundation.lazy.itemsIndexed
|
|||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
import androidx.compose.material3.BottomAppBar
|
import androidx.compose.material3.BottomAppBar
|
||||||
import androidx.compose.material3.BottomAppBarDefaults
|
import androidx.compose.material3.BottomAppBarDefaults
|
||||||
@ -85,6 +87,7 @@ import androidx.compose.ui.platform.LocalContext
|
|||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.platform.LocalWindowInfo
|
import androidx.compose.ui.platform.LocalWindowInfo
|
||||||
import androidx.compose.ui.platform.testTag
|
import androidx.compose.ui.platform.testTag
|
||||||
|
import androidx.compose.ui.res.colorResource
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
@ -119,14 +122,17 @@ import org.kiwix.kiwixmobile.core.utils.ComposeDimens.CLOSE_ALL_TAB_BUTTON_BOTTO
|
|||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.CLOSE_TAB_ICON_ANIMATION_TIMEOUT
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.CLOSE_TAB_ICON_ANIMATION_TIMEOUT
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.CLOSE_TAB_ICON_SIZE
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.CLOSE_TAB_ICON_SIZE
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.EIGHT_DP
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.EIGHT_DP
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FIVE_DP
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FOUR_DP
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.FOUR_DP
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.ONE_DP
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.ONE_DP
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.READER_BOTTOM_APP_BAR_BUTTON_ICON_SIZE
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.READER_BOTTOM_APP_BAR_BUTTON_ICON_SIZE
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.READER_BOTTOM_APP_BAR_DISABLE_BUTTON_ALPHA
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.READER_BOTTOM_APP_BAR_DISABLE_BUTTON_ALPHA
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.READER_BOTTOM_APP_BAR_LAYOUT_HEIGHT
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.READER_BOTTOM_APP_BAR_LAYOUT_HEIGHT
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SEARCH_PLACEHOLDER_TEXT_SIZE
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SEVEN_DP
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SEVEN_DP
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.SIXTEEN_DP
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TEN_DP
|
||||||
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.THREE_DP
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TTS_BUTTONS_CONTROL_ALPHA
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TTS_BUTTONS_CONTROL_ALPHA
|
||||||
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWO_DP
|
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.TWO_DP
|
||||||
import org.kiwix.kiwixmobile.core.utils.StyleUtils.fromHtml
|
import org.kiwix.kiwixmobile.core.utils.StyleUtils.fromHtml
|
||||||
@ -176,12 +182,14 @@ private fun ReaderTopBar(
|
|||||||
scrollBehavior: TopAppBarScrollBehavior,
|
scrollBehavior: TopAppBarScrollBehavior,
|
||||||
navigationIcon: @Composable () -> Unit,
|
navigationIcon: @Composable () -> Unit,
|
||||||
) {
|
) {
|
||||||
if (!state.shouldShowFullScreenMode) {
|
if (!state.shouldShowFullScreenMode && !state.fullScreenItem.first) {
|
||||||
KiwixAppBar(
|
KiwixAppBar(
|
||||||
title = if (state.showTabSwitcher) "" else state.readerScreenTitle,
|
title = if (state.showTabSwitcher) "" else state.readerScreenTitle,
|
||||||
navigationIcon = navigationIcon,
|
navigationIcon = navigationIcon,
|
||||||
actionMenuItems = actionMenuItems,
|
actionMenuItems = actionMenuItems,
|
||||||
topAppBarScrollBehavior = scrollBehavior
|
topAppBarScrollBehavior = scrollBehavior,
|
||||||
|
searchBar =
|
||||||
|
searchPlaceHolderIfActive(state.searchPlaceHolderItemForCustomApps)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -199,6 +207,7 @@ private fun ReaderContentLayout(state: ReaderScreenState, modifier: Modifier = M
|
|||||||
)
|
)
|
||||||
|
|
||||||
state.isNoBookOpenInReader -> NoBookOpenView(state.onOpenLibraryButtonClicked)
|
state.isNoBookOpenInReader -> NoBookOpenView(state.onOpenLibraryButtonClicked)
|
||||||
|
state.fullScreenItem.first -> ShowFullScreenView(state)
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
ShowZIMFileContent(state)
|
ShowZIMFileContent(state)
|
||||||
@ -214,7 +223,6 @@ private fun ReaderContentLayout(state: ReaderScreenState, modifier: Modifier = M
|
|||||||
state.shouldShowBottomAppBar
|
state.shouldShowBottomAppBar
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
ShowFullScreenView(state)
|
|
||||||
CloseFullScreenImageButton(
|
CloseFullScreenImageButton(
|
||||||
state.shouldShowFullScreenMode,
|
state.shouldShowFullScreenMode,
|
||||||
state.onExitFullscreenClick
|
state.onExitFullscreenClick
|
||||||
@ -226,6 +234,53 @@ private fun ReaderContentLayout(state: ReaderScreenState, modifier: Modifier = M
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun searchPlaceHolderIfActive(
|
||||||
|
searchPlaceHolderItemForCustomApps: Pair<Boolean, () -> Unit>
|
||||||
|
): (@Composable () -> Unit)? = if (searchPlaceHolderItemForCustomApps.first) {
|
||||||
|
{
|
||||||
|
SearchPlaceholder(
|
||||||
|
stringResource(R.string.search_label),
|
||||||
|
searchPlaceHolderItemForCustomApps.second
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun SearchPlaceholder(hint: String, searchPlaceHolderClick: () -> Unit) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.background(
|
||||||
|
color = Color.Transparent,
|
||||||
|
shape = RoundedCornerShape(THREE_DP)
|
||||||
|
)
|
||||||
|
.border(
|
||||||
|
width = 1.5.dp,
|
||||||
|
color = colorResource(id = R.color.alabaster_white),
|
||||||
|
shape = RoundedCornerShape(THREE_DP)
|
||||||
|
)
|
||||||
|
.padding(horizontal = FIVE_DP, vertical = FIVE_DP)
|
||||||
|
.clickable(onClick = searchPlaceHolderClick),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = hint,
|
||||||
|
color = Color.Gray,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
fontSize = SEARCH_PLACEHOLDER_TEXT_SIZE
|
||||||
|
)
|
||||||
|
Spacer(modifier = Modifier.width(TEN_DP))
|
||||||
|
Icon(
|
||||||
|
painter = IconItem.Drawable(R.drawable.action_search).toPainter(),
|
||||||
|
contentDescription = null,
|
||||||
|
tint = White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun BoxScope.CloseFullScreenImageButton(
|
private fun BoxScope.CloseFullScreenImageButton(
|
||||||
shouldShowFullScreenMode: Boolean,
|
shouldShowFullScreenMode: Boolean,
|
||||||
@ -254,7 +309,14 @@ private fun ShowZIMFileContent(state: ReaderScreenState) {
|
|||||||
state.selectedWebView?.let { selectedWebView ->
|
state.selectedWebView?.let { selectedWebView ->
|
||||||
key(selectedWebView) {
|
key(selectedWebView) {
|
||||||
AndroidView(
|
AndroidView(
|
||||||
factory = { selectedWebView },
|
factory = { context ->
|
||||||
|
// Create a new container and add the WebView to it
|
||||||
|
FrameLayout(context).apply {
|
||||||
|
// Ensure the WebView has no parent before adding
|
||||||
|
(selectedWebView.parent as? ViewGroup)?.removeView(selectedWebView)
|
||||||
|
addView(selectedWebView)
|
||||||
|
}
|
||||||
|
},
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -263,8 +325,8 @@ private fun ShowZIMFileContent(state: ReaderScreenState) {
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ShowFullScreenView(state: ReaderScreenState) {
|
private fun ShowFullScreenView(state: ReaderScreenState) {
|
||||||
if (state.fullScreenItem.first) {
|
state.fullScreenItem.second?.let { videoView ->
|
||||||
state.fullScreenItem.second
|
AndroidView(factory = { videoView })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.main.reader
|
package org.kiwix.kiwixmobile.core.main.reader
|
||||||
|
|
||||||
|
import android.widget.FrameLayout
|
||||||
import androidx.compose.material3.SnackbarHostState
|
import androidx.compose.material3.SnackbarHostState
|
||||||
import androidx.compose.ui.platform.ComposeView
|
|
||||||
import org.kiwix.kiwixmobile.core.main.DarkModeViewPainter
|
import org.kiwix.kiwixmobile.core.main.DarkModeViewPainter
|
||||||
import org.kiwix.kiwixmobile.core.main.KiwixWebView
|
import org.kiwix.kiwixmobile.core.main.KiwixWebView
|
||||||
import org.kiwix.kiwixmobile.core.ui.models.IconItem.Drawable
|
import org.kiwix.kiwixmobile.core.ui.models.IconItem.Drawable
|
||||||
@ -60,9 +60,9 @@ data class ReaderScreenState(
|
|||||||
*
|
*
|
||||||
* A [Pair] containing:
|
* A [Pair] containing:
|
||||||
* - [Boolean]: Whether to show/hide full screen mode.
|
* - [Boolean]: Whether to show/hide full screen mode.
|
||||||
* - [ComposeView]: full screen view.
|
* - [FrameLayout]: full screen view.
|
||||||
*/
|
*/
|
||||||
val fullScreenItem: Pair<Boolean, ComposeView?>,
|
val fullScreenItem: Pair<Boolean, FrameLayout?>,
|
||||||
/**
|
/**
|
||||||
* Manages the showing of "Full screen mode".
|
* Manages the showing of "Full screen mode".
|
||||||
*/
|
*/
|
||||||
@ -124,7 +124,7 @@ data class ReaderScreenState(
|
|||||||
/**
|
/**
|
||||||
* Handles the clicks of next page button in reader bottom toolbar.
|
* Handles the clicks of next page button in reader bottom toolbar.
|
||||||
*
|
*
|
||||||
* A [Pair] containing:
|
* A [Triple] containing:
|
||||||
* - [Unit]: Handles the normal click of button(For going to next page).
|
* - [Unit]: Handles the normal click of button(For going to next page).
|
||||||
* - [Unit]: Handles the long click of button(For showing the next pages history).
|
* - [Unit]: Handles the long click of button(For showing the next pages history).
|
||||||
* - [Boolean]: Handles the button should enable or not.
|
* - [Boolean]: Handles the button should enable or not.
|
||||||
@ -149,4 +149,8 @@ data class ReaderScreenState(
|
|||||||
* Manages the click event on tabs.
|
* Manages the click event on tabs.
|
||||||
*/
|
*/
|
||||||
val onTabClickListener: TabClickListener,
|
val onTabClickListener: TabClickListener,
|
||||||
|
/**
|
||||||
|
* Manages the showing/hiding of search placeholder in toolbar for custom apps.
|
||||||
|
*/
|
||||||
|
val searchPlaceHolderItemForCustomApps: Pair<Boolean, () -> Unit>
|
||||||
)
|
)
|
||||||
|
@ -192,4 +192,5 @@ object ComposeDimens {
|
|||||||
const val CLOSE_TAB_ICON_ANIMATION_TIMEOUT = 1200L
|
const val CLOSE_TAB_ICON_ANIMATION_TIMEOUT = 1200L
|
||||||
val BACK_TO_TOP_BUTTON_BOTTOM_MARGIN = 80.dp
|
val BACK_TO_TOP_BUTTON_BOTTOM_MARGIN = 80.dp
|
||||||
const val READER_BOTTOM_APP_BAR_DISABLE_BUTTON_ALPHA = 0.38f
|
const val READER_BOTTOM_APP_BAR_DISABLE_BUTTON_ALPHA = 0.38f
|
||||||
|
val SEARCH_PLACEHOLDER_TEXT_SIZE = 12.sp
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
|
||||||
import androidx.core.content.pm.ShortcutInfoCompat
|
import androidx.core.content.pm.ShortcutInfoCompat
|
||||||
import androidx.core.content.pm.ShortcutManagerCompat
|
import androidx.core.content.pm.ShortcutManagerCompat
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
@ -102,8 +101,8 @@ class CustomMainActivity : CoreMainActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupDrawerToggle(toolbar: Toolbar, shouldEnableRightDrawer: Boolean) {
|
override fun setupDrawerToggle(shouldEnableRightDrawer: Boolean) {
|
||||||
super.setupDrawerToggle(toolbar, shouldEnableRightDrawer)
|
super.setupDrawerToggle(shouldEnableRightDrawer)
|
||||||
activityCustomMainBinding.drawerNavView.apply {
|
activityCustomMainBinding.drawerNavView.apply {
|
||||||
/**
|
/**
|
||||||
* Hide the 'ZimHostFragment' option from the navigation menu
|
* Hide the 'ZimHostFragment' option from the navigation menu
|
||||||
|
@ -23,26 +23,27 @@ import android.os.Bundle
|
|||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuInflater
|
import android.view.MenuInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.View.GONE
|
|
||||||
import android.view.View.VISIBLE
|
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.appcompat.widget.Toolbar
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Menu
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.drawerlayout.widget.DrawerLayout
|
import androidx.drawerlayout.widget.DrawerLayout
|
||||||
import androidx.navigation.fragment.findNavController
|
import androidx.navigation.fragment.findNavController
|
||||||
import com.google.android.material.bottomnavigation.BottomNavigationView
|
import com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import org.kiwix.kiwixmobile.core.R.dimen
|
|
||||||
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
import org.kiwix.kiwixmobile.core.base.BaseActivity
|
||||||
import org.kiwix.kiwixmobile.core.extensions.browserIntent
|
import org.kiwix.kiwixmobile.core.extensions.browserIntent
|
||||||
import org.kiwix.kiwixmobile.core.extensions.getResizedDrawable
|
|
||||||
import org.kiwix.kiwixmobile.core.extensions.isFileExist
|
import org.kiwix.kiwixmobile.core.extensions.isFileExist
|
||||||
|
import org.kiwix.kiwixmobile.core.extensions.update
|
||||||
import org.kiwix.kiwixmobile.core.main.reader.CoreReaderFragment
|
import org.kiwix.kiwixmobile.core.main.reader.CoreReaderFragment
|
||||||
import org.kiwix.kiwixmobile.core.main.reader.ReaderMenuState
|
import org.kiwix.kiwixmobile.core.main.reader.ReaderMenuState
|
||||||
import org.kiwix.kiwixmobile.core.main.reader.RestoreOrigin
|
import org.kiwix.kiwixmobile.core.main.reader.RestoreOrigin
|
||||||
import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem
|
import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
import org.kiwix.kiwixmobile.core.reader.ZimReaderSource
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.models.IconItem
|
||||||
|
import org.kiwix.kiwixmobile.core.ui.theme.White
|
||||||
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
import org.kiwix.kiwixmobile.core.utils.LanguageUtils
|
||||||
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower
|
||||||
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getDemoFilePathForCustomApp
|
import org.kiwix.kiwixmobile.core.utils.files.FileUtils.getDemoFilePathForCustomApp
|
||||||
@ -81,10 +82,11 @@ class CustomReaderFragment : CoreReaderFragment() {
|
|||||||
val toolbarToc =
|
val toolbarToc =
|
||||||
activity?.findViewById<ImageView>(org.kiwix.kiwixmobile.core.R.id.bottom_toolbar_toc)
|
activity?.findViewById<ImageView>(org.kiwix.kiwixmobile.core.R.id.bottom_toolbar_toc)
|
||||||
toolbarToc?.isEnabled = false
|
toolbarToc?.isEnabled = false
|
||||||
|
// TODO refactor this with compose UI.
|
||||||
}
|
}
|
||||||
with(activity as AppCompatActivity) {
|
with(activity as AppCompatActivity) {
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||||
toolbar?.let(::setUpDrawerToggle)
|
setUpDrawerToggle()
|
||||||
}
|
}
|
||||||
loadPageFromNavigationArguments()
|
loadPageFromNavigationArguments()
|
||||||
if (BuildConfig.DISABLE_EXTERNAL_LINK) {
|
if (BuildConfig.DISABLE_EXTERNAL_LINK) {
|
||||||
@ -97,25 +99,33 @@ class CustomReaderFragment : CoreReaderFragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides the method to configure the hamburger icon. When the "setting title" is disabled
|
* Returns the tint color for the navigation icon.
|
||||||
* in a custom app, this function set the app logo on hamburger.
|
*
|
||||||
|
* If the custom app is configured to show the app icon in place of the hamburger icon
|
||||||
|
* (i.e., [BuildConfig.DISABLE_TITLE] is true), the tint is set to [Color.Unspecified] to preserve
|
||||||
|
* the original colors of the image.
|
||||||
|
*
|
||||||
|
* Otherwise, [White] is used as the default tint, which is suitable for vector icons.
|
||||||
*/
|
*/
|
||||||
override fun setUpDrawerToggle(toolbar: Toolbar) {
|
override fun navigationIconTint(): Color =
|
||||||
super.setUpDrawerToggle(toolbar)
|
|
||||||
if (BuildConfig.DISABLE_TITLE) {
|
if (BuildConfig.DISABLE_TITLE) {
|
||||||
|
Color.Unspecified
|
||||||
|
} else {
|
||||||
|
White
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun navigationIcon(): IconItem = when {
|
||||||
|
readerMenuState?.isInTabSwitcher == true -> {
|
||||||
|
IconItem.Drawable(org.kiwix.kiwixmobile.core.R.drawable.ic_round_add_white_36dp)
|
||||||
|
}
|
||||||
|
|
||||||
|
BuildConfig.DISABLE_TITLE -> {
|
||||||
// if the title is disable then set the app logo to hamburger icon,
|
// if the title is disable then set the app logo to hamburger icon,
|
||||||
// see https://github.com/kiwix/kiwix-android/issues/3528#issuecomment-1814905330
|
// see https://github.com/kiwix/kiwix-android/issues/3528#issuecomment-1814905330
|
||||||
val iconSize =
|
IconItem.MipmapImage(R.mipmap.ic_launcher)
|
||||||
resources.getDimensionPixelSize(dimen.hamburger_icon_size)
|
|
||||||
requireActivity().getResizedDrawable(R.mipmap.ic_launcher, iconSize, iconSize)
|
|
||||||
?.let { drawable ->
|
|
||||||
super.toolbar?.apply {
|
|
||||||
navigationIcon = drawable
|
|
||||||
// remove the default margin between hamburger and placeholder
|
|
||||||
contentInsetStartWithNavigation = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else -> IconItem.Vector(Icons.Filled.Menu)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -123,17 +133,16 @@ class CustomReaderFragment : CoreReaderFragment() {
|
|||||||
* When the "setting title" is disabled/enabled in a custom app,
|
* When the "setting title" is disabled/enabled in a custom app,
|
||||||
* this function set the visibility of placeholder in toolbar when showing the tabs.
|
* this function set the visibility of placeholder in toolbar when showing the tabs.
|
||||||
*/
|
*/
|
||||||
override fun setTabSwitcherVisibility(visibility: Int) {
|
override fun showSearchPlaceHolderInToolbar(isTabSwitcherShowing: Boolean) {
|
||||||
if (BuildConfig.DISABLE_TITLE) {
|
if (BuildConfig.DISABLE_TITLE) {
|
||||||
// If custom apps are configured to show the placeholder,
|
// If custom apps are configured to show the placeholder,
|
||||||
// and if tabs are visible, hide the placeholder.
|
// and if tabs are visible, hide the placeholder.
|
||||||
// If tabs are hidden, show the placeholder.
|
// If tabs are hidden, show the placeholder.
|
||||||
updateToolbarSearchPlaceholderVisibility(if (visibility == VISIBLE) GONE else VISIBLE)
|
updateToolbarSearchPlaceholderVisibility(!isTabSwitcherShowing)
|
||||||
} else {
|
} else {
|
||||||
// Permanently hide the placeholder if the custom app is not configured to show it.
|
// Permanently hide the placeholder if the custom app is not configured to show it.
|
||||||
updateToolbarSearchPlaceholderVisibility(GONE)
|
updateToolbarSearchPlaceholderVisibility(false)
|
||||||
}
|
}
|
||||||
super.setTabSwitcherVisibility(visibility)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadPageFromNavigationArguments() {
|
private fun loadPageFromNavigationArguments() {
|
||||||
@ -346,21 +355,23 @@ class CustomReaderFragment : CoreReaderFragment() {
|
|||||||
*/
|
*/
|
||||||
override fun updateTitle() {
|
override fun updateTitle() {
|
||||||
if (BuildConfig.DISABLE_TITLE) {
|
if (BuildConfig.DISABLE_TITLE) {
|
||||||
// Set an empty title for the toolbar because we are handling the toolbar click on behalf of this title.
|
|
||||||
// Since we have increased the zone for triggering search suggestions (see https://github.com/kiwix/kiwix-android/pull/3566),
|
// Since we have increased the zone for triggering search suggestions (see https://github.com/kiwix/kiwix-android/pull/3566),
|
||||||
// we need to set this title for handling the toolbar click,
|
// we need to set this title for handling the toolbar click,
|
||||||
// even if it is empty. If we do not set up this title,
|
// even if it is empty. If we do not set up this title,
|
||||||
// the search screen will open if the user clicks on the toolbar from the tabs screen.
|
// the search screen will open if the user clicks on the toolbar from the tabs screen.
|
||||||
actionBar?.title = " "
|
updateToolbarSearchPlaceholderVisibility(true)
|
||||||
updateToolbarSearchPlaceholderVisibility(VISIBLE)
|
|
||||||
} else {
|
} else {
|
||||||
updateToolbarSearchPlaceholderVisibility(GONE)
|
updateToolbarSearchPlaceholderVisibility(false)
|
||||||
super.updateTitle()
|
super.updateTitle()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateToolbarSearchPlaceholderVisibility(visibility: Int) {
|
private fun updateToolbarSearchPlaceholderVisibility(show: Boolean) {
|
||||||
toolbarWithSearchPlaceholder?.visibility = visibility
|
readerScreenState.update {
|
||||||
|
copy(
|
||||||
|
searchPlaceHolderItemForCustomApps = searchPlaceHolderItemForCustomApps.copy(first = show)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun createNewTab() {
|
override fun createNewTab() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user