mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-08 23:07:26 -04:00
cherry pick 3.0.4
This commit is contained in:
parent
11db4504f9
commit
8b8764adbe
@ -1,3 +1,9 @@
|
|||||||
|
3.0.4
|
||||||
|
BUGFIX: Some users language was causing a crash due to unstable ISO codes
|
||||||
|
BUGFIX: Some unstable zim files were crashing when opened
|
||||||
|
BUGFIX: Long titles were rendering off screen on home page
|
||||||
|
BUGFIX: Issues when opening a file externally
|
||||||
|
|
||||||
3.0.0
|
3.0.0
|
||||||
NEW: Androidx support
|
NEW: Androidx support
|
||||||
NEW: In app error reporting
|
NEW: In app error reporting
|
||||||
|
@ -29,7 +29,7 @@ def buildNumber = System.getenv('TRAVIS_BUILD_NUMBER') ?: "dev"
|
|||||||
ext {
|
ext {
|
||||||
versionMajor = 3
|
versionMajor = 3
|
||||||
versionMinor = 0
|
versionMinor = 0
|
||||||
versionPatch = 3
|
versionPatch = 4
|
||||||
}
|
}
|
||||||
|
|
||||||
private String generateVersionName() {
|
private String generateVersionName() {
|
||||||
@ -260,5 +260,4 @@ dependencies {
|
|||||||
// RxJava
|
// RxJava
|
||||||
implementation(Libs.rxandroid)
|
implementation(Libs.rxandroid)
|
||||||
implementation(Libs.rxjava)
|
implementation(Libs.rxjava)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,4 @@
|
|||||||
NEW: Androidx support
|
BUGFIX: Some users language was causing a crash due to unstable ISO codes
|
||||||
NEW: In app error reporting
|
BUGFIX: Some unstable zim files were crashing when opened
|
||||||
NEW: Improved bookmarks
|
BUGFIX: Long titles were rendering off screen on home page
|
||||||
NEW: Help screen
|
BUGFIX: Issues when opening a file externally
|
||||||
NEW: Home page
|
|
||||||
NEW: Zim history
|
|
||||||
NEW: Introductory screen
|
|
||||||
NEW: Improved language selection
|
|
||||||
NEW: Add note to articles
|
|
||||||
NEW: Tabs
|
|
||||||
NEW: Share zim files to other Kiwix users
|
|
||||||
NEW: Host zim files on your phone
|
|
||||||
+ Bugfixes & Lots More
|
|
||||||
|
@ -99,6 +99,7 @@ import org.kiwix.kiwixmobile.core.R2;
|
|||||||
import org.kiwix.kiwixmobile.core.base.BaseActivity;
|
import org.kiwix.kiwixmobile.core.base.BaseActivity;
|
||||||
import org.kiwix.kiwixmobile.core.bookmark.BookmarkItem;
|
import org.kiwix.kiwixmobile.core.bookmark.BookmarkItem;
|
||||||
import org.kiwix.kiwixmobile.core.bookmark.BookmarksActivity;
|
import org.kiwix.kiwixmobile.core.bookmark.BookmarksActivity;
|
||||||
|
import org.kiwix.kiwixmobile.core.extensions.ContextExtensionsKt;
|
||||||
import org.kiwix.kiwixmobile.core.help.HelpActivity;
|
import org.kiwix.kiwixmobile.core.help.HelpActivity;
|
||||||
import org.kiwix.kiwixmobile.core.history.HistoryActivity;
|
import org.kiwix.kiwixmobile.core.history.HistoryActivity;
|
||||||
import org.kiwix.kiwixmobile.core.history.HistoryListItem;
|
import org.kiwix.kiwixmobile.core.history.HistoryListItem;
|
||||||
@ -1067,6 +1068,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback,
|
|||||||
&& Build.VERSION.SDK_INT != 23)) {
|
&& Build.VERSION.SDK_INT != 23)) {
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
zimReaderContainer.setZimFile(file);
|
zimReaderContainer.setZimFile(file);
|
||||||
|
if (zimReaderContainer.getZimFileReader() != null) {
|
||||||
if (clearHistory) {
|
if (clearHistory) {
|
||||||
requestClearHistoryAfterLoad = true;
|
requestClearHistoryAfterLoad = true;
|
||||||
}
|
}
|
||||||
@ -1079,12 +1081,13 @@ public class MainActivity extends BaseActivity implements WebViewCallback,
|
|||||||
}
|
}
|
||||||
openMainPage();
|
openMainPage();
|
||||||
presenter.loadCurrentZimBookmarksUrl();
|
presenter.loadCurrentZimBookmarksUrl();
|
||||||
|
} else {
|
||||||
|
ContextExtensionsKt.toast(this, R.string.error_file_invalid, Toast.LENGTH_LONG);
|
||||||
|
showHomePage();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Log.w(TAG_KIWIX, "ZIM file doesn't exist at " + file.getAbsolutePath());
|
Log.w(TAG_KIWIX, "ZIM file doesn't exist at " + file.getAbsolutePath());
|
||||||
|
ContextExtensionsKt.toast(this, R.string.error_file_not_found, Toast.LENGTH_LONG);
|
||||||
Toast.makeText(this, getResources().getString(R.string.error_file_not_found),
|
|
||||||
Toast.LENGTH_LONG)
|
|
||||||
.show();
|
|
||||||
showHomePage();
|
showHomePage();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1638,7 +1641,7 @@ public class MainActivity extends BaseActivity implements WebViewCallback,
|
|||||||
toggleActionItemsConfig();
|
toggleActionItemsConfig();
|
||||||
this.menu = menu;
|
this.menu = menu;
|
||||||
|
|
||||||
if (tabSwitcherRoot.getVisibility() == View.VISIBLE) {
|
if (tabSwitcherRoot != null && tabSwitcherRoot.getVisibility() == View.VISIBLE) {
|
||||||
menu.findItem(R.id.menu_search).setVisible(false);
|
menu.findItem(R.id.menu_search).setVisible(false);
|
||||||
menu.findItem(R.id.menu_fullscreen).setVisible(false);
|
menu.findItem(R.id.menu_fullscreen).setVisible(false);
|
||||||
menu.findItem(R.id.menu_random_article).setVisible(false);
|
menu.findItem(R.id.menu_random_article).setVisible(false);
|
||||||
|
@ -17,10 +17,12 @@
|
|||||||
*/
|
*/
|
||||||
package org.kiwix.kiwixmobile.core.utils.files
|
package org.kiwix.kiwixmobile.core.utils.files
|
||||||
|
|
||||||
|
import android.annotation.TargetApi
|
||||||
import android.content.ContentUris
|
import android.content.ContentUris
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import android.os.Build.VERSION_CODES
|
||||||
import android.os.Environment
|
import android.os.Environment
|
||||||
import android.provider.DocumentsContract
|
import android.provider.DocumentsContract
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@ -40,15 +42,15 @@ object FileUtils {
|
|||||||
"${Environment.getExternalStorageDirectory()}${File.separator}Android" +
|
"${Environment.getExternalStorageDirectory()}${File.separator}Android" +
|
||||||
"${File.separator}obb${File.separator}${KiwixApplication.getInstance().packageName}"
|
"${File.separator}obb${File.separator}${KiwixApplication.getInstance().packageName}"
|
||||||
|
|
||||||
@JvmStatic fun getFileCacheDir(context: Context): File =
|
@JvmStatic fun getFileCacheDir(context: Context): File? =
|
||||||
if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()) {
|
if (Environment.MEDIA_MOUNTED == Environment.getExternalStorageState()) {
|
||||||
context.externalCacheDir!!
|
context.externalCacheDir
|
||||||
} else {
|
} else {
|
||||||
context.cacheDir
|
context.cacheDir
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic @Synchronized fun deleteCachedFiles(context: Context) {
|
@JvmStatic @Synchronized fun deleteCachedFiles(context: Context) {
|
||||||
getFileCacheDir(context).deleteRecursively()
|
getFileCacheDir(context)?.deleteRecursively()
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic @Synchronized fun deleteZimFile(path: String) {
|
@JvmStatic @Synchronized fun deleteZimFile(path: String) {
|
||||||
@ -147,12 +149,12 @@ object FileUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun getLocalFilePathByUri(
|
@JvmStatic fun getLocalFilePathByUri(
|
||||||
ctx: Context,
|
context: Context,
|
||||||
uri: Uri
|
uri: Uri
|
||||||
): String? {
|
): String? {
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT &&
|
||||||
DocumentsContract.isDocumentUri(ctx, uri)
|
DocumentsContract.isDocumentUri(context, uri)
|
||||||
) {
|
) {
|
||||||
if ("com.android.externalstorage.documents" == uri.authority) {
|
if ("com.android.externalstorage.documents" == uri.authority) {
|
||||||
val documentId = DocumentsContract.getDocumentId(uri)
|
val documentId = DocumentsContract.getDocumentId(uri)
|
||||||
@ -161,10 +163,24 @@ object FileUtils {
|
|||||||
if (documentId[0] == "primary") {
|
if (documentId[0] == "primary") {
|
||||||
return "${Environment.getExternalStorageDirectory()}/${documentId[1]}"
|
return "${Environment.getExternalStorageDirectory()}/${documentId[1]}"
|
||||||
}
|
}
|
||||||
} else if ("com.android.providers.downloads.documents" == uri.authority
|
} else if ("com.android.providers.downloads.documents" == uri.authority)
|
||||||
)
|
return try {
|
||||||
return contentQuery(
|
documentProviderContentQuery(context, uri)
|
||||||
ctx,
|
} catch (ignore: IllegalArgumentException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} else if ("content".equals(uri.scheme!!, ignoreCase = true)) {
|
||||||
|
return contentQuery(context, uri)
|
||||||
|
} else if ("file".equals(uri.scheme!!, ignoreCase = true)) {
|
||||||
|
return uri.path
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(VERSION_CODES.KITKAT)
|
||||||
|
private fun documentProviderContentQuery(context: Context, uri: Uri) =
|
||||||
|
contentQuery(
|
||||||
|
context,
|
||||||
ContentUris.withAppendedId(
|
ContentUris.withAppendedId(
|
||||||
Uri.parse("content://downloads/public_downloads"),
|
Uri.parse("content://downloads/public_downloads"),
|
||||||
try {
|
try {
|
||||||
@ -174,25 +190,22 @@ object FileUtils {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
} else if ("content".equals(uri.scheme!!, ignoreCase = true)) {
|
|
||||||
return contentQuery(ctx, uri)
|
|
||||||
} else if ("file".equals(uri.scheme!!, ignoreCase = true)) {
|
|
||||||
return uri.path
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun contentQuery(
|
private fun contentQuery(
|
||||||
context: Context,
|
context: Context,
|
||||||
uri: Uri
|
uri: Uri
|
||||||
): String? {
|
): String? {
|
||||||
val columnName = "_data"
|
val columnName = "_data"
|
||||||
return context.contentResolver.query(uri, arrayOf(columnName), null, null, null)
|
return try {
|
||||||
|
context.contentResolver.query(uri, arrayOf(columnName), null, null, null)
|
||||||
?.use {
|
?.use {
|
||||||
if (it.moveToFirst() && it.getColumnIndex(columnName) != -1) {
|
if (it.moveToFirst() && it.getColumnIndex(columnName) != -1) {
|
||||||
it[columnName]
|
it[columnName]
|
||||||
} else null
|
} else null
|
||||||
}
|
}
|
||||||
|
} catch (ignore: SecurityException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic fun readLocalesFromAssets(context: Context) =
|
@JvmStatic fun readLocalesFromAssets(context: Context) =
|
||||||
|
@ -26,6 +26,7 @@ import android.webkit.MimeTypeMap
|
|||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import io.reactivex.Single
|
import io.reactivex.Single
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import org.kiwix.kiwixlib.JNIKiwixException
|
||||||
import org.kiwix.kiwixlib.JNIKiwixInt
|
import org.kiwix.kiwixlib.JNIKiwixInt
|
||||||
import org.kiwix.kiwixlib.JNIKiwixReader
|
import org.kiwix.kiwixlib.JNIKiwixReader
|
||||||
import org.kiwix.kiwixlib.JNIKiwixString
|
import org.kiwix.kiwixlib.JNIKiwixString
|
||||||
@ -50,11 +51,15 @@ class ZimFileReader(
|
|||||||
private val sharedPreferenceUtil: SharedPreferenceUtil
|
private val sharedPreferenceUtil: SharedPreferenceUtil
|
||||||
) {
|
) {
|
||||||
interface Factory {
|
interface Factory {
|
||||||
fun create(file: File): ZimFileReader
|
fun create(file: File): ZimFileReader?
|
||||||
|
|
||||||
class Impl @Inject constructor(val sharedPreferenceUtil: SharedPreferenceUtil) : Factory {
|
class Impl @Inject constructor(val sharedPreferenceUtil: SharedPreferenceUtil) : Factory {
|
||||||
override fun create(file: File) =
|
override fun create(file: File) =
|
||||||
|
try {
|
||||||
ZimFileReader(file, sharedPreferenceUtil = sharedPreferenceUtil)
|
ZimFileReader(file, sharedPreferenceUtil = sharedPreferenceUtil)
|
||||||
|
} catch (ignore: JNIKiwixException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view
|
package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view
|
||||||
|
|
||||||
|
import io.reactivex.Flowable
|
||||||
import io.reactivex.functions.BiFunction
|
import io.reactivex.functions.BiFunction
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
|
import org.kiwix.kiwixmobile.core.downloader.model.DownloadModel
|
||||||
@ -34,10 +35,10 @@ class StorageObserver @Inject constructor(
|
|||||||
private val zimReaderFactory: ZimFileReader.Factory
|
private val zimReaderFactory: ZimFileReader.Factory
|
||||||
) {
|
) {
|
||||||
|
|
||||||
val booksOnFileSystem
|
val booksOnFileSystem: Flowable<List<BookOnDisk>>
|
||||||
get() = scanFiles()
|
get() = scanFiles()
|
||||||
.withLatestFrom(downloadDao.downloads(), BiFunction(::toFilesThatAreNotDownloading))
|
.withLatestFrom(downloadDao.downloads(), BiFunction(::toFilesThatAreNotDownloading))
|
||||||
.map { it.map(::convertToBookOnDisk) }
|
.map { it.mapNotNull(::convertToBookOnDisk) }
|
||||||
|
|
||||||
private fun scanFiles() = fileSearch.scan().subscribeOn(Schedulers.io())
|
private fun scanFiles() = fileSearch.scan().subscribeOn(Schedulers.io())
|
||||||
|
|
||||||
@ -47,5 +48,6 @@ class StorageObserver @Inject constructor(
|
|||||||
private fun fileHasNoMatchingDownload(downloads: List<DownloadModel>, file: File) =
|
private fun fileHasNoMatchingDownload(downloads: List<DownloadModel>, file: File) =
|
||||||
downloads.firstOrNull { file.absolutePath.endsWith(it.fileNameFromUrl) } == null
|
downloads.firstOrNull { file.absolutePath.endsWith(it.fileNameFromUrl) } == null
|
||||||
|
|
||||||
private fun convertToBookOnDisk(file: File) = BookOnDisk(file, zimReaderFactory.create(file))
|
private fun convertToBookOnDisk(file: File) =
|
||||||
|
zimReaderFactory.create(file)?.let { BookOnDisk(file, it) }
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user