diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt index 0d4f73656c..11cc8e92db 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt @@ -370,6 +370,11 @@ abstract class CoreReaderFragment : } } + /** + * Handles the start of an action mode when the user selects text or content within a WebView. + * If no action mode is currently active, it configures the action mode to display a menu + * with the "Read Aloud" option. + */ override fun onActionModeStarted( mode: ActionMode, appCompatActivity: AppCompatActivity @@ -384,6 +389,11 @@ abstract class CoreReaderFragment : return FragmentActivityExtensions.Super.ShouldCall } + /** + * Handles the completion or termination of an action mode, typically when the user dismisses + * the contextual action bar. It sets the 'actionMode' variable to null, indicating that no + * action mode is currently active. + */ override fun onActionModeFinished( actionMode: ActionMode, activity: AppCompatActivity @@ -847,10 +857,19 @@ abstract class CoreReaderFragment : } } + /** + * Handles the action when an item is clicked within the NavigationHistory dialog. + * It loads the URL associated with the clicked item in the current WebView. + */ override fun onItemClicked(navigationHistoryListItem: NavigationHistoryListItem) { loadUrlWithCurrentWebview(navigationHistoryListItem.pageUrl) } + /** + * Clears the browsing history of the current WebView and updates the visibility + * of the bottom toolbar arrows. Additionally, it displays a toast message to + * indicate that the navigation history has been cleared. + */ override fun clearHistory() { getCurrentWebView()?.clearHistory() updateBottomToolbarArrowsAlpha() @@ -880,6 +899,20 @@ abstract class CoreReaderFragment : drawerLayout?.openDrawer(GravityCompat.END) } + /** + * Handles the back button press event within the Reader's UI. + * This method is overridden to implement custom behavior for back button interactions. + * It considers various UI states and performs appropriate actions based on the following conditions: + * + * 1. If the tab switcher is visible, it selects the current tab and hides the tab switcher. + * 2. If in full-screen mode, it exits full-screen mode. + * 3. If a `CompatFindActionModeCallback` is active, it finishes the callback. + * 4. If a drawer is open, it closes the drawer. + * 5. If the current WebView has navigation history, it navigates back. + * + * This ensures that the back button does not directly exit the app, but rather provides + * intuitive navigation and interaction with the Reader's UI. + */ @Suppress("ReturnCount") override fun onBackPressed(activity: AppCompatActivity): FragmentActivityExtensions.Super { when { @@ -1206,6 +1239,12 @@ abstract class CoreReaderFragment : else -> position } + /** + * Retrieves the current KiwixWebView based on the currentWebViewIndex. + * If no KiwixWebView is found in the webViewList, it creates a new main page tab. + * + * @return The current KiwixWebView instance to interact with or a newly created main page tab. + */ override fun getCurrentWebView(): KiwixWebView? { if (webViewList.size == 0) { return newMainPageTab() @@ -1233,6 +1272,11 @@ abstract class CoreReaderFragment : ) } + /** + * Handles the action when the user clicks on the full-screen mode toggle option in the menu. + * If the app is currently in full-screen mode, it exits full-screen mode. If not in full-screen mode, + * it enters full-screen mode for an immersive viewing experience. + */ override fun onFullscreenMenuClicked() { if (isInFullScreenMode()) { closeFullScreen() @@ -1241,6 +1285,13 @@ abstract class CoreReaderFragment : } } + /** + * Handles the action when the user clicks on the "Read Aloud" menu item. + * This method checks for notification permissions, and based on the visibility + * of Text-to-Speech (TTS) controls, it either initializes TTS and starts reading the selection, + * or it stops the current reading. Additionally, it manages the visibility of the + * "Back to Top" button when TTS is active. + */ @Suppress("NestedBlockDepth") override fun onReadAloudMenuClicked() { if (requireActivity().hasNotificationPermission(sharedPreferenceUtil)) { @@ -1286,16 +1337,30 @@ abstract class CoreReaderFragment : } } + /** + * Handles the action when the user clicks on the "Random Article" menu icon. + * This method triggers the action to open and display a random article within the app. + */ override fun onRandomArticleMenuClicked() { openRandomArticle() } + /** + * Handles the action when the user clicks on the "Add Note" menu icon. + * This method checks for external storage write permission for adding notes, + * and if permission is granted, it displays the "Add Note" dialog for creating a new note. + */ override fun onAddNoteMenuClicked() { if (requestExternalStorageWritePermissionForNotes()) { showAddNoteDialog() } } + /** + * Handles the action when the user clicks on the "Home" menu icon. + * This method checks if the tab switcher is visible; if so, it hides the tab switcher. + * Additionally, it creates a new tab, effectively taking the user to the home screen. + */ override fun onHomeMenuClicked() { if (tabSwitcherRoot?.visibility == View.VISIBLE) { hideTabSwitcher() @@ -1303,6 +1368,12 @@ abstract class CoreReaderFragment : createNewTab() } + /** + * Handles the action when the user clicks on the "Tab" menu icon. + * This method toggles the visibility of the tab switcher. If the tab switcher is currently + * visible, it hides it and selects the current tab. If the tab switcher is not visible, + * it shows the tab switcher, allowing the user to manage and navigate between open tabs. + */ override fun onTabMenuClicked() { if (tabSwitcherRoot?.visibility == View.VISIBLE) { hideTabSwitcher() @@ -1398,6 +1469,11 @@ abstract class CoreReaderFragment : sharedPreferenceUtil?.putPrefFullScreen(false) } + /** + * Handles the action of opening an external URL when a user clicks on an external link + * within the WebView. This method delegates the task to the externalLinkOpener, allowing + * the app to open the external link in the appropriate external application or browser. + */ override fun openExternalUrl(intent: Intent) { externalLinkOpener?.openExternalUrl(intent) } @@ -1703,6 +1779,13 @@ abstract class CoreReaderFragment : ) } + /** + * Handles incoming Intents when the application is launched or receives actions from outside. + * This method is invoked when the app is already running, and it processes incoming Intents + * by calling two specific handling methods: handleNotificationIntent for notifications + * and handleIntentActions for other actions. The method returns ShouldCall to proceed + * with the default behavior. + */ override fun onNewIntent( intent: Intent, activity: AppCompatActivity @@ -1767,6 +1850,11 @@ abstract class CoreReaderFragment : getCurrentWebView()?.pageUp(true) } + /** + * Handles the device's configuration change, such as a screen rotation. + * This method ensures that the RecyclerView children (tabs) are properly oriented after the + * configuration change by updating the RecyclerView adapter, which forces a redraw of the tabs. + */ override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) // Forcing redraw of RecyclerView children so that the tabs are properly oriented on rotation @@ -1865,6 +1953,11 @@ abstract class CoreReaderFragment : ) } + /** + * Handles actions when the WebView is in the process of loading a URL. + * If it's the first run of the app and not in debug mode, it displays a hint + * for the contents drawer, and updates the app's state to no longer be the first run. + */ override fun webViewUrlLoading() { if (isFirstRun && !BuildConfig.DEBUG) { contentsDrawerHint() @@ -1873,6 +1966,13 @@ abstract class CoreReaderFragment : } } + /** + * Handles actions when a URL has been successfully loaded by the WebView. + * This method performs a series of updates and checks, including updating the table of contents, + * notifying changes in the tabs adapter, updating the URL processor, adjusting the bottom toolbar + * arrows' visibility and opacity, saving the history of the loaded page, and updating other UI elements. + * These actions are carried out if the fragment is added to the activity. + */ override fun webViewUrlFinishedLoading() { if (isAdded) { updateTableOfContents() @@ -1909,6 +2009,11 @@ abstract class CoreReaderFragment : private fun hasValidFileAndUrl(url: String?, zimFileReader: ZimFileReader?): Boolean = url != null && zimFileReader != null + /** + * Handles actions when a URL fails to load in the WebView. + * This method displays a toast message with an error notification, indicating that the requested + * article URL was not found. The action is performed only if the fragment is added to the activity. + */ override fun webViewFailedLoading(url: String) { if (isAdded) { val error = String.format(getString(R.string.error_article_url_not_found), url) @@ -1916,6 +2021,13 @@ abstract class CoreReaderFragment : } } + /** + * Handles actions when the loading progress of a web page in the WebView changes. + * This method updates the progress bar's visibility and progress value, and it logs + * the loaded URL when the progress reaches 100%. Additionally, it triggers a menu + * invalidation to refresh the options menu based on the current context. + * The actions are performed only if the fragment is added to the activity. + */ @Suppress("MagicNumber") override fun webViewProgressChanged(progress: Int, webView: WebView) { if (isAdded) { @@ -1932,10 +2044,21 @@ abstract class CoreReaderFragment : } } + /** + * Handles actions when the WebView receives an updated title for the loaded web page. + * This method notifies the tabs adapter to update the title in response to the title change. + */ override fun webViewTitleUpdated(title: String) { tabsAdapter?.notifyDataSetChanged() } + /** + * Handles actions when the page changes within the WebView. + * This method is responsible for managing the Back to Top button's visibility based on the scroll position. + * If the feature is enabled and the scroll position exceeds a certain threshold, the Back to Top button + * is displayed. When the scroll position is within the threshold, the button is hidden. Additionally, + * it starts a timer to hide the Back to Top button after a certain time. + */ @Suppress("NestedBlockDepth", "MagicNumber") override fun webViewPageChanged(page: Int, maxPages: Int) { if (isBackToTopEnabled) { @@ -1963,6 +2086,14 @@ abstract class CoreReaderFragment : } } + /** + * Handles long-click events within the WebView, typically when a user long-clicks on a link or element. + * This method evaluates the URL clicked during the long-click and determines whether to override + * the event. If the URL meets specific criteria, such as being part of the app's content, a local file, + * or a UI-related URI, the event is handled. In such cases, the method may trigger a dialog to open + * the URL in a new tab. + */ + override fun webViewLongClick(url: String) { var handleEvent = false when { @@ -2066,6 +2197,11 @@ abstract class CoreReaderFragment : } } + /** + * Handles the action when the user pauses or resumes the text-to-speech (TTS) reading. + * This method checks the current TTS task, and if it's in the opposite state (paused/resumed) + * of the provided `isPauseTTS` parameter, it pauses the TTS reading. + */ override fun onReadAloudPauseOrResume(isPauseTTS: Boolean) { tts?.currentTTSTask?.let { if (it.paused != isPauseTTS) { @@ -2074,6 +2210,10 @@ abstract class CoreReaderFragment : } } + /** + * Handles the action when the user clicks on the "Stop" button in the "Read Aloud" menu. + * This method checks if there is an active TTS task, and if so, it stops the TTS reading. + */ override fun onReadAloudStop() { tts?.currentTTSTask?.let { stopTts()