Refactored left drawer to support Kiwix and custom apps dynamically; improved right drawer UI.

This commit is contained in:
MohitMaliFtechiz 2025-07-19 19:09:51 +05:30
parent 4e56c2c781
commit 86d9b1266f
7 changed files with 234 additions and 75 deletions

View File

@ -27,6 +27,7 @@ import android.view.MenuItem
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.ActionMode import androidx.appcompat.view.ActionMode
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.content.pm.ShortcutManagerCompat
@ -36,13 +37,14 @@ import androidx.core.os.bundleOf
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.compose.rememberNavController
import eu.mhutti1.utils.storage.StorageDevice import eu.mhutti1.utils.storage.StorageDevice
import eu.mhutti1.utils.storage.StorageDeviceUtils import eu.mhutti1.utils.storage.StorageDeviceUtils
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.kiwix.kiwixmobile.BuildConfig import org.kiwix.kiwixmobile.BuildConfig
import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.R
import org.kiwix.kiwixmobile.core.CoreApp
import org.kiwix.kiwixmobile.core.R.drawable import org.kiwix.kiwixmobile.core.R.drawable
import org.kiwix.kiwixmobile.core.R.id import org.kiwix.kiwixmobile.core.R.id
import org.kiwix.kiwixmobile.core.R.mipmap import org.kiwix.kiwixmobile.core.R.mipmap
@ -53,6 +55,7 @@ import org.kiwix.kiwixmobile.core.downloader.downloadManager.DOWNLOAD_NOTIFICATI
import org.kiwix.kiwixmobile.core.extensions.toast import org.kiwix.kiwixmobile.core.extensions.toast
import org.kiwix.kiwixmobile.core.main.ACTION_NEW_TAB import org.kiwix.kiwixmobile.core.main.ACTION_NEW_TAB
import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.main.CoreMainActivity
import org.kiwix.kiwixmobile.core.main.DrawerMenuItem
import org.kiwix.kiwixmobile.core.main.NEW_TAB_SHORTCUT_ID import org.kiwix.kiwixmobile.core.main.NEW_TAB_SHORTCUT_ID
import org.kiwix.kiwixmobile.core.main.ZIM_FILE_URI_KEY import org.kiwix.kiwixmobile.core.main.ZIM_FILE_URI_KEY
import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange import org.kiwix.kiwixmobile.core.utils.LanguageUtils.Companion.handleLocaleChange
@ -82,12 +85,6 @@ class KiwixMainActivity : CoreMainActivity() {
// activityKiwixMainBinding.readerDrawerNavView // activityKiwixMainBinding.readerDrawerNavView
// } // }
override val navController: NavController by lazy {
val fragment = supportFragmentManager.findFragmentById(id.nav_host_fragment)
val navHostFragment = requireNotNull(fragment) as NavHostFragment
return@lazy navHostFragment.navController
}
@Inject lateinit var libkiwixBookOnDisk: LibkiwixBookOnDisk @Inject lateinit var libkiwixBookOnDisk: LibkiwixBookOnDisk
override val mainActivity: AppCompatActivity by lazy { this } override val mainActivity: AppCompatActivity by lazy { this }
@ -117,15 +114,24 @@ class KiwixMainActivity : CoreMainActivity() {
cachedComponent.inject(this) cachedComponent.inject(this)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
setContent { setContent {
navController = rememberNavController()
KiwixMainActivityScreen( KiwixMainActivityScreen(
navController = navController, navController = navController,
topLevelDestinations = topLevelDestinations.toList(), topLevelDestinations = topLevelDestinations.toList(),
isBottomBarVisible = isBottomBarVisible.value, isBottomBarVisible = isBottomBarVisible.value,
leftDrawerContent = { }, leftDrawerContent = rightNavigationDrawerMenuItems,
rightDrawerContent = { } rightDrawerContent = { }
) )
LaunchedEffect(navController) {
navController.addOnDestinationChangedListener(finishActionModeOnDestinationChange)
navController.addOnDestinationChangedListener { _, destination, _ ->
isBottomBarVisible.value = destination.id in topLevelDestinations
if (destination.id !in topLevelDestinations) {
handleDrawerOnNavigation()
}
}
}
} }
navController.addOnDestinationChangedListener(finishActionModeOnDestinationChange)
// activityKiwixMainBinding.drawerNavView.apply { // activityKiwixMainBinding.drawerNavView.apply {
// setupWithNavController(navController) // setupWithNavController(navController)
// setNavigationItemSelectedListener { item -> // setNavigationItemSelectedListener { item ->
@ -207,12 +213,6 @@ class KiwixMainActivity : CoreMainActivity() {
override fun onStart() { override fun onStart() {
super.onStart() super.onStart()
// navController.addOnDestinationChangedListener { _, destination, _ ->
// isBottomBarVisible.value = destination.id in topLevelDestinations
// if (destination.id !in topLevelDestinations) {
// handleDrawerOnNavigation()
// }
// }
if (sharedPreferenceUtil.showIntro() && !isIntroScreenNotVisible()) { if (sharedPreferenceUtil.showIntro() && !isIntroScreenNotVisible()) {
// navigate(KiwixReaderFragmentDirections.actionReaderFragmentToIntroFragment()) // navigate(KiwixReaderFragmentDirections.actionReaderFragmentToIntroFragment())
} }
@ -337,6 +337,32 @@ class KiwixMainActivity : CoreMainActivity() {
return true return true
} }
override val zimHostDrawerMenuItem: DrawerMenuItem? = DrawerMenuItem(
title = CoreApp.instance.getString(string.menu_wifi_hotspot),
iconRes = drawable.ic_mobile_screen_share_24px,
true,
onClick = { openZimHostFragment() }
)
override val helpDrawerMenuItem: DrawerMenuItem? = DrawerMenuItem(
title = CoreApp.instance.getString(string.menu_help),
iconRes = drawable.ic_help_24px,
true,
onClick = { openHelpFragment() }
)
override val supportDrawerMenuItem: DrawerMenuItem? = DrawerMenuItem(
title = CoreApp.instance.getString(string.menu_support_kiwix),
iconRes = drawable.ic_support_24px,
true,
onClick = { openSupportKiwixExternalLink() }
)
/**
* In kiwix app we are not showing the "About app" item so returning null.
*/
override val aboutAppDrawerMenuItem: DrawerMenuItem? = null
private fun openZimHostFragment() { private fun openZimHostFragment() {
disableDrawer() disableDrawer()
navigate(R.id.zimHostFragment) navigate(R.id.zimHostFragment)

View File

@ -18,8 +18,6 @@
package org.kiwix.kiwixmobile.main package org.kiwix.kiwixmobile.main
import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.ColumnScope
@ -44,35 +42,31 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
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.viewinterop.AndroidView import androidx.navigation.NavHostController
import androidx.fragment.app.FragmentContainerView
import androidx.navigation.NavController
import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.fragment.NavHostFragment
import org.kiwix.kiwixmobile.R.drawable import org.kiwix.kiwixmobile.R.drawable
import org.kiwix.kiwixmobile.R.id import org.kiwix.kiwixmobile.R.id
import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.R.navigation import org.kiwix.kiwixmobile.core.main.DrawerMenuGroup
import org.kiwix.kiwixmobile.core.main.LeftDrawerMenu
import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme import org.kiwix.kiwixmobile.core.ui.theme.KiwixTheme
import org.kiwix.kiwixmobile.core.utils.ComposeDimens.NAVIGATION_DRAWER_WIDTH import org.kiwix.kiwixmobile.core.utils.ComposeDimens.NAVIGATION_DRAWER_WIDTH
import org.kiwix.kiwixmobile.ui.KiwixNavGraph
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun KiwixMainActivityScreen( fun KiwixMainActivityScreen(
navController: NavController, navController: NavHostController,
topLevelDestinations: List<Int>, topLevelDestinations: List<Int>,
leftDrawerContent: @Composable ColumnScope.() -> Unit, leftDrawerContent: List<DrawerMenuGroup>,
rightDrawerContent: @Composable ColumnScope.() -> Unit, rightDrawerContent: @Composable ColumnScope.() -> Unit,
isBottomBarVisible: Boolean = true isBottomBarVisible: Boolean = true
) { ) {
val rightDrawerState = rememberDrawerState(DrawerValue.Closed) val rightDrawerState = rememberDrawerState(DrawerValue.Closed)
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val scrollingBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior() val scrollingBehavior = BottomAppBarDefaults.exitAlwaysScrollBehavior()
val context = LocalContext.current
val fragmentManager = (context as AppCompatActivity).supportFragmentManager
KiwixTheme { KiwixTheme {
ModalNavigationDrawer( ModalNavigationDrawer(
drawerContent = { drawerContent = {
@ -81,7 +75,7 @@ fun KiwixMainActivityScreen(
.fillMaxHeight() .fillMaxHeight()
.width(NAVIGATION_DRAWER_WIDTH) .width(NAVIGATION_DRAWER_WIDTH)
) { ) {
leftDrawerContent() LeftDrawerMenu(leftDrawerContent)
} }
}, },
gesturesEnabled = true gesturesEnabled = true
@ -99,21 +93,9 @@ fun KiwixMainActivityScreen(
} }
) { paddingValues -> ) { paddingValues ->
Box(modifier = Modifier.padding(paddingValues)) { Box(modifier = Modifier.padding(paddingValues)) {
// AndroidView to host your FragmentContainerView with nav graph KiwixNavGraph(
AndroidView( navController = navController,
modifier = Modifier.fillMaxSize(), modifier = Modifier.fillMaxSize()
factory = { ctx ->
FragmentContainerView(ctx).apply {
id = R.id.nav_host_fragment
if (fragmentManager.findFragmentById(id) == null) {
val navHostFragment = NavHostFragment.create(navigation.kiwix_nav_graph)
fragmentManager.beginTransaction()
.replace(id, navHostFragment)
.setPrimaryNavigationFragment(navHostFragment)
.commitNow()
}
}
}
) )
} }
} }
@ -136,7 +118,7 @@ fun KiwixMainActivityScreen(
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
fun BottomNavigationBar( fun BottomNavigationBar(
navController: NavController, navController: NavHostController,
scrollBehavior: BottomAppBarScrollBehavior, scrollBehavior: BottomAppBarScrollBehavior,
topLevelDestinations: List<Int> topLevelDestinations: List<Int>
) { ) {

View File

@ -29,16 +29,11 @@ import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
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.drawerlayout.widget.DrawerLayout
import androidx.drawerlayout.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED
import androidx.drawerlayout.widget.DrawerLayout.LOCK_MODE_UNLOCKED
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentContainerView
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.NavDestination import androidx.navigation.NavDestination
import androidx.navigation.NavDirections import androidx.navigation.NavDirections
import androidx.navigation.NavHostController
import androidx.navigation.NavOptions import androidx.navigation.NavOptions
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -90,7 +85,12 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
private var drawerToggle: ActionBarDrawerToggle? = null private var drawerToggle: ActionBarDrawerToggle? = null
@Inject lateinit var zimReaderContainer: ZimReaderContainer @Inject lateinit var zimReaderContainer: ZimReaderContainer
abstract val navController: NavController
/**
* We have migrated the UI in compose, so providing the compose based navigation to activity
* is responsibility of child activities such as KiwixMainActivity, and CustomMainActivity.
*/
lateinit var navController: NavHostController
// abstract val drawerContainerLayout: DrawerLayout // abstract val drawerContainerLayout: DrawerLayout
// abstract val drawerNavView: NavigationView // abstract val drawerNavView: NavigationView
@ -102,6 +102,7 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
abstract val helpFragmentResId: Int abstract val helpFragmentResId: Int
abstract val cachedComponent: CoreActivityComponent abstract val cachedComponent: CoreActivityComponent
abstract val topLevelDestinations: Set<Int> abstract val topLevelDestinations: Set<Int>
// abstract val navHostContainer: FragmentContainerView // abstract val navHostContainer: FragmentContainerView
abstract val mainActivity: AppCompatActivity abstract val mainActivity: AppCompatActivity
abstract val appName: String abstract val appName: String
@ -115,7 +116,7 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
@Suppress("InjectDispatcher") @Suppress("InjectDispatcher")
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
// setTheme(R.style.KiwixTheme) setTheme(R.style.KiwixTheme)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
if (!BuildConfig.DEBUG) { if (!BuildConfig.DEBUG) {
val appContext = applicationContext val appContext = applicationContext
@ -322,7 +323,7 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
return true return true
} }
private fun openHelpFragment() { protected fun openHelpFragment() {
navigate(helpFragmentResId) navigate(helpFragmentResId)
handleDrawerOnNavigation() handleDrawerOnNavigation()
} }
@ -490,6 +491,84 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider {
navigate(readerFragmentResId, bundleOf(FIND_IN_PAGE_SEARCH_STRING to searchString)) navigate(readerFragmentResId, bundleOf(FIND_IN_PAGE_SEARCH_STRING to searchString))
} }
private val bookRelatedDrawerGroup = DrawerMenuGroup(
listOfNotNull(
DrawerMenuItem(
title = CoreApp.instance.getString(R.string.bookmarks),
iconRes = R.drawable.ic_bookmark_black_24dp,
true,
onClick = { openBookmarks() }
),
DrawerMenuItem(
title = CoreApp.instance.getString(R.string.history),
iconRes = R.drawable.ic_history_24px,
true,
onClick = { openHistory() }
),
DrawerMenuItem(
title = CoreApp.instance.getString(R.string.pref_notes),
iconRes = R.drawable.ic_add_note,
true,
onClick = { openNotes() }
),
zimHostDrawerMenuItem
)
)
private val settingDrawerGroup = DrawerMenuGroup(
listOf(
DrawerMenuItem(
title = CoreApp.instance.getString(R.string.menu_settings),
iconRes = R.drawable.ic_settings_24px,
true,
onClick = { openSettings() }
)
)
)
open val helpAndSupportDrawerGroup = DrawerMenuGroup(
listOfNotNull(
helpDrawerMenuItem,
supportDrawerMenuItem,
aboutAppDrawerMenuItem
)
)
/**
* Returns the "Wi-Fi Hotspot" menu item in the left drawer.
* Currently, this feature is only included in the main Kiwix app.
* Custom apps do not include this item.
*/
abstract val zimHostDrawerMenuItem: DrawerMenuItem?
/**
* Returns the "Help" menu item in the left drawer.
* In custom apps, this item is hidden.
* Each app (main Kiwix or custom) provides its own implementation.
*/
abstract val helpDrawerMenuItem: DrawerMenuItem?
/**
* Returns the "Support" menu item in the left drawer.
* In custom apps, this item displays the application name dynamically.
* Child activities are responsible for defining this drawer item.
*/
abstract val supportDrawerMenuItem: DrawerMenuItem?
/**
* Returns the "About App" menu item in the left drawer.
* For custom apps, this item is shown if configured.
* It is not included in the main Kiwix app.
* Child activities are responsible for defining this drawer item.
*/
abstract val aboutAppDrawerMenuItem: DrawerMenuItem?
val rightNavigationDrawerMenuItems = listOf<DrawerMenuGroup>(
bookRelatedDrawerGroup,
settingDrawerGroup,
helpAndSupportDrawerGroup
)
protected abstract fun getIconResId(): Int protected abstract fun getIconResId(): Int
abstract val readerFragmentResId: Int abstract val readerFragmentResId: Int
abstract fun createApplicationShortcuts() abstract fun createApplicationShortcuts()

View File

@ -18,10 +18,11 @@
package org.kiwix.kiwixmobile.core.main package org.kiwix.kiwixmobile.core.main
import androidx.annotation.DrawableRes
data class DrawerMenuItem( data class DrawerMenuItem(
val id: Int,
val title: String, val title: String,
val iconRes: Int, @DrawableRes val iconRes: Int,
val visible: Boolean = true, val visible: Boolean = true,
val onClick: () -> Unit val onClick: () -> Unit
) )

View File

@ -28,16 +28,18 @@ import androidx.compose.material3.Icon
import androidx.compose.material3.ListItem import androidx.compose.material3.ListItem
import androidx.compose.material3.Surface import androidx.compose.material3.Surface
import androidx.compose.material3.Text import androidx.compose.material3.Text
import org.kiwix.kiwixmobile.core.R
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.painterResource
import org.kiwix.kiwixmobile.core.R
import org.kiwix.kiwixmobile.core.ui.models.IconItem
import org.kiwix.kiwixmobile.core.ui.models.toPainter
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.NAVIGATION_DRAWER_WIDTH import org.kiwix.kiwixmobile.core.utils.ComposeDimens.NAVIGATION_DRAWER_WIDTH
@Composable @Composable
fun MainDrawerMenu(drawerMenuGroupList: List<DrawerMenuGroup>) { fun LeftDrawerMenu(drawerMenuGroupList: List<DrawerMenuGroup>) {
Surface( Surface(
modifier = Modifier modifier = Modifier
.width(NAVIGATION_DRAWER_WIDTH) .width(NAVIGATION_DRAWER_WIDTH)
@ -47,7 +49,7 @@ fun MainDrawerMenu(drawerMenuGroupList: List<DrawerMenuGroup>) {
Column { Column {
// Banner image at the top // Banner image at the top
Image( Image(
painter = painterResource(id = R.drawable.ic_home_kiwix_banner), painter = IconItem.MipmapImage(R.drawable.ic_home_kiwix_banner).toPainter(),
contentDescription = null, contentDescription = null,
contentScale = ContentScale.FillWidth, contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
@ -60,7 +62,7 @@ fun MainDrawerMenu(drawerMenuGroupList: List<DrawerMenuGroup>) {
} }
@Composable @Composable
fun DrawerGroup(items: List<DrawerMenuItem>) { private fun DrawerGroup(items: List<DrawerMenuItem>) {
Column { Column {
items.filter { it.visible }.forEach { item -> items.filter { it.visible }.forEach { item ->
DrawerMenuItemView(item) DrawerMenuItemView(item)
@ -69,7 +71,7 @@ fun DrawerGroup(items: List<DrawerMenuItem>) {
} }
@Composable @Composable
fun DrawerMenuItemView(item: DrawerMenuItem) { private fun DrawerMenuItemView(item: DrawerMenuItem) {
ListItem( ListItem(
leadingContent = { leadingContent = {
Icon( Icon(

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.core.ui.models package org.kiwix.kiwixmobile.core.ui.models
import android.graphics.Bitmap
import android.graphics.Canvas import android.graphics.Canvas
import android.graphics.drawable.AdaptiveIconDrawable import android.graphics.drawable.AdaptiveIconDrawable
import android.graphics.drawable.BitmapDrawable import android.graphics.drawable.BitmapDrawable
@ -57,20 +58,19 @@ fun IconItem.toPainter(): Painter {
is IconItem.Drawable -> painterResource(drawableRes) is IconItem.Drawable -> painterResource(drawableRes)
is IconItem.ImageBitmap -> remember { BitmapPainter(bitmap) } is IconItem.ImageBitmap -> remember { BitmapPainter(bitmap) }
is IconItem.MipmapImage -> { is IconItem.MipmapImage -> {
val drawable = ContextCompat.getDrawable(LocalContext.current, mipmapResId) val context = LocalContext.current
val imageBitmap = when { val drawable = ContextCompat.getDrawable(context, mipmapResId)
drawable is BitmapDrawable -> drawable.bitmap.asImageBitmap() val imageBitmap = drawable?.let {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && drawable is AdaptiveIconDrawable -> { val width = it.intrinsicWidth.takeIf { w -> w > 0 } ?: 100
val bitmap = createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight) val height = it.intrinsicHeight.takeIf { h -> h > 0 } ?: 100
val canvas = Canvas(bitmap) val bitmap = createBitmap(width, height)
drawable.setBounds(0, 0, canvas.width, canvas.height) val canvas = Canvas(bitmap)
drawable.draw(canvas) it.setBounds(0, 0, canvas.width, canvas.height)
bitmap.asImageBitmap() it.draw(canvas)
} bitmap.asImageBitmap()
} ?: run {
else -> { // fallback empty bitmap if drawable is null
createBitmap(0, 0).asImageBitmap() createBitmap(1, 1).asImageBitmap()
}
} }
return remember { BitmapPainter(imageBitmap) } return remember { BitmapPainter(imageBitmap) }
} }

View File

@ -30,6 +30,7 @@ import androidx.drawerlayout.widget.DrawerLayout
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment import androidx.navigation.fragment.NavHostFragment
import com.google.android.material.navigation.NavigationView import com.google.android.material.navigation.NavigationView
import org.kiwix.kiwixmobile.core.CoreApp
import org.kiwix.kiwixmobile.core.R.drawable import org.kiwix.kiwixmobile.core.R.drawable
import org.kiwix.kiwixmobile.core.R.string import org.kiwix.kiwixmobile.core.R.string
import org.kiwix.kiwixmobile.core.extensions.applyEdgeToEdgeInsets import org.kiwix.kiwixmobile.core.extensions.applyEdgeToEdgeInsets
@ -37,6 +38,7 @@ import org.kiwix.kiwixmobile.core.extensions.browserIntent
import org.kiwix.kiwixmobile.core.extensions.getDialogHostComposeView import org.kiwix.kiwixmobile.core.extensions.getDialogHostComposeView
import org.kiwix.kiwixmobile.core.main.ACTION_NEW_TAB import org.kiwix.kiwixmobile.core.main.ACTION_NEW_TAB
import org.kiwix.kiwixmobile.core.main.CoreMainActivity import org.kiwix.kiwixmobile.core.main.CoreMainActivity
import org.kiwix.kiwixmobile.core.main.DrawerMenuItem
import org.kiwix.kiwixmobile.core.main.NEW_TAB_SHORTCUT_ID import org.kiwix.kiwixmobile.core.main.NEW_TAB_SHORTCUT_ID
import org.kiwix.kiwixmobile.core.utils.dialog.AlertDialogShower import org.kiwix.kiwixmobile.core.utils.dialog.AlertDialogShower
import org.kiwix.kiwixmobile.custom.BuildConfig import org.kiwix.kiwixmobile.custom.BuildConfig
@ -50,7 +52,7 @@ class CustomMainActivity : CoreMainActivity() {
supportFragmentManager.findFragmentById( supportFragmentManager.findFragmentById(
R.id.custom_nav_controller R.id.custom_nav_controller
) as NavHostFragment ) as NavHostFragment
) )
.navController .navController
} }
override val drawerContainerLayout: DrawerLayout by lazy { override val drawerContainerLayout: DrawerLayout by lazy {
@ -192,6 +194,73 @@ class CustomMainActivity : CoreMainActivity() {
override fun getIconResId() = R.mipmap.ic_launcher override fun getIconResId() = R.mipmap.ic_launcher
/**
* Hide the 'ZimHostFragment' option from the navigation menu
* because we are now using fd (FileDescriptor)
* to read the zim file from the asset folder. Currently,
* 'KiwixServer' is unable to host zim files via fd.
* This feature is temporarily removed for custom apps.
* We will re-enable it for custom apps once the issue is resolved.
* For more info see https://github.com/kiwix/kiwix-android/pull/3516,
* https://github.com/kiwix/kiwix-android/issues/4026
*/
override val zimHostDrawerMenuItem: DrawerMenuItem? = null
/**
* Hide the `HelpFragment` from custom apps.
* We have not removed the relevant code for `HelpFragment` from custom apps.
* If, in the future, we need to display this for all/some custom apps,
* we can either remove the line below or configure it according to the requirements.
* For more information, see https://github.com/kiwix/kiwix-android/issues/3584
*/
override val helpDrawerMenuItem: DrawerMenuItem? = null
override val supportDrawerMenuItem: DrawerMenuItem? =
/**
* If custom app is configured to show the "Support app_name" in navigation
* then show it navigation. "app_name" will be replaced with custom app name.
*/
if (BuildConfig.SUPPORT_URL.isNotEmpty()) {
DrawerMenuItem(
title = CoreApp.instance.getString(
string.menu_support_kiwix_for_custom_apps,
CoreApp.instance.getString(R.string.app_name)
),
iconRes = drawable.ic_support_24px,
true,
onClick = {
externalLinkOpener.openExternalUrl(BuildConfig.SUPPORT_URL.toUri().browserIntent(), false)
}
)
} else {
/**
* If custom app is not configured to show the "Support app_name" in navigation
* then remove it from navigation.
*/
null
}
/**
* If custom app is configured to show the "About app_name app" in navigation
* then show it navigation. "app_name" will be replaced with custom app name.
*/
override val aboutAppDrawerMenuItem: DrawerMenuItem? =
if (BuildConfig.ABOUT_APP_URL.isNotEmpty()) {
DrawerMenuItem(
title = CoreApp.instance.getString(
string.menu_about_app,
CoreApp.instance.getString(R.string.app_name)
),
iconRes = drawable.ic_baseline_info,
true,
onClick = {
externalLinkOpener.openExternalUrl(BuildConfig.SUPPORT_URL.toUri().browserIntent(), false)
}
)
} else {
null
}
override fun createApplicationShortcuts() { override fun createApplicationShortcuts() {
// Remove previously added dynamic shortcuts for old ids if any found. // Remove previously added dynamic shortcuts for old ids if any found.
removeOutdatedIdShortcuts() removeOutdatedIdShortcuts()