mirror of
https://github.com/kiwix/kiwix-android.git
synced 2025-09-09 07:16:04 -04:00
Merge pull request #2854 from kiwix/Issue#2851
Upgrading gradle plugin version to 7.1.0
This commit is contained in:
commit
9defd1eba8
9
.github/workflows/coverage.yml
vendored
9
.github/workflows/coverage.yml
vendored
@ -24,6 +24,11 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: create instrumentation coverage
|
||||
uses: ReactiveCircus/android-emulator-runner@v2.23.0
|
||||
env:
|
||||
@ -34,7 +39,6 @@ jobs:
|
||||
ndk: 21.4.7075529
|
||||
script: bash contrib/instrumentation.sh
|
||||
|
||||
|
||||
- name: Upload screenshot result
|
||||
uses: actions/upload-artifact@v1
|
||||
if: failure()
|
||||
@ -48,8 +52,7 @@ jobs:
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
if: ${{ matrix.api-level==21 }}
|
||||
run: |
|
||||
bash <(curl -s https://codecov.io/bash)
|
||||
uses: codecov/codecov-action@v2
|
||||
|
||||
- name: Upload Coverage to GH-Actions
|
||||
uses: actions/upload-artifact@v2.2.0
|
||||
|
6
.github/workflows/nightly.yml
vendored
6
.github/workflows/nightly.yml
vendored
@ -44,6 +44,11 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Install NDK
|
||||
run: echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;22.0.7026061" --sdk_root=${ANDROID_SDK_ROOT}
|
||||
|
||||
@ -70,4 +75,3 @@ jobs:
|
||||
mkdir $DATE
|
||||
cp $UNIVERSAL_DEBUG_APK $DATE
|
||||
scp -P 30022 -vrp -i ssh_key -o StrictHostKeyChecking=no $DATE ci@master.download.kiwix.org:/data/download/nightly/
|
||||
|
||||
|
10
.github/workflows/pull_request.yml
vendored
10
.github/workflows/pull_request.yml
vendored
@ -13,6 +13,11 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Static Analysis
|
||||
run: ./gradlew ktlintCheck detekt app:lintDebug custom:lintCustomexampleDebug
|
||||
|
||||
@ -34,6 +39,11 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Install NDK
|
||||
run: echo "y" | sudo ${ANDROID_HOME}/tools/bin/sdkmanager --install "ndk;22.0.7026061" --sdk_root=${ANDROID_SDK_ROOT}
|
||||
|
||||
|
5
.github/workflows/release.yml
vendored
5
.github/workflows/release.yml
vendored
@ -17,6 +17,11 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
|
||||
- name: Decrypt files
|
||||
env:
|
||||
keystore: ${{ secrets.keystore }}
|
||||
|
@ -30,8 +30,8 @@ fun generateVersionName() = "${ext["versionMajor"]}.${ext["versionMinor"]}.${ext
|
||||
|
||||
fun generateVersionCode() =
|
||||
20 * 10000 +
|
||||
((ext["versionMajor"] as Int) * 10000) +
|
||||
((ext["versionMinor"] as Int) * 100) +
|
||||
ext["versionMajor"] as Int * 10000 +
|
||||
ext["versionMinor"] as Int * 100 +
|
||||
ext["versionPatch"] as Int
|
||||
|
||||
val apkPrefix get() = System.getenv("TAG") ?: "dev"
|
||||
@ -45,7 +45,6 @@ android {
|
||||
versionCode = generateVersionCode()
|
||||
versionName = generateVersionName()
|
||||
}
|
||||
|
||||
lintOptions {
|
||||
isCheckDependencies = true
|
||||
}
|
||||
@ -78,11 +77,11 @@ android {
|
||||
}
|
||||
|
||||
play {
|
||||
isEnabled = true
|
||||
serviceAccountCredentials = file("../google.json")
|
||||
track = "alpha"
|
||||
releaseStatus = "draft"
|
||||
resolutionStrategy = "fail"
|
||||
enabled.set(true)
|
||||
serviceAccountCredentials.set(file("../google.json"))
|
||||
track.set("alpha")
|
||||
releaseStatus.set(com.github.triplet.gradle.androidpublisher.ReleaseStatus.DRAFT)
|
||||
resolutionStrategy.set(com.github.triplet.gradle.androidpublisher.ResolutionStrategy.FAIL)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
@ -1,19 +1,19 @@
|
||||
<?xml version="1.0" ?>
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<SmellBaseline>
|
||||
<Blacklist></Blacklist>
|
||||
<Whitelist>
|
||||
<ManuallySuppressedIssues/>
|
||||
<CurrentIssues>
|
||||
<ID>EmptyFunctionBlock:None.kt$None${ }</ID>
|
||||
<ID>EmptyFunctionBlock:SimplePageChangeListener.kt$SimplePageChangeListener${ }</ID>
|
||||
<ID>LongParameterList:ZimManageViewModel.kt$ZimManageViewModel$( booksOnFileSystem: List<BookOnDisk>, activeDownloads: List<DownloadModel>, allLanguages: List<Language>, libraryNetworkEntity: LibraryNetworkEntity, filter: String, fileSystemState: FileSystemState )</ID>
|
||||
<ID>LongParameterList:ZimManageViewModel.kt$ZimManageViewModel$( booksOnFileSystem: List<BookOnDisk>, activeDownloads: List<DownloadModel>, allLanguages: List<Language>, libraryNetworkEntity: LibraryNetworkEntity, filter: String, fileSystemState: FileSystemState )</ID>
|
||||
<ID>LongParameterList:ZimManageViewModel.kt$ZimManageViewModel$( private val downloadDao: FetchDownloadDao, private val bookDao: NewBookDao, private val languageDao: NewLanguagesDao, private val storageObserver: StorageObserver, private val kiwixService: KiwixService, private val context: Application, private val connectivityBroadcastReceiver: ConnectivityBroadcastReceiver, private val bookUtils: BookUtils, private val fat32Checker: Fat32Checker, private val defaultLanguageProvider: DefaultLanguageProvider, private val dataSource: DataSource, private val connectivityManager: ConnectivityManager, private val sharedPreferenceUtil: SharedPreferenceUtil )</ID>
|
||||
<ID>MagicNumber:LibraryListItem.kt$LibraryListItem.LibraryDownloadItem$1000L</ID>
|
||||
<ID>MagicNumber:PeerGroupHandshake.kt$PeerGroupHandshake$15000</ID>
|
||||
<ID>MagicNumber:ShareFiles.kt$ShareFiles$24</ID>
|
||||
<ID>MagicNumber:ZimManageViewModel.kt$ZimManageViewModel$5</ID>
|
||||
<ID>MagicNumber:ZimManageViewModel.kt$ZimManageViewModel$500</ID>
|
||||
<ID>NestedBlockDepth:LocalLibraryFragment.kt$LocalLibraryFragment$checkPermissions</ID>
|
||||
<ID>NestedBlockDepth:PeerGroupHandshake.kt$PeerGroupHandshake$readHandshakeAndExchangeMetaData</ID>
|
||||
<ID>NestedBlockDepth:ReceiverHandShake.kt$ReceiverHandShake$exchangeFileTransferMetadata</ID>
|
||||
<ID>NestedBlockDepth:LocalLibraryFragment.kt$LocalLibraryFragment$private fun checkPermissions()</ID>
|
||||
<ID>NestedBlockDepth:PeerGroupHandshake.kt$PeerGroupHandshake$private fun readHandshakeAndExchangeMetaData(): InetAddress?</ID>
|
||||
<ID>NestedBlockDepth:ReceiverHandShake.kt$ReceiverHandShake$override fun exchangeFileTransferMetadata(inputStream: InputStream, outputStream: OutputStream)</ID>
|
||||
<ID>PackageNaming:AvailableSpaceCalculator.kt$package org.kiwix.kiwixmobile.zim_manager.library_view</ID>
|
||||
<ID>PackageNaming:ConnectivityBroadcastReceiver.kt$package org.kiwix.kiwixmobile.zim_manager</ID>
|
||||
<ID>PackageNaming:DefaultLanguageProvider.kt$package org.kiwix.kiwixmobile.zim_manager</ID>
|
||||
@ -46,5 +46,5 @@
|
||||
<ID>TooGenericExceptionThrown:LibraryViewHolder.kt$LibraryViewHolder.LibraryBookViewHolder$throw RuntimeException("impossible invalid state: ${item.fileSystemState}")</ID>
|
||||
<ID>TooGenericExceptionThrown:ZimManageViewModel.kt$ZimManageViewModel$throw RuntimeException("Impossible state")</ID>
|
||||
<ID>VariableNaming:PeerGroupHandshake.kt$PeerGroupHandshake$private val HANDSHAKE_MESSAGE = "Request Kiwix File Sharing"</ID>
|
||||
</Whitelist>
|
||||
</CurrentIssues>
|
||||
</SmellBaseline>
|
||||
|
@ -108,4 +108,4 @@ private fun resourceId(view: View) =
|
||||
if (view.id > 0 && view.resources != null) " id:${view.resources.getResourceName(view.id)}"
|
||||
else ""
|
||||
|
||||
private fun numSpaces(marginOffset: Int) = (0..marginOffset).fold("", { acc, _ -> "$acc-" })
|
||||
private fun numSpaces(marginOffset: Int) = (0..marginOffset).fold("") { acc, _ -> "$acc-" }
|
||||
|
@ -48,7 +48,7 @@ abstract class BaseActivityTest {
|
||||
getInstrumentation().targetContext.applicationContext
|
||||
}
|
||||
|
||||
inline fun <reified T : Activity> activityTestRule(
|
||||
protected inline fun <reified T : Activity> activityTestRule(
|
||||
noinline beforeActivityAction: (() -> Unit)? = null
|
||||
) =
|
||||
object : ActivityTestRule<T>(T::class.java) {
|
||||
|
@ -40,8 +40,8 @@ class Matcher {
|
||||
public override fun matchesSafely(view: View): Boolean {
|
||||
val parent = view.parent
|
||||
return parent is ViewGroup && parentMatcher.matches(parent) && view == parent.getChildAt(
|
||||
position
|
||||
)
|
||||
position
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,8 @@
|
||||
android:label="@string/app_name"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/KiwixTheme.Launcher"
|
||||
android:windowSoftInputMode="adjustPan">
|
||||
android:windowSoftInputMode="adjustPan"
|
||||
android:exported="true">
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/shortcuts" />
|
||||
@ -145,7 +146,8 @@
|
||||
|
||||
<service android:name=".webserver.wifi_hotspot.HotspotService" />
|
||||
|
||||
<receiver android:name=".main.KiwixSearchWidget">
|
||||
<receiver android:name=".main.KiwixSearchWidget"
|
||||
android:exported="true">
|
||||
<meta-data
|
||||
android:name="android.appwidget.provider"
|
||||
android:resource="@xml/kiwix_widget_provider_info" />
|
||||
|
@ -72,14 +72,18 @@ class IntroFragment : BaseFragment(), IntroContract.View, FragmentActivityExtens
|
||||
addOnPageChangeListener(SimplePageChangeListener(::updateView, ::handleDraggingState))
|
||||
}
|
||||
tab_indicator.setViewPager(view_pager)
|
||||
timer?.schedule(object : TimerTask() {
|
||||
override fun run() {
|
||||
handler.post {
|
||||
if (currentPage == views.size) currentPage = 0
|
||||
view_pager.setCurrentItem(currentPage++, true)
|
||||
timer?.schedule(
|
||||
object : TimerTask() {
|
||||
override fun run() {
|
||||
handler.post {
|
||||
if (currentPage == views.size) currentPage = 0
|
||||
view_pager.setCurrentItem(currentPage++, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}, timerDelay, timerPeriod)
|
||||
},
|
||||
timerDelay,
|
||||
timerPeriod
|
||||
)
|
||||
views.forEach {
|
||||
it.setOnClickListener { dismissAutoRotate() }
|
||||
}
|
||||
|
@ -125,9 +125,11 @@ class LanguageFragment : BaseFragment() {
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
inflater.inflate(R.menu.menu_language, menu)
|
||||
val search = menu.findItem(R.id.menu_language_search)
|
||||
(search.actionView as SearchView).setOnQueryTextListener(SimpleTextListener {
|
||||
languageViewModel.actions.offer(Filter(it))
|
||||
})
|
||||
(search.actionView as SearchView).setOnQueryTextListener(
|
||||
SimpleTextListener {
|
||||
languageViewModel.actions.offer(Filter(it))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
|
@ -82,7 +82,8 @@ import javax.inject.Inject
|
||||
const val URIS_KEY = "uris"
|
||||
|
||||
@SuppressLint("GoogleAppIndexingApiWarning", "Registered")
|
||||
class LocalFileTransferFragment : BaseFragment(),
|
||||
class LocalFileTransferFragment :
|
||||
BaseFragment(),
|
||||
WifiDirectManager.Callbacks {
|
||||
@Inject
|
||||
lateinit var alertDialogShower: AlertDialogShower
|
||||
|
@ -66,7 +66,8 @@ abstract class PeerGroupHandshake(private var groupInfo: WifiP2pInfo) {
|
||||
InetSocketAddress(
|
||||
groupInfo.groupOwnerAddress.hostAddress,
|
||||
PEER_HANDSHAKE_PORT
|
||||
), 15000
|
||||
),
|
||||
15000
|
||||
)
|
||||
val objectOutputStream = ObjectOutputStream(client.getOutputStream())
|
||||
// Send message for the peer device to verify
|
||||
|
@ -112,16 +112,19 @@ class WifiDirectManager @Inject constructor(
|
||||
private fun unregisterWifiDirectBroadcastReceiver() = context.unregisterReceiver(receiver)
|
||||
|
||||
fun discoverPeerDevices() {
|
||||
manager?.discoverPeers(channel, object : ActionListener {
|
||||
override fun onSuccess() {
|
||||
context.toast(R.string.discovery_initiated, Toast.LENGTH_SHORT)
|
||||
}
|
||||
manager?.discoverPeers(
|
||||
channel,
|
||||
object : ActionListener {
|
||||
override fun onSuccess() {
|
||||
context.toast(R.string.discovery_initiated, Toast.LENGTH_SHORT)
|
||||
}
|
||||
|
||||
override fun onFailure(reason: Int) {
|
||||
Log.d(TAG, "${context.getString(R.string.discovery_failed)}: ${getErrorMessage(reason)}")
|
||||
context.toast(R.string.discovery_failed, Toast.LENGTH_SHORT)
|
||||
override fun onFailure(reason: Int) {
|
||||
Log.d(TAG, "${context.getString(R.string.discovery_failed)}: ${getErrorMessage(reason)}")
|
||||
context.toast(R.string.discovery_failed, Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/* From KiwixWifiP2pBroadcastReceiver.P2pEventListener callback-interface*/
|
||||
@ -188,7 +191,8 @@ class WifiDirectManager @Inject constructor(
|
||||
hasSenderStartedConnection = true
|
||||
connect(senderSelectedPeerDevice)
|
||||
context.toast(R.string.performing_handshake, Toast.LENGTH_LONG)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -197,17 +201,21 @@ class WifiDirectManager @Inject constructor(
|
||||
deviceAddress = senderSelectedPeerDevice.deviceAddress
|
||||
wps.setup = WpsInfo.PBC
|
||||
}
|
||||
manager?.connect(channel, config, object : ActionListener {
|
||||
override fun onSuccess() {
|
||||
// UI updated from broadcast receiver
|
||||
}
|
||||
manager?.connect(
|
||||
channel,
|
||||
config,
|
||||
object : ActionListener {
|
||||
override fun onSuccess() {
|
||||
// UI updated from broadcast receiver
|
||||
}
|
||||
|
||||
override fun onFailure(reason: Int) {
|
||||
val errorMessage = getErrorMessage(reason)
|
||||
Log.d(TAG, context.getString(R.string.connection_failed) + ": " + errorMessage)
|
||||
context.toast(R.string.connection_failed, Toast.LENGTH_LONG)
|
||||
override fun onFailure(reason: Int) {
|
||||
val errorMessage = getErrorMessage(reason)
|
||||
Log.d(TAG, context.getString(R.string.connection_failed) + ": " + errorMessage)
|
||||
context.toast(R.string.connection_failed, Toast.LENGTH_LONG)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
private fun performHandshakeWith(groupInfo: WifiP2pInfo) {
|
||||
@ -291,17 +299,20 @@ class WifiDirectManager @Inject constructor(
|
||||
}
|
||||
|
||||
private fun disconnect() {
|
||||
manager?.removeGroup(channel, object : ActionListener {
|
||||
override fun onFailure(reasonCode: Int) {
|
||||
Log.d(TAG, "Disconnect failed. Reason: $reasonCode")
|
||||
closeChannel()
|
||||
}
|
||||
manager?.removeGroup(
|
||||
channel,
|
||||
object : ActionListener {
|
||||
override fun onFailure(reasonCode: Int) {
|
||||
Log.d(TAG, "Disconnect failed. Reason: $reasonCode")
|
||||
closeChannel()
|
||||
}
|
||||
|
||||
override fun onSuccess() {
|
||||
Log.d(TAG, "Disconnect successful")
|
||||
closeChannel()
|
||||
override fun onSuccess() {
|
||||
Log.d(TAG, "Disconnect successful")
|
||||
closeChannel()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
private fun closeChannel() {
|
||||
|
@ -94,10 +94,12 @@ class LocalLibraryFragment : BaseFragment() {
|
||||
}
|
||||
|
||||
private val bookDelegate: BookOnDiskDelegate.BookDelegate by lazy {
|
||||
BookOnDiskDelegate.BookDelegate(sharedPreferenceUtil,
|
||||
BookOnDiskDelegate.BookDelegate(
|
||||
sharedPreferenceUtil,
|
||||
{ offerAction(RequestNavigateTo(it)) },
|
||||
{ offerAction(RequestMultiSelection(it)) },
|
||||
{ offerAction(RequestSelect(it)) })
|
||||
{ offerAction(RequestSelect(it)) }
|
||||
)
|
||||
}
|
||||
private val booksOnDiskAdapter: BooksOnDiskAdapter by lazy {
|
||||
BooksOnDiskAdapter(bookDelegate, BookOnDiskDelegate.LanguageDelegate)
|
||||
@ -138,9 +140,9 @@ class LocalLibraryFragment : BaseFragment() {
|
||||
}
|
||||
zimManageViewModel.fileSelectListStates.observe(viewLifecycleOwner, Observer(::render))
|
||||
disposable.add(sideEffects())
|
||||
zimManageViewModel.deviceListIsRefreshing.observe(viewLifecycleOwner, Observer {
|
||||
zimManageViewModel.deviceListIsRefreshing.observe(viewLifecycleOwner) {
|
||||
zim_swiperefresh.isRefreshing = it!!
|
||||
})
|
||||
}
|
||||
if (savedInstanceState != null && savedInstanceState.getBoolean(WAS_IN_ACTION_MODE)) {
|
||||
zimManageViewModel.fileSelectActions.offer(FileSelectActions.RestartActionMode)
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.lifecycle.Observer
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.observe
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import eu.mhutti1.utils.storage.StorageDevice
|
||||
@ -107,7 +108,8 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
LibraryDelegate.DownloadDelegate {
|
||||
dialogShower.show(
|
||||
KiwixDialog.YesNoDialog.StopDownload,
|
||||
{ downloader.cancelDownload(it.downloadId) })
|
||||
{ downloader.cancelDownload(it.downloadId) }
|
||||
)
|
||||
},
|
||||
LibraryDelegate.DividerDelegate
|
||||
)
|
||||
@ -153,18 +155,22 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
viewLifecycleOwner, Observer(::onRefreshStateChange)
|
||||
)
|
||||
zimManageViewModel.networkStates.observe(viewLifecycleOwner, Observer(::onNetworkStateChange))
|
||||
zimManageViewModel.shouldShowWifiOnlyDialog.observe(viewLifecycleOwner, Observer {
|
||||
zimManageViewModel.shouldShowWifiOnlyDialog.observe(
|
||||
viewLifecycleOwner
|
||||
) {
|
||||
if (it) {
|
||||
showInternetPermissionDialog()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// hides keyboard when scrolled
|
||||
libraryList.addOnScrollListener(SimpleRecyclerViewScrollListener { _, newState ->
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
libraryList.closeKeyboard()
|
||||
libraryList.addOnScrollListener(
|
||||
SimpleRecyclerViewScrollListener { _, newState ->
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
libraryList.closeKeyboard()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
allowInternetPermissionButton.setOnClickListener {
|
||||
showInternetPermissionDialog()
|
||||
@ -405,7 +411,8 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
})
|
||||
return
|
||||
}
|
||||
else -> availableSpaceCalculator.hasAvailableSpaceFor(item,
|
||||
else -> availableSpaceCalculator.hasAvailableSpaceFor(
|
||||
item,
|
||||
{ downloadFile(item.book) },
|
||||
{
|
||||
libraryList.snack(
|
||||
@ -415,7 +422,8 @@ class OnlineLibraryFragment : BaseFragment(), FragmentActivityExtensions {
|
||||
R.string.download_change_storage,
|
||||
::showStorageSelectDialog
|
||||
)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,8 +41,9 @@ class KiwixPrefsFragment : CorePrefsFragment() {
|
||||
|
||||
override fun setStorage() {
|
||||
findPreference<Preference>(PREF_STORAGE)?.title = getString(
|
||||
if (sharedPreferenceUtil.prefStorage == internalStorage()?.let
|
||||
(sharedPreferenceUtil::getPublicDirectoryPath)
|
||||
if (sharedPreferenceUtil.prefStorage == internalStorage()?.let(
|
||||
sharedPreferenceUtil::getPublicDirectoryPath
|
||||
)
|
||||
) R.string.internal_storage
|
||||
else R.string.external_storage
|
||||
)
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.kiwix.kiwixmobile.webserver.wifi_hotspot
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Notification
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
@ -38,18 +39,20 @@ class HotspotNotificationManager @Inject constructor(
|
||||
|
||||
private fun hotspotNotificationChannel() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
notificationManager.createNotificationChannel(NotificationChannel(
|
||||
HOTSPOT_SERVICE_CHANNEL_ID,
|
||||
context.getString(R.string.hotspot_service_channel_name),
|
||||
NotificationManager.IMPORTANCE_DEFAULT
|
||||
).apply {
|
||||
description = context.getString(R.string.hotspot_channel_description)
|
||||
setSound(null, null)
|
||||
})
|
||||
notificationManager.createNotificationChannel(
|
||||
NotificationChannel(
|
||||
HOTSPOT_SERVICE_CHANNEL_ID,
|
||||
context.getString(R.string.hotspot_service_channel_name),
|
||||
NotificationManager.IMPORTANCE_DEFAULT
|
||||
).apply {
|
||||
description = context.getString(R.string.hotspot_channel_description)
|
||||
setSound(null, null)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun buildForegroundNotification(): Notification {
|
||||
@SuppressLint("UnspecifiedImmutableFlag") fun buildForegroundNotification(): Notification {
|
||||
val contentIntent = NavDeepLinkBuilder(context).setComponentName(
|
||||
KiwixMainActivity::class.java
|
||||
)
|
||||
|
@ -483,6 +483,7 @@ class ZimManageViewModel @Inject constructor(
|
||||
oldBookOnDisk.id == newBookOnDisk.id
|
||||
}
|
||||
newBookOnDisk.apply { isSelected = firstOrNull?.isSelected ?: false }
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -61,7 +61,8 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintVertical_bias="0.45" />
|
||||
app:layout_constraintVertical_bias="0.45"
|
||||
tools:ignore="RequiredSize" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/allowInternetPermissionButton"
|
||||
|
@ -64,6 +64,7 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="RequiredSize"
|
||||
app:layout_constraintVertical_bias="0.45" />
|
||||
|
||||
<Button
|
||||
|
@ -12,12 +12,13 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("com.android.tools.build:gradle:4.0.1")
|
||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72")
|
||||
implementation("com.hiya:jacoco-android:0.2")
|
||||
implementation("org.jlleitschuh.gradle:ktlint-gradle:9.2.1")
|
||||
implementation("com.android.tools.build:gradle:7.1.0")
|
||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.21")
|
||||
implementation("com.dicedmelon.gradle:jacoco-android:0.1.5")
|
||||
implementation("org.jlleitschuh.gradle:ktlint-gradle:10.3.0")
|
||||
implementation("com.google.apis:google-api-services-androidpublisher:v3-rev129-1.25.0")
|
||||
implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.9.1")
|
||||
implementation("io.gitlab.arturbosch.detekt:detekt-gradle-plugin:1.20.0")
|
||||
implementation("com.googlecode.json-simple:json-simple:1.1")
|
||||
|
||||
implementation(gradleApi())
|
||||
implementation(localGroovy())
|
||||
|
@ -22,7 +22,7 @@ object Versions {
|
||||
|
||||
const val com_squareup_okhttp3: String = "4.9.0"
|
||||
|
||||
const val org_jetbrains_kotlin: String = "1.4.20"
|
||||
const val org_jetbrains_kotlin: String = "1.4.21"
|
||||
|
||||
const val androidx_navigation: String = "2.3.1"
|
||||
|
||||
@ -42,11 +42,11 @@ object Versions {
|
||||
|
||||
const val android_arch_lifecycle_extensions: String = "1.1.1"
|
||||
|
||||
const val com_android_tools_build_gradle: String = "4.0.1" // available: "4.1.1"
|
||||
const val com_android_tools_build_gradle: String = "7.1.0"
|
||||
|
||||
const val de_fayard_buildsrcversions_gradle_plugin: String = "0.7.0"
|
||||
|
||||
const val com_github_triplet_play_gradle_plugin: String = "2.8.0" // available: "3.0.0"
|
||||
const val com_github_triplet_play_gradle_plugin: String = "3.7.0"
|
||||
|
||||
const val javax_annotation_api: String = "1.3.2"
|
||||
|
||||
|
@ -23,8 +23,6 @@ import Libs
|
||||
import com.android.build.gradle.BaseExtension
|
||||
import io.gitlab.arturbosch.detekt.extensions.DetektExtension
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.kotlin.dsl.KotlinClosure1
|
||||
import org.gradle.kotlin.dsl.apply
|
||||
import org.gradle.kotlin.dsl.dependencies
|
||||
import org.gradle.testing.jacoco.plugins.JacocoPluginExtension
|
||||
@ -39,7 +37,7 @@ class AllProjectConfigurer {
|
||||
target.plugins.apply("kotlin-android")
|
||||
target.plugins.apply("kotlin-android-extensions")
|
||||
target.plugins.apply("kotlin-kapt")
|
||||
target.plugins.apply("com.hiya.jacoco-android")
|
||||
target.plugins.apply("com.dicedmelon.gradle.jacoco-android")
|
||||
target.plugins.apply("org.jlleitschuh.gradle.ktlint")
|
||||
target.plugins.apply("io.gitlab.arturbosch.detekt")
|
||||
target.plugins.apply("androidx.navigation.safeargs")
|
||||
@ -75,19 +73,21 @@ class AllProjectConfigurer {
|
||||
execution = "ANDROIDX_TEST_ORCHESTRATOR"
|
||||
unitTests.apply {
|
||||
isReturnDefaultValues = true
|
||||
all(KotlinClosure1<Any, Test>({
|
||||
(this as Test).also { testTask ->
|
||||
all {
|
||||
it.also { testTask ->
|
||||
testTask.useJUnitPlatform()
|
||||
testTask.testLogging {
|
||||
setEvents(setOf("passed", "skipped", "failed", "standardOut", "standardError"))
|
||||
outputs.upToDateWhen { false }
|
||||
testTask.outputs.upToDateWhen { false }
|
||||
showStandardStreams = true
|
||||
}
|
||||
testTask.extensions
|
||||
.getByType(JacocoTaskExtension::class.java)
|
||||
.isIncludeNoLocationClasses = true
|
||||
.getByType(JacocoTaskExtension::class.java).apply {
|
||||
isIncludeNoLocationClasses = true
|
||||
excludes = listOf("jdk.internal.*")
|
||||
}
|
||||
}
|
||||
}, this))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,16 +104,18 @@ class AllProjectConfigurer {
|
||||
"CheckResult",
|
||||
"LabelFor",
|
||||
"LogConditional",
|
||||
"ConvertToWebp"
|
||||
)
|
||||
|
||||
warning(
|
||||
"ConvertToWebp",
|
||||
//TODO remove this when we remove jcenter from gradle
|
||||
"JcenterRepositoryObsolete",
|
||||
"UnknownNullness",
|
||||
"SelectableText",
|
||||
"MissingTranslation",
|
||||
"IconDensities",
|
||||
"ContentDescription",
|
||||
"IconDipSize"
|
||||
"IconDipSize",
|
||||
"UnusedResources",
|
||||
"NonConstantResourceId",
|
||||
"NotifyDataSetChanged"
|
||||
)
|
||||
lintConfig = target.rootProject.file("lintConfig.xml")
|
||||
}
|
||||
@ -144,9 +146,11 @@ class AllProjectConfigurer {
|
||||
configureExtension<JacocoPluginExtension> { toolVersion = "0.8.7" }
|
||||
configureExtension<KtlintExtension> { android.set(true) }
|
||||
configureExtension<DetektExtension> {
|
||||
buildUponDefaultConfig = true
|
||||
allRules = false
|
||||
config = target.files("${target.rootDir}/config/detekt/detekt.yml")
|
||||
baseline = project.file("detekt_baseline.xml")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,10 @@ build:
|
||||
maxIssues: 0
|
||||
excludeCorrectable: false
|
||||
weights:
|
||||
# complexity: 2
|
||||
# LongParameterList: 1
|
||||
# style: 1
|
||||
# comments: 1
|
||||
# complexity: 2
|
||||
# LongParameterList: 1
|
||||
# style: 1
|
||||
# comments: 1
|
||||
|
||||
config:
|
||||
validation: true
|
||||
@ -25,11 +25,11 @@ processors:
|
||||
console-reports:
|
||||
active: true
|
||||
exclude:
|
||||
- 'ProjectStatisticsReport'
|
||||
- 'ComplexityReport'
|
||||
- 'NotificationReport'
|
||||
# - 'FindingsReport'
|
||||
- 'FileBasedFindingsReport'
|
||||
- 'ProjectStatisticsReport'
|
||||
- 'ComplexityReport'
|
||||
- 'NotificationReport'
|
||||
# - 'FindingsReport'
|
||||
- 'FileBasedFindingsReport'
|
||||
|
||||
comments:
|
||||
active: true
|
||||
@ -180,130 +180,22 @@ exceptions:
|
||||
active: true
|
||||
excludes: "**/test/**,**/androidTest/**,**/*.Test.kt,**/*.Spec.kt,**/*.Spek.kt"
|
||||
exceptionNames:
|
||||
- ArrayIndexOutOfBoundsException
|
||||
- Error
|
||||
- Exception
|
||||
- IllegalMonitorStateException
|
||||
- NullPointerException
|
||||
- IndexOutOfBoundsException
|
||||
- RuntimeException
|
||||
- Throwable
|
||||
- ArrayIndexOutOfBoundsException
|
||||
- Error
|
||||
- Exception
|
||||
- IllegalMonitorStateException
|
||||
- NullPointerException
|
||||
- IndexOutOfBoundsException
|
||||
- RuntimeException
|
||||
- Throwable
|
||||
allowedExceptionNameRegex: "^(_|(ignore|expected).*)"
|
||||
TooGenericExceptionThrown:
|
||||
active: true
|
||||
exceptionNames:
|
||||
- Error
|
||||
- Exception
|
||||
- Throwable
|
||||
- RuntimeException
|
||||
|
||||
formatting:
|
||||
active: true
|
||||
android: false
|
||||
autoCorrect: true
|
||||
AnnotationOnSeparateLine:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
ChainWrapping:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
CommentSpacing:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
EnumEntryNameCase:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
Filename:
|
||||
active: true
|
||||
FinalNewline:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
ImportOrdering:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
Indentation:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
indentSize: 4
|
||||
continuationIndentSize: 4
|
||||
MaximumLineLength:
|
||||
active: true
|
||||
maxLineLength: 120
|
||||
ModifierOrdering:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
MultiLineIfElse:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoBlankLineBeforeRbrace:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoConsecutiveBlankLines:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoEmptyClassBody:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoEmptyFirstLineInMethodBlock:
|
||||
active: false
|
||||
autoCorrect: true
|
||||
NoLineBreakAfterElse:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoLineBreakBeforeAssignment:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoMultipleSpaces:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoSemicolons:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoTrailingSpaces:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoUnitReturn:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoUnusedImports:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
NoWildcardImports:
|
||||
active: true
|
||||
PackageName:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
ParameterListWrapping:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
indentSize: 4
|
||||
SpacingAroundColon:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundComma:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundCurly:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundDot:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundKeyword:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundOperators:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundParens:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
SpacingAroundRangeOperator:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
StringTemplate:
|
||||
active: true
|
||||
autoCorrect: true
|
||||
- Error
|
||||
- Exception
|
||||
- Throwable
|
||||
- RuntimeException
|
||||
|
||||
naming:
|
||||
active: true
|
||||
|
@ -19,8 +19,34 @@ plugins {
|
||||
plugins.apply(KiwixConfigurationPlugin::class)
|
||||
apply(plugin = "io.objectbox")
|
||||
apply(plugin = "com.jakewharton.butterknife")
|
||||
ext {
|
||||
set("versionMajor", 3)
|
||||
set("versionMinor", 5)
|
||||
set("versionPatch", 0)
|
||||
}
|
||||
|
||||
/*
|
||||
* max version code: 21-0-0-00-00-00
|
||||
* our template : UU-D-A-ZZ-YY-XX
|
||||
* where:
|
||||
* X = patch version
|
||||
* Y = minor version
|
||||
* Z = major version (+ 20 to distinguish from previous, non semantic, versions of the app)
|
||||
* A = number representing ABI split
|
||||
* D = number representing density split
|
||||
* U = unused
|
||||
*/
|
||||
|
||||
fun generateVersionCode() =
|
||||
20 * 10000 +
|
||||
ext["versionMajor"] as Int * 10000 +
|
||||
ext["versionMinor"] as Int * 100 +
|
||||
ext["versionPatch"] as Int
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
buildConfigField("long", "VERSION_CODE", "${generateVersionCode()}")
|
||||
}
|
||||
buildTypes {
|
||||
getByName("release") {
|
||||
isMinifyEnabled = false
|
||||
@ -31,7 +57,6 @@ android {
|
||||
fun shouldUseLocalVersion() = File(projectDir, "libs").exists()
|
||||
|
||||
dependencies {
|
||||
|
||||
// use jdk8 java.time backport, as long app < Build.VERSION_CODES.O
|
||||
implementation(Libs.threetenabp)
|
||||
|
||||
|
@ -1,18 +1,20 @@
|
||||
<?xml version="1.0" ?>
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<SmellBaseline>
|
||||
<Blacklist></Blacklist>
|
||||
<Whitelist>
|
||||
<ManuallySuppressedIssues/>
|
||||
<CurrentIssues>
|
||||
<ID>EmptyFunctionBlock:BooksOnDiskViewHolder.kt$BookOnDiskViewHolder.BookViewHolder${ }</ID>
|
||||
<ID>EmptyFunctionBlock:FetchDownloadMonitor.kt$FetchDownloadMonitor.<no name provided>${}</ID>
|
||||
<ID>EmptyFunctionBlock:FetchDownloadMonitor.kt$FetchDownloadMonitor.<no name provided>${}</ID>
|
||||
<ID>EmptyFunctionBlock:OnSwipeTouchListener.kt$OnSwipeTouchListener${}</ID>
|
||||
<ID>ForbiddenComment:JNIInitialiser.kt$JNIInitialiser$// TODO: Consider surfacing to user</ID>
|
||||
<ID>LongMethod:TabsAdapter.kt$TabsAdapter$onCreateViewHolder</ID>
|
||||
<ID>LongParameterList:KiwixDialog.kt$KiwixDialog$( val title: Int?, val message: Int?, val positiveMessage: Int, val negativeMessage: Int?, val cancelable: Boolean = true, val icon: Int? = null, val neutralMessage: Int? = null, val getView: (() -> View)? = null )</ID>
|
||||
<ID>LongParameterList:MainMenu.kt$MainMenu$( private val activity: Activity, zimFileReader: ZimFileReader?, menu: Menu, webViews: MutableList<KiwixWebView>, urlIsValid: Boolean, disableReadAloud: Boolean = false, disableTabs: Boolean = false, private val menuClickListener: MenuClickListener )</ID>
|
||||
<ID>LongParameterList:MainMenu.kt$MainMenu.Factory$( menu: Menu, webViews: MutableList<KiwixWebView>, urlIsValid: Boolean, menuClickListener: MenuClickListener, disableReadAloud: Boolean, disableTabs: Boolean )</ID>
|
||||
<ID>ForbiddenComment:NetworkUtilsTest.kt$NetworkUtilsTest$// TODO: find a way to assert regex matching via JUnit and rewrite the test</ID>
|
||||
<ID>LongMethod:ChunkUtilsTest.kt$ChunkUtilsTest$@Test fun testGetChunks()</ID>
|
||||
<ID>LongMethod:TabsAdapter.kt$TabsAdapter$@SuppressLint("ResourceType") override fun onCreateViewHolder( parent: ViewGroup, viewType: Int ): ViewHolder</ID>
|
||||
<ID>LongParameterList:KiwixDialog.kt$KiwixDialog$( val title: Int?, val message: Int?, val positiveMessage: Int, val negativeMessage: Int?, val cancelable: Boolean = true, val icon: Int? = null, val neutralMessage: Int? = null, val getView: (() -> View)? = null )</ID>
|
||||
<ID>LongParameterList:MainMenu.kt$MainMenu$( private val activity: Activity, zimFileReader: ZimFileReader?, menu: Menu, webViews: MutableList<KiwixWebView>, urlIsValid: Boolean, disableReadAloud: Boolean = false, disableTabs: Boolean = false, private val menuClickListener: MenuClickListener )</ID>
|
||||
<ID>LongParameterList:MainMenu.kt$MainMenu.Factory$( menu: Menu, webViews: MutableList<KiwixWebView>, urlIsValid: Boolean, menuClickListener: MenuClickListener, disableReadAloud: Boolean, disableTabs: Boolean )</ID>
|
||||
<ID>LongParameterList:PageTestHelpers.kt$( bookmarkTitle: String = "bookmarkTitle", isSelected: Boolean = false, id: Long = 2, zimId: String = "zimId", zimName: String = "zimName", zimFilePath: String = "zimFilePath", bookmarkUrl: String = "bookmarkUrl", favicon: String = "favicon" )</ID>
|
||||
<ID>LongParameterList:Repository.kt$Repository$( @param:IO private val io: Scheduler, @param:MainThread private val mainThread: Scheduler, private val bookDao: NewBookDao, private val bookmarksDao: NewBookmarksDao, private val historyDao: HistoryDao, private val languageDao: NewLanguagesDao, private val recentSearchDao: NewRecentSearchDao, private val zimReaderContainer: ZimReaderContainer )</ID>
|
||||
<ID>LongParameterList:ToolbarScrollingKiwixWebView.kt$ToolbarScrollingKiwixWebView$( context: Context, callback: WebViewCallback, attrs: AttributeSet, nonVideoView: ViewGroup, videoView: ViewGroup, webViewClient: CoreWebViewClient, private val toolbarView: View, private val bottomBarView: View, sharedPreferenceUtil: SharedPreferenceUtil, private val parentNavigationBar: View? = null )</ID>
|
||||
<ID>MagicNumber:ArticleCount.kt$ArticleCount$1000.0</ID>
|
||||
<ID>MagicNumber:ArticleCount.kt$ArticleCount$3</ID>
|
||||
<ID>MagicNumber:CompatFindActionModeCallback.kt$CompatFindActionModeCallback$100</ID>
|
||||
<ID>MagicNumber:DownloadItem.kt$DownloadItem$1000L</ID>
|
||||
@ -29,11 +31,15 @@
|
||||
<ID>MagicNumber:Seconds.kt$Seconds$60</ID>
|
||||
<ID>MagicNumber:Seconds.kt$Seconds$60.0</ID>
|
||||
<ID>MagicNumber:TabsAdapter.kt$TabsAdapter$8</ID>
|
||||
<ID>NestedBlockDepth:FileUtils.kt$FileUtils$deleteZimFile</ID>
|
||||
<ID>NestedBlockDepth:ImageUtils.kt$ImageUtils$getBitmapFromView</ID>
|
||||
<ID>NestedBlockDepth:JNIInitialiser.kt$JNIInitialiser$loadICUData</ID>
|
||||
<ID>NestedBlockDepth:OnSwipeTouchListener.kt$OnSwipeTouchListener.GestureListener$onFling</ID>
|
||||
<ID>NestedBlockDepth:StorageDeviceUtils.kt$StorageDeviceUtils$canWrite</ID>
|
||||
<ID>MatchingDeclarationName:PageTestHelpers.kt$PageImpl : Page</ID>
|
||||
<ID>MaxLineLength:BookUtilsTest.kt$BookUtilsTest$// this case uses the result from the container nested class inside LanguageUtils. It will be tested in LanguageUtilsTest</ID>
|
||||
<ID>MaxLineLength:MetaLinkNetworkEntityTest.kt$MetaLinkNetworkEntityTest$"http://www.mirrorservice.org/sites/download.kiwix.org/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"</ID>
|
||||
<ID>MaxLineLength:NetworkUtilsTest.kt$NetworkUtilsTest$// Here the Method should return the substring between the first '?' character and the nearest '/' character preceeding it</ID>
|
||||
<ID>NestedBlockDepth:FileUtils.kt$FileUtils$@JvmStatic @Synchronized fun deleteZimFile(path: String)</ID>
|
||||
<ID>NestedBlockDepth:ImageUtils.kt$ImageUtils$private fun getBitmapFromView(width: Int, height: Int, viewToDrawFrom: View): Bitmap?</ID>
|
||||
<ID>NestedBlockDepth:JNIInitialiser.kt$JNIInitialiser$private fun loadICUData(context: Context): String?</ID>
|
||||
<ID>NestedBlockDepth:OnSwipeTouchListener.kt$OnSwipeTouchListener.GestureListener$override fun onFling( e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float ): Boolean</ID>
|
||||
<ID>NestedBlockDepth:StorageDeviceUtils.kt$StorageDeviceUtils$// Amazingly file.canWrite() does not always return the correct value private fun canWrite(file: File): Boolean</ID>
|
||||
<ID>PackageNaming:ArticleCount.kt$package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view</ID>
|
||||
<ID>PackageNaming:BookOnDiskDelegate.kt$package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter</ID>
|
||||
<ID>PackageNaming:BooksOnDiskAdapter.kt$package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view.adapter</ID>
|
||||
@ -45,7 +51,7 @@
|
||||
<ID>PackageNaming:MountPointProducer.kt$package org.kiwix.kiwixmobile.core.zim_manager</ID>
|
||||
<ID>PackageNaming:SelectionMode.kt$package org.kiwix.kiwixmobile.core.zim_manager.fileselect_view</ID>
|
||||
<ID>PackageNaming:TagsView.kt$package org.kiwix.kiwixmobile.core.zim_manager</ID>
|
||||
<ID>ReturnCount:FileUtils.kt$FileUtils$@JvmStatic fun getAllZimParts(book: Book): List<File></ID>
|
||||
<ID>ReturnCount:FileUtils.kt$FileUtils$@JvmStatic fun getAllZimParts(book: Book): List<File></ID>
|
||||
<ID>ReturnCount:FileUtils.kt$FileUtils$@JvmStatic fun getLocalFilePathByUri( context: Context, uri: Uri ): String?</ID>
|
||||
<ID>ReturnCount:FileUtils.kt$FileUtils$@JvmStatic fun hasPart(file: File): Boolean</ID>
|
||||
<ID>ReturnCount:FileUtils.kt$FileUtils$@Synchronized private fun deleteZimFileParts(path: String): Boolean</ID>
|
||||
@ -68,5 +74,5 @@
|
||||
<ID>TopLevelPropertyNaming:Bytes.kt$const val Mb = Kb * 1024</ID>
|
||||
<ID>TopLevelPropertyNaming:Bytes.kt$const val Pb = Tb * 1024</ID>
|
||||
<ID>TopLevelPropertyNaming:Bytes.kt$const val Tb = Gb * 1024</ID>
|
||||
</Whitelist>
|
||||
</CurrentIssues>
|
||||
</SmellBaseline>
|
||||
|
@ -4,7 +4,8 @@
|
||||
android:installLocation="auto">
|
||||
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
|
||||
tools:ignore="ScopedStorage" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
|
||||
|
@ -22,8 +22,10 @@ import android.view.View
|
||||
import androidx.recyclerview.widget.RecyclerView.ViewHolder
|
||||
import kotlinx.android.extensions.LayoutContainer
|
||||
|
||||
abstract class BaseViewHolder<in ITEM>(override val containerView: View) : ViewHolder(
|
||||
containerView
|
||||
), LayoutContainer {
|
||||
abstract class BaseViewHolder<in ITEM>(override val containerView: View) :
|
||||
ViewHolder(
|
||||
containerView
|
||||
),
|
||||
LayoutContainer {
|
||||
abstract fun bind(item: ITEM)
|
||||
}
|
||||
|
@ -30,9 +30,11 @@ import org.kiwix.kiwixmobile.core.reader.ZimFileReader
|
||||
import javax.inject.Inject
|
||||
|
||||
class NewBookmarksDao @Inject constructor(val box: Box<BookmarkEntity>) : PageDao {
|
||||
fun bookmarks(): Flowable<List<Page>> = box.asFlowable(box.query {
|
||||
order(BookmarkEntity_.bookmarkTitle)
|
||||
}).map { it.map(::BookmarkItem) }
|
||||
fun bookmarks(): Flowable<List<Page>> = box.asFlowable(
|
||||
box.query {
|
||||
order(BookmarkEntity_.bookmarkTitle)
|
||||
}
|
||||
).map { it.map(::BookmarkItem) }
|
||||
|
||||
override fun pages(): Flowable<List<Page>> = bookmarks()
|
||||
override fun deletePages(pagesToDelete: List<Page>) =
|
||||
@ -55,7 +57,8 @@ class NewBookmarksDao @Inject constructor(val box: Box<BookmarkEntity>) : PageDa
|
||||
.or()
|
||||
.equal(BookmarkEntity_.zimName, zimFileReader?.name ?: "")
|
||||
order(BookmarkEntity_.bookmarkTitle)
|
||||
}).map { it.map(BookmarkEntity::bookmarkUrl) }
|
||||
}
|
||||
).map { it.map(BookmarkEntity::bookmarkUrl) }
|
||||
.subscribeOn(Schedulers.io())
|
||||
|
||||
fun saveBookmark(bookmarkItem: BookmarkItem) {
|
||||
|
@ -68,7 +68,8 @@ class Repository @Inject internal constructor(
|
||||
.map {
|
||||
HeaderizableList<BooksOnDiskListItem, BookOnDisk, LanguageItem>(it).foldOverAddingHeaders(
|
||||
{ bookOnDisk -> LanguageItem(bookOnDisk.locale) },
|
||||
{ current, next -> current.locale.displayName != next.locale.displayName })
|
||||
{ current, next -> current.locale.displayName != next.locale.displayName }
|
||||
)
|
||||
}
|
||||
.map { it.toList() }
|
||||
|
||||
|
@ -45,9 +45,11 @@ class NetworkModule {
|
||||
.connectTimeout(CONNECTION_TIMEOUT, SECONDS)
|
||||
.readTimeout(READ_TIMEOUT, SECONDS)
|
||||
.callTimeout(CALL_TIMEOUT, SECONDS)
|
||||
.addNetworkInterceptor(HttpLoggingInterceptor().apply {
|
||||
level = if (BuildConfig.DEBUG) BASIC else NONE
|
||||
})
|
||||
.addNetworkInterceptor(
|
||||
HttpLoggingInterceptor().apply {
|
||||
level = if (BuildConfig.DEBUG) BASIC else NONE
|
||||
}
|
||||
)
|
||||
.addNetworkInterceptor(UserAgentInterceptor(USER_AGENT))
|
||||
.build()
|
||||
}
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.kiwix.kiwixmobile.core.downloader.fetch
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.NotificationChannel
|
||||
import android.app.NotificationManager
|
||||
import android.app.PendingIntent.FLAG_UPDATE_CURRENT
|
||||
@ -107,6 +108,7 @@ class FetchDownloadNotificationManager(context: Context) :
|
||||
notificationCustomisation(downloadNotification, notificationBuilder, context)
|
||||
}
|
||||
|
||||
@SuppressLint("UnspecifiedImmutableFlag")
|
||||
private fun notificationCustomisation(
|
||||
downloadNotification: DownloadNotification,
|
||||
notificationBuilder: NotificationCompat.Builder,
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.kiwix.kiwixmobile.core.error
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Intent
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
@ -139,7 +140,7 @@ open class ErrorActivity : BaseActivity() {
|
||||
All Zim Files in DB:
|
||||
$allZimFiles
|
||||
|
||||
""".trimIndent()
|
||||
""".trimIndent()
|
||||
}
|
||||
|
||||
private fun languageLocale(): String = """
|
||||
@ -184,13 +185,15 @@ open class ErrorActivity : BaseActivity() {
|
||||
get() = """
|
||||
Hi Kiwix Developers!
|
||||
The Android app crashed, here are some details to help fix it:
|
||||
""".trimIndent()
|
||||
""".trimIndent()
|
||||
|
||||
private val versionCode: Int
|
||||
@SuppressLint("WrongConstant")
|
||||
get() = packageManager
|
||||
.getPackageInfo(packageName, ZERO).versionCode
|
||||
|
||||
private val versionName: String
|
||||
@SuppressLint("WrongConstant")
|
||||
get() = packageManager
|
||||
.getPackageInfo(packageName, ZERO).versionName
|
||||
|
||||
|
@ -29,11 +29,13 @@ fun Book.calculateSearchMatches(
|
||||
) {
|
||||
val searchableText = buildSearchableText(bookUtils)
|
||||
searchMatches = filter.split("\\s+")
|
||||
.foldRight(0,
|
||||
.foldRight(
|
||||
0,
|
||||
{ filterWord, acc ->
|
||||
if (searchableText.contains(filterWord, true)) acc + 1
|
||||
else acc
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun Book.buildSearchableText(bookUtils: BookUtils): String =
|
||||
|
@ -85,10 +85,14 @@ abstract class HelpFragment : BaseFragment() {
|
||||
|
||||
private fun sendFeedback() {
|
||||
val intent = Intent(Intent.ACTION_SENDTO)
|
||||
intent.data = ("mailto:${Uri.encode(CONTACT_EMAIL_ADDRESS)}" +
|
||||
"?subject=${
|
||||
Uri.encode("Feedback in ${getCurrentLocale(requireActivity()).displayLanguage}")
|
||||
}").toUri()
|
||||
intent.data = (
|
||||
"mailto:${Uri.encode(CONTACT_EMAIL_ADDRESS)}" +
|
||||
"?subject=" +
|
||||
Uri.encode(
|
||||
"Feedback in " +
|
||||
getCurrentLocale(requireActivity()).displayLanguage
|
||||
)
|
||||
).toUri()
|
||||
startActivity(Intent.createChooser(intent, "Send Feedback via Email"))
|
||||
}
|
||||
}
|
||||
|
@ -243,11 +243,13 @@ class AddNoteDialog : DialogFragment() {
|
||||
|
||||
// Show the previously saved note if it exists
|
||||
displayNote()
|
||||
add_note_edit_text.addTextChangedListener(SimpleTextWatcher { _, _, _, _ ->
|
||||
noteEdited = true
|
||||
enableSaveNoteMenuItem()
|
||||
enableShareNoteMenuItem()
|
||||
})
|
||||
add_note_edit_text.addTextChangedListener(
|
||||
SimpleTextWatcher { _, _, _, _ ->
|
||||
noteEdited = true
|
||||
enableSaveNoteMenuItem()
|
||||
enableShareNoteMenuItem()
|
||||
}
|
||||
)
|
||||
if (!noteFileExists) {
|
||||
// Prepare for input in case of empty/new note
|
||||
add_note_edit_text.requestFocus()
|
||||
|
@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.kiwix.kiwixmobile.core.main
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.PendingIntent
|
||||
import android.appwidget.AppWidgetManager
|
||||
import android.appwidget.AppWidgetProvider
|
||||
@ -46,6 +47,7 @@ abstract class CoreSearchWidget : AppWidgetProvider() {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("UnspecifiedImmutableFlag")
|
||||
private fun pendingIntent(context: Context, action: String) = PendingIntent.getActivity(
|
||||
context,
|
||||
(System.currentTimeMillis() % Int.MAX_VALUE).toInt(),
|
||||
|
@ -58,16 +58,19 @@ class KiwixTextToSpeech internal constructor(
|
||||
private val focusLock: Any = Any()
|
||||
private val am: AudioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
@JvmField var currentTTSTask: TTSTask? = null
|
||||
private val tts: TextToSpeech = TextToSpeech(instance, OnInitListener { status: Int ->
|
||||
if (status == SUCCESS) {
|
||||
Log.d(TAG_KIWIX, "TextToSpeech was initialized successfully.")
|
||||
this.isInitialized = true
|
||||
onInitSucceedListener.onInitSucceed()
|
||||
} else {
|
||||
Log.e(TAG_KIWIX, "Initialization of TextToSpeech Failed!")
|
||||
context.toast(R.string.texttospeech_initialization_failed, Toast.LENGTH_SHORT)
|
||||
private val tts: TextToSpeech = TextToSpeech(
|
||||
instance,
|
||||
OnInitListener { status: Int ->
|
||||
if (status == SUCCESS) {
|
||||
Log.d(TAG_KIWIX, "TextToSpeech was initialized successfully.")
|
||||
this.isInitialized = true
|
||||
onInitSucceedListener.onInitSucceed()
|
||||
} else {
|
||||
Log.e(TAG_KIWIX, "Initialization of TextToSpeech Failed!")
|
||||
context.toast(R.string.texttospeech_initialization_failed, Toast.LENGTH_SHORT)
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
|
||||
/**
|
||||
* Returns whether the TTS is initialized.
|
||||
@ -139,7 +142,7 @@ class KiwixTextToSpeech internal constructor(
|
||||
Array.prototype.forEach.call(toRemove, function(elem) {
|
||||
elem.parentElement.removeChild(elem);});
|
||||
tts.speakAloud(body.innerText);
|
||||
""".trimIndent()
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -166,9 +166,11 @@ open class KiwixWebView @SuppressLint("SetJavaScriptEnabled") constructor(
|
||||
}
|
||||
val fileToSave = sequence {
|
||||
yield(File(root, fileName))
|
||||
yieldAll(generateSequence(1) { it + 1 }.map {
|
||||
File(root, fileName.replace(".", "_$it."))
|
||||
})
|
||||
yieldAll(
|
||||
generateSequence(1) { it + 1 }.map {
|
||||
File(root, fileName.replace(".", "_$it."))
|
||||
}
|
||||
)
|
||||
}.first { !it.exists() }
|
||||
val source = Uri.parse(src)
|
||||
try {
|
||||
|
@ -102,9 +102,11 @@ abstract class PageFragment : OnItemClickListener, BaseFragment(), FragmentActiv
|
||||
inflater.inflate(R.menu.menu_page, menu)
|
||||
val search = menu.findItem(R.id.menu_page_search).actionView as SearchView
|
||||
search.queryHint = searchQueryHint
|
||||
search.setOnQueryTextListener(SimpleTextListener {
|
||||
pageViewModel.actions.offer(Action.Filter(it))
|
||||
})
|
||||
search.setOnQueryTextListener(
|
||||
SimpleTextListener {
|
||||
pageViewModel.actions.offer(Action.Filter(it))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
@ -139,11 +141,13 @@ abstract class PageFragment : OnItemClickListener, BaseFragment(), FragmentActiv
|
||||
pageViewModel.state.observe(viewLifecycleOwner, Observer(::render))
|
||||
|
||||
// hides keyboard when scrolled
|
||||
recycler_view.addOnScrollListener(SimpleRecyclerViewScrollListener { _, newState ->
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
recycler_view.closeKeyboard()
|
||||
recycler_view.addOnScrollListener(
|
||||
SimpleRecyclerViewScrollListener { _, newState ->
|
||||
if (newState == RecyclerView.SCROLL_STATE_DRAGGING) {
|
||||
recycler_view.closeKeyboard()
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
override fun onCreateView(
|
||||
|
@ -39,7 +39,9 @@ data class ShowDeleteBookmarksDialog(
|
||||
@Inject lateinit var dialogShower: DialogShower
|
||||
override fun invokeWith(activity: AppCompatActivity) {
|
||||
activity.cachedComponent.inject(this)
|
||||
dialogShower.show(if (state.isInSelectionState) DeleteSelectedBookmarks else DeleteAllBookmarks,
|
||||
{ effects.offer(DeletePageItems(state, pageDao)) })
|
||||
dialogShower.show(
|
||||
if (state.isInSelectionState) DeleteSelectedBookmarks else DeleteAllBookmarks,
|
||||
{ effects.offer(DeletePageItems(state, pageDao)) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -32,8 +32,10 @@ data class HistoryState(
|
||||
) : PageState<HistoryItem>() {
|
||||
override val visiblePageItems: List<HistoryListItem> =
|
||||
HeaderizableList<HistoryListItem, HistoryItem, DateItem>(filteredPageItems)
|
||||
.foldOverAddingHeaders({ historyItem -> DateItem(historyItem.dateString) },
|
||||
{ current, next -> current.dateString != next.dateString })
|
||||
.foldOverAddingHeaders(
|
||||
{ historyItem -> DateItem(historyItem.dateString) },
|
||||
{ current, next -> current.dateString != next.dateString }
|
||||
)
|
||||
|
||||
override fun copyWithNewItems(newItems: List<HistoryItem>): PageState<HistoryItem> =
|
||||
copy(pageItems = (newItems))
|
||||
|
@ -119,7 +119,8 @@ class SearchFragment : BaseFragment() {
|
||||
override fun handleOnBackPressed() {
|
||||
goBack()
|
||||
}
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun setupToolbar(view: View) {
|
||||
@ -149,11 +150,13 @@ class SearchFragment : BaseFragment() {
|
||||
val searchMenuItem = menu.findItem(R.id.menu_search)
|
||||
searchMenuItem.expandActionView()
|
||||
searchView = searchMenuItem.actionView as SearchView
|
||||
searchView.setOnQueryTextListener(SimpleTextListener {
|
||||
if (it.isNotEmpty()) {
|
||||
searchViewModel.actions.offer(Filter(it))
|
||||
searchView.setOnQueryTextListener(
|
||||
SimpleTextListener {
|
||||
if (it.isNotEmpty()) {
|
||||
searchViewModel.actions.offer(Filter(it))
|
||||
}
|
||||
}
|
||||
})
|
||||
)
|
||||
searchMenuItem.setOnActionExpandListener(object : OnActionExpandListener {
|
||||
override fun onMenuItemActionExpand(item: MenuItem) = false
|
||||
|
||||
|
@ -25,9 +25,11 @@ import androidx.appcompat.R
|
||||
|
||||
object DimenUtils {
|
||||
@JvmStatic fun Context.getToolbarHeight(): Int {
|
||||
return resources.getDimensionPixelSize(TypedValue().apply {
|
||||
theme.resolveAttribute(R.attr.actionBarSize, this, true)
|
||||
}.resourceId)
|
||||
return resources.getDimensionPixelSize(
|
||||
TypedValue().apply {
|
||||
theme.resolveAttribute(R.attr.actionBarSize, this, true)
|
||||
}.resourceId
|
||||
)
|
||||
}
|
||||
|
||||
@JvmStatic fun Activity.getWindowHeight(): Int =
|
||||
|
@ -58,6 +58,7 @@ class ExternalLinkOpener @Inject constructor(
|
||||
{
|
||||
sharedPreferenceUtil.putPrefExternalLinkPopup(false)
|
||||
openLink(intent)
|
||||
})
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
package org.kiwix.kiwixmobile.core.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Typeface
|
||||
@ -54,12 +55,14 @@ class LanguageUtils(private val context: Context) {
|
||||
MutableList<LanguageContainer> {
|
||||
val localeCollator =
|
||||
Collator.getInstance(context.locale).apply { strength = Collator.SECONDARY }
|
||||
languageCodesFromAssets.sortWith(Comparator { o1, o2 ->
|
||||
localeCollator.compare(
|
||||
o1.languageName,
|
||||
o2.languageName
|
||||
)
|
||||
})
|
||||
languageCodesFromAssets.sortWith(
|
||||
Comparator { o1, o2 ->
|
||||
localeCollator.compare(
|
||||
o1.languageName,
|
||||
o2.languageName
|
||||
)
|
||||
}
|
||||
)
|
||||
return languageCodesFromAssets
|
||||
}
|
||||
|
||||
@ -80,7 +83,10 @@ class LanguageUtils(private val context: Context) {
|
||||
// which also sets a Factory on the LayoutInflator, we have to access the private field of the
|
||||
// LayoutInflater, that handles this restriction via Java's reflection API
|
||||
// and make it accessible set it to false again.
|
||||
fun changeFont(layoutInflater: LayoutInflater, sharedPreferenceUtil: SharedPreferenceUtil) {
|
||||
@SuppressLint("SoonBlockedPrivateApi") fun changeFont(
|
||||
layoutInflater: LayoutInflater,
|
||||
sharedPreferenceUtil: SharedPreferenceUtil
|
||||
) {
|
||||
|
||||
if (!haveToChangeFont(sharedPreferenceUtil)) {
|
||||
return
|
||||
@ -187,6 +193,7 @@ class LanguageUtils(private val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressLint("AppBundleLocaleChanges")
|
||||
@JvmStatic
|
||||
fun handleLocaleChange(context: Context, language: String) {
|
||||
val locale =
|
||||
|
@ -34,9 +34,11 @@ sealed class KiwixDialog(
|
||||
val getView: (() -> View)? = null
|
||||
) {
|
||||
|
||||
data class DeleteZims(override val args: List<Any>) : KiwixDialog(
|
||||
null, R.string.delete_zim_body, R.string.delete, R.string.no
|
||||
), HasBodyFormatArgs {
|
||||
data class DeleteZims(override val args: List<Any>) :
|
||||
KiwixDialog(
|
||||
null, R.string.delete_zim_body, R.string.delete, R.string.no
|
||||
),
|
||||
HasBodyFormatArgs {
|
||||
constructor(zimNameList: String) : this(listOf(zimNameList))
|
||||
}
|
||||
|
||||
@ -99,12 +101,14 @@ sealed class KiwixDialog(
|
||||
cancelable = false
|
||||
)
|
||||
|
||||
data class ShowHotspotDetails(override val args: List<Any>) : KiwixDialog(
|
||||
R.string.hotspot_turned_on,
|
||||
R.string.hotspot_details_message,
|
||||
android.R.string.ok,
|
||||
null
|
||||
), HasBodyFormatArgs {
|
||||
data class ShowHotspotDetails(override val args: List<Any>) :
|
||||
KiwixDialog(
|
||||
R.string.hotspot_turned_on,
|
||||
R.string.hotspot_details_message,
|
||||
android.R.string.ok,
|
||||
null
|
||||
),
|
||||
HasBodyFormatArgs {
|
||||
constructor(wifiConfiguration: WifiConfiguration) : this(
|
||||
listOf(wifiConfiguration.SSID, wifiConfiguration.preSharedKey)
|
||||
)
|
||||
@ -125,9 +129,11 @@ sealed class KiwixDialog(
|
||||
neutralMessage = R.string.hotspot_dialog_neutral_button
|
||||
)
|
||||
|
||||
data class FileTransferConfirmation(override val args: List<Any>) : KiwixDialog(
|
||||
null, R.string.transfer_to, R.string.yes, android.R.string.cancel
|
||||
), HasBodyFormatArgs {
|
||||
data class FileTransferConfirmation(override val args: List<Any>) :
|
||||
KiwixDialog(
|
||||
null, R.string.transfer_to, R.string.yes, android.R.string.cancel
|
||||
),
|
||||
HasBodyFormatArgs {
|
||||
constructor(selectedPeerDeviceName: String) : this(listOf(selectedPeerDeviceName))
|
||||
}
|
||||
|
||||
|
@ -36,8 +36,6 @@ import org.kiwix.kiwixmobile.core.extensions.toast
|
||||
import java.io.BufferedReader
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.lang.Exception
|
||||
import java.util.ArrayList
|
||||
|
||||
object FileUtils {
|
||||
|
||||
@ -252,8 +250,10 @@ object FileUtils {
|
||||
@SuppressLint("WrongConstant")
|
||||
@JvmStatic fun getPathFromUri(activity: Activity, data: Intent): String? {
|
||||
val uri: Uri? = data.data
|
||||
val takeFlags: Int = data.flags and (Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
|
||||
val takeFlags: Int = data.flags and (
|
||||
Intent.FLAG_GRANT_READ_URI_PERMISSION
|
||||
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION
|
||||
)
|
||||
uri?.let {
|
||||
activity.grantUriPermission(
|
||||
activity.packageName, it,
|
||||
|
@ -27,9 +27,11 @@ inline class KiloByte(private val kilobyteString: String?) {
|
||||
get() = kilobyteString?.toLongOrNull()?.let {
|
||||
val units = arrayOf("KB", "MB", "GB", "TB")
|
||||
val conversion = (log10(it.toDouble()) / log10(1024.0)).toInt()
|
||||
(DecimalFormat("#,##0.#")
|
||||
.format(it / 1024.0.pow(conversion.toDouble())) +
|
||||
" " +
|
||||
units[conversion])
|
||||
(
|
||||
DecimalFormat("#,##0.#")
|
||||
.format(it / 1024.0.pow(conversion.toDouble())) +
|
||||
" " +
|
||||
units[conversion]
|
||||
)
|
||||
} ?: ""
|
||||
}
|
||||
|
@ -34,7 +34,8 @@ inline class ArticleCount(val articleCount: String) {
|
||||
val units = arrayOf("", "K", "M", "B", "T")
|
||||
val conversion = (log10(size.toDouble()) / 3).toInt()
|
||||
context.getString(
|
||||
R.string.articleCount, DecimalFormat("#,##0.#")
|
||||
R.string.articleCount,
|
||||
DecimalFormat("#,##0.#")
|
||||
.format(size / 1000.0.pow(conversion.toDouble())) + units[conversion]
|
||||
)
|
||||
}
|
||||
|
@ -82,7 +82,8 @@ class ChunkUtilsTest {
|
||||
|
||||
assertEquals(
|
||||
"verify that the same notificationID is passed on to each chunk",
|
||||
true, listReturned[0].url == url &&
|
||||
true,
|
||||
listReturned[0].url == url &&
|
||||
listReturned[1].url == url &&
|
||||
listReturned[2].url == url &&
|
||||
listReturned[3].url == url &&
|
||||
@ -92,7 +93,8 @@ class ChunkUtilsTest {
|
||||
|
||||
assertEquals(
|
||||
"verify that the same URL is passed on to each chunk",
|
||||
true, listReturned[0].notificationID == 56 &&
|
||||
true,
|
||||
listReturned[0].notificationID == 56 &&
|
||||
listReturned[1].notificationID == 56 &&
|
||||
listReturned[2].notificationID == 56 &&
|
||||
listReturned[3].notificationID == 56 &&
|
||||
|
@ -200,32 +200,37 @@ class NetworkUtilsTest {
|
||||
|
||||
// Using the standard Kiwix Download URLs
|
||||
assertEquals(
|
||||
"URL Parsing", "No Pictures", NetworkUtils.parseURL(
|
||||
"URL Parsing", "No Pictures",
|
||||
NetworkUtils.parseURL(
|
||||
context,
|
||||
"http://ftpmirror.your.org/pub/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"
|
||||
)
|
||||
)
|
||||
assertEquals(
|
||||
"URL Parsing", "No Videos", NetworkUtils.parseURL(
|
||||
"URL Parsing", "No Videos",
|
||||
NetworkUtils.parseURL(
|
||||
context,
|
||||
"http://www.mirrorservice.org/sites/download.kiwix.org/zim/wikipedia/" +
|
||||
"wikipedia_af_all_novid_2016-05.zim"
|
||||
)
|
||||
)
|
||||
assertEquals(
|
||||
"URL Parsing", "Simple", NetworkUtils.parseURL(
|
||||
"URL Parsing", "Simple",
|
||||
NetworkUtils.parseURL(
|
||||
context,
|
||||
"http://download.wikimedia.org/kiwix/zim/wikipedia/wikipedia_af_all_simple_2016-05.zim"
|
||||
)
|
||||
)
|
||||
assertEquals(
|
||||
"URL Parsing", "No Pictures", NetworkUtils.parseURL(
|
||||
"URL Parsing", "No Pictures",
|
||||
NetworkUtils.parseURL(
|
||||
context,
|
||||
"http://mirror.netcologne.de/kiwix/zim/wikipedia/wikipedia_af_all_nopic_2016-05.zim"
|
||||
)
|
||||
)
|
||||
assertEquals(
|
||||
"URL Parsing", "Simple", NetworkUtils.parseURL(
|
||||
"URL Parsing", "Simple",
|
||||
NetworkUtils.parseURL(
|
||||
context,
|
||||
"http://mirror3.kiwix.org/zim/wikipedia/wikipedia_af_all_simple_2016-05.zim"
|
||||
)
|
||||
|
@ -34,7 +34,7 @@ internal class ServerUtilsTest {
|
||||
fec0::d8d1:9ff:fe42:160c
|
||||
fec0::8d6e:2327:6d9f:ce75
|
||||
192.168.200.2
|
||||
""".trimIndent()
|
||||
""".trimIndent()
|
||||
)
|
||||
).isEqualTo(
|
||||
"192.168.232.2"
|
||||
|
@ -105,7 +105,8 @@ class FileSearchTest {
|
||||
val zimFile = File.createTempFile(
|
||||
"fileToFind",
|
||||
".zim",
|
||||
File("$tempRoot${File.separator}dir").apply { mkdirs() })
|
||||
File("$tempRoot${File.separator}dir").apply(File::mkdirs)
|
||||
)
|
||||
every { contentResolver.query(any(), any(), any(), any(), any()) } returns null
|
||||
every { storageDevice.name } returns zimFile.parentFile.parent
|
||||
val fileList = fileSearch.scan()
|
||||
|
@ -20,7 +20,7 @@ android {
|
||||
}
|
||||
|
||||
flavorDimensions("default")
|
||||
productFlavors {
|
||||
productFlavors.apply {
|
||||
CustomApps.createDynamically(project.file("src"), this)
|
||||
all {
|
||||
File("$projectDir/src", "$name/$name.zim").let {
|
||||
|
@ -17,7 +17,8 @@
|
||||
android:configChanges="orientation|keyboardHidden|screenSize|locale"
|
||||
android:theme="@style/KiwixTheme.Launcher"
|
||||
android:label="@string/app_name"
|
||||
android:windowSoftInputMode="adjustPan">
|
||||
android:windowSoftInputMode="adjustPan"
|
||||
android:exported="true">
|
||||
<meta-data
|
||||
android:name="android.app.shortcuts"
|
||||
android:resource="@xml/shortcuts" />
|
||||
@ -53,7 +54,8 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<receiver android:name=".main.CustomSearchWidget">
|
||||
<receiver android:name=".main.CustomSearchWidget"
|
||||
android:exported="false">
|
||||
<intent-filter>
|
||||
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
|
||||
<action android:name="KiwixSearchWidget.TEXT_CLICKED" />
|
||||
|
@ -183,9 +183,11 @@ class CustomReaderFragment : CoreReaderFragment() {
|
||||
}
|
||||
|
||||
private fun goToSettings() {
|
||||
startActivity(Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.fromParts("package", activity?.packageName, null)
|
||||
})
|
||||
startActivity(
|
||||
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply {
|
||||
data = Uri.fromParts("package", activity?.packageName, null)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun readStorageHasBeenPermanentlyDenied(grantResults: IntArray) =
|
||||
|
6
gradle/wrapper/gradle-wrapper.properties
vendored
6
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,6 +1,6 @@
|
||||
#Tue Feb 25 11:46:45 IST 2020
|
||||
#Wed Jun 01 10:28:35 IST 2022
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
@ -4,7 +4,20 @@
|
||||
<ignore path="**-qq/**.xml" />
|
||||
<ignore path="**-iw/**.xml" />
|
||||
</issue>
|
||||
|
||||
<issue id="LintError">
|
||||
<ignore regexp=".*BookmarksRobot.kt.*"/>
|
||||
<ignore regexp=".*DebugFunctions.kt.*"/>
|
||||
<ignore regexp=".*HistoryRobot.kt.*"/>
|
||||
<ignore regexp=".*IntroRobot.kt.*"/>
|
||||
<ignore regexp=".*LanguageRobot.kt.*"/>
|
||||
<ignore regexp=".*LibraryRobot.kt.*"/>
|
||||
<ignore regexp=".*LocalFileTransferRobot.kt.*"/>
|
||||
<ignore regexp=".*OnlineLibraryRobot.kt.*"/>
|
||||
<ignore regexp=".*ReaderRobot.kt.*"/>
|
||||
<ignore regexp=".*SettingsRobot.kt.*"/>
|
||||
<ignore regexp=".*TopLevelDestinationRobot.kt.*"/>
|
||||
<ignore regexp=".*ZimHostRobot.kt.*"/>
|
||||
</issue>
|
||||
<issue id="TypographyEllipsis">
|
||||
<ignore path="**-iw/**.xml" />
|
||||
</issue>
|
||||
@ -19,10 +32,11 @@
|
||||
<issue id="InvalidPackage">
|
||||
<ignore path="**simple-xml-2.7.1.jar" />
|
||||
<ignore path="**/squidb*.jar" />
|
||||
<ignore path="**/org.jacoco.agent-0.8.3-runtime.jar" />
|
||||
</issue>
|
||||
<issue id="IconLocation">
|
||||
<ignore path="src/main/res/drawable/kiwix_icon_with_title.png" />
|
||||
<ignore path="src/main/res/drawable/search_widget_preview.png" />
|
||||
<ignore path="core/src/main/res/drawable/search_widget_preview.png" />
|
||||
</issue>
|
||||
<issue id="ConvertToWebp">
|
||||
<ignore path="src/main/res/drawable/search_widget_preview.png" />
|
||||
|
Loading…
x
Reference in New Issue
Block a user