mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-09 23:40:26 -04:00
Merge pull request #4231 from kiwix/Fixes#4165
Added support for Android 16.
This commit is contained in:
commit
e939ff770d
24
.github/workflows/ci.yml
vendored
24
.github/workflows/ci.yml
vendored
@ -12,7 +12,7 @@ jobs:
|
|||||||
name: Automated tests
|
name: Automated tests
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
api-level: [ 25, 30, 33, 34, 35 ]
|
api-level: [ 25, 30, 33, 34, 35, 36 ]
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
@ -57,7 +57,7 @@ jobs:
|
|||||||
uses: reactivecircus/android-emulator-runner@v2
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
with:
|
with:
|
||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ (matrix.api-level == 35) && 'google_apis' || 'default' }}
|
target: ${{ (matrix.api-level >= 35) && 'google_apis' || 'default' }}
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
profile: pixel_2
|
profile: pixel_2
|
||||||
ram-size: 3072M
|
ram-size: 3072M
|
||||||
@ -76,7 +76,7 @@ jobs:
|
|||||||
GRADLE_OPTS: "-Dorg.gradle.internal.http.connectionTimeout=60000 -Dorg.gradle.internal.http.socketTimeout=60000 -Dorg.gradle.internal.network.retry.max.attempts=6 -Dorg.gradle.internal.network.retry.initial.backOff=2000"
|
GRADLE_OPTS: "-Dorg.gradle.internal.http.connectionTimeout=60000 -Dorg.gradle.internal.http.socketTimeout=60000 -Dorg.gradle.internal.network.retry.max.attempts=6 -Dorg.gradle.internal.network.retry.initial.backOff=2000"
|
||||||
with:
|
with:
|
||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ (matrix.api-level == 35) && 'google_apis' || 'default' }}
|
target: ${{ (matrix.api-level >= 35) && 'google_apis' || 'default' }}
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
profile: pixel_2
|
profile: pixel_2
|
||||||
ram-size: 3072M
|
ram-size: 3072M
|
||||||
@ -118,7 +118,7 @@ jobs:
|
|||||||
name: Automated tests for PlayStore variant
|
name: Automated tests for PlayStore variant
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
api-level: [ 25, 30, 33, 34, 35 ]
|
api-level: [ 25, 30, 33, 34, 35, 36 ]
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
@ -163,7 +163,7 @@ jobs:
|
|||||||
uses: reactivecircus/android-emulator-runner@v2
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
with:
|
with:
|
||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ (matrix.api-level == 35) && 'google_apis' || 'default' }}
|
target: ${{ (matrix.api-level >= 35) && 'google_apis' || 'default' }}
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
profile: pixel_2
|
profile: pixel_2
|
||||||
ram-size: 2048M
|
ram-size: 2048M
|
||||||
@ -182,7 +182,7 @@ jobs:
|
|||||||
GRADLE_OPTS: "-Dorg.gradle.internal.http.connectionTimeout=60000 -Dorg.gradle.internal.http.socketTimeout=60000 -Dorg.gradle.internal.network.retry.max.attempts=6 -Dorg.gradle.internal.network.retry.initial.backOff=2000"
|
GRADLE_OPTS: "-Dorg.gradle.internal.http.connectionTimeout=60000 -Dorg.gradle.internal.http.socketTimeout=60000 -Dorg.gradle.internal.network.retry.max.attempts=6 -Dorg.gradle.internal.network.retry.initial.backOff=2000"
|
||||||
with:
|
with:
|
||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ (matrix.api-level == 35) && 'google_apis' || 'default' }}
|
target: ${{ (matrix.api-level >= 35) && 'google_apis' || 'default' }}
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
profile: pixel_2
|
profile: pixel_2
|
||||||
ram-size: 2048M
|
ram-size: 2048M
|
||||||
@ -199,7 +199,7 @@ jobs:
|
|||||||
name: Automated tests for Custom app
|
name: Automated tests for Custom app
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
api-level: [ 25, 30, 33, 34, 35 ]
|
api-level: [ 25, 30, 33, 34, 35, 36 ]
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
@ -244,7 +244,7 @@ jobs:
|
|||||||
uses: reactivecircus/android-emulator-runner@v2
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
with:
|
with:
|
||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ (matrix.api-level == 35) && 'google_apis' || 'default' }}
|
target: ${{ (matrix.api-level >= 35) && 'google_apis' || 'default' }}
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
profile: pixel_2
|
profile: pixel_2
|
||||||
ram-size: 2048M
|
ram-size: 2048M
|
||||||
@ -263,7 +263,7 @@ jobs:
|
|||||||
GRADLE_OPTS: "-Dorg.gradle.internal.http.connectionTimeout=60000 -Dorg.gradle.internal.http.socketTimeout=60000 -Dorg.gradle.internal.network.retry.max.attempts=6 -Dorg.gradle.internal.network.retry.initial.backOff=2000"
|
GRADLE_OPTS: "-Dorg.gradle.internal.http.connectionTimeout=60000 -Dorg.gradle.internal.http.socketTimeout=60000 -Dorg.gradle.internal.network.retry.max.attempts=6 -Dorg.gradle.internal.network.retry.initial.backOff=2000"
|
||||||
with:
|
with:
|
||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ (matrix.api-level == 35) && 'google_apis' || 'default' }}
|
target: ${{ (matrix.api-level >= 35) && 'google_apis' || 'default' }}
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
profile: pixel_2
|
profile: pixel_2
|
||||||
ram-size: 2048M
|
ram-size: 2048M
|
||||||
@ -280,7 +280,7 @@ jobs:
|
|||||||
name: Automated tests on Tablet
|
name: Automated tests on Tablet
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
api-level: [ 25, 30, 33, 34, 35 ]
|
api-level: [ 25, 30, 33, 34, 35, 36 ]
|
||||||
fail-fast: true
|
fail-fast: true
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
@ -325,7 +325,7 @@ jobs:
|
|||||||
uses: reactivecircus/android-emulator-runner@v2
|
uses: reactivecircus/android-emulator-runner@v2
|
||||||
with:
|
with:
|
||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ (matrix.api-level == 35) && 'google_apis' || 'default' }}
|
target: ${{ (matrix.api-level >= 35) && 'google_apis' || 'default' }}
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
profile: pixel_2
|
profile: pixel_2
|
||||||
ram-size: 2048M
|
ram-size: 2048M
|
||||||
@ -344,7 +344,7 @@ jobs:
|
|||||||
GRADLE_OPTS: "-Dorg.gradle.internal.http.connectionTimeout=60000 -Dorg.gradle.internal.http.socketTimeout=60000 -Dorg.gradle.internal.network.retry.max.attempts=6 -Dorg.gradle.internal.network.retry.initial.backOff=2000"
|
GRADLE_OPTS: "-Dorg.gradle.internal.http.connectionTimeout=60000 -Dorg.gradle.internal.http.socketTimeout=60000 -Dorg.gradle.internal.network.retry.max.attempts=6 -Dorg.gradle.internal.network.retry.initial.backOff=2000"
|
||||||
with:
|
with:
|
||||||
api-level: ${{ matrix.api-level }}
|
api-level: ${{ matrix.api-level }}
|
||||||
target: ${{ (matrix.api-level == 35) && 'google_apis' || 'default' }}
|
target: ${{ (matrix.api-level >= 35) && 'google_apis' || 'default' }}
|
||||||
arch: x86_64
|
arch: x86_64
|
||||||
profile: pixel_c
|
profile: pixel_c
|
||||||
ram-size: 2048M
|
ram-size: 2048M
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import com.android.build.gradle.internal.tasks.factory.dependsOn
|
||||||
import com.slack.keeper.optInToKeeper
|
import com.slack.keeper.optInToKeeper
|
||||||
import org.w3c.dom.Element
|
import org.w3c.dom.Element
|
||||||
import plugin.KiwixConfigurationPlugin
|
import plugin.KiwixConfigurationPlugin
|
||||||
@ -29,12 +30,12 @@ android {
|
|||||||
// it directly in the AndroidManifest file.
|
// it directly in the AndroidManifest file.
|
||||||
namespace = "org.kiwix.kiwixmobile"
|
namespace = "org.kiwix.kiwixmobile"
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
base.archivesName.set(apkPrefix)
|
|
||||||
resValue("string", "app_name", "Kiwix")
|
resValue("string", "app_name", "Kiwix")
|
||||||
resValue("string", "app_search_string", "Search Kiwix")
|
resValue("string", "app_search_string", "Search Kiwix")
|
||||||
versionCode = "".getVersionCode()
|
versionCode = "".getVersionCode()
|
||||||
versionName = generateVersionName()
|
versionName = generateVersionName()
|
||||||
manifestPlaceholders["permission"] = "android.permission.MANAGE_EXTERNAL_STORAGE"
|
manifestPlaceholders["permission"] = "android.permission.MANAGE_EXTERNAL_STORAGE"
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
lint {
|
lint {
|
||||||
checkDependencies = true
|
checkDependencies = true
|
||||||
@ -130,7 +131,7 @@ dependencies {
|
|||||||
androidTestImplementation(Libs.leakcanary_android_instrumentation)
|
androidTestImplementation(Libs.leakcanary_android_instrumentation)
|
||||||
testImplementation(Libs.kotlinx_coroutines_test)
|
testImplementation(Libs.kotlinx_coroutines_test)
|
||||||
}
|
}
|
||||||
task("generateVersionCodeAndName") {
|
tasks.register("generateVersionCodeAndName") {
|
||||||
val file = File("VERSION_INFO")
|
val file = File("VERSION_INFO")
|
||||||
if (!file.exists()) file.createNewFile()
|
if (!file.exists()) file.createNewFile()
|
||||||
file.printWriter().use {
|
file.printWriter().use {
|
||||||
@ -138,7 +139,7 @@ task("generateVersionCodeAndName") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
task("renameTarakFile") {
|
tasks.register("renameTarakFile") {
|
||||||
val taraskFile = File("$rootDir/core/src/main/res/values-b+be+tarask/strings.xml")
|
val taraskFile = File("$rootDir/core/src/main/res/values-b+be+tarask/strings.xml")
|
||||||
val mainStringsFile = File("$rootDir/core/src/main/res/values/strings.xml")
|
val mainStringsFile = File("$rootDir/core/src/main/res/values/strings.xml")
|
||||||
|
|
||||||
@ -214,6 +215,10 @@ fun elementToString(element: Element): String {
|
|||||||
return result.writer.toString()
|
return result.writer.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.build {
|
gradle.projectsEvaluated {
|
||||||
dependsOn("renameTarakFile")
|
tasks.forEach { task ->
|
||||||
|
if (task.name != "renameTarakFile") {
|
||||||
|
task.dependsOn("renameTarakFile")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -119,8 +119,11 @@ class ObjectBoxToRoomMigratorTest {
|
|||||||
val expectedSearchTerm = "test search"
|
val expectedSearchTerm = "test search"
|
||||||
val expectedZimId = "8812214350305159407L"
|
val expectedZimId = "8812214350305159407L"
|
||||||
val expectedUrl = "http://kiwix.app/mainPage"
|
val expectedUrl = "http://kiwix.app/mainPage"
|
||||||
val recentSearchEntity =
|
val recentSearchEntity = RecentSearchEntity(
|
||||||
RecentSearchEntity(searchTerm = expectedSearchTerm, zimId = expectedZimId, url = expectedUrl)
|
searchTerm = expectedSearchTerm,
|
||||||
|
zimId = expectedZimId,
|
||||||
|
url = expectedUrl
|
||||||
|
)
|
||||||
// insert into object box
|
// insert into object box
|
||||||
box.put(recentSearchEntity)
|
box.put(recentSearchEntity)
|
||||||
// migrate data into room database
|
// migrate data into room database
|
||||||
|
@ -68,7 +68,9 @@ class DownloadRobot : BaseRobot() {
|
|||||||
clickOn(ViewId(R.id.downloadsFragment))
|
clickOn(ViewId(R.id.downloadsFragment))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun waitForDataToLoad(retryCountForDataToLoad: Int = 10) {
|
// Increasing the default timeout for data loading because, on the Android 16 Emulator,
|
||||||
|
// the internet connection is slow, and the library download takes longer.
|
||||||
|
fun waitForDataToLoad(retryCountForDataToLoad: Int = 20) {
|
||||||
try {
|
try {
|
||||||
isVisible(TextId(string.your_languages))
|
isVisible(TextId(string.your_languages))
|
||||||
} catch (e: RuntimeException) {
|
} catch (e: RuntimeException) {
|
||||||
|
@ -56,7 +56,9 @@ class InitialDownloadRobot : BaseRobot() {
|
|||||||
refresh(R.id.librarySwipeRefresh)
|
refresh(R.id.librarySwipeRefresh)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun waitForDataToLoad(retryCountForDataToLoad: Int = 10) {
|
// Increasing the default timeout for data loading because, on the Android 16 Emulator,
|
||||||
|
// the internet connection is slow, and the library download takes longer.
|
||||||
|
fun waitForDataToLoad(retryCountForDataToLoad: Int = 20) {
|
||||||
try {
|
try {
|
||||||
isVisible(TextId(string.your_languages))
|
isVisible(TextId(string.your_languages))
|
||||||
} catch (e: RuntimeException) {
|
} catch (e: RuntimeException) {
|
||||||
|
@ -21,6 +21,7 @@ import android.animation.Animator
|
|||||||
import android.animation.AnimatorListenerAdapter
|
import android.animation.AnimatorListenerAdapter
|
||||||
import android.animation.AnimatorSet
|
import android.animation.AnimatorSet
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.database.DataSetObserver
|
import android.database.DataSetObserver
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
@ -776,13 +777,17 @@ class CustomPageIndicator @JvmOverloads constructor(
|
|||||||
val density = context.resources.displayMetrics.density.toInt()
|
val density = context.resources.displayMetrics.density.toInt()
|
||||||
|
|
||||||
// Load attributes
|
// Load attributes
|
||||||
val a =
|
@SuppressLint("UseKtx")
|
||||||
getContext().obtainStyledAttributes(attrs, R.styleable.CustomPageIndicator, defStyle, 0)
|
val a = getContext().obtainStyledAttributes(
|
||||||
dotDiameter =
|
attrs,
|
||||||
a.getDimensionPixelSize(
|
R.styleable.CustomPageIndicator,
|
||||||
R.styleable.CustomPageIndicator_ipi_dotDiameter,
|
defStyle,
|
||||||
DEFAULT_DOT_SIZE * density
|
0
|
||||||
)
|
)
|
||||||
|
dotDiameter = a.getDimensionPixelSize(
|
||||||
|
R.styleable.CustomPageIndicator_ipi_dotDiameter,
|
||||||
|
DEFAULT_DOT_SIZE * density
|
||||||
|
)
|
||||||
dotRadius = (dotDiameter / 2).toFloat()
|
dotRadius = (dotDiameter / 2).toFloat()
|
||||||
halfDotRadius = dotRadius / 2
|
halfDotRadius = dotRadius / 2
|
||||||
gap =
|
gap =
|
||||||
|
@ -366,18 +366,17 @@ class LocalLibraryFragment : BaseFragment(), CopyMoveFileHandler.FileCopyMoveCal
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun showFileChooser() {
|
private fun showFileChooser() {
|
||||||
val intent =
|
val intent = Intent().apply {
|
||||||
Intent().apply {
|
action = Intent.ACTION_OPEN_DOCUMENT
|
||||||
action = Intent.ACTION_OPEN_DOCUMENT
|
type = "*/*"
|
||||||
type = "*/*"
|
addCategory(Intent.CATEGORY_OPENABLE)
|
||||||
addCategory(Intent.CATEGORY_OPENABLE)
|
if (sharedPreferenceUtil.prefIsTest) {
|
||||||
if (sharedPreferenceUtil.prefIsTest) {
|
putExtra(
|
||||||
putExtra(
|
"android.provider.extra.INITIAL_URI",
|
||||||
"android.provider.extra.INITIAL_URI",
|
"content://com.android.externalstorage.documents/document/primary:Download".toUri()
|
||||||
"content://com.android.externalstorage.documents/document/primary:Download".toUri()
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
fileSelectLauncher.launch(Intent.createChooser(intent, "Select a zim file"))
|
fileSelectLauncher.launch(Intent.createChooser(intent, "Select a zim file"))
|
||||||
} catch (_: ActivityNotFoundException) {
|
} catch (_: ActivityNotFoundException) {
|
||||||
|
@ -135,11 +135,10 @@ class KiwixReaderFragment : CoreReaderFragment() {
|
|||||||
// Update the reader screen title to prevent showing the previously set title
|
// Update the reader screen title to prevent showing the previously set title
|
||||||
// when creating the new archive object.
|
// when creating the new archive object.
|
||||||
updateTitle()
|
updateTitle()
|
||||||
val filePath =
|
val filePath = FileUtils.getLocalFilePathByUri(
|
||||||
FileUtils.getLocalFilePathByUri(
|
requireActivity().applicationContext,
|
||||||
requireActivity().applicationContext,
|
zimFileUri.toUri()
|
||||||
zimFileUri.toUri()
|
)
|
||||||
)
|
|
||||||
if (filePath == null || !File(filePath).isFileExist()) {
|
if (filePath == null || !File(filePath).isFileExist()) {
|
||||||
// Close the previously opened book in the reader. Since this file is not found,
|
// Close the previously opened book in the reader. Since this file is not found,
|
||||||
// it will not be set in the zimFileReader. The previously opened ZIM file
|
// it will not be set in the zimFileReader. The previously opened ZIM file
|
||||||
|
@ -42,6 +42,7 @@ import org.kiwix.kiwixmobile.BuildConfig.DEBUG
|
|||||||
import org.kiwix.kiwixmobile.core.R
|
import org.kiwix.kiwixmobile.core.R
|
||||||
import org.kiwix.kiwixmobile.core.StorageObserver
|
import org.kiwix.kiwixmobile.core.StorageObserver
|
||||||
import org.kiwix.kiwixmobile.core.base.SideEffect
|
import org.kiwix.kiwixmobile.core.base.SideEffect
|
||||||
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
|
||||||
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.isWifi
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.isWifi
|
||||||
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
|
import org.kiwix.kiwixmobile.core.dao.DownloadRoomDao
|
||||||
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
import org.kiwix.kiwixmobile.core.dao.NewBookDao
|
||||||
@ -475,7 +476,7 @@ class ZimManageViewModel @Inject constructor(
|
|||||||
networkLanguageCounts: MutableMap<String, Int>,
|
networkLanguageCounts: MutableMap<String, Int>,
|
||||||
listToActivateBy: List<Language>
|
listToActivateBy: List<Language>
|
||||||
) = Locale.getISOLanguages()
|
) = Locale.getISOLanguages()
|
||||||
.map(::Locale)
|
.map { it.convertToLocal() }
|
||||||
.filter { networkLanguageCounts.containsKey(it.isO3Language) }
|
.filter { networkLanguageCounts.containsKey(it.isO3Language) }
|
||||||
.map { locale ->
|
.map { locale ->
|
||||||
Language(
|
Language(
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Kiwix Android
|
|
||||||
~ Copyright (c) 2020 Kiwix <android.kiwix.org>
|
|
||||||
~ 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 <http://www.gnu.org/licenses/>.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<alpha
|
|
||||||
android:duration="300"
|
|
||||||
android:fromAlpha="0.0"
|
|
||||||
android:interpolator="@android:anim/accelerate_interpolator"
|
|
||||||
android:toAlpha="1.0" />
|
|
||||||
</set>
|
|
@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Kiwix Android
|
|
||||||
~ Copyright (c) 2020 Kiwix <android.kiwix.org>
|
|
||||||
~ 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 <http://www.gnu.org/licenses/>.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<alpha
|
|
||||||
android:duration="300"
|
|
||||||
android:fromAlpha="1.0"
|
|
||||||
android:interpolator="@android:anim/accelerate_interpolator"
|
|
||||||
android:toAlpha="0.0" />
|
|
||||||
</set>
|
|
@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Kiwix Android
|
|
||||||
~ Copyright (c) 2020 Kiwix <android.kiwix.org>
|
|
||||||
~ 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 <http://www.gnu.org/licenses/>.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<alpha
|
|
||||||
android:duration="300"
|
|
||||||
android:fromAlpha="0.0"
|
|
||||||
android:interpolator="@android:anim/accelerate_interpolator"
|
|
||||||
android:toAlpha="1.0" />
|
|
||||||
</set>
|
|
@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!--
|
|
||||||
~ Kiwix Android
|
|
||||||
~ Copyright (c) 2020 Kiwix <android.kiwix.org>
|
|
||||||
~ 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 <http://www.gnu.org/licenses/>.
|
|
||||||
~
|
|
||||||
-->
|
|
||||||
|
|
||||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<alpha
|
|
||||||
android:duration="300"
|
|
||||||
android:fromAlpha="1.0"
|
|
||||||
android:interpolator="@android:anim/accelerate_interpolator"
|
|
||||||
android:toAlpha="0.0" />
|
|
||||||
</set>
|
|
@ -1,3 +1,5 @@
|
|||||||
|
import org.gradle.kotlin.dsl.register
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
@ -28,6 +30,6 @@ allprojects {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.create<Delete>("clean") {
|
tasks.register<Delete>("clean") {
|
||||||
delete(rootProject.layout.buildDirectory)
|
delete(rootProject.layout.buildDirectory)
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("com.android.tools.build:gradle:8.7.2")
|
implementation("com.android.tools.build:gradle:8.11.0-alpha03")
|
||||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.0")
|
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.0")
|
||||||
implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.0.0-1.0.24")
|
implementation("com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:2.0.0-1.0.24")
|
||||||
implementation("org.jacoco:org.jacoco.core:0.8.12")
|
implementation("org.jacoco:org.jacoco.core:0.8.12")
|
||||||
@ -23,8 +23,8 @@ dependencies {
|
|||||||
exclude(group = "com.google.guava", module = "guava")
|
exclude(group = "com.google.guava", module = "guava")
|
||||||
}
|
}
|
||||||
implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.8")
|
implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.23.8")
|
||||||
implementation("com.googlecode.json-simple:json-simple:1.1")
|
implementation("com.googlecode.json-simple:json-simple:1.1.1")
|
||||||
implementation("com.squareup.okhttp3:okhttp:4.10.0")
|
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||||
|
|
||||||
implementation(gradleApi())
|
implementation(gradleApi())
|
||||||
implementation(localGroovy())
|
implementation(localGroovy())
|
||||||
|
@ -22,9 +22,9 @@ object Config {
|
|||||||
|
|
||||||
// Here is a list of all Android versions with their corresponding API
|
// Here is a list of all Android versions with their corresponding API
|
||||||
// levels: https://apilevels.com/
|
// levels: https://apilevels.com/
|
||||||
const val compileSdk = 35 // SDK version used by Gradle to compile our app.
|
const val compileSdk = 36 // SDK version used by Gradle to compile our app.
|
||||||
const val minSdk = 25 // Minimum SDK (Minimum Support Device) is 25 (Android 7.1 Nougat).
|
const val minSdk = 25 // Minimum SDK (Minimum Support Device) is 25 (Android 7.1 Nougat).
|
||||||
const val targetSdk = 35 // Target SDK (Maximum Support Device) is 34 (Android 14).
|
const val targetSdk = 36 // Target SDK (Maximum Support Device) is 36 (Android 16).
|
||||||
|
|
||||||
val javaVersion = JavaVersion.VERSION_17
|
val javaVersion = JavaVersion.VERSION_17
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ object Versions {
|
|||||||
|
|
||||||
const val org_jetbrains_kotlinx_kotlinx_coroutines: String = "1.10.1"
|
const val org_jetbrains_kotlinx_kotlinx_coroutines: String = "1.10.1"
|
||||||
|
|
||||||
const val kotlinx_coroutines_rx3: String = "1.3.9"
|
const val kotlinx_coroutines_rx3: String = "1.10.1"
|
||||||
|
|
||||||
const val androidx_test_espresso: String = "3.6.1"
|
const val androidx_test_espresso: String = "3.6.1"
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ object Versions {
|
|||||||
|
|
||||||
const val androidx_test_core: String = "1.6.1"
|
const val androidx_test_core: String = "1.6.1"
|
||||||
|
|
||||||
const val androidx_test_orchestrator: String = "1.5.0"
|
const val androidx_test_orchestrator: String = "1.5.1"
|
||||||
|
|
||||||
const val io_objectbox: String = "4.0.3"
|
const val io_objectbox: String = "4.0.3"
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ object Versions {
|
|||||||
|
|
||||||
const val android_arch_lifecycle_extensions: String = "1.1.1"
|
const val android_arch_lifecycle_extensions: String = "1.1.1"
|
||||||
|
|
||||||
const val com_android_tools_build_gradle: String = "8.7.2"
|
const val com_android_tools_build_gradle: String = "8.11.0-alpha03"
|
||||||
|
|
||||||
const val de_fayard_buildsrcversions_gradle_plugin: String = "0.7.0"
|
const val de_fayard_buildsrcversions_gradle_plugin: String = "0.7.0"
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ object Versions {
|
|||||||
|
|
||||||
const val leakcanary_android: String = "2.14"
|
const val leakcanary_android: String = "2.14"
|
||||||
|
|
||||||
const val constraintlayout: String = "2.1.4"
|
const val constraintlayout: String = "2.2.0"
|
||||||
|
|
||||||
const val swipe_refresh_layout: String = "1.1.0"
|
const val swipe_refresh_layout: String = "1.1.0"
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ import org.json.simple.JSONObject
|
|||||||
import org.json.simple.parser.JSONParser
|
import org.json.simple.parser.JSONParser
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
typealias ProductFlavors = NamedDomainObjectContainer<ProductFlavor>
|
typealias ProductFlavors = NamedDomainObjectContainer<out ProductFlavor>
|
||||||
|
|
||||||
object CustomApps {
|
object CustomApps {
|
||||||
|
|
||||||
|
@ -58,6 +58,7 @@ class AllProjectConfigurer {
|
|||||||
if (isLibrary) {
|
if (isLibrary) {
|
||||||
namespace = "org.kiwix.kiwixmobile.core"
|
namespace = "org.kiwix.kiwixmobile.core"
|
||||||
}
|
}
|
||||||
|
|
||||||
setCompileSdkVersion(Config.compileSdk)
|
setCompileSdkVersion(Config.compileSdk)
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdk = Config.minSdk
|
minSdk = Config.minSdk
|
||||||
@ -161,6 +162,9 @@ class AllProjectConfigurer {
|
|||||||
add("UnusedResources")
|
add("UnusedResources")
|
||||||
add("NonConstantResourceId")
|
add("NonConstantResourceId")
|
||||||
add("NotifyDataSetChanged")
|
add("NotifyDataSetChanged")
|
||||||
|
add("Aligned16KB") // TODO Remove when properly migrated to Android 16.
|
||||||
|
add("AndroidGradlePluginVersion")
|
||||||
|
add("MemberExtensionConflict")
|
||||||
}
|
}
|
||||||
lintConfig = target.rootProject.file("lintConfig.xml")
|
lintConfig = target.rootProject.file("lintConfig.xml")
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,10 @@
|
|||||||
# Enable Wi-Fi on the emulator
|
# Enable Wi-Fi on the emulator
|
||||||
adb shell svc wifi enable
|
adb shell svc wifi enable
|
||||||
adb logcat -c
|
adb logcat -c
|
||||||
|
# Check if the stylus_handwriting_enabled setting exists before disabling
|
||||||
|
if adb shell settings list secure | grep -q "stylus_handwriting_enabled"; then
|
||||||
|
adb shell settings put secure stylus_handwriting_enabled 0
|
||||||
|
fi
|
||||||
# shellcheck disable=SC2035
|
# shellcheck disable=SC2035
|
||||||
adb logcat *:E -v color &
|
adb logcat *:E -v color &
|
||||||
|
|
||||||
@ -61,6 +65,10 @@ while [ $retry -le 3 ]; do
|
|||||||
# Enable Wi-Fi on the emulator
|
# Enable Wi-Fi on the emulator
|
||||||
adb shell svc wifi enable
|
adb shell svc wifi enable
|
||||||
adb logcat -c
|
adb logcat -c
|
||||||
|
# Check if the stylus_handwriting_enabled setting exists before disabling
|
||||||
|
if adb shell settings list secure | grep -q "stylus_handwriting_enabled"; then
|
||||||
|
adb shell settings put secure stylus_handwriting_enabled 0
|
||||||
|
fi
|
||||||
# shellcheck disable=SC2035
|
# shellcheck disable=SC2035
|
||||||
adb logcat *:E -v color &
|
adb logcat *:E -v color &
|
||||||
|
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
# Enable Wi-Fi on the emulator
|
# Enable Wi-Fi on the emulator
|
||||||
adb shell svc wifi enable
|
adb shell svc wifi enable
|
||||||
adb logcat -c
|
adb logcat -c
|
||||||
|
# Check if the stylus_handwriting_enabled setting exists before disabling
|
||||||
|
if adb shell settings list secure | grep -q "stylus_handwriting_enabled"; then
|
||||||
|
adb shell settings put secure stylus_handwriting_enabled 0
|
||||||
|
fi
|
||||||
# shellcheck disable=SC2035
|
# shellcheck disable=SC2035
|
||||||
adb logcat *:E -v color &
|
adb logcat *:E -v color &
|
||||||
|
|
||||||
@ -42,6 +46,10 @@ while [ $retry -le 3 ]; do
|
|||||||
# Enable Wi-Fi on the emulator
|
# Enable Wi-Fi on the emulator
|
||||||
adb shell svc wifi enable
|
adb shell svc wifi enable
|
||||||
adb logcat -c
|
adb logcat -c
|
||||||
|
# Check if the stylus_handwriting_enabled setting exists before disabling
|
||||||
|
if adb shell settings list secure | grep -q "stylus_handwriting_enabled"; then
|
||||||
|
adb shell settings put secure stylus_handwriting_enabled 0
|
||||||
|
fi
|
||||||
# shellcheck disable=SC2035
|
# shellcheck disable=SC2035
|
||||||
adb logcat *:E -v color &
|
adb logcat *:E -v color &
|
||||||
|
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
# Enable Wi-Fi on the emulator
|
# Enable Wi-Fi on the emulator
|
||||||
adb shell svc wifi enable
|
adb shell svc wifi enable
|
||||||
adb logcat -c
|
adb logcat -c
|
||||||
|
# Check if the stylus_handwriting_enabled setting exists before disabling
|
||||||
|
if adb shell settings list secure | grep -q "stylus_handwriting_enabled"; then
|
||||||
|
adb shell settings put secure stylus_handwriting_enabled 0
|
||||||
|
fi
|
||||||
# shellcheck disable=SC2035
|
# shellcheck disable=SC2035
|
||||||
adb logcat *:E -v color &
|
adb logcat *:E -v color &
|
||||||
|
|
||||||
@ -42,6 +46,10 @@ while [ $retry -le 3 ]; do
|
|||||||
# Enable Wi-Fi on the emulator
|
# Enable Wi-Fi on the emulator
|
||||||
adb shell svc wifi enable
|
adb shell svc wifi enable
|
||||||
adb logcat -c
|
adb logcat -c
|
||||||
|
# Check if the stylus_handwriting_enabled setting exists before disabling
|
||||||
|
if adb shell settings list secure | grep -q "stylus_handwriting_enabled"; then
|
||||||
|
adb shell settings put secure stylus_handwriting_enabled 0
|
||||||
|
fi
|
||||||
# shellcheck disable=SC2035
|
# shellcheck disable=SC2035
|
||||||
adb logcat *:E -v color &
|
adb logcat *:E -v color &
|
||||||
|
|
||||||
|
@ -3,6 +3,10 @@
|
|||||||
# Enable Wi-Fi on the emulator
|
# Enable Wi-Fi on the emulator
|
||||||
adb shell svc wifi enable
|
adb shell svc wifi enable
|
||||||
adb logcat -c
|
adb logcat -c
|
||||||
|
# Check if the stylus_handwriting_enabled setting exists before disabling
|
||||||
|
if adb shell settings list secure | grep -q "stylus_handwriting_enabled"; then
|
||||||
|
adb shell settings put secure stylus_handwriting_enabled 0
|
||||||
|
fi
|
||||||
# shellcheck disable=SC2035
|
# shellcheck disable=SC2035
|
||||||
adb logcat *:E -v color &
|
adb logcat *:E -v color &
|
||||||
|
|
||||||
@ -43,6 +47,10 @@ while [ $retry -le 3 ]; do
|
|||||||
# Enable Wi-Fi on the emulator
|
# Enable Wi-Fi on the emulator
|
||||||
adb shell svc wifi enable
|
adb shell svc wifi enable
|
||||||
adb logcat -c
|
adb logcat -c
|
||||||
|
# Check if the stylus_handwriting_enabled setting exists before disabling
|
||||||
|
if adb shell settings list secure | grep -q "stylus_handwriting_enabled"; then
|
||||||
|
adb shell settings put secure stylus_handwriting_enabled 0
|
||||||
|
fi
|
||||||
# shellcheck disable=SC2035
|
# shellcheck disable=SC2035
|
||||||
adb logcat *:E -v color &
|
adb logcat *:E -v color &
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@ apply(plugin = "io.objectbox")
|
|||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
buildConfigField("long", "VERSION_CODE", "".getVersionCode().toString())
|
buildConfigField("long", "VERSION_CODE", "".getVersionCode().toString())
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
getByName("release") {
|
getByName("release") {
|
||||||
|
@ -52,12 +52,13 @@
|
|||||||
<application
|
<application
|
||||||
android:allowBackup="true"
|
android:allowBackup="true"
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||||
|
android:enableOnBackInvokedCallback="false"
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
android:fullBackupContent="@xml/backup_rules"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
|
android:hasFragileUserData="true"
|
||||||
android:largeHeap="true"
|
android:largeHeap="true"
|
||||||
android:requestLegacyExternalStorage="true"
|
android:requestLegacyExternalStorage="true"
|
||||||
android:resizeableActivity="true"
|
android:resizeableActivity="true"
|
||||||
android:hasFragileUserData="true"
|
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/KiwixTheme"
|
android:theme="@style/KiwixTheme"
|
||||||
tools:targetApi="tiramisu">
|
tools:targetApi="tiramisu">
|
||||||
@ -91,6 +92,7 @@
|
|||||||
<activity
|
<activity
|
||||||
android:name=".error.DiagnosticReportActivity"
|
android:name=".error.DiagnosticReportActivity"
|
||||||
android:exported="false" />
|
android:exported="false" />
|
||||||
|
|
||||||
<service android:name=".read_aloud.ReadAloudService" />
|
<service android:name=".read_aloud.ReadAloudService" />
|
||||||
<service
|
<service
|
||||||
android:name=".downloader.downloadManager.DownloadMonitorService"
|
android:name=".downloader.downloadManager.DownloadMonitorService"
|
||||||
|
@ -23,6 +23,7 @@ import android.content.pm.PackageInfo
|
|||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.pm.ResolveInfo
|
import android.content.pm.ResolveInfo
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This interface defines a set of functions that are not available on all platforms.
|
* This interface defines a set of functions that are not available on all platforms.
|
||||||
@ -76,4 +77,6 @@ interface Compat {
|
|||||||
fun isNetworkAvailable(connectivity: ConnectivityManager): Boolean
|
fun isNetworkAvailable(connectivity: ConnectivityManager): Boolean
|
||||||
|
|
||||||
fun isWifi(connectivity: ConnectivityManager): Boolean
|
fun isWifi(connectivity: ConnectivityManager): Boolean
|
||||||
|
|
||||||
|
fun convertToLocal(language: String): Locale
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,8 @@ import android.os.Build
|
|||||||
class CompatHelper private constructor() {
|
class CompatHelper private constructor() {
|
||||||
// Note: Needs ": Compat" or the type system assumes `Compat21`
|
// Note: Needs ": Compat" or the type system assumes `Compat21`
|
||||||
private val compatValue: Compat = when {
|
private val compatValue: Compat = when {
|
||||||
sdkVersion >= Build.VERSION_CODES.TIRAMISU -> CompatV33()
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA -> CompatV36()
|
||||||
|
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU -> CompatV33()
|
||||||
else -> CompatV25()
|
else -> CompatV25()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,10 +37,6 @@ class CompatHelper private constructor() {
|
|||||||
/** Singleton instance of [CompatHelper] */
|
/** Singleton instance of [CompatHelper] */
|
||||||
private val instance by lazy(::CompatHelper)
|
private val instance by lazy(::CompatHelper)
|
||||||
|
|
||||||
/** Get the current Android API level. */
|
|
||||||
val sdkVersion: Int
|
|
||||||
get() = Build.VERSION.SDK_INT
|
|
||||||
|
|
||||||
val compat get() = instance.compatValue
|
val compat get() = instance.compatValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,5 +76,7 @@ class CompatHelper private constructor() {
|
|||||||
|
|
||||||
fun ConnectivityManager.isWifi(): Boolean =
|
fun ConnectivityManager.isWifi(): Boolean =
|
||||||
compat.isWifi(this)
|
compat.isWifi(this)
|
||||||
|
|
||||||
|
fun String.convertToLocal() = compat.convertToLocal(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ import android.content.pm.ResolveInfo
|
|||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
||||||
import android.net.NetworkCapabilities.TRANSPORT_WIFI
|
import android.net.NetworkCapabilities.TRANSPORT_WIFI
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
open class CompatV25 : Compat {
|
open class CompatV25 : Compat {
|
||||||
override fun queryIntentActivities(
|
override fun queryIntentActivities(
|
||||||
@ -61,4 +62,6 @@ open class CompatV25 : Compat {
|
|||||||
return connectivity.getNetworkCapabilities(connectivity.activeNetwork)
|
return connectivity.getNetworkCapabilities(connectivity.activeNetwork)
|
||||||
?.hasTransport(TRANSPORT_WIFI) == true
|
?.hasTransport(TRANSPORT_WIFI) == true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun convertToLocal(language: String): Locale = Locale(language)
|
||||||
}
|
}
|
||||||
|
@ -18,17 +18,17 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.compat
|
package org.kiwix.kiwixmobile.core.compat
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageInfo
|
import android.content.pm.PackageInfo
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.content.pm.PackageManager.PackageInfoFlags
|
import android.content.pm.PackageManager.PackageInfoFlags
|
||||||
import android.content.pm.ResolveInfo
|
import android.content.pm.ResolveInfo
|
||||||
import android.net.ConnectivityManager
|
import android.net.ConnectivityManager
|
||||||
|
import android.os.Build.VERSION_CODES.TIRAMISU
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
const val API_33 = 33
|
@RequiresApi(TIRAMISU)
|
||||||
|
|
||||||
@TargetApi(API_33)
|
|
||||||
open class CompatV33 : Compat {
|
open class CompatV33 : Compat {
|
||||||
private val compatV25 = CompatV25()
|
private val compatV25 = CompatV25()
|
||||||
override fun queryIntentActivities(
|
override fun queryIntentActivities(
|
||||||
@ -52,4 +52,6 @@ open class CompatV33 : Compat {
|
|||||||
|
|
||||||
override fun isWifi(connectivity: ConnectivityManager): Boolean =
|
override fun isWifi(connectivity: ConnectivityManager): Boolean =
|
||||||
compatV25.isWifi(connectivity)
|
compatV25.isWifi(connectivity)
|
||||||
|
|
||||||
|
override fun convertToLocal(language: String): Locale = compatV25.convertToLocal(language)
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Kiwix Android
|
||||||
|
* Copyright (c) 2025 Kiwix <android.kiwix.org>
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.kiwix.kiwixmobile.core.compat
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.content.pm.PackageInfo
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.content.pm.ResolveInfo
|
||||||
|
import android.net.ConnectivityManager
|
||||||
|
import android.os.Build.VERSION_CODES.BAKLAVA
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
|
@RequiresApi(BAKLAVA)
|
||||||
|
open class CompatV36 : Compat {
|
||||||
|
private val compatV33 = CompatV33()
|
||||||
|
override fun queryIntentActivities(
|
||||||
|
packageManager: PackageManager,
|
||||||
|
intent: Intent,
|
||||||
|
flags: ResolveInfoFlagsCompat
|
||||||
|
): List<ResolveInfo> = compatV33.queryIntentActivities(packageManager, intent, flags)
|
||||||
|
|
||||||
|
override fun getPackageInformation(
|
||||||
|
packageName: String,
|
||||||
|
packageManager: PackageManager,
|
||||||
|
flag: Int
|
||||||
|
): PackageInfo =
|
||||||
|
compatV33.getPackageInformation(packageName, packageManager, flag)
|
||||||
|
|
||||||
|
override fun isNetworkAvailable(connectivity: ConnectivityManager): Boolean =
|
||||||
|
compatV33.isNetworkAvailable(connectivity)
|
||||||
|
|
||||||
|
override fun isWifi(connectivity: ConnectivityManager): Boolean =
|
||||||
|
compatV33.isWifi(connectivity)
|
||||||
|
|
||||||
|
override fun convertToLocal(language: String): Locale = Locale.of(language)
|
||||||
|
}
|
@ -22,6 +22,7 @@ import io.objectbox.annotation.Convert
|
|||||||
import io.objectbox.annotation.Entity
|
import io.objectbox.annotation.Entity
|
||||||
import io.objectbox.annotation.Id
|
import io.objectbox.annotation.Id
|
||||||
import io.objectbox.converter.PropertyConverter
|
import io.objectbox.converter.PropertyConverter
|
||||||
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
|
||||||
import org.kiwix.kiwixmobile.core.zim_manager.Language
|
import org.kiwix.kiwixmobile.core.zim_manager.Language
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@ -35,7 +36,7 @@ data class LanguageEntity(
|
|||||||
) {
|
) {
|
||||||
constructor(language: Language) : this(
|
constructor(language: Language) : this(
|
||||||
0,
|
0,
|
||||||
Locale(language.languageCode),
|
language.languageCode.convertToLocal(),
|
||||||
language.active,
|
language.active,
|
||||||
language.occurencesOfLanguage
|
language.occurencesOfLanguage
|
||||||
)
|
)
|
||||||
@ -49,5 +50,5 @@ class StringToLocaleConverter : PropertyConverter<Locale, String> {
|
|||||||
entityProperty?.isO3Language ?: Locale.ENGLISH.isO3Language
|
entityProperty?.isO3Language ?: Locale.ENGLISH.isO3Language
|
||||||
|
|
||||||
override fun convertToEntityProperty(databaseValue: String?): Locale =
|
override fun convertToEntityProperty(databaseValue: String?): Locale =
|
||||||
databaseValue?.let(::Locale) ?: Locale.ENGLISH
|
databaseValue?.convertToLocal() ?: Locale.ENGLISH
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,9 @@ import android.util.TypedValue
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.annotation.AttrRes
|
import androidx.annotation.AttrRes
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.graphics.createBitmap
|
||||||
|
import androidx.core.graphics.drawable.toDrawable
|
||||||
|
import androidx.core.graphics.scale
|
||||||
import org.kiwix.kiwixmobile.core.base.BaseBroadcastReceiver
|
import org.kiwix.kiwixmobile.core.base.BaseBroadcastReceiver
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@ -87,14 +90,9 @@ fun Context.getResizedDrawable(resourceId: Int, width: Int, height: Int): Drawab
|
|||||||
val drawable = ContextCompat.getDrawable(this, resourceId)
|
val drawable = ContextCompat.getDrawable(this, resourceId)
|
||||||
|
|
||||||
return if (drawable != null) {
|
return if (drawable != null) {
|
||||||
val bitmap = Bitmap.createScaledBitmap(
|
val bitmap = getBitmapFromDrawable(drawable).scale(width, height, false)
|
||||||
getBitmapFromDrawable(drawable),
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
|
|
||||||
BitmapDrawable(resources, bitmap).apply {
|
bitmap.toDrawable(resources).apply {
|
||||||
bounds = drawable.bounds
|
bounds = drawable.bounds
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -107,11 +105,7 @@ fun Context.getBitmapFromDrawable(drawable: Drawable): Bitmap {
|
|||||||
return drawable.bitmap
|
return drawable.bitmap
|
||||||
}
|
}
|
||||||
|
|
||||||
val bitmap = Bitmap.createBitmap(
|
val bitmap = createBitmap(drawable.intrinsicWidth, drawable.intrinsicHeight)
|
||||||
drawable.intrinsicWidth,
|
|
||||||
drawable.intrinsicHeight,
|
|
||||||
Bitmap.Config.ARGB_8888
|
|
||||||
)
|
|
||||||
val canvas = Canvas(bitmap)
|
val canvas = Canvas(bitmap)
|
||||||
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
drawable.setBounds(0, 0, canvas.width, canvas.height)
|
||||||
drawable.draw(canvas)
|
drawable.draw(canvas)
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.extensions
|
package org.kiwix.kiwixmobile.core.extensions
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.view.ViewGroup.LayoutParams
|
import android.view.ViewGroup.LayoutParams
|
||||||
import android.widget.EditText
|
import android.widget.EditText
|
||||||
@ -29,6 +30,7 @@ import org.kiwix.kiwixmobile.core.R
|
|||||||
|
|
||||||
const val CLOSE_ICON_PADDING = 30
|
const val CLOSE_ICON_PADDING = 30
|
||||||
|
|
||||||
|
@SuppressLint("PrivateResource")
|
||||||
fun SearchView.setUpSearchView(context: Context) {
|
fun SearchView.setUpSearchView(context: Context) {
|
||||||
val heightAndWidth = context.resources.getDimensionPixelSize(
|
val heightAndWidth = context.resources.getDimensionPixelSize(
|
||||||
R.dimen.material_minimum_height_and_width
|
R.dimen.material_minimum_height_and_width
|
||||||
|
@ -72,6 +72,7 @@ import androidx.constraintlayout.widget.Group
|
|||||||
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
import androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
import androidx.core.app.ActivityCompat
|
import androidx.core.app.ActivityCompat
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.content.edit
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.view.GravityCompat
|
import androidx.core.view.GravityCompat
|
||||||
import androidx.core.view.MenuHost
|
import androidx.core.view.MenuHost
|
||||||
@ -2516,7 +2517,6 @@ abstract class CoreReaderFragment :
|
|||||||
SharedPreferenceUtil.PREF_KIWIX_MOBILE,
|
SharedPreferenceUtil.PREF_KIWIX_MOBILE,
|
||||||
0
|
0
|
||||||
)
|
)
|
||||||
val editor = settings.edit()
|
|
||||||
val webViewHistoryEntityList = arrayListOf<WebViewHistoryEntity>()
|
val webViewHistoryEntityList = arrayListOf<WebViewHistoryEntity>()
|
||||||
webViewList.forEachIndexed { index, view ->
|
webViewList.forEachIndexed { index, view ->
|
||||||
if (view.url == null) return@forEachIndexed
|
if (view.url == null) return@forEachIndexed
|
||||||
@ -2525,9 +2525,10 @@ abstract class CoreReaderFragment :
|
|||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
repositoryActions?.saveWebViewPageHistory(webViewHistoryEntityList)
|
repositoryActions?.saveWebViewPageHistory(webViewHistoryEntityList)
|
||||||
}
|
}
|
||||||
editor.putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase())
|
settings.edit {
|
||||||
editor.putInt(TAG_CURRENT_TAB, currentWebViewIndex)
|
putString(TAG_CURRENT_FILE, zimReaderContainer?.zimReaderSource?.toDatabase())
|
||||||
editor.apply()
|
putInt(TAG_CURRENT_TAB, currentWebViewIndex)
|
||||||
|
}
|
||||||
Log.d(
|
Log.d(
|
||||||
TAG_KIWIX,
|
TAG_KIWIX,
|
||||||
"Save current zim file to preferences: " +
|
"Save current zim file to preferences: " +
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.qr
|
package org.kiwix.kiwixmobile.core.qr
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import com.google.zxing.BarcodeFormat
|
import com.google.zxing.BarcodeFormat
|
||||||
@ -39,6 +40,7 @@ class GenerateQR @Inject constructor() {
|
|||||||
* @param foregroundColor The color of the QR code.
|
* @param foregroundColor The color of the QR code.
|
||||||
* @param backgroundColor The background color of the QR code.
|
* @param backgroundColor The background color of the QR code.
|
||||||
*/
|
*/
|
||||||
|
@SuppressLint("UseKtx")
|
||||||
fun createQR(
|
fun createQR(
|
||||||
code: String,
|
code: String,
|
||||||
size: Int = 512,
|
size: Int = 512,
|
||||||
|
@ -46,6 +46,7 @@ import org.kiwix.kiwixmobile.core.CoreApp.Companion.coreComponent
|
|||||||
import org.kiwix.kiwixmobile.core.CoreApp.Companion.instance
|
import org.kiwix.kiwixmobile.core.CoreApp.Companion.instance
|
||||||
import org.kiwix.kiwixmobile.core.DarkModeConfig
|
import org.kiwix.kiwixmobile.core.DarkModeConfig
|
||||||
import org.kiwix.kiwixmobile.core.R
|
import org.kiwix.kiwixmobile.core.R
|
||||||
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
|
||||||
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getPackageInformation
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getPackageInformation
|
||||||
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getVersionCode
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.getVersionCode
|
||||||
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
import org.kiwix.kiwixmobile.core.dao.LibkiwixBookmarks
|
||||||
@ -169,9 +170,7 @@ abstract class CorePrefsFragment :
|
|||||||
if (selectedLang == Locale.ROOT.toString()) {
|
if (selectedLang == Locale.ROOT.toString()) {
|
||||||
getString(R.string.device_default)
|
getString(R.string.device_default)
|
||||||
} else {
|
} else {
|
||||||
Locale(
|
selectedLang.convertToLocal().displayLanguage
|
||||||
selectedLang
|
|
||||||
).displayLanguage
|
|
||||||
}
|
}
|
||||||
languagePref.onPreferenceChangeListener =
|
languagePref.onPreferenceChangeListener =
|
||||||
Preference.OnPreferenceChangeListener { _, newValue ->
|
Preference.OnPreferenceChangeListener { _, newValue ->
|
||||||
@ -206,7 +205,7 @@ abstract class CorePrefsFragment :
|
|||||||
val entries = arrayOfNulls<String>(languageCodeList.size)
|
val entries = arrayOfNulls<String>(languageCodeList.size)
|
||||||
entries[0] = getString(R.string.device_default)
|
entries[0] = getString(R.string.device_default)
|
||||||
for (i in 1 until languageCodeList.size) {
|
for (i in 1 until languageCodeList.size) {
|
||||||
val locale = Locale(languageCodeList[i])
|
val locale = languageCodeList[i].convertToLocal()
|
||||||
entries[i] = locale.displayLanguage + " (" + locale.getDisplayLanguage(locale) + ") "
|
entries[i] = locale.displayLanguage + " (" + locale.getDisplayLanguage(locale) + ") "
|
||||||
}
|
}
|
||||||
return entries
|
return entries
|
||||||
@ -389,7 +388,7 @@ abstract class CorePrefsFragment :
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
fileSelectLauncher.launch(Intent.createChooser(intent, "Select a bookmark file"))
|
fileSelectLauncher.launch(Intent.createChooser(intent, "Select a bookmark file"))
|
||||||
} catch (ex: ActivityNotFoundException) {
|
} catch (_: ActivityNotFoundException) {
|
||||||
activity.toast(
|
activity.toast(
|
||||||
resources.getString(R.string.no_app_found_to_select_bookmark_file),
|
resources.getString(R.string.no_app_found_to_select_bookmark_file),
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
|
@ -17,13 +17,15 @@
|
|||||||
*/
|
*/
|
||||||
package org.kiwix.kiwixmobile.core.utils
|
package org.kiwix.kiwixmobile.core.utils
|
||||||
|
|
||||||
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by mhutti1 on 19/04/17.
|
* Created by mhutti1 on 19/04/17.
|
||||||
*/
|
*/
|
||||||
class BookUtils {
|
class BookUtils {
|
||||||
val localeMap = Locale.getISOLanguages().map(::Locale).associateBy { it.isO3Language }
|
val localeMap =
|
||||||
|
Locale.getISOLanguages().map { it.convertToLocal() }.associateBy { it.isO3Language }
|
||||||
|
|
||||||
// Get the language from the language codes of the parsed xml stream
|
// Get the language from the language codes of the parsed xml stream
|
||||||
@Suppress("MagicNumber")
|
@Suppress("MagicNumber")
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.utils
|
package org.kiwix.kiwixmobile.core.utils
|
||||||
|
|
||||||
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class LanguageContainer private constructor(val languageCode: String, val languageName: String) {
|
class LanguageContainer private constructor(val languageCode: String, val languageName: String) {
|
||||||
@ -25,7 +26,7 @@ class LanguageContainer private constructor(val languageCode: String, val langua
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private fun chooseLanguageName(languageCode: String): String {
|
private fun chooseLanguageName(languageCode: String): String {
|
||||||
val displayLanguage = Locale(languageCode).displayLanguage
|
val displayLanguage = languageCode.convertToLocal().displayLanguage
|
||||||
return if (displayLanguage.length == 2 || displayLanguage.isEmpty()) {
|
return if (displayLanguage.length == 2 || displayLanguage.isEmpty()) {
|
||||||
Locale.ENGLISH.displayLanguage
|
Locale.ENGLISH.displayLanguage
|
||||||
} else {
|
} else {
|
||||||
|
@ -21,6 +21,7 @@ import android.content.Context
|
|||||||
import android.content.ContextWrapper
|
import android.content.ContextWrapper
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
|
import androidx.annotation.ChecksSdkIntAtLeast
|
||||||
import androidx.appcompat.app.AppCompatDelegate
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
import androidx.core.content.edit
|
import androidx.core.content.edit
|
||||||
import androidx.preference.PreferenceManager
|
import androidx.preference.PreferenceManager
|
||||||
@ -136,9 +137,6 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
|
|||||||
ContextWrapper(context).externalMediaDirs[0]?.path
|
ContextWrapper(context).externalMediaDirs[0]?.path
|
||||||
?: context.filesDir.path // a workaround for emulators
|
?: context.filesDir.path // a workaround for emulators
|
||||||
|
|
||||||
fun getPrefStorageTitle(defaultTitle: String): String =
|
|
||||||
sharedPreferences.getString(PREF_STORAGE_TITLE, defaultTitle) ?: defaultTitle
|
|
||||||
|
|
||||||
fun putPrefBookMarkMigrated(isMigrated: Boolean) =
|
fun putPrefBookMarkMigrated(isMigrated: Boolean) =
|
||||||
sharedPreferences.edit { putBoolean(PREF_BOOKMARKS_MIGRATED, isMigrated) }
|
sharedPreferences.edit { putBoolean(PREF_BOOKMARKS_MIGRATED, isMigrated) }
|
||||||
|
|
||||||
@ -168,9 +166,6 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
|
|||||||
_prefWifiOnlys.onNext(wifiOnly)
|
_prefWifiOnlys.onNext(wifiOnly)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun putPrefStorageTitle(storageTitle: String) =
|
|
||||||
sharedPreferences.edit { putString(PREF_STORAGE_TITLE, storageTitle) }
|
|
||||||
|
|
||||||
fun putPrefStorage(storage: String) {
|
fun putPrefStorage(storage: String) {
|
||||||
sharedPreferences.edit { putString(PREF_STORAGE, storage) }
|
sharedPreferences.edit { putString(PREF_STORAGE, storage) }
|
||||||
_prefStorages.onNext(storage)
|
_prefStorages.onNext(storage)
|
||||||
@ -294,9 +289,11 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
|
|||||||
path.substringBefore(context.getString(R.string.android_directory_seperator))
|
path.substringBefore(context.getString(R.string.android_directory_seperator))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.R)
|
||||||
fun isPlayStoreBuildWithAndroid11OrAbove(): Boolean =
|
fun isPlayStoreBuildWithAndroid11OrAbove(): Boolean =
|
||||||
isPlayStoreBuild && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
isPlayStoreBuild && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
||||||
|
|
||||||
|
@ChecksSdkIntAtLeast(api = Build.VERSION_CODES.R)
|
||||||
fun isNotPlayStoreBuildWithAndroid11OrAbove(): Boolean =
|
fun isNotPlayStoreBuildWithAndroid11OrAbove(): Boolean =
|
||||||
!isPlayStoreBuild && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
!isPlayStoreBuild && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R
|
||||||
|
|
||||||
@ -316,7 +313,6 @@ class SharedPreferenceUtil @Inject constructor(val context: Context) {
|
|||||||
private const val PREF_BACK_TO_TOP = "pref_backtotop"
|
private const val PREF_BACK_TO_TOP = "pref_backtotop"
|
||||||
private const val PREF_FULLSCREEN = "pref_fullscreen"
|
private const val PREF_FULLSCREEN = "pref_fullscreen"
|
||||||
private const val PREF_NEW_TAB_BACKGROUND = "pref_newtab_background"
|
private const val PREF_NEW_TAB_BACKGROUND = "pref_newtab_background"
|
||||||
private const val PREF_STORAGE_TITLE = "pref_selected_title"
|
|
||||||
const val PREF_EXTERNAL_LINK_POPUP = "pref_external_link_popup"
|
const val PREF_EXTERNAL_LINK_POPUP = "pref_external_link_popup"
|
||||||
const val PREF_SHOW_STORAGE_OPTION = "show_storgae_option"
|
const val PREF_SHOW_STORAGE_OPTION = "show_storgae_option"
|
||||||
private const val PREF_IS_FIRST_RUN = "isFirstRun"
|
private const val PREF_IS_FIRST_RUN = "isFirstRun"
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* Kiwix Android
|
|
||||||
* Copyright (c) 2020 Kiwix <android.kiwix.org>
|
|
||||||
* 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 <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.utils
|
|
||||||
|
|
||||||
import android.text.Editable
|
|
||||||
import android.text.TextWatcher
|
|
||||||
|
|
||||||
class SimpleTextWatcher(
|
|
||||||
private val onTextWatcherChangeAction: (CharSequence?, Int, Int, Int) -> Unit
|
|
||||||
) : TextWatcher {
|
|
||||||
@SuppressWarnings("EmptyFunctionBlock")
|
|
||||||
override fun afterTextChanged(p0: Editable?) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("EmptyFunctionBlock")
|
|
||||||
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
|
||||||
onTextWatcherChangeAction.invoke(s, start, before, count)
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,6 +20,7 @@ package org.kiwix.kiwixmobile.core.zim_manager
|
|||||||
|
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import kotlinx.parcelize.Parcelize
|
import kotlinx.parcelize.Parcelize
|
||||||
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
@ -51,7 +52,7 @@ data class Language constructor(
|
|||||||
languageCode: String,
|
languageCode: String,
|
||||||
active: Boolean,
|
active: Boolean,
|
||||||
occurrencesOfLanguage: Int
|
occurrencesOfLanguage: Int
|
||||||
) : this(Locale(languageCode), active, occurrencesOfLanguage)
|
) : this(languageCode.convertToLocal(), active, occurrencesOfLanguage)
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean =
|
override fun equals(other: Any?): Boolean =
|
||||||
(other as Language).language == language && other.active == active
|
(other as Language).language == language && other.active == active
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view
|
package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view
|
||||||
|
|
||||||
|
import org.kiwix.kiwixmobile.core.compat.CompatHelper.Companion.convertToLocal
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity
|
import org.kiwix.kiwixmobile.core.dao.entities.BookOnDiskEntity
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity
|
import org.kiwix.kiwixmobile.core.dao.entities.DownloadRoomEntity
|
||||||
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity
|
import org.kiwix.kiwixmobile.core.entity.LibraryNetworkEntity
|
||||||
@ -50,7 +51,7 @@ sealed class BooksOnDiskListItem {
|
|||||||
override val id: Long = databaseId
|
override val id: Long = databaseId
|
||||||
) : BooksOnDiskListItem() {
|
) : BooksOnDiskListItem() {
|
||||||
val locale: Locale by lazy {
|
val locale: Locale by lazy {
|
||||||
Locale(book.language)
|
book.language.convertToLocal()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(bookOnDiskEntity: BookOnDiskEntity) : this(
|
constructor(bookOnDiskEntity: BookOnDiskEntity) : this(
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="48dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="48dp">
|
|
||||||
|
|
||||||
<path android:fillColor="@android:color/white" android:pathData="M15,21h-2v-2h2V21zM13,14h-2v5h2V14zM21,12h-2v4h2V12zM19,10h-2v2h2V10zM7,12H5v2h2V12zM5,10H3v2h2V10zM12,5h2V3h-2V5zM4.5,4.5v3h3v-3H4.5zM9,9H3V3h6V9zM4.5,16.5v3h3v-3H4.5zM9,21H3v-6h6V21zM16.5,4.5v3h3v-3H16.5zM21,9h-6V3h6V9zM19,19v-3l-4,0v2h2v3h4v-2H19zM17,12l-4,0v2h4V12zM13,10H7v2h2v2h2v-2h2V10zM14,9V7h-2V5h-2v4L14,9zM6.75,5.25h-1.5v1.5h1.5V5.25zM6.75,17.25h-1.5v1.5h1.5V17.25zM18.75,5.25h-1.5v1.5h1.5V5.25z"/>
|
|
||||||
|
|
||||||
</vector>
|
|
@ -1,17 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/header_language"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/activity_horizontal_margin"
|
|
||||||
android:textAppearance="?textAppearanceSubtitle1"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:text="English" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,130 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_margin="@dimen/card_margin">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent">
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
|
||||||
android:id="@+id/horizontal_padding"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
app:layout_constraintGuide_begin="@dimen/activity_horizontal_margin" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.widget.Guideline
|
|
||||||
android:id="@+id/vertical_padding"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
app:layout_constraintGuide_begin="@dimen/activity_vertical_margin" />
|
|
||||||
|
|
||||||
<CheckBox
|
|
||||||
android:id="@+id/itemBookCheckbox"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:paddingEnd="10dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/horizontal_padding"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:ignore="RtlSymmetry" />
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/item_book_icon"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:contentDescription="@string/fav_icon"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/itemBookCheckbox"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:src="@mipmap/ic_launcher_round" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/item_book_title"
|
|
||||||
style="@style/list_item_title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/activity_horizontal_margin"
|
|
||||||
android:layout_marginEnd="@dimen/activity_horizontal_margin"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/item_book_icon"
|
|
||||||
app:layout_constraintTop_toBottomOf="@+id/vertical_padding"
|
|
||||||
tools:text="Wikipedia" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/item_book_description"
|
|
||||||
style="@style/list_item_body"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:textColor="?textSecondary"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/item_book_title"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/item_book_title"
|
|
||||||
tools:text="All wikipedia articles" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/item_book_date"
|
|
||||||
style="@style/list_item_body"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textColor="?textTertiary"
|
|
||||||
app:layout_constraintStart_toStartOf="@id/item_book_title"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/item_book_description"
|
|
||||||
tools:text="1 Jan 2018" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/item_book_size"
|
|
||||||
style="@style/list_item_body"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/activity_horizontal_margin"
|
|
||||||
android:layout_marginEnd="@dimen/activity_horizontal_margin"
|
|
||||||
android:textColor="?textTertiary"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/item_book_date"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/item_book_date"
|
|
||||||
tools:text="20 GB" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/item_book_article_count"
|
|
||||||
style="@style/list_item_body"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="@dimen/activity_horizontal_margin"
|
|
||||||
android:layout_marginEnd="@dimen/activity_horizontal_margin"
|
|
||||||
android:textColor="?textTertiary"
|
|
||||||
app:layout_constraintStart_toEndOf="@id/item_book_size"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/item_book_size"
|
|
||||||
tools:text="10.1 K articles" />
|
|
||||||
|
|
||||||
<org.kiwix.kiwixmobile.core.zim_manager.TagsView
|
|
||||||
android:id="@+id/tags"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="@+id/item_book_description"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/item_book_date" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/item_book_clickable_area"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:background="?android:attr/selectableItemBackground"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:contentDescription="@string/zim_file_content_description"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:visibility="gone" />
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
|
@ -1,23 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/delete_note"
|
|
||||||
android:icon="@drawable/ic_delete_white_24dp"
|
|
||||||
android:title="@string/delete"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/share_note"
|
|
||||||
android:icon="@drawable/baseline_share_24"
|
|
||||||
android:title="@string/share"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
|
|
||||||
<item
|
|
||||||
android:id="@+id/save_note"
|
|
||||||
android:icon="@drawable/ic_save"
|
|
||||||
android:title="@string/save"
|
|
||||||
app:showAsAction="ifRoom" />
|
|
||||||
|
|
||||||
</menu>
|
|
@ -91,7 +91,9 @@ internal class NewBookDaoTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun expectEmissionOfExistingAndNotExistingBook(isInTrashFolder: Boolean = false): Pair<BookOnDiskEntity, BookOnDiskEntity> {
|
private fun expectEmissionOfExistingAndNotExistingBook(
|
||||||
|
isInTrashFolder: Boolean = false
|
||||||
|
): Pair<BookOnDiskEntity, BookOnDiskEntity> {
|
||||||
val query: Query<BookOnDiskEntity> = mockk()
|
val query: Query<BookOnDiskEntity> = mockk()
|
||||||
every { box.query().build() } returns query
|
every { box.query().build() } returns query
|
||||||
val zimReaderSourceThatExists = mockk<ZimReaderSource>()
|
val zimReaderSourceThatExists = mockk<ZimReaderSource>()
|
||||||
|
@ -18,17 +18,17 @@
|
|||||||
|
|
||||||
package org.kiwix.kiwixmobile.core.dao
|
package org.kiwix.kiwixmobile.core.dao
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test
|
|
||||||
import io.mockk.every
|
import io.mockk.every
|
||||||
import io.mockk.mockk
|
import io.mockk.mockk
|
||||||
import io.mockk.verify
|
import io.mockk.verify
|
||||||
import io.objectbox.Box
|
import io.objectbox.Box
|
||||||
import io.objectbox.query.Query
|
import io.objectbox.query.Query
|
||||||
import io.objectbox.query.QueryBuilder
|
import io.objectbox.query.QueryBuilder
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_
|
import org.junit.jupiter.api.Test
|
||||||
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity
|
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity
|
||||||
import org.kiwix.kiwixmobile.core.page.bookmark
|
import org.kiwix.kiwixmobile.core.dao.entities.BookmarkEntity_
|
||||||
import org.kiwix.kiwixmobile.core.page.adapter.Page
|
import org.kiwix.kiwixmobile.core.page.adapter.Page
|
||||||
|
import org.kiwix.kiwixmobile.core.page.bookmark
|
||||||
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem
|
import org.kiwix.kiwixmobile.core.page.bookmark.adapter.BookmarkItem
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||||
|
|
||||||
@ -69,7 +69,6 @@ internal class NewBookmarksDaoTest {
|
|||||||
every { bookmarkItem.zimName } returns ""
|
every { bookmarkItem.zimName } returns ""
|
||||||
every { bookmarkItem.databaseId } returns 0L
|
every { bookmarkItem.databaseId } returns 0L
|
||||||
newBookmarksDao.getCurrentZimBookmarksUrl(zimFileReader)
|
newBookmarksDao.getCurrentZimBookmarksUrl(zimFileReader)
|
||||||
val bookmarkEntity: BookmarkEntity = mockk()
|
|
||||||
every {
|
every {
|
||||||
query.property(BookmarkEntity_.bookmarkUrl).findStrings().toList().distinct()
|
query.property(BookmarkEntity_.bookmarkUrl).findStrings().toList().distinct()
|
||||||
} returns listOf("")
|
} returns listOf("")
|
||||||
|
@ -27,13 +27,12 @@ class MetaLinkNetworkEntityTest {
|
|||||||
@Throws(Exception::class)
|
@Throws(Exception::class)
|
||||||
fun testDeserialize() {
|
fun testDeserialize() {
|
||||||
val serializer = Persister()
|
val serializer = Persister()
|
||||||
val result =
|
val result = serializer.read(
|
||||||
serializer.read(
|
MetaLinkNetworkEntity::class.java,
|
||||||
MetaLinkNetworkEntity::class.java,
|
MetaLinkNetworkEntityTest::class.java.classLoader!!.getResourceAsStream(
|
||||||
MetaLinkNetworkEntityTest::class.java.classLoader!!.getResourceAsStream(
|
"wikipedia_af_all_nopic_2016-05.zim.meta4"
|
||||||
"wikipedia_af_all_nopic_2016-05.zim.meta4"
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
result?.urls?.let {
|
result?.urls?.let {
|
||||||
MetaLinkNetworkEntityUrlAssert(it).hasItems(
|
MetaLinkNetworkEntityUrlAssert(it).hasItems(
|
||||||
listOf(
|
listOf(
|
||||||
@ -68,9 +67,7 @@ class MetaLinkNetworkEntityTest {
|
|||||||
}
|
}
|
||||||
// Basic file attributes
|
// Basic file attributes
|
||||||
assertThat(result.file?.name).isEqualTo("wikipedia_af_all_nopic_2016-05.zim")
|
assertThat(result.file?.name).isEqualTo("wikipedia_af_all_nopic_2016-05.zim")
|
||||||
|
|
||||||
assertThat(result.file?.size).isEqualTo(63973123L)
|
assertThat(result.file?.size).isEqualTo(63973123L)
|
||||||
|
|
||||||
// File hashes
|
// File hashes
|
||||||
assertThat(result.file?.getHash("md5")).isEqualTo("6f06866b61c4a921b57f28cfd4307220")
|
assertThat(result.file?.getHash("md5")).isEqualTo("6f06866b61c4a921b57f28cfd4307220")
|
||||||
assertThat(
|
assertThat(
|
||||||
@ -103,21 +100,17 @@ class MetaLinkNetworkEntityTest {
|
|||||||
*/
|
*/
|
||||||
class MetaLinkNetworkEntityUrlAssert(
|
class MetaLinkNetworkEntityUrlAssert(
|
||||||
actual: List<MetaLinkNetworkEntity.Url>
|
actual: List<MetaLinkNetworkEntity.Url>
|
||||||
) :
|
) : AbstractAssert<MetaLinkNetworkEntityUrlAssert, List<MetaLinkNetworkEntity.Url>>(
|
||||||
AbstractAssert<MetaLinkNetworkEntityUrlAssert, List<MetaLinkNetworkEntity.Url>>(
|
actual,
|
||||||
actual,
|
MetaLinkNetworkEntityUrlAssert::class.java
|
||||||
MetaLinkNetworkEntityUrlAssert::class.java
|
) {
|
||||||
) {
|
|
||||||
private fun <S, T> intersectionWith(
|
private fun <S, T> intersectionWith(
|
||||||
first: List<S>,
|
first: List<S>,
|
||||||
second: List<T>,
|
second: List<T>,
|
||||||
function: (S, T) -> Boolean
|
function: (S, T) -> Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
val filtered = first.filter { a -> second.any { b -> function(a, b) } }
|
val filtered = first.filter { a -> second.any { b -> function(a, b) } }
|
||||||
if (filtered.isNotEmpty()) {
|
return filtered.isNotEmpty()
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun hasItems(items: List<DummyUrl>): Boolean {
|
fun hasItems(items: List<DummyUrl>): Boolean {
|
||||||
|
@ -43,8 +43,9 @@ internal class SearchStateTest {
|
|||||||
val estimatedMatches = 100
|
val estimatedMatches = 100
|
||||||
every { suggestionSearchWrapper.estimatedMatches } returns estimatedMatches.toLong()
|
every { suggestionSearchWrapper.estimatedMatches } returns estimatedMatches.toLong()
|
||||||
// Settings list to hasNext() to ensure it returns true only for the first call.
|
// Settings list to hasNext() to ensure it returns true only for the first call.
|
||||||
// Otherwise, if we do not set this, the method will always return true when checking if the iterator has a next value,
|
// Otherwise, if we do not set this, the method will always return true when
|
||||||
// causing our test case to get stuck in an infinite loop due to this explicit setting.
|
// checking if the iterator has a next value, causing our test case to get stuck
|
||||||
|
// in an infinite loop due to this explicit setting.
|
||||||
every { searchIteratorWrapper.hasNext() } returnsMany listOf(true, false)
|
every { searchIteratorWrapper.hasNext() } returnsMany listOf(true, false)
|
||||||
every { searchIteratorWrapper.next() } returns entryWrapper
|
every { searchIteratorWrapper.next() } returns entryWrapper
|
||||||
every { entryWrapper.title } returns searchTerm
|
every { entryWrapper.title } returns searchTerm
|
||||||
@ -119,7 +120,8 @@ internal class SearchStateTest {
|
|||||||
every { entryWrapper.path } returns "path"
|
every { entryWrapper.path } returns "path"
|
||||||
every { suggestionSearchWrapper.getResults(any(), any()) } returns searchIteratorWrapper
|
every { suggestionSearchWrapper.getResults(any(), any()) } returns searchIteratorWrapper
|
||||||
|
|
||||||
val searchResultsWithTerm = SearchResultsWithTerm(searchTerm, suggestionSearchWrapper, mockk())
|
val searchResultsWithTerm =
|
||||||
|
SearchResultsWithTerm(searchTerm, suggestionSearchWrapper, mockk())
|
||||||
val searchState = SearchState(searchTerm, searchResultsWithTerm, emptyList(), FromWebView)
|
val searchState = SearchState(searchTerm, searchResultsWithTerm, emptyList(), FromWebView)
|
||||||
var list: List<SearchListItem.RecentSearchListItem>? = emptyList()
|
var list: List<SearchListItem.RecentSearchListItem>? = emptyList()
|
||||||
var list1: List<SearchListItem.RecentSearchListItem>? = emptyList()
|
var list1: List<SearchListItem.RecentSearchListItem>? = emptyList()
|
||||||
|
@ -50,7 +50,6 @@ import org.kiwix.kiwixmobile.core.dao.RecentSearchRoomDao
|
|||||||
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||||
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
import org.kiwix.kiwixmobile.core.reader.ZimReaderContainer
|
||||||
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.RecentSearchListItem
|
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.RecentSearchListItem
|
||||||
import org.kiwix.kiwixmobile.core.search.adapter.SearchListItem.ZimSearchResultListItem
|
|
||||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ActivityResultReceived
|
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ActivityResultReceived
|
||||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ClickedSearchInText
|
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ClickedSearchInText
|
||||||
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ConfirmedDelete
|
import org.kiwix.kiwixmobile.core.search.viewmodel.Action.ConfirmedDelete
|
||||||
@ -123,7 +122,6 @@ internal class SearchViewModelTest {
|
|||||||
@Test
|
@Test
|
||||||
fun `SearchState combines sources from inputs`() =
|
fun `SearchState combines sources from inputs`() =
|
||||||
runTest {
|
runTest {
|
||||||
val item = ZimSearchResultListItem("", "")
|
|
||||||
val searchTerm = "searchTerm"
|
val searchTerm = "searchTerm"
|
||||||
val searchOrigin = FromWebView
|
val searchOrigin = FromWebView
|
||||||
val suggestionSearch: SuggestionSearch = mockk()
|
val suggestionSearch: SuggestionSearch = mockk()
|
||||||
|
@ -21,7 +21,9 @@ package org.kiwix.kiwixmobile.core.search.viewmodel
|
|||||||
import org.kiwix.libzim.SuggestionIterator
|
import org.kiwix.libzim.SuggestionIterator
|
||||||
|
|
||||||
class SuggestionIteratorWrapper : SuggestionIterator() {
|
class SuggestionIteratorWrapper : SuggestionIterator() {
|
||||||
override fun remove() {}
|
override fun remove() {
|
||||||
|
// Do nothing just to ignore the EmptyFunctionBlock detekt error.
|
||||||
|
}
|
||||||
|
|
||||||
override fun hasNext(): Boolean = super.hasNext()
|
override fun hasNext(): Boolean = super.hasNext()
|
||||||
override fun next(): SuggestionItemWrapper = super.next() as SuggestionItemWrapper
|
override fun next(): SuggestionItemWrapper = super.next() as SuggestionItemWrapper
|
||||||
|
@ -4,16 +4,16 @@ import com.android.build.gradle.internal.dsl.ProductFlavor
|
|||||||
import custom.CustomApps
|
import custom.CustomApps
|
||||||
import custom.createPublisher
|
import custom.createPublisher
|
||||||
import custom.transactionWithCommit
|
import custom.transactionWithCommit
|
||||||
import plugin.KiwixConfigurationPlugin
|
|
||||||
import java.net.URI
|
|
||||||
import java.net.URLDecoder
|
|
||||||
import java.util.Locale
|
|
||||||
import java.util.Base64
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.ResponseBody
|
import okhttp3.ResponseBody
|
||||||
|
import plugin.KiwixConfigurationPlugin
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
|
import java.io.FileOutputStream
|
||||||
|
import java.net.URI
|
||||||
|
import java.net.URLDecoder
|
||||||
|
import java.util.Base64
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
android
|
android
|
||||||
@ -24,6 +24,7 @@ plugins.apply(KiwixConfigurationPlugin::class)
|
|||||||
android {
|
android {
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId = "org.kiwix"
|
applicationId = "org.kiwix"
|
||||||
|
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|
||||||
flavorDimensions += "default"
|
flavorDimensions += "default"
|
||||||
@ -59,8 +60,8 @@ android {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ProductFlavor.createDownloadTask(file: File): Task {
|
fun ProductFlavor.createDownloadTask(file: File): TaskProvider<Task> {
|
||||||
return tasks.create(
|
return tasks.register(
|
||||||
"download${
|
"download${
|
||||||
name.replaceFirstChar {
|
name.replaceFirstChar {
|
||||||
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it"
|
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it"
|
||||||
@ -156,8 +157,8 @@ fun writeZimFileDataInChunk(
|
|||||||
outputStream?.close()
|
outputStream?.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ProductFlavor.createDownloadTaskForPlayAssetDelivery(file: File): Task {
|
fun ProductFlavor.createDownloadTaskForPlayAssetDelivery(file: File): TaskProvider<Task> {
|
||||||
return tasks.create(
|
return tasks.register(
|
||||||
"download${
|
"download${
|
||||||
name.replaceFirstChar {
|
name.replaceFirstChar {
|
||||||
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it"
|
if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it"
|
||||||
@ -205,10 +206,10 @@ val String.removeAuthenticationFromUrl: String
|
|||||||
fun ProductFlavor.createPublishApkWithExpansionTask(
|
fun ProductFlavor.createPublishApkWithExpansionTask(
|
||||||
file: File,
|
file: File,
|
||||||
applicationVariants: DomainObjectSet<ApplicationVariant>
|
applicationVariants: DomainObjectSet<ApplicationVariant>
|
||||||
): Task {
|
): TaskProvider<Task> {
|
||||||
val capitalizedName =
|
val capitalizedName =
|
||||||
name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" }
|
name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" }
|
||||||
return tasks.create("publish${capitalizedName}ReleaseApkWithExpansionFile") {
|
return tasks.register("publish${capitalizedName}ReleaseApkWithExpansionFile") {
|
||||||
group = "publishing"
|
group = "publishing"
|
||||||
description = "Uploads $capitalizedName to the Play Console with an Expansion file"
|
description = "Uploads $capitalizedName to the Play Console with an Expansion file"
|
||||||
doLast {
|
doLast {
|
||||||
@ -236,10 +237,10 @@ fun DomainObjectSet<ApplicationVariant>.releaseVariantsFor(productFlavor: Produc
|
|||||||
.filter { !it.outputFileName.contains("universal") }
|
.filter { !it.outputFileName.contains("universal") }
|
||||||
.sortedBy { it.versionCodeOverride }
|
.sortedBy { it.versionCodeOverride }
|
||||||
|
|
||||||
fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(): Task {
|
fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(): TaskProvider<Task> {
|
||||||
val capitalizedName =
|
val capitalizedName =
|
||||||
name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" }
|
name.replaceFirstChar { if (it.isLowerCase()) it.titlecase(Locale.getDefault()) else "$it" }
|
||||||
return tasks.create("publish${capitalizedName}ReleaseBundleWithPlayAssetDelivery") {
|
return tasks.register("publish${capitalizedName}ReleaseBundleWithPlayAssetDelivery") {
|
||||||
group = "publishing"
|
group = "publishing"
|
||||||
description = "Uploads $capitalizedName to the Play Console with an Play Asset delivery mode"
|
description = "Uploads $capitalizedName to the Play Console with an Play Asset delivery mode"
|
||||||
doLast {
|
doLast {
|
||||||
@ -249,7 +250,7 @@ fun ProductFlavor.createPublishBundleWithAssetPlayDelivery(): Task {
|
|||||||
.transactionWithCommit(packageName) {
|
.transactionWithCommit(packageName) {
|
||||||
val generatedBundleFile =
|
val generatedBundleFile =
|
||||||
File(
|
File(
|
||||||
"$buildDir/outputs/bundle/${capitalizedName.lowercase(Locale.getDefault())}" +
|
"${layout.buildDirectory}/outputs/bundle/${capitalizedName.lowercase(Locale.getDefault())}" +
|
||||||
"Release/custom-${capitalizedName.lowercase(Locale.getDefault())}-release.aab"
|
"Release/custom-${capitalizedName.lowercase(Locale.getDefault())}-release.aab"
|
||||||
)
|
)
|
||||||
if (generatedBundleFile.exists()) {
|
if (generatedBundleFile.exists()) {
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
|||||||
#Mon Dec 19 16:13:45 IST 2022
|
#Mon Dec 19 16:13:45 IST 2022
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-bin.zip
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
Loading…
x
Reference in New Issue
Block a user