From a6d5ef0636079c94d676fe67889d4bc995c5c108 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 6 Dec 2024 11:41:33 +0530 Subject: [PATCH 01/22] Saved webbackforwardlist to room --- .../kiwixmobile/core/dao/HistoryRoomDao.kt | 2 +- .../core/dao/PageHistoryRoomDao.kt | 45 ++++++++++++++++ .../dao/entities/PageHistoryRoomEntity.kt | 42 +++++++++++++++ .../kiwix/kiwixmobile/core/data/DataSource.kt | 5 ++ .../core/data/KiwixRoomDatabase.kt | 29 ++++++++-- .../kiwix/kiwixmobile/core/data/Repository.kt | 19 +++++++ .../core/di/components/CoreComponent.kt | 2 + .../core/di/modules/DatabaseModule.kt | 4 ++ .../core/main/CoreReaderFragment.kt | 45 ++++++++++++++++ .../core/main/MainRepositoryActions.kt | 15 ++++++ .../page/history/adapter/PageHistoryItem.kt | 54 +++++++++++++++++++ .../res/values-b+be+tarask+old/strings.xml | 33 +++++++++--- 12 files changed, 284 insertions(+), 11 deletions(-) create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/PageHistoryRoomEntity.kt create mode 100644 core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryRoomDao.kt index 79ab8bebbd..1c6aa3a474 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryRoomDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/HistoryRoomDao.kt @@ -69,7 +69,7 @@ abstract class HistoryRoomDao : PageDao { historyItem.dateString )?.let { it.apply { - // update the exiting entity + // update the existing entity historyUrl = historyItem.historyUrl historyTitle = historyItem.title timeStamp = historyItem.timeStamp diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt new file mode 100644 index 0000000000..93e8deaa35 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt @@ -0,0 +1,45 @@ +/* + * Kiwix Android + * Copyright (c) 2024 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.dao + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.Query +import io.reactivex.Flowable +import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity + +@Dao +abstract class PageHistoryRoomDao { + @Insert + abstract fun insertPageHistoryItem(pageHistoryRoomEntity: PageHistoryRoomEntity) + + @Query("SELECT * FROM PageHistoryRoomEntity") + abstract fun getAllPageHistory(): Flowable> + + @Query("Delete from PageHistoryRoomEntity") + abstract fun clearPageHistory() + + fun clearPageHistoryWithPrimaryKey() { + clearPageHistory() + resetPrimaryKey() + } + + @Query("DELETE FROM sqlite_sequence WHERE name='PageHistoryRoomEntity'") + abstract fun resetPrimaryKey() +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/PageHistoryRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/PageHistoryRoomEntity.kt new file mode 100644 index 0000000000..9acf14a571 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/PageHistoryRoomEntity.kt @@ -0,0 +1,42 @@ +/* + * Kiwix Android + * Copyright (c) 2024 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.dao.entities + +import androidx.room.Entity +import androidx.room.PrimaryKey +import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem + +@Entity +data class PageHistoryRoomEntity( + @PrimaryKey(autoGenerate = true) var id: Long = 0L, + val zimId: String, + val title: String, + val pageUrl: String, + val isForward: Boolean = false, + val timeStamp: Long +) { + constructor(pageHistoryItem: PageHistoryItem) : this( + pageHistoryItem.databaseId, + pageHistoryItem.zimId, + pageHistoryItem.title, + pageHistoryItem.pageUrl, + pageHistoryItem.isForward, + pageHistoryItem.timeStamp + ) +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt index 0b897b0393..3a2d4d20a3 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt @@ -23,6 +23,7 @@ import io.reactivex.Single import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem +import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.zim_manager.Language import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem @@ -53,4 +54,8 @@ interface DataSource { fun saveNote(noteListItem: NoteListItem): Completable fun deleteNote(noteTitle: String): Completable fun deleteNotes(noteList: List): Completable + + fun insertPageHistoryItem(pageHistory: PageHistoryItem): Completable + fun getAllPageHistory(): Flowable> + fun clearPageHistory(): Completable } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt index 44a50b6801..8ef77c1f47 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt @@ -29,10 +29,12 @@ import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao import org.kiwix.kiwixmobile.core.dao.HistoryRoomDao import org.kiwix.kiwixmobile.core.dao.HistoryRoomDaoCoverts import org.kiwix.kiwixmobile.core.dao.NotesRoomDao +import org.kiwix.kiwixmobile.core.dao.PageHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.HistoryRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity +import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter @@ -42,9 +44,10 @@ import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter RecentSearchRoomEntity::class, HistoryRoomEntity::class, NotesRoomEntity::class, - DownloadRoomEntity::class + DownloadRoomEntity::class, + PageHistoryRoomEntity::class ], - version = 7, + version = 8, exportSchema = false ) @TypeConverters(HistoryRoomDaoCoverts::class, ZimSourceRoomConverter::class) @@ -53,6 +56,7 @@ abstract class KiwixRoomDatabase : RoomDatabase() { abstract fun historyRoomDao(): HistoryRoomDao abstract fun notesRoomDao(): NotesRoomDao abstract fun downloadRoomDao(): DownloadRoomDao + abstract fun pageHistoryRoomDao(): PageHistoryRoomDao companion object { private var db: KiwixRoomDatabase? = null @@ -68,7 +72,8 @@ abstract class KiwixRoomDatabase : RoomDatabase() { MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6, - MIGRATION_6_7 + MIGRATION_6_7, + MIGRATION_7_8 ) .build().also { db = it } } @@ -271,6 +276,24 @@ abstract class KiwixRoomDatabase : RoomDatabase() { } } + @Suppress("MagicNumber") + private val MIGRATION_7_8 = object : Migration(7, 8) { + override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL( + """ + CREATE TABLE IF NOT EXISTS `PageHistoryRoomEntity` ( + `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, + `zimId` TEXT NOT NULL, + `title` TEXT NOT NULL, + `pageUrl` TEXT NOT NULL, + `isForward` INTEGER NOT NULL DEFAULT 0 + `timeStamp` INTEGER NOT NULL + ) + """ + ) + } + } + fun destroyInstance() { db = null } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt index de4c7884d4..90aeb258fd 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt @@ -28,13 +28,16 @@ import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.dao.NotesRoomDao +import org.kiwix.kiwixmobile.core.dao.PageHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao +import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity import org.kiwix.kiwixmobile.core.di.qualifiers.IO import org.kiwix.kiwixmobile.core.di.qualifiers.MainThread import org.kiwix.kiwixmobile.core.extensions.HeaderizableList import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem +import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.zim_manager.Language @@ -55,6 +58,7 @@ class Repository @Inject internal constructor( private val bookDao: NewBookDao, private val libkiwixBookmarks: LibkiwixBookmarks, private val historyRoomDao: HistoryRoomDao, + private val pageHistoryRoomDao: PageHistoryRoomDao, private val notesRoomDao: NotesRoomDao, private val languageDao: NewLanguagesDao, private val recentSearchRoomDao: RecentSearchRoomDao, @@ -144,6 +148,21 @@ class Repository @Inject internal constructor( Completable.fromAction { notesRoomDao.deleteNotes(noteList) } .subscribeOn(ioThread) + override fun insertPageHistoryItem(pageHistory: PageHistoryItem): Completable = + Completable.fromAction { + pageHistoryRoomDao.insertPageHistoryItem( + PageHistoryRoomEntity(pageHistory) + ) + } + .subscribeOn(io) + + override fun getAllPageHistory() = + pageHistoryRoomDao.getAllPageHistory() as Flowable> + + override fun clearPageHistory(): Completable = + Completable.fromAction(pageHistoryRoomDao::clearPageHistoryWithPrimaryKey) + .subscribeOn(io) + override fun deleteNote(noteTitle: String): Completable = Completable.fromAction { notesRoomDao.deleteNote(noteTitle) } .subscribeOn(ioThread) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt index 54a0405abf..a9c3560486 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt @@ -37,6 +37,7 @@ import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.dao.NewNoteDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao import org.kiwix.kiwixmobile.core.dao.NotesRoomDao +import org.kiwix.kiwixmobile.core.dao.PageHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao import org.kiwix.kiwixmobile.core.data.DataModule import org.kiwix.kiwixmobile.core.data.DataSource @@ -105,6 +106,7 @@ interface CoreComponent { fun libkiwixBookmarks(): LibkiwixBookmarks fun recentSearchRoomDao(): RecentSearchRoomDao fun historyRoomDao(): HistoryRoomDao + fun pageHistoryRoomDao(): PageHistoryRoomDao fun noteRoomDao(): NotesRoomDao fun objectBoxToRoomMigrator(): ObjectBoxToRoomMigrator fun context(): Context diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt index c7b374e5aa..667807cafc 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt @@ -86,6 +86,10 @@ open class DatabaseModule { @Singleton fun provideHistoryDao(db: KiwixRoomDatabase) = db.historyRoomDao() + @Provides + @Singleton + fun providePageHistoryRoomDao(db: KiwixRoomDatabase) = db.pageHistoryRoomDao() + @Singleton @Provides fun provideNoteRoomDao(db: KiwixRoomDatabase) = db.notesRoomDao() 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 6ad2b4cef1..584919aec3 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 @@ -135,6 +135,7 @@ import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryClickListener import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryDialog import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.page.history.adapter.NavigationHistoryListItem +import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudCallbacks import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudService import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudService.Companion.ACTION_PAUSE_OR_RESUME_TTS @@ -326,6 +327,7 @@ abstract class CoreReaderFragment : private lateinit var serviceConnection: ServiceConnection private var readAloudService: ReadAloudService? = null private var navigationHistoryList: MutableList = ArrayList() + private var pageTimeStamp: MutableList = ArrayList() private var isReadSelection = false private var isReadAloudServiceRunning = false private var readerLifeCycleScope: CoroutineScope? = null @@ -2364,9 +2366,51 @@ abstract class CoreReaderFragment : editor.apply() } + private fun saveWebBackForwardListToRoom() { + val webBackForwardList = getCurrentWebView()?.copyBackForwardList() + val currentIndex = webBackForwardList?.currentIndex + if (currentIndex != null) { + repositoryActions?.clearPageHistory() + // Save BackStack + webBackForwardList.let { historyList -> + (0 until historyList.currentIndex) + .asSequence() + .forEach { + val historyItem = webBackForwardList.getItemAtIndex(it) + val pageHistory = PageHistoryItem( + zimId = zimReaderContainer?.zimFileReader?.id ?: "", + title = historyItem.title, + pageUrl = historyItem.url, + isForward = false, + timeStamp = 0 + ) + repositoryActions?.savePageHistory(pageHistory) + } + } + + // Save ForwardStack + webBackForwardList.let { historyList -> + (historyList.currentIndex + 1 until webBackForwardList.size) + .asSequence() + .forEach { + val historyItem = webBackForwardList.getItemAtIndex(it) + val pageHistory = PageHistoryItem( + zimId = zimReaderContainer?.zimFileReader?.id ?: "", + title = historyItem.title, + pageUrl = historyItem.url, + isForward = true, + timeStamp = 0 + ) + repositoryActions?.savePageHistory(pageHistory) + } + } + } + } + override fun onPause() { super.onPause() saveTabStates() + saveWebBackForwardListToRoom() Log.d( TAG_KIWIX, "onPause Save current zim file to preferences: " + @@ -2416,6 +2460,7 @@ abstract class CoreReaderFragment : val zimFileReader = zimReaderContainer?.zimFileReader if (hasValidFileAndUrl(getCurrentWebView()?.url, zimFileReader)) { val timeStamp = System.currentTimeMillis() + pageTimeStamp.add(timeStamp) val sdf = SimpleDateFormat( "d MMM yyyy", getCurrentLocale( diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt index 5557c2b23c..a98eb705be 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt @@ -22,6 +22,7 @@ import org.kiwix.kiwixmobile.core.data.DataSource import org.kiwix.kiwixmobile.core.di.ActivityScope import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem +import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.utils.files.Log import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk @@ -36,6 +37,8 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour private var saveNoteDisposable: Disposable? = null private var saveBookDisposable: Disposable? = null private var deleteNoteDisposable: Disposable? = null + private var savePageHistoryDisposable: Disposable? = null + private var clearPageHistoryDisposable: Disposable? = null fun saveHistory(history: HistoryItem) { saveHistoryDisposable = dataSource.saveHistory(history) @@ -68,11 +71,23 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour .subscribe({}, { e -> Log.e(TAG, "Unable to save book", e) }) } + fun savePageHistory(pageHistory: PageHistoryItem) { + savePageHistoryDisposable = dataSource.insertPageHistoryItem(pageHistory) + .subscribe({}, { e -> Log.e(TAG, "Unable to save page history", e) }) + } + + fun clearPageHistory() { + clearPageHistoryDisposable = dataSource.clearPageHistory() + .subscribe({}, { e -> Log.e(TAG, "Unable to clear page history", e) }) + } + fun dispose() { saveHistoryDisposable?.dispose() saveBookmarkDisposable?.dispose() saveNoteDisposable?.dispose() deleteNoteDisposable?.dispose() saveBookDisposable?.dispose() + savePageHistoryDisposable?.dispose() + clearPageHistoryDisposable?.dispose() } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt new file mode 100644 index 0000000000..436ec1da71 --- /dev/null +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt @@ -0,0 +1,54 @@ +/* + * Kiwix Android + * Copyright (c) 2024 Kiwix + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package org.kiwix.kiwixmobile.core.page.history.adapter + +import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity + +data class PageHistoryItem( + val databaseId: Long = 0L, + val zimId: String, + val title: String, + val pageUrl: String, + val isForward: Boolean, + val timeStamp: Long +) { + constructor( + zimId: String, + title: String, + pageUrl: String, + isForward: Boolean, + timeStamp: Long + ) : this( + 0L, + zimId, + title, + pageUrl, + isForward, + timeStamp + ) + + constructor(pageHistoryRoomEntity: PageHistoryRoomEntity) : this( + pageHistoryRoomEntity.id, + pageHistoryRoomEntity.zimId, + pageHistoryRoomEntity.title, + pageHistoryRoomEntity.pageUrl, + pageHistoryRoomEntity.isForward, + pageHistoryRoomEntity.timeStamp + ) +} diff --git a/core/src/main/res/values-b+be+tarask+old/strings.xml b/core/src/main/res/values-b+be+tarask+old/strings.xml index f7b21eb9f4..e692b350e5 100644 --- a/core/src/main/res/values-b+be+tarask+old/strings.xml +++ b/core/src/main/res/values-b+be+tarask+old/strings.xml @@ -1,8 +1,4 @@ - Дапамога Галоўная @@ -15,28 +11,36 @@ Чытаць уголас Спыніць чытаньне ўголас Падтрымаць Kiwix + Падтрымка %s + Пра праграму %s Пункт доступу WiFi Захаваць мэдыя Узьнікла памылка пры захаваньні мэдыяфайлу! Мэдыя-файл захаваны як %s у Downloads/org.kiwix…/ + Пошук + Пошукавы сьпіс Абярыце файл зьместу (*.zim) Адкрыць спасылку ў новай укладцы? + Сэрвісны канал пункту досягу Падобна, што ваш пункт доступу ўжо ўключаны. Каб працягнуць, адключыце пункт доступу вай-фай. Перайсьці да наладаў вай-фаю Немагчыма запусьціць сэрвэр. Калі ласка, уключыце ваш пункт доступу Немагчыма запусьціць сэрвэр. + Дэталі вашага лякальнага пункту досягу. \nSSID: %1$s \nСпокліч: %2$s Памылка: абраны ZIM-файл ня знойдзены. Памылка: абраны файл не зьяўляецца слушным ZIM-файлам. Памылка: загрузка артыкула (Url: %1$s) не атрымалася. Інфармацыя Вэрсія - Начны рэжым - Паказваць артыкулы ў інвэртаваных колерах + Цёмны рэжым + Паказваць артыкулы ў інвэртаваных колерах Вярнуцца ўгару Паказваць кнопку ў канцы старонкі для пракручваньня ўверх Мова Абярыце мову - Мова гэтай старонкі не падтрымліваецца або адпаведныя зьвесткі мовы не былі ўсталяваныя. Артыкул можа быць няправільна прачытаны. + Удзельнікі й ліцэнзіі + Стваральнікі + Мова гэтай старонкі не падтрымліваецца. Артыкул можа быць няправільна прачытаны. Ня знойдзеныя ўсталяваныя праграмы для гэтага тыпу файлу Ня знойдзеныя загалоўкі зьместу Каб атрымаць доступ да зьместу оф-лайн, нам трэба мець доступ да вашага сховішча @@ -44,10 +48,16 @@ Выдаліць гэты элемэнт? Уся гісторыя ачышчаная Ачысьціць усю гісторыю? + Падзяліцца файламі ZIM з: Выдаліць + Скасаваць Нядаўні пошук выдалены + Каб убачыць зьмест артыкулу, можаце прагарнуць улева Зразумела Ці ведалі вы? + Скасаваць + Закладка закрытая + Закладкі закрытыя Закладка дададзеная Калі ласка, ацаніце нас Ацаніць! @@ -57,12 +67,21 @@ Адкрыць новую ўкладку на фоне Пры адкрыцьці новай укладкі, яна будзе адкрытая на заднім пляне Дадаткова + Пошук у Kiwix Прылада + Анляйн + Бібліятэка Што робіць Kiwix? + Хоць Kiwix першапачаткова быў распрацаваны для афляйнавай падтрымкі Вікіпэдыі, але можа чытаць іншыя віды зьместу. Дзе зьмест? Выбачайце, мы не змаглі выдаліць некаторыя файлы. Паспрабуйце скарыстацца файлавым кіраўніком. Спыніць загрузку? Вы ўпэўненыя, што хочаце спыніць гэтую загрузку? + Няўдалая спроба ініцыялізацыі Тэксту-ў-Размову. Калі ласка, паспрабуйце яшчэ раз + засталося + Сёньня + Учора + Папярэджваць падчас уводу вонкавых спасылак Вы ўводзіце вонкавую спасылку. Гэта можа прывесьці да зьняцьця грошай мабільным апэратарам ці проста не спрацаваць, калі вы знаходзіцеся ў офлайне. Хочаце працягнуць? Болей не пытаць Выбраныя мовы: From 64f1bc47e045ce22833e05775f817a2509f38ac0 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Tue, 22 Oct 2024 14:20:00 +0530 Subject: [PATCH 02/22] Retrieving page history from room --- .../core/dao/PageHistoryRoomDao.kt | 3 +- .../kiwix/kiwixmobile/core/data/DataSource.kt | 3 +- .../kiwix/kiwixmobile/core/data/Repository.kt | 9 ++- .../core/main/CoreReaderFragment.kt | 55 ++++++++++++++++--- .../core/main/MainRepositoryActions.kt | 11 ++++ .../page/history/adapter/PageHistoryItem.kt | 5 ++ 6 files changed, 71 insertions(+), 15 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt index 93e8deaa35..afe290bfa6 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt @@ -29,7 +29,7 @@ abstract class PageHistoryRoomDao { @Insert abstract fun insertPageHistoryItem(pageHistoryRoomEntity: PageHistoryRoomEntity) - @Query("SELECT * FROM PageHistoryRoomEntity") + @Query("SELECT * FROM PageHistoryRoomEntity ORDER BY isForward ASC,timestamp DESC") abstract fun getAllPageHistory(): Flowable> @Query("Delete from PageHistoryRoomEntity") @@ -37,7 +37,6 @@ abstract class PageHistoryRoomDao { fun clearPageHistoryWithPrimaryKey() { clearPageHistory() - resetPrimaryKey() } @Query("DELETE FROM sqlite_sequence WHERE name='PageHistoryRoomEntity'") diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt index 3a2d4d20a3..7c1cd599b7 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt @@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.core.data import io.reactivex.Completable import io.reactivex.Flowable import io.reactivex.Single +import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem @@ -56,6 +57,6 @@ interface DataSource { fun deleteNotes(noteList: List): Completable fun insertPageHistoryItem(pageHistory: PageHistoryItem): Completable - fun getAllPageHistory(): Flowable> + fun getAllPageHistory(): Single> fun clearPageHistory(): Completable } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt index 90aeb258fd..c7f2dc9af3 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt @@ -154,14 +154,17 @@ class Repository @Inject internal constructor( PageHistoryRoomEntity(pageHistory) ) } - .subscribeOn(io) + .subscribeOn(ioThread) override fun getAllPageHistory() = - pageHistoryRoomDao.getAllPageHistory() as Flowable> + pageHistoryRoomDao.getAllPageHistory() + .first(emptyList()) + .subscribeOn(ioThread) + .observeOn(mainThread) override fun clearPageHistory(): Completable = Completable.fromAction(pageHistoryRoomDao::clearPageHistoryWithPrimaryKey) - .subscribeOn(io) + .subscribeOn(ioThread) override fun deleteNote(noteTitle: String): Completable = Completable.fromAction { notesRoomDao.deleteNote(noteTitle) } 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 584919aec3..82ab05c7a5 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 @@ -133,6 +133,7 @@ import org.kiwix.kiwixmobile.core.navigateToAppSettings import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryClickListener import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryDialog +import org.kiwix.kiwixmobile.core.page.history.adapter.DataCallback import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.page.history.adapter.NavigationHistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem @@ -193,7 +194,8 @@ abstract class CoreReaderFragment : WebViewProvider, ReadAloudCallbacks, NavigationHistoryClickListener, - ShowDonationDialogCallback { + ShowDonationDialogCallback, + DataCallback { protected val webViewList: MutableList = ArrayList() private val webUrlsProcessor = BehaviorProcessor.create() private var fragmentReaderBinding: FragmentReaderBinding? = null @@ -327,7 +329,6 @@ abstract class CoreReaderFragment : private lateinit var serviceConnection: ServiceConnection private var readAloudService: ReadAloudService? = null private var navigationHistoryList: MutableList = ArrayList() - private var pageTimeStamp: MutableList = ArrayList() private var isReadSelection = false private var isReadAloudServiceRunning = false private var readerLifeCycleScope: CoroutineScope? = null @@ -990,6 +991,7 @@ abstract class CoreReaderFragment : override fun clearHistory() { getCurrentWebView()?.clearHistory() + repositoryActions?.clearPageHistory() updateBottomToolbarArrowsAlpha() toast(R.string.navigation_history_cleared) } @@ -1972,10 +1974,44 @@ abstract class CoreReaderFragment : } } + private fun loadWebViewHistory(pageHistory: List) { + val backStack = pageHistory.filter { !it.isForward } + val forwardStack = pageHistory.filter(PageHistoryItem::isForward) + activity.toast("${pageHistory.size} ${backStack.size}", Toast.LENGTH_LONG) + val currentPage = getCurrentWebView()?.copyBackForwardList()?.currentItem?.url + + // Now, restore the back and forward history manually + // First restore back history + backStack.indices.reversed() + .asSequence() + .map { backStack[it] } + .forEach { url -> loadUrlWithCurrentWebview(url.pageUrl) } + + loadUrlWithCurrentWebview(currentPage) + + forwardStack.indices.reversed() + .asSequence() + .map { forwardStack[it] } + .forEach { url -> loadUrlWithCurrentWebview(url.pageUrl) } + + repeat( + forwardStack.indices.count() + ) { getCurrentWebView()?.goBack() } + } + + override fun onDataFetched(pageHistory: List) { + loadWebViewHistory(pageHistory) + } + + override fun onError(error: Throwable) { + activity.toast(R.string.could_not_restore_tabs, Toast.LENGTH_LONG) + } + override fun onResume() { super.onResume() updateBottomToolbarVisibility() updateNightMode() + repositoryActions?.loadPageHistory(this) if (tts == null) { setUpTTS() } @@ -2369,8 +2405,9 @@ abstract class CoreReaderFragment : private fun saveWebBackForwardListToRoom() { val webBackForwardList = getCurrentWebView()?.copyBackForwardList() val currentIndex = webBackForwardList?.currentIndex + val zimId = zimReaderContainer?.zimFileReader?.id ?: "" + if (currentIndex != null) { - repositoryActions?.clearPageHistory() // Save BackStack webBackForwardList.let { historyList -> (0 until historyList.currentIndex) @@ -2378,11 +2415,11 @@ abstract class CoreReaderFragment : .forEach { val historyItem = webBackForwardList.getItemAtIndex(it) val pageHistory = PageHistoryItem( - zimId = zimReaderContainer?.zimFileReader?.id ?: "", + zimId = zimId, title = historyItem.title, pageUrl = historyItem.url, isForward = false, - timeStamp = 0 + timeStamp = it.toLong() ) repositoryActions?.savePageHistory(pageHistory) } @@ -2395,11 +2432,11 @@ abstract class CoreReaderFragment : .forEach { val historyItem = webBackForwardList.getItemAtIndex(it) val pageHistory = PageHistoryItem( - zimId = zimReaderContainer?.zimFileReader?.id ?: "", + zimId = zimId, title = historyItem.title, pageUrl = historyItem.url, isForward = true, - timeStamp = 0 + timeStamp = it.toLong() ) repositoryActions?.savePageHistory(pageHistory) } @@ -2409,8 +2446,9 @@ abstract class CoreReaderFragment : override fun onPause() { super.onPause() - saveTabStates() + repositoryActions?.clearPageHistory() saveWebBackForwardListToRoom() + saveTabStates() Log.d( TAG_KIWIX, "onPause Save current zim file to preferences: " + @@ -2460,7 +2498,6 @@ abstract class CoreReaderFragment : val zimFileReader = zimReaderContainer?.zimFileReader if (hasValidFileAndUrl(getCurrentWebView()?.url, zimFileReader)) { val timeStamp = System.currentTimeMillis() - pageTimeStamp.add(timeStamp) val sdf = SimpleDateFormat( "d MMM yyyy", getCurrentLocale( diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt index a98eb705be..6c621aec23 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt @@ -21,6 +21,7 @@ import io.reactivex.disposables.Disposable import org.kiwix.kiwixmobile.core.data.DataSource import org.kiwix.kiwixmobile.core.di.ActivityScope import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem +import org.kiwix.kiwixmobile.core.page.history.adapter.DataCallback import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem @@ -39,6 +40,7 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour private var deleteNoteDisposable: Disposable? = null private var savePageHistoryDisposable: Disposable? = null private var clearPageHistoryDisposable: Disposable? = null + private var getPageHistoryDisposable: Disposable? = null fun saveHistory(history: HistoryItem) { saveHistoryDisposable = dataSource.saveHistory(history) @@ -81,6 +83,14 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour .subscribe({}, { e -> Log.e(TAG, "Unable to clear page history", e) }) } + fun loadPageHistory(callBack: DataCallback) { + getPageHistoryDisposable = dataSource.getAllPageHistory() + .map { roomEntities -> + roomEntities.map(::PageHistoryItem) + } + .subscribe(callBack::onDataFetched) { e -> Log.e(TAG, "Unable to load page history", e) } + } + fun dispose() { saveHistoryDisposable?.dispose() saveBookmarkDisposable?.dispose() @@ -89,5 +99,6 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour saveBookDisposable?.dispose() savePageHistoryDisposable?.dispose() clearPageHistoryDisposable?.dispose() + getPageHistoryDisposable?.dispose() } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt index 436ec1da71..65c572e699 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt @@ -52,3 +52,8 @@ data class PageHistoryItem( pageHistoryRoomEntity.timeStamp ) } + +interface DataCallback { + fun onDataFetched(pageHistory: List) + fun onError(error: Throwable) +} From 5a7dc92e2cca3463b5d4910cc26ae905ca31ce0d Mon Sep 17 00:00:00 2001 From: Saifuddin Date: Thu, 19 Sep 2024 10:48:47 +0530 Subject: [PATCH 03/22] Restoring the internal webbackforwardlist --- .idea/codeStyles/Project.xml | 21 +----- .../core/dao/PageHistoryRoomDao.kt | 2 +- .../core/main/CoreReaderFragment.kt | 65 ++++++++++++++----- 3 files changed, 50 insertions(+), 38 deletions(-) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index ec9393b3a7..1e51fb58b9 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,7 +1,5 @@ - - + \ No newline at end of file diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt index afe290bfa6..d5d3b93a93 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt @@ -29,7 +29,7 @@ abstract class PageHistoryRoomDao { @Insert abstract fun insertPageHistoryItem(pageHistoryRoomEntity: PageHistoryRoomEntity) - @Query("SELECT * FROM PageHistoryRoomEntity ORDER BY isForward ASC,timestamp DESC") + @Query("SELECT * FROM PageHistoryRoomEntity ORDER BY isForward ASC,timestamp ASC") abstract fun getAllPageHistory(): Flowable> @Query("Delete from PageHistoryRoomEntity") 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 82ab05c7a5..4a9db790d1 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 @@ -1977,26 +1977,57 @@ abstract class CoreReaderFragment : private fun loadWebViewHistory(pageHistory: List) { val backStack = pageHistory.filter { !it.isForward } val forwardStack = pageHistory.filter(PageHistoryItem::isForward) - activity.toast("${pageHistory.size} ${backStack.size}", Toast.LENGTH_LONG) - val currentPage = getCurrentWebView()?.copyBackForwardList()?.currentItem?.url + val currentWebView = getCurrentWebView() ?: return + val currentPageUrl = currentWebView.copyBackForwardList().currentItem?.url - // Now, restore the back and forward history manually - // First restore back history - backStack.indices.reversed() - .asSequence() - .map { backStack[it] } - .forEach { url -> loadUrlWithCurrentWebview(url.pageUrl) } + // If backStack and forwardStack are empty, return + if (backStack.isEmpty() && forwardStack.isEmpty()) { + return + } - loadUrlWithCurrentWebview(currentPage) + // Debug info: Toast to check the size of back and forward stack + activity.toast( + "${pageHistory.size} items loaded. Back stack size: ${backStack.size}", + Toast.LENGTH_LONG + ) - forwardStack.indices.reversed() - .asSequence() - .map { forwardStack[it] } - .forEach { url -> loadUrlWithCurrentWebview(url.pageUrl) } + if (backStack.isNotEmpty()) { + // Step 1: Load the first item immediately (0th index) + currentWebView.loadUrl(backStack[0].pageUrl) + } + + currentWebView.postDelayed({ + // Step 2: Clear WebView history after loading the first page + currentWebView.clearHistory() + + // Step 3: Load the remaining items from the backStack (starting from index 1) + backStack.drop(1).forEachIndexed { index, page -> + currentWebView.postDelayed({ + currentWebView.loadUrl(page.pageUrl) + }, index * 500L) // Delay to load each page sequentially + } - repeat( - forwardStack.indices.count() - ) { getCurrentWebView()?.goBack() } + // Step 4: After loading the back stack, load the current page + currentWebView.postDelayed({ + currentPageUrl?.let(::loadUrlWithCurrentWebview) + }, backStack.size * 500L) + + // Step 5: Load forward stack URLs sequentially + currentWebView.postDelayed({ + forwardStack.forEachIndexed { index, page -> + currentWebView.postDelayed({ + currentWebView.loadUrl(page.pageUrl) + }, index * 500L) // Delay for loading forward stack + } + + // Step 6: After loading forward stack, go back to the current page + currentWebView.postDelayed({ + repeat(forwardStack.size) { + currentWebView.goBack() + } + }, forwardStack.size * 500L) // Delay based on forward stack size + }, (backStack.size + 1) * 500L) // Delay based on the back stack size + }, 500L) // Initial delay to allow the first page to load } override fun onDataFetched(pageHistory: List) { @@ -2009,9 +2040,9 @@ abstract class CoreReaderFragment : override fun onResume() { super.onResume() + repositoryActions?.loadPageHistory(this) updateBottomToolbarVisibility() updateNightMode() - repositoryActions?.loadPageHistory(this) if (tts == null) { setUpTTS() } From 775d9439f3992d3d6320e542b9db128dcde1bda1 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Thu, 19 Sep 2024 12:51:43 +0530 Subject: [PATCH 04/22] Fixed the detekt issue --- .../core/main/CoreReaderFragment.kt | 59 +++++++++++-------- 1 file changed, 33 insertions(+), 26 deletions(-) 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 4a9db790d1..826fb049ae 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 @@ -1974,6 +1974,7 @@ abstract class CoreReaderFragment : } } + @Suppress("MagicNumber") private fun loadWebViewHistory(pageHistory: List) { val backStack = pageHistory.filter { !it.isForward } val forwardStack = pageHistory.filter(PageHistoryItem::isForward) @@ -1996,38 +1997,44 @@ abstract class CoreReaderFragment : currentWebView.loadUrl(backStack[0].pageUrl) } - currentWebView.postDelayed({ - // Step 2: Clear WebView history after loading the first page - currentWebView.clearHistory() - - // Step 3: Load the remaining items from the backStack (starting from index 1) - backStack.drop(1).forEachIndexed { index, page -> - currentWebView.postDelayed({ - currentWebView.loadUrl(page.pageUrl) - }, index * 500L) // Delay to load each page sequentially - } - - // Step 4: After loading the back stack, load the current page - currentWebView.postDelayed({ - currentPageUrl?.let(::loadUrlWithCurrentWebview) - }, backStack.size * 500L) + currentWebView.postDelayed( + { + // Step 2: Clear WebView history after loading the first page + currentWebView.clearHistory() - // Step 5: Load forward stack URLs sequentially - currentWebView.postDelayed({ - forwardStack.forEachIndexed { index, page -> + // Step 3: Load the remaining items from the backStack (starting from index 1) + backStack.drop(1).forEachIndexed { index, page -> currentWebView.postDelayed({ currentWebView.loadUrl(page.pageUrl) - }, index * 500L) // Delay for loading forward stack + }, index * 500L) // Delay to load each page sequentially } - // Step 6: After loading forward stack, go back to the current page + // Step 4: After loading the back stack, load the current page currentWebView.postDelayed({ - repeat(forwardStack.size) { - currentWebView.goBack() - } - }, forwardStack.size * 500L) // Delay based on forward stack size - }, (backStack.size + 1) * 500L) // Delay based on the back stack size - }, 500L) // Initial delay to allow the first page to load + currentPageUrl?.let(::loadUrlWithCurrentWebview) + }, backStack.size * 500L) + + // Step 5: Load forward stack URLs sequentially + currentWebView.postDelayed( + { + forwardStack.forEachIndexed { index, page -> + currentWebView.postDelayed({ + currentWebView.loadUrl(page.pageUrl) + }, index * 500L) // Delay for loading forward stack + } + + // Step 6: After loading forward stack, go back to the current page + currentWebView.postDelayed({ + repeat(forwardStack.size) { + currentWebView.goBack() + } + }, forwardStack.size * 500L) // Delay based on forward stack size + }, + (backStack.size + 1) * 500L + ) // Delay based on the back stack size + }, + 500L + ) // Initial delay to allow the first page to load } override fun onDataFetched(pageHistory: List) { From b81e4b5c97f1bebe3211bd8a6adec807197d7ee2 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Tue, 22 Oct 2024 14:22:05 +0530 Subject: [PATCH 05/22] Naming convention improved --- ...oryRoomDao.kt => WebViewHistoryRoomDao.kt} | 16 ++--- ...yRoomEntity.kt => WebViewHistoryEntity.kt} | 18 ++--- .../kiwix/kiwixmobile/core/data/DataSource.kt | 10 +-- .../core/data/KiwixRoomDatabase.kt | 13 ++-- .../kiwix/kiwixmobile/core/data/Repository.kt | 22 +++--- .../core/di/components/CoreComponent.kt | 4 +- .../core/main/CoreReaderFragment.kt | 72 +++++++++---------- .../core/main/MainRepositoryActions.kt | 16 ++--- ...geHistoryItem.kt => WebViewHistoryItem.kt} | 20 +++--- 9 files changed, 92 insertions(+), 99 deletions(-) rename core/src/main/java/org/kiwix/kiwixmobile/core/dao/{PageHistoryRoomDao.kt => WebViewHistoryRoomDao.kt} (68%) rename core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/{PageHistoryRoomEntity.kt => WebViewHistoryEntity.kt} (73%) rename core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/{PageHistoryItem.kt => WebViewHistoryItem.kt} (73%) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/WebViewHistoryRoomDao.kt similarity index 68% rename from core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt rename to core/src/main/java/org/kiwix/kiwixmobile/core/dao/WebViewHistoryRoomDao.kt index d5d3b93a93..fe10889fd0 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/PageHistoryRoomDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/WebViewHistoryRoomDao.kt @@ -22,21 +22,21 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.Query import io.reactivex.Flowable -import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity +import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity @Dao -abstract class PageHistoryRoomDao { +abstract class WebViewHistoryRoomDao { @Insert - abstract fun insertPageHistoryItem(pageHistoryRoomEntity: PageHistoryRoomEntity) + abstract fun insertWebViewPageHistoryItem(webViewHistoryEntity: WebViewHistoryEntity) - @Query("SELECT * FROM PageHistoryRoomEntity ORDER BY isForward ASC,timestamp ASC") - abstract fun getAllPageHistory(): Flowable> + @Query("SELECT * FROM WebViewHistoryEntity ORDER BY isForward ASC,timestamp ASC") + abstract fun getAllWebViewPagesHistory(): Flowable> - @Query("Delete from PageHistoryRoomEntity") - abstract fun clearPageHistory() + @Query("Delete from WebViewHistoryEntity") + abstract fun clearWebViewPagesHistory() fun clearPageHistoryWithPrimaryKey() { - clearPageHistory() + clearWebViewPagesHistory() } @Query("DELETE FROM sqlite_sequence WHERE name='PageHistoryRoomEntity'") diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/PageHistoryRoomEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/WebViewHistoryEntity.kt similarity index 73% rename from core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/PageHistoryRoomEntity.kt rename to core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/WebViewHistoryEntity.kt index 9acf14a571..5ae7494bdd 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/PageHistoryRoomEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/WebViewHistoryEntity.kt @@ -20,10 +20,10 @@ package org.kiwix.kiwixmobile.core.dao.entities import androidx.room.Entity import androidx.room.PrimaryKey -import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem +import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem @Entity -data class PageHistoryRoomEntity( +data class WebViewHistoryEntity( @PrimaryKey(autoGenerate = true) var id: Long = 0L, val zimId: String, val title: String, @@ -31,12 +31,12 @@ data class PageHistoryRoomEntity( val isForward: Boolean = false, val timeStamp: Long ) { - constructor(pageHistoryItem: PageHistoryItem) : this( - pageHistoryItem.databaseId, - pageHistoryItem.zimId, - pageHistoryItem.title, - pageHistoryItem.pageUrl, - pageHistoryItem.isForward, - pageHistoryItem.timeStamp + constructor(webViewHistoryItem: WebViewHistoryItem) : this( + webViewHistoryItem.databaseId, + webViewHistoryItem.zimId, + webViewHistoryItem.title, + webViewHistoryItem.pageUrl, + webViewHistoryItem.isForward, + webViewHistoryItem.timeStamp ) } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt index 7c1cd599b7..db32ca28c4 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt @@ -20,11 +20,11 @@ package org.kiwix.kiwixmobile.core.data import io.reactivex.Completable import io.reactivex.Flowable import io.reactivex.Single -import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity +import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem -import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem +import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.zim_manager.Language import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem @@ -56,7 +56,7 @@ interface DataSource { fun deleteNote(noteTitle: String): Completable fun deleteNotes(noteList: List): Completable - fun insertPageHistoryItem(pageHistory: PageHistoryItem): Completable - fun getAllPageHistory(): Single> - fun clearPageHistory(): Completable + fun insertWebViewHistoryItem(pageHistory: WebViewHistoryItem): Completable + fun getAllWebViewPagesHistory(): Single> + fun clearWebViewPagesHistory(): Completable } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt index 8ef77c1f47..29d0ceb0cd 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt @@ -29,13 +29,13 @@ import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao import org.kiwix.kiwixmobile.core.dao.HistoryRoomDao import org.kiwix.kiwixmobile.core.dao.HistoryRoomDaoCoverts import org.kiwix.kiwixmobile.core.dao.NotesRoomDao -import org.kiwix.kiwixmobile.core.dao.PageHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao +import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.HistoryRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity -import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.RecentSearchRoomEntity +import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter @Suppress("UnnecessaryAbstractClass") @@ -45,7 +45,7 @@ import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter HistoryRoomEntity::class, NotesRoomEntity::class, DownloadRoomEntity::class, - PageHistoryRoomEntity::class + WebViewHistoryEntity::class ], version = 8, exportSchema = false @@ -56,7 +56,7 @@ abstract class KiwixRoomDatabase : RoomDatabase() { abstract fun historyRoomDao(): HistoryRoomDao abstract fun notesRoomDao(): NotesRoomDao abstract fun downloadRoomDao(): DownloadRoomDao - abstract fun pageHistoryRoomDao(): PageHistoryRoomDao + abstract fun pageHistoryRoomDao(): WebViewHistoryRoomDao companion object { private var db: KiwixRoomDatabase? = null @@ -279,14 +279,15 @@ abstract class KiwixRoomDatabase : RoomDatabase() { @Suppress("MagicNumber") private val MIGRATION_7_8 = object : Migration(7, 8) { override fun migrate(database: SupportSQLiteDatabase) { + database.execSQL("DROP TABLE PageHistoryRoomEntity") database.execSQL( """ - CREATE TABLE IF NOT EXISTS `PageHistoryRoomEntity` ( + CREATE TABLE IF NOT EXISTS `WebViewHistoryEntity` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `zimId` TEXT NOT NULL, `title` TEXT NOT NULL, `pageUrl` TEXT NOT NULL, - `isForward` INTEGER NOT NULL DEFAULT 0 + `isForward` INTEGER NOT NULL DEFAULT 0, `timeStamp` INTEGER NOT NULL ) """ diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt index c7f2dc9af3..56e0a10e88 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt @@ -28,16 +28,16 @@ import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.dao.NotesRoomDao -import org.kiwix.kiwixmobile.core.dao.PageHistoryRoomDao +import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao -import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity +import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity import org.kiwix.kiwixmobile.core.di.qualifiers.IO import org.kiwix.kiwixmobile.core.di.qualifiers.MainThread import org.kiwix.kiwixmobile.core.extensions.HeaderizableList import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem -import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem +import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.zim_manager.Language @@ -58,7 +58,7 @@ class Repository @Inject internal constructor( private val bookDao: NewBookDao, private val libkiwixBookmarks: LibkiwixBookmarks, private val historyRoomDao: HistoryRoomDao, - private val pageHistoryRoomDao: PageHistoryRoomDao, + private val webViewHistoryRoomDao: WebViewHistoryRoomDao, private val notesRoomDao: NotesRoomDao, private val languageDao: NewLanguagesDao, private val recentSearchRoomDao: RecentSearchRoomDao, @@ -148,22 +148,22 @@ class Repository @Inject internal constructor( Completable.fromAction { notesRoomDao.deleteNotes(noteList) } .subscribeOn(ioThread) - override fun insertPageHistoryItem(pageHistory: PageHistoryItem): Completable = + override fun insertWebViewHistoryItem(pageHistory: WebViewHistoryItem): Completable = Completable.fromAction { - pageHistoryRoomDao.insertPageHistoryItem( - PageHistoryRoomEntity(pageHistory) + webViewHistoryRoomDao.insertWebViewPageHistoryItem( + WebViewHistoryEntity(pageHistory) ) } .subscribeOn(ioThread) - override fun getAllPageHistory() = - pageHistoryRoomDao.getAllPageHistory() + override fun getAllWebViewPagesHistory() = + webViewHistoryRoomDao.getAllWebViewPagesHistory() .first(emptyList()) .subscribeOn(ioThread) .observeOn(mainThread) - override fun clearPageHistory(): Completable = - Completable.fromAction(pageHistoryRoomDao::clearPageHistoryWithPrimaryKey) + override fun clearWebViewPagesHistory(): Completable = + Completable.fromAction(webViewHistoryRoomDao::clearPageHistoryWithPrimaryKey) .subscribeOn(ioThread) override fun deleteNote(noteTitle: String): Completable = diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt index a9c3560486..9f7b1ce12a 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt @@ -37,7 +37,7 @@ import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.dao.NewNoteDao import org.kiwix.kiwixmobile.core.dao.NewRecentSearchDao import org.kiwix.kiwixmobile.core.dao.NotesRoomDao -import org.kiwix.kiwixmobile.core.dao.PageHistoryRoomDao +import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao import org.kiwix.kiwixmobile.core.data.DataModule import org.kiwix.kiwixmobile.core.data.DataSource @@ -106,7 +106,7 @@ interface CoreComponent { fun libkiwixBookmarks(): LibkiwixBookmarks fun recentSearchRoomDao(): RecentSearchRoomDao fun historyRoomDao(): HistoryRoomDao - fun pageHistoryRoomDao(): PageHistoryRoomDao + fun pageHistoryRoomDao(): WebViewHistoryRoomDao fun noteRoomDao(): NotesRoomDao fun objectBoxToRoomMigrator(): ObjectBoxToRoomMigrator fun context(): Context 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 826fb049ae..340f81f8da 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 @@ -136,7 +136,7 @@ import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryDialog import org.kiwix.kiwixmobile.core.page.history.adapter.DataCallback import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.page.history.adapter.NavigationHistoryListItem -import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem +import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudCallbacks import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudService import org.kiwix.kiwixmobile.core.read_aloud.ReadAloudService.Companion.ACTION_PAUSE_OR_RESUME_TTS @@ -991,7 +991,7 @@ abstract class CoreReaderFragment : override fun clearHistory() { getCurrentWebView()?.clearHistory() - repositoryActions?.clearPageHistory() + repositoryActions?.clearWebViewPagesHistory() updateBottomToolbarArrowsAlpha() toast(R.string.navigation_history_cleared) } @@ -1975,23 +1975,19 @@ abstract class CoreReaderFragment : } @Suppress("MagicNumber") - private fun loadWebViewHistory(pageHistory: List) { + private fun loadWebViewHistory(pageHistory: List) { val backStack = pageHistory.filter { !it.isForward } - val forwardStack = pageHistory.filter(PageHistoryItem::isForward) + val forwardStack = pageHistory.filter(WebViewHistoryItem::isForward) val currentWebView = getCurrentWebView() ?: return val currentPageUrl = currentWebView.copyBackForwardList().currentItem?.url + val currentZimId = zimReaderContainer?.zimFileReader?.id // If backStack and forwardStack are empty, return - if (backStack.isEmpty() && forwardStack.isEmpty()) { + if (backStack.isEmpty() && forwardStack.isEmpty() || currentZimId != pageHistory[0].zimId) { + repositoryActions?.clearWebViewPagesHistory() return } - // Debug info: Toast to check the size of back and forward stack - activity.toast( - "${pageHistory.size} items loaded. Back stack size: ${backStack.size}", - Toast.LENGTH_LONG - ) - if (backStack.isNotEmpty()) { // Step 1: Load the first item immediately (0th index) currentWebView.loadUrl(backStack[0].pageUrl) @@ -2037,7 +2033,7 @@ abstract class CoreReaderFragment : ) // Initial delay to allow the first page to load } - override fun onDataFetched(pageHistory: List) { + override fun onDataFetched(pageHistory: List) { loadWebViewHistory(pageHistory) } @@ -2047,7 +2043,7 @@ abstract class CoreReaderFragment : override fun onResume() { super.onResume() - repositoryActions?.loadPageHistory(this) + repositoryActions?.loadWebViewPagesHistory(this) updateBottomToolbarVisibility() updateNightMode() if (tts == null) { @@ -2448,43 +2444,39 @@ abstract class CoreReaderFragment : if (currentIndex != null) { // Save BackStack webBackForwardList.let { historyList -> - (0 until historyList.currentIndex) - .asSequence() - .forEach { - val historyItem = webBackForwardList.getItemAtIndex(it) - val pageHistory = PageHistoryItem( - zimId = zimId, - title = historyItem.title, - pageUrl = historyItem.url, - isForward = false, - timeStamp = it.toLong() - ) - repositoryActions?.savePageHistory(pageHistory) - } + for (index in 0 until historyList.currentIndex) { + val historyItem = historyList.getItemAtIndex(index) + val pageHistory = WebViewHistoryItem( + zimId = zimId, + title = historyItem.title, + pageUrl = historyItem.url, + isForward = false, + timeStamp = index.toLong() + ) + repositoryActions?.saveWebViewPageHistory(pageHistory) + } } // Save ForwardStack webBackForwardList.let { historyList -> - (historyList.currentIndex + 1 until webBackForwardList.size) - .asSequence() - .forEach { - val historyItem = webBackForwardList.getItemAtIndex(it) - val pageHistory = PageHistoryItem( - zimId = zimId, - title = historyItem.title, - pageUrl = historyItem.url, - isForward = true, - timeStamp = it.toLong() - ) - repositoryActions?.savePageHistory(pageHistory) - } + for (index in (historyList.currentIndex + 1) until historyList.size) { + val historyItem = historyList.getItemAtIndex(index) + val pageHistory = WebViewHistoryItem( + zimId = zimId, + title = historyItem.title, + pageUrl = historyItem.url, + isForward = true, + timeStamp = index.toLong() + ) + repositoryActions?.saveWebViewPageHistory(pageHistory) + } } } } override fun onPause() { super.onPause() - repositoryActions?.clearPageHistory() + repositoryActions?.clearWebViewPagesHistory() saveWebBackForwardListToRoom() saveTabStates() Log.d( diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt index 6c621aec23..8872398d30 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt @@ -23,7 +23,7 @@ import org.kiwix.kiwixmobile.core.di.ActivityScope import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.DataCallback import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem -import org.kiwix.kiwixmobile.core.page.history.adapter.PageHistoryItem +import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.utils.files.Log import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk @@ -73,20 +73,20 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour .subscribe({}, { e -> Log.e(TAG, "Unable to save book", e) }) } - fun savePageHistory(pageHistory: PageHistoryItem) { - savePageHistoryDisposable = dataSource.insertPageHistoryItem(pageHistory) + fun saveWebViewPageHistory(pageHistory: WebViewHistoryItem) { + savePageHistoryDisposable = dataSource.insertWebViewHistoryItem(pageHistory) .subscribe({}, { e -> Log.e(TAG, "Unable to save page history", e) }) } - fun clearPageHistory() { - clearPageHistoryDisposable = dataSource.clearPageHistory() + fun clearWebViewPagesHistory() { + clearPageHistoryDisposable = dataSource.clearWebViewPagesHistory() .subscribe({}, { e -> Log.e(TAG, "Unable to clear page history", e) }) } - fun loadPageHistory(callBack: DataCallback) { - getPageHistoryDisposable = dataSource.getAllPageHistory() + fun loadWebViewPagesHistory(callBack: DataCallback) { + getPageHistoryDisposable = dataSource.getAllWebViewPagesHistory() .map { roomEntities -> - roomEntities.map(::PageHistoryItem) + roomEntities.map(::WebViewHistoryItem) } .subscribe(callBack::onDataFetched) { e -> Log.e(TAG, "Unable to load page history", e) } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt similarity index 73% rename from core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt rename to core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt index 65c572e699..aa4e912861 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/PageHistoryItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt @@ -18,9 +18,9 @@ package org.kiwix.kiwixmobile.core.page.history.adapter -import org.kiwix.kiwixmobile.core.dao.entities.PageHistoryRoomEntity +import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity -data class PageHistoryItem( +data class WebViewHistoryItem( val databaseId: Long = 0L, val zimId: String, val title: String, @@ -43,17 +43,17 @@ data class PageHistoryItem( timeStamp ) - constructor(pageHistoryRoomEntity: PageHistoryRoomEntity) : this( - pageHistoryRoomEntity.id, - pageHistoryRoomEntity.zimId, - pageHistoryRoomEntity.title, - pageHistoryRoomEntity.pageUrl, - pageHistoryRoomEntity.isForward, - pageHistoryRoomEntity.timeStamp + constructor(webViewHistoryEntity: WebViewHistoryEntity) : this( + webViewHistoryEntity.id, + webViewHistoryEntity.zimId, + webViewHistoryEntity.title, + webViewHistoryEntity.pageUrl, + webViewHistoryEntity.isForward, + webViewHistoryEntity.timeStamp ) } interface DataCallback { - fun onDataFetched(pageHistory: List) + fun onDataFetched(pageHistory: List) fun onError(error: Throwable) } From cdf22a56f5b10d365498c915f4c5887fc898202f Mon Sep 17 00:00:00 2001 From: Saifuddin Date: Thu, 19 Sep 2024 23:05:32 +0530 Subject: [PATCH 06/22] Code factor improvements --- .../java/org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 340f81f8da..29e6ae617d 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 @@ -2459,7 +2459,7 @@ abstract class CoreReaderFragment : // Save ForwardStack webBackForwardList.let { historyList -> - for (index in (historyList.currentIndex + 1) until historyList.size) { + for (index in historyList.currentIndex + 1 until historyList.size) { val historyItem = historyList.getItemAtIndex(index) val pageHistory = WebViewHistoryItem( zimId = zimId, From 0d13e5b559aca1410d54f775de6c283b835a44e8 Mon Sep 17 00:00:00 2001 From: Saifuddin Date: Fri, 20 Sep 2024 18:37:39 +0530 Subject: [PATCH 07/22] Automated changes reverted --- .idea/codeStyles/Project.xml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 1e51fb58b9..ec9393b3a7 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -1,5 +1,7 @@ + - \ No newline at end of file + From a4c6070eab137e28324d6071aa61da6b35ebeae0 Mon Sep 17 00:00:00 2001 From: Saifuddin Date: Fri, 20 Sep 2024 18:54:09 +0530 Subject: [PATCH 08/22] Automated changes reverted --- .../res/values-b+be+tarask+old/strings.xml | 33 ++++--------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/core/src/main/res/values-b+be+tarask+old/strings.xml b/core/src/main/res/values-b+be+tarask+old/strings.xml index e692b350e5..f7b21eb9f4 100644 --- a/core/src/main/res/values-b+be+tarask+old/strings.xml +++ b/core/src/main/res/values-b+be+tarask+old/strings.xml @@ -1,4 +1,8 @@ + Дапамога Галоўная @@ -11,36 +15,28 @@ Чытаць уголас Спыніць чытаньне ўголас Падтрымаць Kiwix - Падтрымка %s - Пра праграму %s Пункт доступу WiFi Захаваць мэдыя Узьнікла памылка пры захаваньні мэдыяфайлу! Мэдыя-файл захаваны як %s у Downloads/org.kiwix…/ - Пошук - Пошукавы сьпіс Абярыце файл зьместу (*.zim) Адкрыць спасылку ў новай укладцы? - Сэрвісны канал пункту досягу Падобна, што ваш пункт доступу ўжо ўключаны. Каб працягнуць, адключыце пункт доступу вай-фай. Перайсьці да наладаў вай-фаю Немагчыма запусьціць сэрвэр. Калі ласка, уключыце ваш пункт доступу Немагчыма запусьціць сэрвэр. - Дэталі вашага лякальнага пункту досягу. \nSSID: %1$s \nСпокліч: %2$s Памылка: абраны ZIM-файл ня знойдзены. Памылка: абраны файл не зьяўляецца слушным ZIM-файлам. Памылка: загрузка артыкула (Url: %1$s) не атрымалася. Інфармацыя Вэрсія - Цёмны рэжым - Паказваць артыкулы ў інвэртаваных колерах + Начны рэжым + Паказваць артыкулы ў інвэртаваных колерах Вярнуцца ўгару Паказваць кнопку ў канцы старонкі для пракручваньня ўверх Мова Абярыце мову - Удзельнікі й ліцэнзіі - Стваральнікі - Мова гэтай старонкі не падтрымліваецца. Артыкул можа быць няправільна прачытаны. + Мова гэтай старонкі не падтрымліваецца або адпаведныя зьвесткі мовы не былі ўсталяваныя. Артыкул можа быць няправільна прачытаны. Ня знойдзеныя ўсталяваныя праграмы для гэтага тыпу файлу Ня знойдзеныя загалоўкі зьместу Каб атрымаць доступ да зьместу оф-лайн, нам трэба мець доступ да вашага сховішча @@ -48,16 +44,10 @@ Выдаліць гэты элемэнт? Уся гісторыя ачышчаная Ачысьціць усю гісторыю? - Падзяліцца файламі ZIM з: Выдаліць - Скасаваць Нядаўні пошук выдалены - Каб убачыць зьмест артыкулу, можаце прагарнуць улева Зразумела Ці ведалі вы? - Скасаваць - Закладка закрытая - Закладкі закрытыя Закладка дададзеная Калі ласка, ацаніце нас Ацаніць! @@ -67,21 +57,12 @@ Адкрыць новую ўкладку на фоне Пры адкрыцьці новай укладкі, яна будзе адкрытая на заднім пляне Дадаткова - Пошук у Kiwix Прылада - Анляйн - Бібліятэка Што робіць Kiwix? - Хоць Kiwix першапачаткова быў распрацаваны для афляйнавай падтрымкі Вікіпэдыі, але можа чытаць іншыя віды зьместу. Дзе зьмест? Выбачайце, мы не змаглі выдаліць некаторыя файлы. Паспрабуйце скарыстацца файлавым кіраўніком. Спыніць загрузку? Вы ўпэўненыя, што хочаце спыніць гэтую загрузку? - Няўдалая спроба ініцыялізацыі Тэксту-ў-Размову. Калі ласка, паспрабуйце яшчэ раз - засталося - Сёньня - Учора - Папярэджваць падчас уводу вонкавых спасылак Вы ўводзіце вонкавую спасылку. Гэта можа прывесьці да зьняцьця грошай мабільным апэратарам ці проста не спрацаваць, калі вы знаходзіцеся ў офлайне. Хочаце працягнуць? Болей не пытаць Выбраныя мовы: From 4cdd4495641ed48eefd3cb6123538b4544bcef41 Mon Sep 17 00:00:00 2001 From: Saifuddin Date: Fri, 11 Oct 2024 11:39:38 +0530 Subject: [PATCH 09/22] Updated room schema --- .../java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt index 29d0ceb0cd..ff333ef295 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt @@ -279,7 +279,6 @@ abstract class KiwixRoomDatabase : RoomDatabase() { @Suppress("MagicNumber") private val MIGRATION_7_8 = object : Migration(7, 8) { override fun migrate(database: SupportSQLiteDatabase) { - database.execSQL("DROP TABLE PageHistoryRoomEntity") database.execSQL( """ CREATE TABLE IF NOT EXISTS `WebViewHistoryEntity` ( From 5390c98d83c6e8f0ee62d2076ebd59ab4c218596 Mon Sep 17 00:00:00 2001 From: Saifuddin Date: Fri, 18 Oct 2024 11:02:41 +0530 Subject: [PATCH 10/22] Naming conventions improved and some reviewed changes --- .../core/data/KiwixRoomDatabase.kt | 2 +- .../core/di/components/CoreComponent.kt | 2 +- .../core/di/modules/DatabaseModule.kt | 2 +- .../core/main/CoreReaderFragment.kt | 72 ++++++++++--------- .../core/main/MainRepositoryActions.kt | 24 +++---- .../history/adapter/WebViewHistoryItem.kt | 2 +- core/src/main/res/values/strings.xml | 1 + 7 files changed, 57 insertions(+), 48 deletions(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt index ff333ef295..fab3b14777 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt @@ -56,7 +56,7 @@ abstract class KiwixRoomDatabase : RoomDatabase() { abstract fun historyRoomDao(): HistoryRoomDao abstract fun notesRoomDao(): NotesRoomDao abstract fun downloadRoomDao(): DownloadRoomDao - abstract fun pageHistoryRoomDao(): WebViewHistoryRoomDao + abstract fun webViewHistoryRoomDao(): WebViewHistoryRoomDao companion object { private var db: KiwixRoomDatabase? = null diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt index 9f7b1ce12a..367f47be06 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/components/CoreComponent.kt @@ -106,7 +106,7 @@ interface CoreComponent { fun libkiwixBookmarks(): LibkiwixBookmarks fun recentSearchRoomDao(): RecentSearchRoomDao fun historyRoomDao(): HistoryRoomDao - fun pageHistoryRoomDao(): WebViewHistoryRoomDao + fun webViewHistoryRoomDao(): WebViewHistoryRoomDao fun noteRoomDao(): NotesRoomDao fun objectBoxToRoomMigrator(): ObjectBoxToRoomMigrator fun context(): Context diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt index 667807cafc..31eb596cb7 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/di/modules/DatabaseModule.kt @@ -88,7 +88,7 @@ open class DatabaseModule { @Provides @Singleton - fun providePageHistoryRoomDao(db: KiwixRoomDatabase) = db.pageHistoryRoomDao() + fun provideWebViewHistoryRoomDao(db: KiwixRoomDatabase) = db.webViewHistoryRoomDao() @Singleton @Provides 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 29e6ae617d..1cdbf9d2b7 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 @@ -133,7 +133,7 @@ import org.kiwix.kiwixmobile.core.navigateToAppSettings import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryClickListener import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryDialog -import org.kiwix.kiwixmobile.core.page.history.adapter.DataCallback +import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryCallback import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.page.history.adapter.NavigationHistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem @@ -195,7 +195,7 @@ abstract class CoreReaderFragment : ReadAloudCallbacks, NavigationHistoryClickListener, ShowDonationDialogCallback, - DataCallback { + WebViewHistoryCallback { protected val webViewList: MutableList = ArrayList() private val webUrlsProcessor = BehaviorProcessor.create() private var fragmentReaderBinding: FragmentReaderBinding? = null @@ -991,7 +991,7 @@ abstract class CoreReaderFragment : override fun clearHistory() { getCurrentWebView()?.clearHistory() - repositoryActions?.clearWebViewPagesHistory() + repositoryActions?.clearWebViewPageHistory() updateBottomToolbarArrowsAlpha() toast(R.string.navigation_history_cleared) } @@ -1984,7 +1984,7 @@ abstract class CoreReaderFragment : // If backStack and forwardStack are empty, return if (backStack.isEmpty() && forwardStack.isEmpty() || currentZimId != pageHistory[0].zimId) { - repositoryActions?.clearWebViewPagesHistory() + repositoryActions?.clearWebViewPageHistory() return } @@ -2038,7 +2038,7 @@ abstract class CoreReaderFragment : } override fun onError(error: Throwable) { - activity.toast(R.string.could_not_restore_tabs, Toast.LENGTH_LONG) + activity.toast(R.string.could_not_restore_web_view_history, Toast.LENGTH_LONG) } override fun onResume() { @@ -2436,6 +2436,26 @@ abstract class CoreReaderFragment : editor.apply() } + private fun saveWebViewHistoryItems( + startIndex: Int, + endIndex: Int, + zimId: String, + isForward: Boolean, + historyList: WebBackForwardList + ) { + for (index in startIndex until endIndex) { + val historyItem = historyList.getItemAtIndex(index) + val pageHistory = WebViewHistoryItem( + zimId = zimId, + title = historyItem.title, + pageUrl = historyItem.url, + isForward = isForward, + timeStamp = index.toLong() + ) + repositoryActions?.saveWebViewPageHistory(pageHistory) + } + } + private fun saveWebBackForwardListToRoom() { val webBackForwardList = getCurrentWebView()?.copyBackForwardList() val currentIndex = webBackForwardList?.currentIndex @@ -2443,40 +2463,28 @@ abstract class CoreReaderFragment : if (currentIndex != null) { // Save BackStack - webBackForwardList.let { historyList -> - for (index in 0 until historyList.currentIndex) { - val historyItem = historyList.getItemAtIndex(index) - val pageHistory = WebViewHistoryItem( - zimId = zimId, - title = historyItem.title, - pageUrl = historyItem.url, - isForward = false, - timeStamp = index.toLong() - ) - repositoryActions?.saveWebViewPageHistory(pageHistory) - } - } + saveWebViewHistoryItems( + 0, + webBackForwardList.currentIndex, + zimId, + false, + webBackForwardList + ) // Save ForwardStack - webBackForwardList.let { historyList -> - for (index in historyList.currentIndex + 1 until historyList.size) { - val historyItem = historyList.getItemAtIndex(index) - val pageHistory = WebViewHistoryItem( - zimId = zimId, - title = historyItem.title, - pageUrl = historyItem.url, - isForward = true, - timeStamp = index.toLong() - ) - repositoryActions?.saveWebViewPageHistory(pageHistory) - } - } + saveWebViewHistoryItems( + currentIndex + 1, + webBackForwardList.size, + zimId, + true, + webBackForwardList + ) } } override fun onPause() { super.onPause() - repositoryActions?.clearWebViewPagesHistory() + repositoryActions?.clearWebViewPageHistory() saveWebBackForwardListToRoom() saveTabStates() Log.d( diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt index 8872398d30..3fb5d5abf0 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt @@ -21,7 +21,7 @@ import io.reactivex.disposables.Disposable import org.kiwix.kiwixmobile.core.data.DataSource import org.kiwix.kiwixmobile.core.di.ActivityScope import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem -import org.kiwix.kiwixmobile.core.page.history.adapter.DataCallback +import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryCallback import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem @@ -38,9 +38,9 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour private var saveNoteDisposable: Disposable? = null private var saveBookDisposable: Disposable? = null private var deleteNoteDisposable: Disposable? = null - private var savePageHistoryDisposable: Disposable? = null - private var clearPageHistoryDisposable: Disposable? = null - private var getPageHistoryDisposable: Disposable? = null + private var saveWebViewHistoryDisposable: Disposable? = null + private var clearWebViewHistoryDisposable: Disposable? = null + private var getWebViewHistoryDisposable: Disposable? = null fun saveHistory(history: HistoryItem) { saveHistoryDisposable = dataSource.saveHistory(history) @@ -74,17 +74,17 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour } fun saveWebViewPageHistory(pageHistory: WebViewHistoryItem) { - savePageHistoryDisposable = dataSource.insertWebViewHistoryItem(pageHistory) + saveWebViewHistoryDisposable = dataSource.insertWebViewHistoryItem(pageHistory) .subscribe({}, { e -> Log.e(TAG, "Unable to save page history", e) }) } - fun clearWebViewPagesHistory() { - clearPageHistoryDisposable = dataSource.clearWebViewPagesHistory() + fun clearWebViewPageHistory() { + clearWebViewHistoryDisposable = dataSource.clearWebViewPagesHistory() .subscribe({}, { e -> Log.e(TAG, "Unable to clear page history", e) }) } - fun loadWebViewPagesHistory(callBack: DataCallback) { - getPageHistoryDisposable = dataSource.getAllWebViewPagesHistory() + fun loadWebViewPagesHistory(callBack: WebViewHistoryCallback) { + getWebViewHistoryDisposable = dataSource.getAllWebViewPagesHistory() .map { roomEntities -> roomEntities.map(::WebViewHistoryItem) } @@ -97,8 +97,8 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour saveNoteDisposable?.dispose() deleteNoteDisposable?.dispose() saveBookDisposable?.dispose() - savePageHistoryDisposable?.dispose() - clearPageHistoryDisposable?.dispose() - getPageHistoryDisposable?.dispose() + saveWebViewHistoryDisposable?.dispose() + clearWebViewHistoryDisposable?.dispose() + getWebViewHistoryDisposable?.dispose() } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt index aa4e912861..fdcf7c8e4c 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt @@ -53,7 +53,7 @@ data class WebViewHistoryItem( ) } -interface DataCallback { +interface WebViewHistoryCallback { fun onDataFetched(pageHistory: List) fun onError(error: Throwable) } diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index bfac610fd6..fd674e90fc 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -233,6 +233,7 @@ Close all tabs Close tab Could not restore tabs. + Could not restore web view history Pending In Progress Complete From 1e9dfd1531f88372b965cc1f7840f7916daf6fe6 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Tue, 22 Oct 2024 14:39:34 +0530 Subject: [PATCH 11/22] Fixed detekt issue. --- core/detekt_baseline.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/detekt_baseline.xml b/core/detekt_baseline.xml index 6415a52a83..0d97ca687a 100644 --- a/core/detekt_baseline.xml +++ b/core/detekt_baseline.xml @@ -12,7 +12,7 @@ LongParameterList:MainMenu.kt$MainMenu$( private val activity: Activity, zimFileReader: ZimFileReader?, menu: Menu, webViews: MutableList<KiwixWebView>, urlIsValid: Boolean, disableReadAloud: Boolean = false, disableTabs: Boolean = false, private val menuClickListener: MenuClickListener ) LongParameterList:MainMenu.kt$MainMenu.Factory$( menu: Menu, webViews: MutableList<KiwixWebView>, urlIsValid: Boolean, menuClickListener: MenuClickListener, disableReadAloud: Boolean, disableTabs: Boolean ) LongParameterList:PageTestHelpers.kt$( bookmarkTitle: String = "bookmarkTitle", isSelected: Boolean = false, id: Long = 2, zimId: String = "zimId", zimName: String = "zimName", zimFilePath: String = "zimFilePath", bookmarkUrl: String = "bookmarkUrl", favicon: String = "favicon" ) - LongParameterList:Repository.kt$Repository$( @param:IO private val ioThread: Scheduler, @param:MainThread private val mainThread: Scheduler, private val bookDao: NewBookDao, private val libkiwixBookmarks: LibkiwixBookmarks, private val historyRoomDao: HistoryRoomDao, private val notesRoomDao: NotesRoomDao, private val languageDao: NewLanguagesDao, private val recentSearchRoomDao: RecentSearchRoomDao, private val zimReaderContainer: ZimReaderContainer ) + LongParameterList:Repository.kt$Repository$( @param:IO private val ioThread: Scheduler, @param:MainThread private val mainThread: Scheduler, private val bookDao: NewBookDao, private val libkiwixBookmarks: LibkiwixBookmarks, private val historyRoomDao: HistoryRoomDao, private val webViewHistoryRoomDao: WebViewHistoryRoomDao, private val notesRoomDao: NotesRoomDao, private val languageDao: NewLanguagesDao, private val recentSearchRoomDao: RecentSearchRoomDao, private val zimReaderContainer: ZimReaderContainer ) LongParameterList:ToolbarScrollingKiwixWebView.kt$ToolbarScrollingKiwixWebView$( context: Context, callback: WebViewCallback, attrs: AttributeSet, nonVideoView: ViewGroup, videoView: ViewGroup, webViewClient: CoreWebViewClient, private val toolbarView: View, private val bottomBarView: View, sharedPreferenceUtil: SharedPreferenceUtil, private val parentNavigationBar: View? = null ) MagicNumber:ArticleCount.kt$ArticleCount$3 MagicNumber:CompatFindActionModeCallback.kt$CompatFindActionModeCallback$100 From ee50417154926f4a542b8272ce07f2daca862417 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 6 Dec 2024 11:44:02 +0530 Subject: [PATCH 12/22] Implemented new approach to save and retrieve the webView history. --- .../destination/reader/KiwixReaderFragment.kt | 13 +- .../core/dao/WebViewHistoryRoomDao.kt | 9 +- .../core/dao/entities/WebViewHistoryEntity.kt | 42 ++- .../kiwix/kiwixmobile/core/data/DataSource.kt | 4 +- .../core/data/KiwixRoomDatabase.kt | 14 +- .../kiwix/kiwixmobile/core/data/Repository.kt | 16 +- .../core/main/CoreReaderFragment.kt | 272 +++++++----------- .../core/main/MainRepositoryActions.kt | 23 +- .../history/adapter/WebViewHistoryItem.kt | 34 +-- core/src/main/res/values/strings.xml | 1 - .../custom/main/CustomReaderFragment.kt | 27 +- 11 files changed, 204 insertions(+), 251 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt index eaf1c41311..3bc8e5c2b0 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt @@ -55,6 +55,7 @@ import org.kiwix.kiwixmobile.core.main.RestoreOrigin import org.kiwix.kiwixmobile.core.main.RestoreOrigin.FromExternalLaunch import org.kiwix.kiwixmobile.core.main.RestoreOrigin.FromSearchScreen import org.kiwix.kiwixmobile.core.main.ToolbarScrollingKiwixWebView +import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil @@ -248,22 +249,20 @@ class KiwixReaderFragment : CoreReaderFragment() { } /** - * Restores the view state based on the provided JSON data and restore origin. + * Restores the view state based on the provided webViewHistoryItemList data and restore origin. * * Depending on the `restoreOrigin`, this method either restores the last opened ZIM file * (if the launch is external) or skips re-opening the ZIM file when coming from the search screen, * as the ZIM file is already set in the reader. The method handles setting up the ZIM file and bookmarks, * and restores the tabs and positions from the provided data. * - * @param zimArticles JSON string representing the list of articles to be restored. - * @param zimPositions JSON string representing the positions of the restored articles. + * @param webViewHistoryItemList JSON string representing the list of articles to be restored. * @param currentTab Index of the tab to be restored as the currently active one. * @param restoreOrigin Indicates whether the restoration is triggered from an external launch or the search screen. */ override fun restoreViewStateOnValidJSON( - zimArticles: String?, - zimPositions: String?, + webViewHistoryItemList: List, currentTab: Int, restoreOrigin: RestoreOrigin ) { @@ -283,7 +282,7 @@ class KiwixReaderFragment : CoreReaderFragment() { } else { zimReaderContainer?.zimFileReader?.let(::setUpBookmarks) } - restoreTabs(zimArticles, zimPositions, currentTab) + restoreTabs(webViewHistoryItemList, currentTab) } else { getCurrentWebView()?.snack(string.zim_not_opened) exitBook() // hide the options for zim file to avoid unexpected UI behavior @@ -292,7 +291,7 @@ class KiwixReaderFragment : CoreReaderFragment() { } FromSearchScreen -> { - restoreTabs(zimArticles, zimPositions, currentTab) + restoreTabs(webViewHistoryItemList, currentTab) } } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/WebViewHistoryRoomDao.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/WebViewHistoryRoomDao.kt index fe10889fd0..19431f9687 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/WebViewHistoryRoomDao.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/WebViewHistoryRoomDao.kt @@ -26,10 +26,15 @@ import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity @Dao abstract class WebViewHistoryRoomDao { + + fun insertWebViewPageHistoryItem(webViewHistoryEntity: WebViewHistoryEntity) { + insertWebViewPageHistoryItems(listOf(webViewHistoryEntity)) + } + @Insert - abstract fun insertWebViewPageHistoryItem(webViewHistoryEntity: WebViewHistoryEntity) + abstract fun insertWebViewPageHistoryItems(webViewHistoryEntityList: List) - @Query("SELECT * FROM WebViewHistoryEntity ORDER BY isForward ASC,timestamp ASC") + @Query("SELECT * FROM WebViewHistoryEntity ORDER BY webViewIndex ASC") abstract fun getAllWebViewPagesHistory(): Flowable> @Query("Delete from WebViewHistoryEntity") diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/WebViewHistoryEntity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/WebViewHistoryEntity.kt index 5ae7494bdd..1e868b133b 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/WebViewHistoryEntity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/dao/entities/WebViewHistoryEntity.kt @@ -18,25 +18,51 @@ package org.kiwix.kiwixmobile.core.dao.entities +import android.os.Bundle +import android.os.Parcel import androidx.room.Entity import androidx.room.PrimaryKey +import androidx.room.TypeConverter +import androidx.room.TypeConverters import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem @Entity data class WebViewHistoryEntity( @PrimaryKey(autoGenerate = true) var id: Long = 0L, val zimId: String, - val title: String, - val pageUrl: String, - val isForward: Boolean = false, - val timeStamp: Long + val webViewIndex: Int, + val webViewCurrentPosition: Int, + @TypeConverters(BundleRoomConverter::class) + val webViewBackForwardListBundle: Bundle? ) { constructor(webViewHistoryItem: WebViewHistoryItem) : this( webViewHistoryItem.databaseId, webViewHistoryItem.zimId, - webViewHistoryItem.title, - webViewHistoryItem.pageUrl, - webViewHistoryItem.isForward, - webViewHistoryItem.timeStamp + webViewHistoryItem.webViewIndex, + webViewHistoryItem.webViewCurrentPosition, + webViewHistoryItem.webViewBackForwardListBundle, ) } + +class BundleRoomConverter { + @TypeConverter + fun convertToDatabaseValue(bundle: Bundle?): ByteArray? { + if (bundle == null) return null + val parcel = Parcel.obtain() + parcel.writeBundle(bundle) + val bytes = parcel.marshall() + parcel.recycle() + return bytes + } + + @TypeConverter + fun convertToEntityProperty(byteArray: ByteArray?): Bundle? { + if (byteArray == null) return null + val parcel = Parcel.obtain() + parcel.unmarshall(byteArray, 0, byteArray.size) + parcel.setDataPosition(0) + val bundle = parcel.readBundle(Bundle::class.java.classLoader) + parcel.recycle() + return bundle + } +} diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt index db32ca28c4..149258556c 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt @@ -56,7 +56,7 @@ interface DataSource { fun deleteNote(noteTitle: String): Completable fun deleteNotes(noteList: List): Completable - fun insertWebViewHistoryItem(pageHistory: WebViewHistoryItem): Completable + suspend fun insertWebViewPageHistoryItems(webViewHistoryEntityList: List) fun getAllWebViewPagesHistory(): Single> - fun clearWebViewPagesHistory(): Completable + suspend fun clearWebViewPagesHistory() } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt index fab3b14777..d918a82b91 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/KiwixRoomDatabase.kt @@ -31,6 +31,7 @@ import org.kiwix.kiwixmobile.core.dao.HistoryRoomDaoCoverts import org.kiwix.kiwixmobile.core.dao.NotesRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao +import org.kiwix.kiwixmobile.core.dao.entities.BundleRoomConverter import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.HistoryRoomEntity import org.kiwix.kiwixmobile.core.dao.entities.NotesRoomEntity @@ -50,7 +51,11 @@ import org.kiwix.kiwixmobile.core.dao.entities.ZimSourceRoomConverter version = 8, exportSchema = false ) -@TypeConverters(HistoryRoomDaoCoverts::class, ZimSourceRoomConverter::class) +@TypeConverters( + HistoryRoomDaoCoverts::class, + ZimSourceRoomConverter::class, + BundleRoomConverter::class +) abstract class KiwixRoomDatabase : RoomDatabase() { abstract fun recentSearchRoomDao(): RecentSearchRoomDao abstract fun historyRoomDao(): HistoryRoomDao @@ -284,10 +289,9 @@ abstract class KiwixRoomDatabase : RoomDatabase() { CREATE TABLE IF NOT EXISTS `WebViewHistoryEntity` ( `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `zimId` TEXT NOT NULL, - `title` TEXT NOT NULL, - `pageUrl` TEXT NOT NULL, - `isForward` INTEGER NOT NULL DEFAULT 0, - `timeStamp` INTEGER NOT NULL + `webViewIndex` INTEGER NOT NULL, + `webViewCurrentPosition` INTEGER NOT NULL, + `webViewBackForwardListBundle` BLOB NULL ) """ ) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt index 56e0a10e88..3a06d4f781 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt @@ -148,13 +148,9 @@ class Repository @Inject internal constructor( Completable.fromAction { notesRoomDao.deleteNotes(noteList) } .subscribeOn(ioThread) - override fun insertWebViewHistoryItem(pageHistory: WebViewHistoryItem): Completable = - Completable.fromAction { - webViewHistoryRoomDao.insertWebViewPageHistoryItem( - WebViewHistoryEntity(pageHistory) - ) - } - .subscribeOn(ioThread) + override suspend fun insertWebViewPageHistoryItems(webViewHistoryEntityList: List) { + webViewHistoryRoomDao.insertWebViewPageHistoryItems(webViewHistoryEntityList) + } override fun getAllWebViewPagesHistory() = webViewHistoryRoomDao.getAllWebViewPagesHistory() @@ -162,9 +158,9 @@ class Repository @Inject internal constructor( .subscribeOn(ioThread) .observeOn(mainThread) - override fun clearWebViewPagesHistory(): Completable = - Completable.fromAction(webViewHistoryRoomDao::clearPageHistoryWithPrimaryKey) - .subscribeOn(ioThread) + override suspend fun clearWebViewPagesHistory() { + webViewHistoryRoomDao.clearPageHistoryWithPrimaryKey() + } override fun deleteNote(noteTitle: String): Completable = Completable.fromAction { notesRoomDao.deleteNote(noteTitle) } 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 1cdbf9d2b7..69c3f3477c 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 @@ -99,7 +99,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.launch -import org.json.JSONArray +import kotlinx.coroutines.withContext import org.json.JSONException import org.kiwix.kiwixmobile.core.BuildConfig import org.kiwix.kiwixmobile.core.DarkModeConfig @@ -108,6 +108,7 @@ import org.kiwix.kiwixmobile.core.StorageObserver import org.kiwix.kiwixmobile.core.base.BaseFragment import org.kiwix.kiwixmobile.core.base.FragmentActivityExtensions import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks +import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity import org.kiwix.kiwixmobile.core.databinding.FragmentReaderBinding import org.kiwix.kiwixmobile.core.downloader.downloadManager.ZERO import org.kiwix.kiwixmobile.core.extensions.ActivityExtensions.consumeObservable @@ -133,7 +134,6 @@ import org.kiwix.kiwixmobile.core.navigateToAppSettings import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryClickListener import org.kiwix.kiwixmobile.core.page.history.NavigationHistoryDialog -import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryCallback import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.page.history.adapter.NavigationHistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem @@ -159,14 +159,11 @@ import org.kiwix.kiwixmobile.core.utils.REQUEST_POST_NOTIFICATION_PERMISSION import org.kiwix.kiwixmobile.core.utils.REQUEST_STORAGE_PERMISSION import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.StyleUtils.getAttributes -import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_ARTICLES import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_FILE -import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_POSITIONS import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_TAB import org.kiwix.kiwixmobile.core.utils.TAG_FILE_SEARCHED import org.kiwix.kiwixmobile.core.utils.TAG_FILE_SEARCHED_NEW_TAB import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX -import org.kiwix.kiwixmobile.core.utils.UpdateUtils.reformatProviderUrl import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower import org.kiwix.kiwixmobile.core.utils.dialog.KiwixDialog import org.kiwix.kiwixmobile.core.utils.dialog.UnsupportedMimeTypeHandler @@ -194,8 +191,7 @@ abstract class CoreReaderFragment : WebViewProvider, ReadAloudCallbacks, NavigationHistoryClickListener, - ShowDonationDialogCallback, - WebViewHistoryCallback { + ShowDonationDialogCallback { protected val webViewList: MutableList = ArrayList() private val webUrlsProcessor = BehaviorProcessor.create() private var fragmentReaderBinding: FragmentReaderBinding? = null @@ -289,6 +285,7 @@ abstract class CoreReaderFragment : private var bottomToolbarToc: ImageView? = null private var isFirstTimeMainPageLoaded = true + private var isFromManageExternalLaunch = false @JvmField @Inject @@ -991,7 +988,9 @@ abstract class CoreReaderFragment : override fun clearHistory() { getCurrentWebView()?.clearHistory() - repositoryActions?.clearWebViewPageHistory() + CoroutineScope(Dispatchers.IO).launch { + repositoryActions?.clearWebViewPageHistory() + } updateBottomToolbarArrowsAlpha() toast(R.string.navigation_history_cleared) } @@ -1307,7 +1306,7 @@ abstract class CoreReaderFragment : } } - private fun initalizeWebView(url: String): KiwixWebView? { + private fun initalizeWebView(url: String, shouldLoadUrl: Boolean = true): KiwixWebView? { if (isAdded) { val attrs = requireActivity().getAttributes(R.xml.webview) val webView: KiwixWebView? = try { @@ -1320,7 +1319,9 @@ abstract class CoreReaderFragment : null } webView?.let { - loadUrl(url, it) + if (shouldLoadUrl) { + loadUrl(url, it) + } setUpWithTextToSpeech(it) documentParser?.initInterface(it) ServiceWorkerUninitialiser(::openMainPage).initInterface(it) @@ -1353,8 +1354,12 @@ abstract class CoreReaderFragment : newTab(url, false) } - private fun newTab(url: String, selectTab: Boolean = true): KiwixWebView? { - val webView = initalizeWebView(url) + private fun newTab( + url: String, + selectTab: Boolean = true, + shouldLoadUrl: Boolean = true + ): KiwixWebView? { + val webView = initalizeWebView(url, shouldLoadUrl) webView?.let { webViewList.add(it) if (selectTab) { @@ -1709,7 +1714,12 @@ abstract class CoreReaderFragment : ) } - suspend fun openZimFile(zimReaderSource: ZimReaderSource, isCustomApp: Boolean = false) { + suspend fun openZimFile( + zimReaderSource: ZimReaderSource, + isCustomApp: Boolean = false, + isFromManageExternalLaunch: Boolean = false + ) { + this.isFromManageExternalLaunch = isFromManageExternalLaunch if (hasPermission(Manifest.permission.READ_EXTERNAL_STORAGE) || isCustomApp) { if (zimReaderSource.canOpenInLibkiwix()) { // Show content if there is `Open Library` button showing @@ -1755,7 +1765,9 @@ abstract class CoreReaderFragment : val zimFileReader = zimReaderContainer.zimFileReader zimFileReader?.let { zimFileReader -> // uninitialized the service worker to fix https://github.com/kiwix/kiwix-android/issues/2561 - openArticle(UNINITIALISER_ADDRESS) + if (!isFromManageExternalLaunch) { + openArticle(UNINITIALISER_ADDRESS) + } mainMenu?.onFileOpened(urlIsValid()) setUpBookmarks(zimFileReader) } ?: kotlin.run { @@ -1974,76 +1986,8 @@ abstract class CoreReaderFragment : } } - @Suppress("MagicNumber") - private fun loadWebViewHistory(pageHistory: List) { - val backStack = pageHistory.filter { !it.isForward } - val forwardStack = pageHistory.filter(WebViewHistoryItem::isForward) - val currentWebView = getCurrentWebView() ?: return - val currentPageUrl = currentWebView.copyBackForwardList().currentItem?.url - val currentZimId = zimReaderContainer?.zimFileReader?.id - - // If backStack and forwardStack are empty, return - if (backStack.isEmpty() && forwardStack.isEmpty() || currentZimId != pageHistory[0].zimId) { - repositoryActions?.clearWebViewPageHistory() - return - } - - if (backStack.isNotEmpty()) { - // Step 1: Load the first item immediately (0th index) - currentWebView.loadUrl(backStack[0].pageUrl) - } - - currentWebView.postDelayed( - { - // Step 2: Clear WebView history after loading the first page - currentWebView.clearHistory() - - // Step 3: Load the remaining items from the backStack (starting from index 1) - backStack.drop(1).forEachIndexed { index, page -> - currentWebView.postDelayed({ - currentWebView.loadUrl(page.pageUrl) - }, index * 500L) // Delay to load each page sequentially - } - - // Step 4: After loading the back stack, load the current page - currentWebView.postDelayed({ - currentPageUrl?.let(::loadUrlWithCurrentWebview) - }, backStack.size * 500L) - - // Step 5: Load forward stack URLs sequentially - currentWebView.postDelayed( - { - forwardStack.forEachIndexed { index, page -> - currentWebView.postDelayed({ - currentWebView.loadUrl(page.pageUrl) - }, index * 500L) // Delay for loading forward stack - } - - // Step 6: After loading forward stack, go back to the current page - currentWebView.postDelayed({ - repeat(forwardStack.size) { - currentWebView.goBack() - } - }, forwardStack.size * 500L) // Delay based on forward stack size - }, - (backStack.size + 1) * 500L - ) // Delay based on the back stack size - }, - 500L - ) // Initial delay to allow the first page to load - } - - override fun onDataFetched(pageHistory: List) { - loadWebViewHistory(pageHistory) - } - - override fun onError(error: Throwable) { - activity.toast(R.string.could_not_restore_web_view_history, Toast.LENGTH_LONG) - } - override fun onResume() { super.onResume() - repositoryActions?.loadWebViewPagesHistory(this) updateBottomToolbarVisibility() updateNightMode() if (tts == null) { @@ -2417,75 +2361,53 @@ abstract class CoreReaderFragment : } private fun saveTabStates() { - val settings = requireActivity().getSharedPreferences( - SharedPreferenceUtil.PREF_KIWIX_MOBILE, - 0 - ) - val editor = settings.edit() - val urls = JSONArray() - val positions = JSONArray() - for (view in webViewList) { - if (view.url == null) continue - urls.put(view.url) - positions.put(view.scrollY) - } - editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase()) - editor.putString(TAG_CURRENT_ARTICLES, "$urls") - editor.putString(TAG_CURRENT_POSITIONS, "$positions") - editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex) - editor.apply() - } - - private fun saveWebViewHistoryItems( - startIndex: Int, - endIndex: Int, - zimId: String, - isForward: Boolean, - historyList: WebBackForwardList - ) { - for (index in startIndex until endIndex) { - val historyItem = historyList.getItemAtIndex(index) - val pageHistory = WebViewHistoryItem( - zimId = zimId, - title = historyItem.title, - pageUrl = historyItem.url, - isForward = isForward, - timeStamp = index.toLong() - ) - repositoryActions?.saveWebViewPageHistory(pageHistory) - } - } - - private fun saveWebBackForwardListToRoom() { - val webBackForwardList = getCurrentWebView()?.copyBackForwardList() - val currentIndex = webBackForwardList?.currentIndex - val zimId = zimReaderContainer?.zimFileReader?.id ?: "" - - if (currentIndex != null) { - // Save BackStack - saveWebViewHistoryItems( - 0, - webBackForwardList.currentIndex, - zimId, - false, - webBackForwardList + CoroutineScope(Dispatchers.Main).launch { + // clear the previous history saved in database + withContext(Dispatchers.IO) { + repositoryActions?.clearWebViewPageHistory() + } + val settings = requireActivity().getSharedPreferences( + SharedPreferenceUtil.PREF_KIWIX_MOBILE, + 0 ) - - // Save ForwardStack - saveWebViewHistoryItems( - currentIndex + 1, - webBackForwardList.size, - zimId, - true, - webBackForwardList + val editor = settings.edit() + val webViewHistoryEntityList = arrayListOf() + webViewList.forEachIndexed { index, view -> + if (view.url == null) return@forEachIndexed + getWebViewHistoryEntity(view, index)?.let(webViewHistoryEntityList::add) + } + withContext(Dispatchers.IO) { + repositoryActions?.saveWebViewPageHistory(webViewHistoryEntityList) + } + editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase()) + editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex) + editor.apply() + } + } + + private fun getWebViewHistoryEntity( + webView: KiwixWebView, + webViewIndex: Int + ): WebViewHistoryEntity? { + val bundle = Bundle() + val webBackForwardList = webView.saveState(bundle) + val zimId = zimReaderContainer?.zimFileReader?.id + + if (zimId != null && webBackForwardList != null && webBackForwardList.size > 0) { + return WebViewHistoryEntity( + WebViewHistoryItem( + zimId = zimId, + webViewIndex = webViewIndex, + webViewPosition = webView.scrollY, + webViewBackForwardList = bundle + ) ) } + return null } override fun onPause() { super.onPause() - repositoryActions?.clearWebViewPageHistory() - saveWebBackForwardListToRoom() saveTabStates() Log.d( TAG_KIWIX, @@ -2512,9 +2434,9 @@ abstract class CoreReaderFragment : // it will not remove the service worker from the history, so it will remain in the history. // To clear this, we are clearing the history when the main page is loaded for the first time. val mainPageUrl = zimReaderContainer?.mainPage - if (mainPageUrl != null && - isFirstTimeMainPageLoaded && - getCurrentWebView()?.url?.endsWith(mainPageUrl) == true + if (isFirstTimeMainPageLoaded && + !isFromManageExternalLaunch && + mainPageUrl?.let { getCurrentWebView()?.url?.endsWith(it) } == true ) { // Set isFirstTimeMainPageLoaded to false. This ensures that if the user clicks // on the home menu after visiting multiple pages, the history will not be erased. @@ -2673,9 +2595,7 @@ abstract class CoreReaderFragment : ) } - private fun isInvalidJson(jsonString: String?): Boolean = - jsonString == null || jsonString == "[]" - + @SuppressLint("CheckResult") protected fun manageExternalLaunchAndRestoringViewState( restoreOrigin: RestoreOrigin = FromExternalLaunch ) { @@ -2683,14 +2603,22 @@ abstract class CoreReaderFragment : SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0 ) - val zimArticles = settings.getString(TAG_CURRENT_ARTICLES, null) - val zimPositions = settings.getString(TAG_CURRENT_POSITIONS, null) val currentTab = safelyGetCurrentTab(settings) - if (isInvalidJson(zimArticles) || isInvalidJson(zimPositions)) { - restoreViewStateOnInvalidJSON() - } else { - restoreViewStateOnValidJSON(zimArticles, zimPositions, currentTab, restoreOrigin) - } + repositoryActions?.loadWebViewPagesHistory() + ?.subscribe({ webViewHistoryItemList -> + Log.e( + "VALID_DATA", + "manageExternalLaunchAndRestoringViewState: ${webViewHistoryItemList.size}" + ) + if (webViewHistoryItemList.isEmpty()) { + restoreViewStateOnInvalidJSON() + return@subscribe + } + restoreViewStateOnValidJSON(webViewHistoryItemList, currentTab, restoreOrigin) + }, { + Log.e("INVALID_DATA", "manageExternalLaunchAndRestoringViewState: $it") + restoreViewStateOnInvalidJSON() + }) } private fun safelyGetCurrentTab(settings: SharedPreferences): Int = @@ -2699,30 +2627,22 @@ abstract class CoreReaderFragment : /* This method restores tabs state in new launches, do not modify it unless it is explicitly mentioned in the issue you're fixing */ protected fun restoreTabs( - zimArticles: String?, - zimPositions: String?, + webViewHistoryItemList: List, currentTab: Int ) { try { - val urls = JSONArray(zimArticles) - val positions = JSONArray(zimPositions) currentWebViewIndex = 0 tabsAdapter?.apply { + webViewList.removeAt(0) notifyItemRemoved(0) notifyDataSetChanged() } - var cursor = 0 - getCurrentWebView()?.let { kiwixWebView -> - kiwixWebView.loadUrl(reformatProviderUrl(urls.getString(cursor))) - kiwixWebView.scrollY = positions.getInt(cursor) - cursor++ - while (cursor < urls.length()) { - newTab(reformatProviderUrl(urls.getString(cursor))) - kiwixWebView.scrollY = positions.getInt(cursor) - cursor++ + webViewHistoryItemList.forEach { webViewHistoryItem -> + newTab("", shouldLoadUrl = false)?.let { + restoreTabState(it, webViewHistoryItem) } - selectTab(currentTab) } + selectTab(currentTab) } catch (e: JSONException) { Log.w(TAG_KIWIX, "Kiwix shared preferences corrupted", e) activity.toast(R.string.could_not_restore_tabs, Toast.LENGTH_LONG) @@ -2751,6 +2671,13 @@ abstract class CoreReaderFragment : ) } + private fun restoreTabState(webView: KiwixWebView, webViewHistoryItem: WebViewHistoryItem?) { + webViewHistoryItem?.webViewBackForwardListBundle?.let { bundle -> + webView.restoreState(bundle) + webView.scrollY = webViewHistoryItem.webViewCurrentPosition + } + } + override fun onReadAloudPauseOrResume(isPauseTTS: Boolean) { tts?.currentTTSTask?.let { if (it.paused != isPauseTTS) { @@ -2825,8 +2752,7 @@ abstract class CoreReaderFragment : * when handling valid JSON scenarios. */ protected abstract fun restoreViewStateOnValidJSON( - zimArticles: String?, - zimPositions: String?, + webViewHistoryItemList: List, currentTab: Int, restoreOrigin: RestoreOrigin ) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt index 3fb5d5abf0..1b9b60cd71 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainRepositoryActions.kt @@ -17,11 +17,12 @@ */ package org.kiwix.kiwixmobile.core.main +import io.reactivex.Single import io.reactivex.disposables.Disposable +import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity import org.kiwix.kiwixmobile.core.data.DataSource import org.kiwix.kiwixmobile.core.di.ActivityScope import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem -import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryCallback import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem @@ -73,23 +74,23 @@ class MainRepositoryActions @Inject constructor(private val dataSource: DataSour .subscribe({}, { e -> Log.e(TAG, "Unable to save book", e) }) } - fun saveWebViewPageHistory(pageHistory: WebViewHistoryItem) { - saveWebViewHistoryDisposable = dataSource.insertWebViewHistoryItem(pageHistory) - .subscribe({}, { e -> Log.e(TAG, "Unable to save page history", e) }) + suspend fun saveWebViewPageHistory(webViewHistoryEntityList: List) { + dataSource.insertWebViewPageHistoryItems(webViewHistoryEntityList) } - fun clearWebViewPageHistory() { - clearWebViewHistoryDisposable = dataSource.clearWebViewPagesHistory() - .subscribe({}, { e -> Log.e(TAG, "Unable to clear page history", e) }) + suspend fun clearWebViewPageHistory() { + dataSource.clearWebViewPagesHistory() } - fun loadWebViewPagesHistory(callBack: WebViewHistoryCallback) { - getWebViewHistoryDisposable = dataSource.getAllWebViewPagesHistory() + fun loadWebViewPagesHistory(): Single> = + dataSource.getAllWebViewPagesHistory() .map { roomEntities -> roomEntities.map(::WebViewHistoryItem) } - .subscribe(callBack::onDataFetched) { e -> Log.e(TAG, "Unable to load page history", e) } - } + .onErrorReturn { + Log.e(TAG, "Unable to load page history", it) + emptyList() + } fun dispose() { saveHistoryDisposable?.dispose() diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt index fdcf7c8e4c..1e19d5340c 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt @@ -18,42 +18,34 @@ package org.kiwix.kiwixmobile.core.page.history.adapter +import android.os.Bundle import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity data class WebViewHistoryItem( val databaseId: Long = 0L, val zimId: String, - val title: String, - val pageUrl: String, - val isForward: Boolean, - val timeStamp: Long + val webViewIndex: Int, + val webViewCurrentPosition: Int, + val webViewBackForwardListBundle: Bundle? ) { constructor( zimId: String, - title: String, - pageUrl: String, - isForward: Boolean, - timeStamp: Long + webViewIndex: Int, + webViewPosition: Int, + webViewBackForwardList: Bundle ) : this( 0L, zimId, - title, - pageUrl, - isForward, - timeStamp + webViewIndex, + webViewPosition, + webViewBackForwardList ) constructor(webViewHistoryEntity: WebViewHistoryEntity) : this( webViewHistoryEntity.id, webViewHistoryEntity.zimId, - webViewHistoryEntity.title, - webViewHistoryEntity.pageUrl, - webViewHistoryEntity.isForward, - webViewHistoryEntity.timeStamp + webViewHistoryEntity.webViewIndex, + webViewHistoryEntity.webViewCurrentPosition, + webViewHistoryEntity.webViewBackForwardListBundle ) } - -interface WebViewHistoryCallback { - fun onDataFetched(pageHistory: List) - fun onError(error: Throwable) -} diff --git a/core/src/main/res/values/strings.xml b/core/src/main/res/values/strings.xml index fd674e90fc..bfac610fd6 100644 --- a/core/src/main/res/values/strings.xml +++ b/core/src/main/res/values/strings.xml @@ -233,7 +233,6 @@ Close all tabs Close tab Could not restore tabs. - Could not restore web view history Pending In Progress Complete diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt index a5b5730ad0..9fc4e6de48 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt @@ -40,6 +40,7 @@ import org.kiwix.kiwixmobile.core.extensions.isFileExist import org.kiwix.kiwixmobile.core.main.CoreReaderFragment import org.kiwix.kiwixmobile.core.main.MainMenu import org.kiwix.kiwixmobile.core.main.RestoreOrigin +import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.utils.LanguageUtils import org.kiwix.kiwixmobile.core.utils.dialog.DialogShower @@ -143,7 +144,7 @@ class CustomReaderFragment : CoreReaderFragment() { // See https://github.com/kiwix/kiwix-android/issues/3541 zimReaderContainer?.zimFileReader?.let(::setUpBookmarks) } else { - openObbOrZim() + openObbOrZim(true) } requireArguments().clear() } @@ -162,13 +163,12 @@ class CustomReaderFragment : CoreReaderFragment() { * and loads the last opened article in the specified tab. */ override fun restoreViewStateOnValidJSON( - zimArticles: String?, - zimPositions: String?, + webViewHistoryItemList: List, currentTab: Int, // Unused in custom apps as there is only one ZIM file that is already set. restoreOrigin: RestoreOrigin ) { - restoreTabs(zimArticles, zimPositions, currentTab) + restoreTabs(webViewHistoryItemList, currentTab) } /** @@ -183,7 +183,7 @@ class CustomReaderFragment : CoreReaderFragment() { ) } - private fun openObbOrZim() { + private fun openObbOrZim(shouldManageExternalLaunch: Boolean = false) { customFileValidator.validate( onFilesFound = { coreReaderLifeCycleScope?.launch { @@ -195,7 +195,8 @@ class CustomReaderFragment : CoreReaderFragment() { null, it.assetFileDescriptorList ), - true + true, + shouldManageExternalLaunch ) // Save book in the database to display it in `ZimHostFragment`. zimReaderContainer?.zimFileReader?.let { zimFileReader -> @@ -206,15 +207,19 @@ class CustomReaderFragment : CoreReaderFragment() { val bookOnDisk = BookOnDisk(zimFileReader) repositoryActions?.saveBook(bookOnDisk) } - // Open the previous loaded pages after ZIM file loads. - manageExternalLaunchAndRestoringViewState() + if (shouldManageExternalLaunch) { + // Open the previous loaded pages after ZIM file loads. + manageExternalLaunchAndRestoringViewState() + } } is ValidationState.HasBothFiles -> { it.zimFile.delete() - openZimFile(ZimReaderSource(it.obbFile), true) - // Open the previous loaded pages after ZIM file loads. - manageExternalLaunchAndRestoringViewState() + openZimFile(ZimReaderSource(it.obbFile), true, shouldManageExternalLaunch) + if (shouldManageExternalLaunch) { + // Open the previous loaded pages after ZIM file loads. + manageExternalLaunchAndRestoringViewState() + } } else -> {} From 2fb1896ceabbd6dc88aabf5d9fcd8b3edc6b341d Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 25 Oct 2024 16:23:23 +0530 Subject: [PATCH 13/22] Fixed: Restore web view history in Kiwix app. * Improved restoration of web view history after opening a searched article. * Refactored `restoreViewStateOnValidJSON` and `restoreViewStateOnInvalidJSON` methods to save and retrieve web view history from the Room database. * Added detailed comments to methods for better understanding, including guidance for developers to check subclass implementations before making modifications. * Fixed the `static analysis` errors. --- .../destination/reader/KiwixReaderFragment.kt | 44 +++- .../kiwix/kiwixmobile/core/data/DataSource.kt | 1 - .../kiwix/kiwixmobile/core/data/Repository.kt | 9 +- .../core/main/CoreReaderFragment.kt | 218 +++++++++++++++--- .../kiwix/kiwixmobile/core/main/MainMenu.kt | 3 +- .../custom/main/CustomReaderFragment.kt | 40 +++- 6 files changed, 254 insertions(+), 61 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt index 3bc8e5c2b0..00e9f05cdc 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt @@ -58,6 +58,7 @@ import org.kiwix.kiwixmobile.core.main.ToolbarScrollingKiwixWebView import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue +import org.kiwix.kiwixmobile.core.search.viewmodel.effects.SearchItemToOpen import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_FILE import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX @@ -69,6 +70,7 @@ private const val HIDE_TAB_SWITCHER_DELAY: Long = 300 class KiwixReaderFragment : CoreReaderFragment() { private var isFullScreenVideo: Boolean = false + private var searchItemToOpen: SearchItemToOpen? = null override fun inject(baseActivity: BaseActivity) { baseActivity.cachedComponent.inject(this) @@ -111,7 +113,16 @@ class KiwixReaderFragment : CoreReaderFragment() { } else { val restoreOrigin = if (args.searchItemTitle.isNotEmpty()) FromSearchScreen else FromExternalLaunch - manageExternalLaunchAndRestoringViewState(restoreOrigin) + manageExternalLaunchAndRestoringViewState(restoreOrigin) { + // This lambda function is invoked after restoring the tabs. It checks if there is a + // search item to open. If `searchItemToOpen` is not null, it will call the superclass + // method to open the specified search item. After opening, it sets `searchItemToOpen` + // to null to prevent any unexpected behavior on subsequent calls. + searchItemToOpen?.let { + super.openSearchItem(it) + } + searchItemToOpen = null + } } } requireArguments().clear() @@ -151,6 +162,18 @@ class KiwixReaderFragment : CoreReaderFragment() { openZimFile(zimReaderSource) } + /** + * Stores the specified search item to be opened later. + * + * This method saves the provided `SearchItemToOpen` object, which will be used to + * open the searched item after the tabs have been restored. + * + * @param item The search item to be opened after restoring the tabs. + */ + override fun openSearchItem(item: SearchItemToOpen) { + searchItemToOpen = item + } + override fun loadDrawerViews() { drawerLayout = requireActivity().findViewById(R.id.navigation_container) tableDrawerRightContainer = requireActivity().findViewById(R.id.reader_drawer_nav_view) @@ -243,7 +266,7 @@ class KiwixReaderFragment : CoreReaderFragment() { } } - override fun restoreViewStateOnInvalidJSON() { + override fun restoreViewStateOnInvalidWebViewHistory() { Log.d(TAG_KIWIX, "Kiwix normal start, no zimFile loaded last time -> display home page") exitBook() } @@ -256,15 +279,16 @@ class KiwixReaderFragment : CoreReaderFragment() { * as the ZIM file is already set in the reader. The method handles setting up the ZIM file and bookmarks, * and restores the tabs and positions from the provided data. * - * @param webViewHistoryItemList JSON string representing the list of articles to be restored. - * @param currentTab Index of the tab to be restored as the currently active one. + * @param webViewHistoryItemList WebViewHistoryItem list representing the list of articles to be restored. + * @param currentTab Index of the tab to be restored as the currently active one. * @param restoreOrigin Indicates whether the restoration is triggered from an external launch or the search screen. + * @param onComplete Callback to be invoked upon completion of the restoration process. */ - - override fun restoreViewStateOnValidJSON( + override fun restoreViewStateOnValidWebViewHistory( webViewHistoryItemList: List, currentTab: Int, - restoreOrigin: RestoreOrigin + restoreOrigin: RestoreOrigin, + onComplete: () -> Unit ) { when (restoreOrigin) { FromExternalLaunch -> { @@ -274,7 +298,7 @@ class KiwixReaderFragment : CoreReaderFragment() { val zimReaderSource = fromDatabaseValue(settings.getString(TAG_CURRENT_FILE, null)) if (zimReaderSource?.canOpenInLibkiwix() == true) { if (zimReaderContainer?.zimReaderSource == null) { - openZimFile(zimReaderSource) + openZimFile(zimReaderSource, isFromManageExternalLaunch = true) Log.d( TAG_KIWIX, "Kiwix normal start, Opened last used zimFile: -> ${zimReaderSource.toDatabase()}" @@ -282,7 +306,7 @@ class KiwixReaderFragment : CoreReaderFragment() { } else { zimReaderContainer?.zimFileReader?.let(::setUpBookmarks) } - restoreTabs(webViewHistoryItemList, currentTab) + restoreTabs(webViewHistoryItemList, currentTab, onComplete) } else { getCurrentWebView()?.snack(string.zim_not_opened) exitBook() // hide the options for zim file to avoid unexpected UI behavior @@ -291,7 +315,7 @@ class KiwixReaderFragment : CoreReaderFragment() { } FromSearchScreen -> { - restoreTabs(webViewHistoryItemList, currentTab) + restoreTabs(webViewHistoryItemList, currentTab, onComplete) } } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt index 149258556c..45713cb45a 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/DataSource.kt @@ -24,7 +24,6 @@ import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem -import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.zim_manager.Language import org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter.BooksOnDiskListItem diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt index 3a06d4f781..8938cf27bd 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/data/Repository.kt @@ -28,8 +28,8 @@ import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks import org.kiwix.kiwixmobile.core.dao.NewBookDao import org.kiwix.kiwixmobile.core.dao.NewLanguagesDao import org.kiwix.kiwixmobile.core.dao.NotesRoomDao -import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao +import org.kiwix.kiwixmobile.core.dao.WebViewHistoryRoomDao import org.kiwix.kiwixmobile.core.dao.entities.WebViewHistoryEntity import org.kiwix.kiwixmobile.core.di.qualifiers.IO import org.kiwix.kiwixmobile.core.di.qualifiers.MainThread @@ -37,7 +37,6 @@ import org.kiwix.kiwixmobile.core.extensions.HeaderizableList import org.kiwix.kiwixmobile.core.page.bookmark.adapter.LibkiwixBookmarkItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem import org.kiwix.kiwixmobile.core.page.history.adapter.HistoryListItem.HistoryItem -import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.page.notes.adapter.NoteListItem import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer import org.kiwix.kiwixmobile.core.zim_manager.Language @@ -148,7 +147,9 @@ class Repository @Inject internal constructor( Completable.fromAction { notesRoomDao.deleteNotes(noteList) } .subscribeOn(ioThread) - override suspend fun insertWebViewPageHistoryItems(webViewHistoryEntityList: List) { + override suspend fun insertWebViewPageHistoryItems( + webViewHistoryEntityList: List + ) { webViewHistoryRoomDao.insertWebViewPageHistoryItems(webViewHistoryEntityList) } @@ -159,7 +160,7 @@ class Repository @Inject internal constructor( .observeOn(mainThread) override suspend fun clearWebViewPagesHistory() { - webViewHistoryRoomDao.clearPageHistoryWithPrimaryKey() + webViewHistoryRoomDao.clearWebViewPagesHistory() } override fun deleteNote(noteTitle: String): Completable = 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 69c3f3477c..839ec6eb66 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 @@ -100,8 +100,8 @@ import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import org.json.JSONException import org.kiwix.kiwixmobile.core.BuildConfig +import org.kiwix.kiwixmobile.core.CoreApp import org.kiwix.kiwixmobile.core.DarkModeConfig import org.kiwix.kiwixmobile.core.R import org.kiwix.kiwixmobile.core.StorageObserver @@ -286,6 +286,7 @@ abstract class CoreReaderFragment : private var isFirstTimeMainPageLoaded = true private var isFromManageExternalLaunch = false + private var shouldSaveTabsOnPause = true @JvmField @Inject @@ -421,6 +422,9 @@ abstract class CoreReaderFragment : savedInstanceState: Bundle? ) { super.onViewCreated(view, savedInstanceState) + // Set this to true to enable saving the tab history + // when the fragment goes into the paused state. + shouldSaveTabsOnPause = true setupMenu() donationDialogHandler?.setDonationDialogCallBack(this) val activity = requireActivity() as AppCompatActivity? @@ -1306,6 +1310,15 @@ abstract class CoreReaderFragment : } } + /** + * Initializes a new instance of `KiwixWebView` with the specified URL. + * + * @param url The URL to load in the web view. This is ignored if `shouldLoadUrl` is false. + * @param shouldLoadUrl A flag indicating whether to load the specified URL in the web view. + * When restoring tabs, this should be set to false to avoid loading + * an extra page, as the previous web view history will be restored directly. + * @return The initialized `KiwixWebView` instance, or null if initialization fails. + */ private fun initalizeWebView(url: String, shouldLoadUrl: Boolean = true): KiwixWebView? { if (isAdded) { val attrs = requireActivity().getAttributes(R.xml.webview) @@ -1354,6 +1367,17 @@ abstract class CoreReaderFragment : newTab(url, false) } + /** + * Creates a new instance of `KiwixWebView` and adds it to the list of web views. + * + * @param url The URL to load in the newly created web view. + * @param selectTab A flag indicating whether to select the newly created tab immediately. + * Defaults to true, which means the new tab will be selected. + * @param shouldLoadUrl A flag indicating whether to load the specified URL in the web view. + * If set to false, the web view will be created without loading the URL, + * which is useful when restoring tabs. + * @return The newly created `KiwixWebView` instance, or null if the initialization fails. + */ private fun newTab( url: String, selectTab: Boolean = true, @@ -1529,6 +1553,17 @@ abstract class CoreReaderFragment : } } + override fun onSearchMenuClickedMenuClicked() { + // Set this to false to prevent saving the tab history in onPause + // when opening the search fragment. + shouldSaveTabsOnPause = false + saveTabStates { + // Pass this function to saveTabStates so that after saving + // the tab state in the database, it will open the search fragment. + openSearch("", isOpenedFromTabView = isInTabSwitcher, false) + } + } + @Suppress("NestedBlockDepth") override fun onReadAloudMenuClicked() { if (requireActivity().hasNotificationPermission(sharedPreferenceUtil)) { @@ -2103,7 +2138,21 @@ abstract class CoreReaderFragment : openSearch("", isOpenedFromTabView = false, isVoice) } - private fun openSearchItem(item: SearchItemToOpen) { + /** + * Opens a search item based on its properties. + * + * If the item should open in a new tab, a new tab is created. + * + * The method attempts to load the page URL directly. If the page URL is not available, + * it attempts to convert the page title to a URL using the ZIM reader container. The + * resulting URL is then loaded in the current web view. + * + * Note: This method is overridden in the `KiwixReaderFragment` class to store the + * `SearchItemToOpen` object for later use. If modifications are made to this method, + * please check the overridden version to understand how it interacts with the fragment's + * navigation logic. + */ + open fun openSearchItem(item: SearchItemToOpen) { if (item.shouldOpenInNewTab) { createNewTab() } @@ -2360,13 +2409,42 @@ abstract class CoreReaderFragment : updateNightMode() } - private fun saveTabStates() { + /** + * Saves the current state of tabs and web view history to persistent storage. + * + * This method is designed to be called when the fragment is about to pause, + * ensuring that the current tab states are preserved. It performs the following steps: + * + * 1. Clears any previous web view page history stored in the database. + * 2. Retrieves the current activity's shared preferences to store the tab states. + * 3. Iterates over the currently opened web views, creating a list of + * `WebViewHistoryEntity` objects based on their URLs. + * 4. Saves the collected web view history entities to the database. + * 5. Updates the shared preferences with the current ZIM file and tab index. + * 6. Logs the current ZIM file being saved for debugging purposes. + * 7. Calls the provided `onComplete` callback function once all operations are finished. + * + * Note: This method runs on the main thread and performs database operations + * in a background thread to avoid blocking the UI. + * + * @param onComplete A lambda function to be executed after the tab states have + * been successfully saved. This is optional and defaults to + * an empty function. + * + * Example usage: + * ``` + * saveTabStates { + * openSearch("", isOpenedFromTabView = isInTabSwitcher, false) + * } + */ + private fun saveTabStates(onComplete: () -> Unit = {}) { CoroutineScope(Dispatchers.Main).launch { // clear the previous history saved in database withContext(Dispatchers.IO) { repositoryActions?.clearWebViewPageHistory() } - val settings = requireActivity().getSharedPreferences( + val coreApp = sharedPreferenceUtil?.context as CoreApp + val settings = coreApp.getMainActivity().getSharedPreferences( SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0 ) @@ -2382,10 +2460,43 @@ abstract class CoreReaderFragment : editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase()) editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex) editor.apply() + Log.d( + TAG_KIWIX, + "Save current zim file to preferences: " + + "${zimReaderContainer?.zimReaderSource?.toDatabase()}" + ) + onComplete.invoke() } } - private fun getWebViewHistoryEntity( + /** + * Retrieves a `WebViewHistoryEntity` from the given `KiwixWebView` instance. + * + * This method captures the current state of the specified web view, including its + * scroll position and back-forward list, and creates a `WebViewHistoryEntity` + * if the necessary conditions are met. The steps involved are as follows: + * + * 1. Initializes a `Bundle` to store the state of the web view. + * 2. Calls `saveState` on the provided `webView`, which populates the bundle + * with the current state of the web view's back-forward list. + * 3. Retrieves the ID of the currently loaded ZIM file from the `zimReaderContainer`. + * 4. Checks if the ZIM ID is not null and if the web back-forward list contains any entries: + * - If both conditions are satisfied, it creates and returns a `WebViewHistoryEntity` + * containing a `WebViewHistoryItem` with the following data: + * - `zimId`: The ID of the current ZIM file. + * - `webViewIndex`: The index of the web view in the list of opened views. + * - `webViewPosition`: The current vertical scroll position of the web view. + * - `webViewBackForwardList`: The bundle containing the saved state of the + * web view's back-forward list. + * 5. If the ZIM ID is null or the web back-forward list is empty, the method returns null. + * + * @param webView The `KiwixWebView` instance from which to retrieve the history entity. + * @param webViewIndex The index of the web view in the list of opened web views, + * used to identify the position of this web view in the history. + * @return A `WebViewHistoryEntity` containing the state information of the web view, + * or null if the necessary conditions for creating the entity are not met. + */ + private suspend fun getWebViewHistoryEntity( webView: KiwixWebView, webViewIndex: Int ): WebViewHistoryEntity? { @@ -2406,14 +2517,14 @@ abstract class CoreReaderFragment : return null } + /** + * @see shouldSaveTabsOnPause + */ override fun onPause() { super.onPause() - saveTabStates() - Log.d( - TAG_KIWIX, - "onPause Save current zim file to preferences: " + - "${zimReaderContainer?.zimReaderSource?.toDatabase()}" - ) + if (shouldSaveTabsOnPause) { + saveTabStates() + } } override fun webViewUrlLoading() { @@ -2597,7 +2708,8 @@ abstract class CoreReaderFragment : @SuppressLint("CheckResult") protected fun manageExternalLaunchAndRestoringViewState( - restoreOrigin: RestoreOrigin = FromExternalLaunch + restoreOrigin: RestoreOrigin = FromExternalLaunch, + onComplete: () -> Unit = {} ) { val settings = requireActivity().getSharedPreferences( SharedPreferenceUtil.PREF_KIWIX_MOBILE, @@ -2606,29 +2718,49 @@ abstract class CoreReaderFragment : val currentTab = safelyGetCurrentTab(settings) repositoryActions?.loadWebViewPagesHistory() ?.subscribe({ webViewHistoryItemList -> - Log.e( - "VALID_DATA", - "manageExternalLaunchAndRestoringViewState: ${webViewHistoryItemList.size}" - ) if (webViewHistoryItemList.isEmpty()) { - restoreViewStateOnInvalidJSON() + restoreViewStateOnInvalidWebViewHistory() return@subscribe } - restoreViewStateOnValidJSON(webViewHistoryItemList, currentTab, restoreOrigin) + restoreViewStateOnValidWebViewHistory( + webViewHistoryItemList, + currentTab, + restoreOrigin, + onComplete + ) }, { - Log.e("INVALID_DATA", "manageExternalLaunchAndRestoringViewState: $it") - restoreViewStateOnInvalidJSON() + restoreViewStateOnInvalidWebViewHistory() }) } private fun safelyGetCurrentTab(settings: SharedPreferences): Int = max(settings.getInt(TAG_CURRENT_TAB, 0), 0) - /* This method restores tabs state in new launches, do not modify it - unless it is explicitly mentioned in the issue you're fixing */ + /** + * Restores the tabs based on the provided webViewHistoryItemList. + * + * This method performs the following actions: + * - Resets the current web view index to zero. + * - Removes the first tab from the webViewList and updates the tabs adapter. + * - Iterates over the provided webViewHistoryItemList, creating new tabs and restoring + * their states based on the historical data. + * - Selects the specified tab to make it the currently active one. + * - Invokes the onComplete callback once the restoration is finished. + * + * If any error occurs during the restoration process, it logs a warning and displays + * a toast message to inform the user that the tabs could not be restored. + * + * @param webViewHistoryItemList List of WebViewHistoryItem representing the historical data for restoring tabs. + * @param currentTab Index of the tab to be set as the currently active tab after restoration. + * @param onComplete Callback to be invoked upon successful restoration of the tabs. + * + * @Warning: This method restores tabs state in new launches, do not modify it + * unless it is explicitly mentioned in the issue you're fixing. + */ protected fun restoreTabs( webViewHistoryItemList: List, - currentTab: Int + currentTab: Int, + onComplete: () -> Unit ) { try { currentWebViewIndex = 0 @@ -2643,8 +2775,9 @@ abstract class CoreReaderFragment : } } selectTab(currentTab) - } catch (e: JSONException) { - Log.w(TAG_KIWIX, "Kiwix shared preferences corrupted", e) + onComplete.invoke() + } catch (ignore: Exception) { + Log.w(TAG_KIWIX, "Kiwix shared preferences corrupted", ignore) activity.toast(R.string.could_not_restore_tabs, Toast.LENGTH_LONG) } // After restoring the tabs, observe any search actions that the user might have triggered. @@ -2671,6 +2804,18 @@ abstract class CoreReaderFragment : ) } + /** + * Restores the state of a given KiwixWebView based on the provided WebViewHistoryItem. + * + * This method retrieves the back-forward list from the WebViewHistoryItem and + * uses it to restore the web view's state. It also sets the vertical scroll position + * of the web view to the position stored in the WebViewHistoryItem. + * + * If the provided WebViewHistoryItem is null, the method does nothing. + * + * @param webView The KiwixWebView instance whose state is to be restored. + * @param webViewHistoryItem The WebViewHistoryItem containing the saved state and scroll position. + */ private fun restoreTabState(webView: KiwixWebView, webViewHistoryItem: WebViewHistoryItem?) { webViewHistoryItem?.webViewBackForwardListBundle?.let { bundle -> webView.restoreState(bundle) @@ -2744,28 +2889,29 @@ abstract class CoreReaderFragment : } /** - * Restores the view state after successfully reading valid JSON from shared preferences. + * Restores the view state after successfully reading valid webViewHistory from room database. * Developers modifying this method in subclasses, such as CustomReaderFragment and * KiwixReaderFragment, should review and consider the implementations in those subclasses - * (e.g., CustomReaderFragment.restoreViewStateOnValidJSON, - * KiwixReaderFragment.restoreViewStateOnValidJSON) to ensure consistent behavior - * when handling valid JSON scenarios. + * (e.g., CustomReaderFragment.restoreViewStateOnValidWebViewHistory, + * KiwixReaderFragment.restoreViewStateOnValidWebViewHistory) to ensure consistent behavior + * when handling valid webViewHistory scenarios. */ - protected abstract fun restoreViewStateOnValidJSON( + protected abstract fun restoreViewStateOnValidWebViewHistory( webViewHistoryItemList: List, currentTab: Int, - restoreOrigin: RestoreOrigin + restoreOrigin: RestoreOrigin, + onComplete: () -> Unit ) /** - * Restores the view state when the attempt to read JSON from shared preferences fails - * due to invalid or corrupted data. Developers modifying this method in subclasses, such as + * Restores the view state when the attempt to read webViewHistory from room database fails + * due to the absence of any history records. Developers modifying this method in subclasses, such as * CustomReaderFragment and KiwixReaderFragment, should review and consider the implementations - * in those subclasses (e.g., CustomReaderFragment.restoreViewStateOnInvalidJSON, - * KiwixReaderFragment.restoreViewStateOnInvalidJSON) to ensure consistent behavior + * in those subclasses (e.g., CustomReaderFragment.restoreViewStateOnInvalidWebViewHistory, + * KiwixReaderFragment.restoreViewStateOnInvalidWebViewHistory) to ensure consistent behavior * when handling invalid JSON scenarios. */ - abstract fun restoreViewStateOnInvalidJSON() + abstract fun restoreViewStateOnInvalidWebViewHistory() } enum class RestoreOrigin { diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainMenu.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainMenu.kt index 6123f1cfb8..277b8a2fef 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainMenu.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/MainMenu.kt @@ -61,6 +61,7 @@ class MainMenu( fun onRandomArticleMenuClicked() fun onReadAloudMenuClicked() fun onFullscreenMenuClicked() + fun onSearchMenuClickedMenuClicked() } init { @@ -154,7 +155,7 @@ class MainMenu( } private fun navigateToSearch(): Boolean { - (activity as CoreMainActivity).openSearch(isOpenedFromTabView = isInTabSwitcher) + menuClickListener.onSearchMenuClickedMenuClicked() return true } diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt index 9fc4e6de48..9e3602498a 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt @@ -150,25 +150,26 @@ class CustomReaderFragment : CoreReaderFragment() { } /** - * Restores the view state when the attempt to read JSON from shared preferences fails - * due to invalid or corrupted data. In this case, it opens the homepage of the zim file, - * as custom apps always have the zim file available. + * Restores the view state when the attempt to read web view history from the room database fails + * due to the absence of any history records. In this case, it navigates to the homepage of the + * ZIM file, as custom apps are expected to have the ZIM file readily available. */ - override fun restoreViewStateOnInvalidJSON() { + override fun restoreViewStateOnInvalidWebViewHistory() { openHomeScreen() } /** - * Restores the view state when the JSON data is valid. This method restores the tabs - * and loads the last opened article in the specified tab. + * Restores the view state when the webViewHistory data is valid. + * This method restores the tabs with webView pages history. */ - override fun restoreViewStateOnValidJSON( + override fun restoreViewStateOnValidWebViewHistory( webViewHistoryItemList: List, currentTab: Int, // Unused in custom apps as there is only one ZIM file that is already set. - restoreOrigin: RestoreOrigin + restoreOrigin: RestoreOrigin, + onComplete: () -> Unit ) { - restoreTabs(webViewHistoryItemList, currentTab) + restoreTabs(webViewHistoryItemList, currentTab, onComplete) } /** @@ -183,6 +184,27 @@ class CustomReaderFragment : CoreReaderFragment() { ) } + /** + * Opens a ZIM file or an OBB file based on the validation of available files. + * + * This method uses the `customFileValidator` to check for the presence of required files. + * Depending on the validation results, it performs the following actions: + * + * - If a valid ZIM file is found: + * - It opens the ZIM file and creates a `ZimReaderSource` for it. + * - Saves the book information in the database to be displayed in the `ZimHostFragment`. + * - Manages the external launch and restores the view state if specified. + * + * - If both ZIM and OBB files are found: + * - The ZIM file is deleted, and the OBB file is opened instead. + * - Manages the external launch and restores the view state if specified. + * + * If no valid files are found and the app is not in test mode, the user is navigated to + * the `customDownloadFragment` to facilitate downloading the required files. + * + * @param shouldManageExternalLaunch Indicates whether to manage external launch and + * restore the view state after opening the file. Default is false. + */ private fun openObbOrZim(shouldManageExternalLaunch: Boolean = false) { customFileValidator.validate( onFilesFound = { From 67111ef84852a972e51c3f5708300abf892f292f Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 25 Oct 2024 17:17:21 +0530 Subject: [PATCH 14/22] Fixed: Searched item was not opening in custom apps. --- .../destination/reader/KiwixReaderFragment.kt | 25 +------------ .../core/main/CoreReaderFragment.kt | 37 +++++++++++++------ .../custom/main/CustomReaderFragment.kt | 3 ++ 3 files changed, 29 insertions(+), 36 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt index 00e9f05cdc..eaf54ef774 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt @@ -58,7 +58,6 @@ import org.kiwix.kiwixmobile.core.main.ToolbarScrollingKiwixWebView import org.kiwix.kiwixmobile.core.page.history.adapter.WebViewHistoryItem import org.kiwix.kiwixmobile.core.reader.ZimReaderSource import org.kiwix.kiwixmobile.core.reader.ZimReaderSource.Companion.fromDatabaseValue -import org.kiwix.kiwixmobile.core.search.viewmodel.effects.SearchItemToOpen import org.kiwix.kiwixmobile.core.utils.SharedPreferenceUtil import org.kiwix.kiwixmobile.core.utils.TAG_CURRENT_FILE import org.kiwix.kiwixmobile.core.utils.TAG_KIWIX @@ -70,7 +69,6 @@ private const val HIDE_TAB_SWITCHER_DELAY: Long = 300 class KiwixReaderFragment : CoreReaderFragment() { private var isFullScreenVideo: Boolean = false - private var searchItemToOpen: SearchItemToOpen? = null override fun inject(baseActivity: BaseActivity) { baseActivity.cachedComponent.inject(this) @@ -113,16 +111,7 @@ class KiwixReaderFragment : CoreReaderFragment() { } else { val restoreOrigin = if (args.searchItemTitle.isNotEmpty()) FromSearchScreen else FromExternalLaunch - manageExternalLaunchAndRestoringViewState(restoreOrigin) { - // This lambda function is invoked after restoring the tabs. It checks if there is a - // search item to open. If `searchItemToOpen` is not null, it will call the superclass - // method to open the specified search item. After opening, it sets `searchItemToOpen` - // to null to prevent any unexpected behavior on subsequent calls. - searchItemToOpen?.let { - super.openSearchItem(it) - } - searchItemToOpen = null - } + manageExternalLaunchAndRestoringViewState(restoreOrigin) } } requireArguments().clear() @@ -162,18 +151,6 @@ class KiwixReaderFragment : CoreReaderFragment() { openZimFile(zimReaderSource) } - /** - * Stores the specified search item to be opened later. - * - * This method saves the provided `SearchItemToOpen` object, which will be used to - * open the searched item after the tabs have been restored. - * - * @param item The search item to be opened after restoring the tabs. - */ - override fun openSearchItem(item: SearchItemToOpen) { - searchItemToOpen = item - } - override fun loadDrawerViews() { drawerLayout = requireActivity().findViewById(R.id.navigation_container) tableDrawerRightContainer = requireActivity().findViewById(R.id.reader_drawer_nav_view) 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 839ec6eb66..dfd3ea9a34 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 @@ -287,6 +287,7 @@ abstract class CoreReaderFragment : private var isFirstTimeMainPageLoaded = true private var isFromManageExternalLaunch = false private var shouldSaveTabsOnPause = true + private var searchItemToOpen: SearchItemToOpen? = null @JvmField @Inject @@ -2138,6 +2139,18 @@ abstract class CoreReaderFragment : openSearch("", isOpenedFromTabView = false, isVoice) } + /** + * Stores the specified search item to be opened later. + * + * This method saves the provided `SearchItemToOpen` object, which will be used to + * open the searched item after the tabs have been restored. + * + * @param item The search item to be opened after restoring the tabs. + */ + private fun storeSearchItem(item: SearchItemToOpen) { + searchItemToOpen = item + } + /** * Opens a search item based on its properties. * @@ -2146,13 +2159,8 @@ abstract class CoreReaderFragment : * The method attempts to load the page URL directly. If the page URL is not available, * it attempts to convert the page title to a URL using the ZIM reader container. The * resulting URL is then loaded in the current web view. - * - * Note: This method is overridden in the `KiwixReaderFragment` class to store the - * `SearchItemToOpen` object for later use. If modifications are made to this method, - * please check the overridden version to understand how it interacts with the fragment's - * navigation logic. */ - open fun openSearchItem(item: SearchItemToOpen) { + private fun openSearchItem(item: SearchItemToOpen) { if (item.shouldOpenInNewTab) { createNewTab() } @@ -2708,8 +2716,7 @@ abstract class CoreReaderFragment : @SuppressLint("CheckResult") protected fun manageExternalLaunchAndRestoringViewState( - restoreOrigin: RestoreOrigin = FromExternalLaunch, - onComplete: () -> Unit = {} + restoreOrigin: RestoreOrigin = FromExternalLaunch ) { val settings = requireActivity().getSharedPreferences( SharedPreferenceUtil.PREF_KIWIX_MOBILE, @@ -2725,9 +2732,15 @@ abstract class CoreReaderFragment : restoreViewStateOnValidWebViewHistory( webViewHistoryItemList, currentTab, - restoreOrigin, - onComplete - ) + restoreOrigin + ) { + // This lambda function is invoked after restoring the tabs. It checks if there is a + // search item to open. If `searchItemToOpen` is not null, it will call the openSearchItem + // method to open the specified search item. After opening, it sets `searchItemToOpen` + // to null to prevent any unexpected behavior on subsequent calls. + searchItemToOpen?.let(::openSearchItem) + searchItemToOpen = null + } }, { restoreViewStateOnInvalidWebViewHistory() }) @@ -2800,7 +2813,7 @@ abstract class CoreReaderFragment : requireActivity().observeNavigationResult( TAG_FILE_SEARCHED, viewLifecycleOwner, - Observer(::openSearchItem) + Observer(::storeSearchItem) ) } diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt index 9e3602498a..42852ba08a 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt @@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.custom.main import android.app.Dialog import android.os.Bundle +import android.util.Log import android.view.Menu import android.view.MenuInflater import android.view.View @@ -139,11 +140,13 @@ class CustomReaderFragment : CoreReaderFragment() { private fun loadPageFromNavigationArguments() { val args = CustomReaderFragmentArgs.fromBundle(requireArguments()) if (args.pageUrl.isNotEmpty()) { + Log.e("OPEN_PAGE", "loadPageFromNavigationArguments: ${args.pageUrl}") loadUrlWithCurrentWebview(args.pageUrl) // Setup bookmark for current book // See https://github.com/kiwix/kiwix-android/issues/3541 zimReaderContainer?.zimFileReader?.let(::setUpBookmarks) } else { + Log.e("OPEN_PAGE", "loadPageFromNavigationArguments: else part") openObbOrZim(true) } requireArguments().clear() From 83337ac5f1552a24e57c8e79c99000c7e6de5076 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 25 Oct 2024 17:32:08 +0530 Subject: [PATCH 15/22] Fixed: FindInPage functionality not working in Kiwix and custom apps. --- .../core/main/CoreReaderFragment.kt | 31 ++++++++++++++++--- .../custom/main/CustomReaderFragment.kt | 3 -- 2 files changed, 26 insertions(+), 8 deletions(-) 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 dfd3ea9a34..407705e7f5 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 @@ -288,6 +288,7 @@ abstract class CoreReaderFragment : private var isFromManageExternalLaunch = false private var shouldSaveTabsOnPause = true private var searchItemToOpen: SearchItemToOpen? = null + private var findInPageTitle: String? = null @JvmField @Inject @@ -2358,6 +2359,23 @@ abstract class CoreReaderFragment : } } + /** + * Stores the given title for a "find in page" search operation. + * This title is used later when triggering the "find in page" functionality. + * + * @param title The title or keyword to search for within the current WebView content. + */ + private fun storeFindInPageTitle(title: String) { + findInPageTitle = title + } + + /** + * Initiates the "find in page" UI for searching within the current WebView content. + * If the `compatCallback` is active, it sets up the WebView to search for the + * specified title and displays the search input UI. + * + * @param title The search term or keyword to locate within the page. If null, no action is taken. + */ private fun findInPage(title: String?) { // if the search is localized trigger find in page UI. compatCallback?.apply { @@ -2734,12 +2752,15 @@ abstract class CoreReaderFragment : currentTab, restoreOrigin ) { - // This lambda function is invoked after restoring the tabs. It checks if there is a - // search item to open. If `searchItemToOpen` is not null, it will call the openSearchItem - // method to open the specified search item. After opening, it sets `searchItemToOpen` - // to null to prevent any unexpected behavior on subsequent calls. + // This lambda is executed after the tabs have been restored. It checks if there is a + // search item to open. If `searchItemToOpen` is not null, it calls `openSearchItem` + // to open the specified item, then sets `searchItemToOpen` to null to prevent + // any unexpected behavior on future calls. Similarly, if `findInPageTitle` is set, + // it invokes `findInPage` and resets `findInPageTitle` to null. searchItemToOpen?.let(::openSearchItem) searchItemToOpen = null + findInPageTitle?.let(::findInPage) + findInPageTitle = null } }, { restoreViewStateOnInvalidWebViewHistory() @@ -2808,7 +2829,7 @@ abstract class CoreReaderFragment : requireActivity().observeNavigationResult( FIND_IN_PAGE_SEARCH_STRING, viewLifecycleOwner, - Observer(::findInPage) + Observer(::storeFindInPageTitle) ) requireActivity().observeNavigationResult( TAG_FILE_SEARCHED, diff --git a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt index 42852ba08a..9e3602498a 100644 --- a/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt +++ b/custom/src/main/java/org/kiwix/kiwixmobile/custom/main/CustomReaderFragment.kt @@ -20,7 +20,6 @@ package org.kiwix.kiwixmobile.custom.main import android.app.Dialog import android.os.Bundle -import android.util.Log import android.view.Menu import android.view.MenuInflater import android.view.View @@ -140,13 +139,11 @@ class CustomReaderFragment : CoreReaderFragment() { private fun loadPageFromNavigationArguments() { val args = CustomReaderFragmentArgs.fromBundle(requireArguments()) if (args.pageUrl.isNotEmpty()) { - Log.e("OPEN_PAGE", "loadPageFromNavigationArguments: ${args.pageUrl}") loadUrlWithCurrentWebview(args.pageUrl) // Setup bookmark for current book // See https://github.com/kiwix/kiwix-android/issues/3541 zimReaderContainer?.zimFileReader?.let(::setUpBookmarks) } else { - Log.e("OPEN_PAGE", "loadPageFromNavigationArguments: else part") openObbOrZim(true) } requireArguments().clear() From d3f40f22197edb64d607e8fa62b6c92567d78fea Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 6 Dec 2024 11:46:31 +0530 Subject: [PATCH 16/22] Improved the saving of tabs. --- .../core/main/CoreReaderFragment.kt | 77 ++++++++----------- 1 file changed, 33 insertions(+), 44 deletions(-) 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 407705e7f5..138e81dd9a 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 @@ -99,6 +99,8 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.cancel import kotlinx.coroutines.launch +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.withContext import org.kiwix.kiwixmobile.core.BuildConfig import org.kiwix.kiwixmobile.core.CoreApp @@ -286,7 +288,7 @@ abstract class CoreReaderFragment : private var isFirstTimeMainPageLoaded = true private var isFromManageExternalLaunch = false - private var shouldSaveTabsOnPause = true + private val savingTabsMutex = Mutex() private var searchItemToOpen: SearchItemToOpen? = null private var findInPageTitle: String? = null @@ -424,9 +426,6 @@ abstract class CoreReaderFragment : savedInstanceState: Bundle? ) { super.onViewCreated(view, savedInstanceState) - // Set this to true to enable saving the tab history - // when the fragment goes into the paused state. - shouldSaveTabsOnPause = true setupMenu() donationDialogHandler?.setDonationDialogCallBack(this) val activity = requireActivity() as AppCompatActivity? @@ -1556,9 +1555,6 @@ abstract class CoreReaderFragment : } override fun onSearchMenuClickedMenuClicked() { - // Set this to false to prevent saving the tab history in onPause - // when opening the search fragment. - shouldSaveTabsOnPause = false saveTabStates { // Pass this function to saveTabStates so that after saving // the tab state in the database, it will open the search fragment. @@ -2465,33 +2461,35 @@ abstract class CoreReaderFragment : */ private fun saveTabStates(onComplete: () -> Unit = {}) { CoroutineScope(Dispatchers.Main).launch { - // clear the previous history saved in database - withContext(Dispatchers.IO) { - repositoryActions?.clearWebViewPageHistory() - } - val coreApp = sharedPreferenceUtil?.context as CoreApp - val settings = coreApp.getMainActivity().getSharedPreferences( - SharedPreferenceUtil.PREF_KIWIX_MOBILE, - 0 - ) - val editor = settings.edit() - val webViewHistoryEntityList = arrayListOf() - webViewList.forEachIndexed { index, view -> - if (view.url == null) return@forEachIndexed - getWebViewHistoryEntity(view, index)?.let(webViewHistoryEntityList::add) - } - withContext(Dispatchers.IO) { - repositoryActions?.saveWebViewPageHistory(webViewHistoryEntityList) - } - editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase()) - editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex) - editor.apply() - Log.d( - TAG_KIWIX, - "Save current zim file to preferences: " + - "${zimReaderContainer?.zimReaderSource?.toDatabase()}" - ) - onComplete.invoke() + savingTabsMutex.withLock { + // clear the previous history saved in database + withContext(Dispatchers.IO) { + repositoryActions?.clearWebViewPageHistory() + } + val coreApp = sharedPreferenceUtil?.context as CoreApp + val settings = coreApp.getMainActivity().getSharedPreferences( + SharedPreferenceUtil.PREF_KIWIX_MOBILE, + 0 + ) + val editor = settings.edit() + val webViewHistoryEntityList = arrayListOf() + webViewList.forEachIndexed { index, view -> + if (view.url == null) return@forEachIndexed + getWebViewHistoryEntity(view, index)?.let(webViewHistoryEntityList::add) + } + withContext(Dispatchers.IO) { + repositoryActions?.saveWebViewPageHistory(webViewHistoryEntityList) + } + editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase()) + editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex) + editor.apply() + Log.d( + TAG_KIWIX, + "Save current zim file to preferences: " + + "${zimReaderContainer?.zimReaderSource?.toDatabase()}" + ) + onComplete.invoke() + } } } @@ -2543,16 +2541,6 @@ abstract class CoreReaderFragment : return null } - /** - * @see shouldSaveTabsOnPause - */ - override fun onPause() { - super.onPause() - if (shouldSaveTabsOnPause) { - saveTabStates() - } - } - override fun webViewUrlLoading() { if (isFirstRun && !BuildConfig.DEBUG) { contentsDrawerHint() @@ -2639,6 +2627,7 @@ abstract class CoreReaderFragment : showProgressBarWithProgress(progress) if (progress == 100) { hideProgressBar() + saveTabStates() Log.d(TAG_KIWIX, "Loaded URL: " + getCurrentWebView()?.url) } (webView.context as AppCompatActivity).invalidateOptionsMenu() From 5a47a7ba947f96c639fdca5d375e011f7010f0e5 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Tue, 29 Oct 2024 15:16:33 +0530 Subject: [PATCH 17/22] Fixed: Reader screen was showing twice when pressing the back button after opening a page from the history, bookmarks, or notes screens in custom apps. --- .../kiwix/kiwixmobile/core/main/CoreMainActivity.kt | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt index eb33f72812..1d2ba9acc1 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/main/CoreMainActivity.kt @@ -40,6 +40,7 @@ import androidx.lifecycle.lifecycleScope import androidx.navigation.NavController import androidx.navigation.NavDestination import androidx.navigation.NavDirections +import androidx.navigation.NavOptions import com.google.android.material.navigation.NavigationView import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers @@ -393,6 +394,10 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { navController.navigate(fragmentId, bundle) } + fun navigate(fragmentId: Int, bundle: Bundle, navOptions: NavOptions) { + navController.navigate(fragmentId, bundle, navOptions) + } + private fun openSettings() { handleDrawerOnNavigation() navigate(settingsFragmentResId) @@ -435,13 +440,18 @@ abstract class CoreMainActivity : BaseActivity(), WebViewProvider { if (zimReaderSource != null) { zimFileUri = zimReaderSource.toDatabase() } + val navOptions = NavOptions.Builder() + .setLaunchSingleTop(true) + .setPopUpTo(readerFragmentResId, inclusive = true) + .build() navigate( readerFragmentResId, bundleOf( PAGE_URL_KEY to pageUrl, ZIM_FILE_URI_KEY to zimFileUri, SHOULD_OPEN_IN_NEW_TAB to shouldOpenInNewTab - ) + ), + navOptions ) } From 8a124d82ac93e8bf69c53983cb6a57dfad980780 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Tue, 29 Oct 2024 17:50:27 +0530 Subject: [PATCH 18/22] Fix: Main page of ZIM file not loading when opening a note in the notes screen * Resolved the issue where the main page of the ZIM file was not loading when a note was opened from the notes screen, when a different ZIM file was set in the reader. Now, when opening notes, the application correctly sets the corresponding ZIM file in the reader, ensuring the main page is displayed as expected. --- .../kiwixmobile/core/main/CoreReaderFragment.kt | 14 +++++++++++--- .../page/history/adapter/WebViewHistoryItem.kt | 2 +- .../org/kiwix/kiwixmobile/core/utils/Constants.kt | 2 -- 3 files changed, 12 insertions(+), 6 deletions(-) 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 138e81dd9a..fbc0bd098b 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 @@ -2828,21 +2828,29 @@ abstract class CoreReaderFragment : } /** - * Restores the state of a given KiwixWebView based on the provided WebViewHistoryItem. + * Restores the state of the specified KiwixWebView based on the provided WebViewHistoryItem. * * This method retrieves the back-forward list from the WebViewHistoryItem and * uses it to restore the web view's state. It also sets the vertical scroll position * of the web view to the position stored in the WebViewHistoryItem. * - * If the provided WebViewHistoryItem is null, the method does nothing. + * If the provided WebViewHistoryItem is null, the method instead loads the main page + * of the currently opened ZIM file. This fallback behavior is triggered, for example, + * when opening a note in the notes screen, where the webViewHistoryList is intentionally + * set to null to indicate that the main page of the newly opened ZIM file should be loaded. * * @param webView The KiwixWebView instance whose state is to be restored. - * @param webViewHistoryItem The WebViewHistoryItem containing the saved state and scroll position. + * @param webViewHistoryItem The WebViewHistoryItem containing the saved state and scroll position, + * or null if the main page should be loaded. */ private fun restoreTabState(webView: KiwixWebView, webViewHistoryItem: WebViewHistoryItem?) { webViewHistoryItem?.webViewBackForwardListBundle?.let { bundle -> webView.restoreState(bundle) webView.scrollY = webViewHistoryItem.webViewCurrentPosition + } ?: kotlin.run { + zimReaderContainer?.zimFileReader?.let { + webView.loadUrl(redirectOrOriginal(contentUrl("${it.mainPage}"))) + } } } diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt index 1e19d5340c..6d711e7a51 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/page/history/adapter/WebViewHistoryItem.kt @@ -32,7 +32,7 @@ data class WebViewHistoryItem( zimId: String, webViewIndex: Int, webViewPosition: Int, - webViewBackForwardList: Bundle + webViewBackForwardList: Bundle? ) : this( 0L, zimId, diff --git a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/Constants.kt b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/Constants.kt index b1b0361bed..6d1139feb7 100644 --- a/core/src/main/java/org/kiwix/kiwixmobile/core/utils/Constants.kt +++ b/core/src/main/java/org/kiwix/kiwixmobile/core/utils/Constants.kt @@ -29,8 +29,6 @@ const val REQUEST_POST_NOTIFICATION_PERMISSION = 4 const val TAG_FILE_SEARCHED = "searchedarticle" const val TAG_FILE_SEARCHED_NEW_TAB = "searchedarticlenewtab" const val TAG_CURRENT_FILE = "currentzimfile" -const val TAG_CURRENT_ARTICLES = "currentarticles" -const val TAG_CURRENT_POSITIONS = "currentpositions" const val TAG_CURRENT_TAB = "currenttab" const val TAG_FROM_TAB_SWITCHER = "fromtabswitcher" From af8ca7f62002b8a119086295236f0e47b2b78811 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 6 Dec 2024 17:41:56 +0530 Subject: [PATCH 19/22] Fixed: SearchFragmentTest for custom apps was failing. --- .../search/SearchFragmentTestForCustomApp.kt | 30 ++----------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt index c0307a1ceb..0cc7a9d850 100644 --- a/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt +++ b/custom/src/androidTest/java/org/kiwix/kiwixmobile/custom/search/SearchFragmentTestForCustomApp.kt @@ -21,7 +21,7 @@ package org.kiwix.kiwixmobile.custom.search import android.Manifest import android.content.Context import android.content.res.AssetFileDescriptor -import android.os.ParcelFileDescriptor +import androidx.core.content.ContextCompat import androidx.core.content.edit import androidx.lifecycle.Lifecycle import androidx.navigation.fragment.NavHostFragment @@ -61,7 +61,6 @@ import org.kiwix.kiwixmobile.custom.testutils.TestUtils.closeSystemDialogs import org.kiwix.kiwixmobile.custom.testutils.TestUtils.isSystemUINotRespondingDialogVisible import java.io.File import java.io.FileOutputStream -import java.io.IOException import java.net.URI import java.util.concurrent.TimeUnit import javax.inject.Singleton @@ -225,7 +224,7 @@ class SearchFragmentTestForCustomApp { UiThreadStatement.runOnUiThread { customMainActivity.navigate(customMainActivity.readerFragmentResId) } - openZimFileInReaderWithAssetFileDescriptor(downloadingZimFile) + openZimFileInReader(zimFile = downloadingZimFile) openSearchWithQuery(searchTerms[0]) // wait for searchFragment become visible on screen. delay(2000) @@ -304,12 +303,6 @@ class SearchFragmentTestForCustomApp { } } - private fun openZimFileInReaderWithAssetFileDescriptor(downloadingZimFile: File) { - getAssetFileDescriptorFromFile(downloadingZimFile)?.let(::openZimFileInReader) ?: run { - throw RuntimeException("Unable to get fileDescriptor from file. Original exception") - } - } - private fun openZimFileInReader( assetFileDescriptor: AssetFileDescriptor? = null, zimFile: File? = null @@ -338,23 +331,6 @@ class SearchFragmentTestForCustomApp { } } - private fun getAssetFileDescriptorFromFile(file: File): AssetFileDescriptor? { - val parcelFileDescriptor = getFileDescriptor(file) - if (parcelFileDescriptor != null) { - return AssetFileDescriptor(parcelFileDescriptor, 0, file.length()) - } - return null - } - - private fun getFileDescriptor(file: File?): ParcelFileDescriptor? { - try { - return ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY) - } catch (e: IOException) { - e.printStackTrace() - return null - } - } - private fun writeZimFileData(responseBody: ResponseBody, file: File) { FileOutputStream(file).use { outputStream -> responseBody.byteStream().use { inputStream -> @@ -374,7 +350,7 @@ class SearchFragmentTestForCustomApp { .build() private fun getDownloadingZimFile(): File { - val zimFile = File(context.cacheDir, "ray_charles.zim") + val zimFile = File(ContextCompat.getExternalFilesDirs(context, null)[0], "ray_charles.zim") if (zimFile.exists()) zimFile.delete() zimFile.createNewFile() return zimFile From fe3597aa7bb3d69dd8a3884db0425127bedc5a0c Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 6 Dec 2024 18:13:18 +0530 Subject: [PATCH 20/22] Fixed: Application crashes at first launch. --- .../nav/destination/reader/KiwixReaderFragment.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt index eaf54ef774..6a6d0f8118 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/nav/destination/reader/KiwixReaderFragment.kt @@ -270,9 +270,10 @@ class KiwixReaderFragment : CoreReaderFragment() { when (restoreOrigin) { FromExternalLaunch -> { coreReaderLifeCycleScope?.launch { + if (!isAdded) return@launch val settings = - requireActivity().getSharedPreferences(SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0) - val zimReaderSource = fromDatabaseValue(settings.getString(TAG_CURRENT_FILE, null)) + activity?.getSharedPreferences(SharedPreferenceUtil.PREF_KIWIX_MOBILE, 0) + val zimReaderSource = fromDatabaseValue(settings?.getString(TAG_CURRENT_FILE, null)) if (zimReaderSource?.canOpenInLibkiwix() == true) { if (zimReaderContainer?.zimReaderSource == null) { openZimFile(zimReaderSource, isFromManageExternalLaunch = true) From 3f80e9d8522f4b846f6e55f619f96527f14779ba Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Mon, 9 Dec 2024 14:25:59 +0530 Subject: [PATCH 21/22] Added debug logs which will help us in debugging if any error happens. --- .../org/kiwix/kiwixmobile/core/main/CoreReaderFragment.kt | 4 ++++ 1 file changed, 4 insertions(+) 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 fbc0bd098b..7fb73b6f94 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 @@ -2752,6 +2752,10 @@ abstract class CoreReaderFragment : findInPageTitle = null } }, { + Log.e( + TAG_KIWIX, + "Could not restore tabs. Original exception = ${it.printStackTrace()}" + ) restoreViewStateOnInvalidWebViewHistory() }) } From c29997aa1254fd0e982db2b42f12dcdf5b74dda8 Mon Sep 17 00:00:00 2001 From: MohitMaliFtechiz Date: Fri, 7 Feb 2025 22:32:19 +0530 Subject: [PATCH 22/22] Fixed: Opening a searched item and "Find in Page" was not working after rebasing. * Removed unnecessary code from the project to simplify it and make it more robust. --- .../core/main/CoreReaderFragment.kt | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) 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 7fb73b6f94..3d49580f3f 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 @@ -510,6 +510,16 @@ abstract class CoreReaderFragment : readAloudService?.registerCallBack(this@CoreReaderFragment) } } + requireActivity().observeNavigationResult( + FIND_IN_PAGE_SEARCH_STRING, + viewLifecycleOwner, + Observer(::storeFindInPageTitle) + ) + requireActivity().observeNavigationResult( + TAG_FILE_SEARCHED, + viewLifecycleOwner, + Observer(::storeSearchItem) + ) handleClicks() } @@ -2790,6 +2800,7 @@ abstract class CoreReaderFragment : onComplete: () -> Unit ) { try { + isFromManageExternalLaunch = true currentWebViewIndex = 0 tabsAdapter?.apply { webViewList.removeAt(0) @@ -2807,28 +2818,6 @@ abstract class CoreReaderFragment : Log.w(TAG_KIWIX, "Kiwix shared preferences corrupted", ignore) activity.toast(R.string.could_not_restore_tabs, Toast.LENGTH_LONG) } - // After restoring the tabs, observe any search actions that the user might have triggered. - // Since the ZIM file opening functionality has been moved to a background thread, - // we ensure that all necessary actions are completed before observing these search actions. - observeSearchActions() - } - - /** - * Observes any search-related actions triggered by the user, such as "Find in Page" or - * opening a specific search item. - * This method sets up observers for navigation results related to search functionality. - */ - private fun observeSearchActions() { - requireActivity().observeNavigationResult( - FIND_IN_PAGE_SEARCH_STRING, - viewLifecycleOwner, - Observer(::storeFindInPageTitle) - ) - requireActivity().observeNavigationResult( - TAG_FILE_SEARCHED, - viewLifecycleOwner, - Observer(::storeSearchItem) - ) } /**