Merge pull request #1192 from kiwix/macgills/2.5-mergeable-to-dev

Merge 2.5 to dev
This commit is contained in:
macgills 2019-06-20 09:55:30 +01:00 committed by GitHub
commit 55aa28e7d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
225 changed files with 7351 additions and 4120 deletions

View File

@ -15,6 +15,6 @@ charset = utf-8
continuation_indent_size = 4
# windows command files need windows newline
[*.{bat,cmd}]
[*.{bat, cmd}]
end_of_line = crlf

3
.gitignore vendored
View File

@ -53,4 +53,5 @@ glassify
.project
.classpath
.vscode
.vscode
captures/

View File

@ -4,19 +4,89 @@ jdk: oraclejdk8
sudo: required
env:
global:
- ANDROID_TARGET=android-22
- ANDROID_ABI=armeabi-v7a
before_install:
- openssl aes-256-cbc -K $encrypted_82adfa9c3806_key -iv $encrypted_82adfa9c3806_iv -in secrets.tar.enc -out secrets.tar -d
- tar xvf secrets.tar
install:
- pip install --user 'requests[security]'
- wget -r -nH -nd -np -R index.html* robots.txt* http://download.kiwix.org/dev/android/api/licenses/ -e robots=off -P $ANDROID_HOME/licenses || true
- pip install --user 'requests[security]'
- wget -r -nH -nd -np -R index.html* robots.txt* http://download.kiwix.org/dev/android/api/licenses/ -e robots=off -P $ANDROID_HOME/licenses || true
addons:
apt:
packages:
- lynx
before_cache:
- rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
- rm -fr $HOME/.gradle/caches/*/plugin-resolution/
cache:
directories:
- "$HOME/.gradle/caches/"
- "$HOME/.gradle/wrapper/"
- "$HOME/.android/build-cache"
android:
components:
- tools
- platform-tools
- tools
- build-tools-28.0.3
- android-28
- tools
- platform-tools
- build-tools-28.0.3
- android-28
- extra-android-m2repository
- $ANDROID_TARGET
- sys-img-${ANDROID_ABI}-${ANDROID_TARGET}
licenses:
- '.+'
- ".+"
script: ./gradlew assembleKiwixRelease kiwixtestUploadKiwix && ./testdroid.py
script:
- ./gradlew lintKiwixDebug jacocoTestKiwixDebugUnitTestReport
- echo no | android create avd --force -n test -t $ANDROID_TARGET --abi $ANDROID_ABI -c 100M
- emulator -avd test -no-window &
- android-wait-for-emulator
- adb shell setprop dalvik.vm.dexopt-flags v=n,o=v
- adb shell input keyevent 82 & # unlock screen by pressing menu button
- adb -e logcat *:D > logcat.log &
- ./gradlew createKiwixDebugCoverageReport
after_success:
- bash <(curl -s https://codecov.io/bash)
- ./gradlew kiwixtestUploadKiwix
after_failure:
- export LOG_DIR = ${TRAVIS_HOME}/build/kiwix/kiwix-android/app/build/outputs/reports/androidTests/connected/flavors/KIWIX/
- lynx --dump ${LOG_DIR}com.android.builder.testing.ConnectedDevice.html
- lynx --dump ${LOG_DIR}com.android.builder.testing.html
- lynx --dump ${LOG_DIR}org.kiwix.kiwixmobile.tests.BasicTest.html;
- echo " LOGCAT "; echo "========"; cat logcat.log; pkill -KILL -f adb
before_deploy:
# - export APP_CHANGELOG=$(cat app/src/kiwix/play/release-notes/en-US/default.txt)
- ./gradlew assembleKiwixRelease
deploy:
#publish on github releases
- provider: releases
api_key: "$GITHUB_TOKEN"
file: app/build/outputs/apk/kiwix/release/*
file_glob: true
skip_cleanup: true
overwrite: true
# body: "$APP_CHANGELOG" broken because travis can't escape newlines
draft: true
on:
tags: true
#publish on play store
- provider: script
skip_cleanup: true
script: ./gradlew publishKiwixRelease
on:
tags: true

View File

@ -1,3 +1,7 @@
2.5
NEW: Downloads are now using the DownloadManager
NEW: Downloads/Device/Library completely rewritten
2.4
FIX: External SD card problems
FIX: Some UI translation

View File

@ -40,4 +40,47 @@ Our process for accepting changes operates by [Pull Request (PR)](https://help.g
1. Once you have integrated comments, or waited for feedback, a Lieutenant should merge your changes in!
### Building
The default build is `debug`, with this variant you can use a debugger while developing. To install the application click the `run` button in Android Studio with the `app` configuration selected while you have a device connected. All other build types but `release` can be ignored, the `release` build is what gets uploaded to the Google Play store and can be built locally with the dummy credentials/keystore provided.
### Testing
Unit tests are located in `app/src/test` and to run them locally you
can use the gradle command:
$ gradlew testKiwixDebugUnitTest
or the abbreviated:
$ gradlew tKDUT
Automated tests that require a connected device (UI related tests) are located in `app/src/androidTest` & `app/src/androidTestKiwix`, to run them locally you can use the gradle command:
$ gradlew connectedKiwixDebugAndroidTest
or the abbreviated:
$ gradlew cKDAT
All local test results can be seen under `app/build/reports/`
### Code coverage
To generate coverage reports for your unit tests run:
$ gradlew jacocoTestKiwixDebugUnitTest
To generate coverage reports for your automated tests run:
$ gradlew createKiwixDebugCoverageReport
Code coverage results can be seen under `app/build/reports/`
### Continous Integration
All PRs will have all these tests run and a combined coverage report will be attached, if coverage is to go down the PR will be marked failed. On Travis CI the automated tests are run on an emulator. To
learn more about the commands run on the CI please refer to [.travis.yml](https://github.com/kiwix/kiwix-android/blob/master/.travis.yml)
_These guidelines are based on [Tools for Government Data Archiving](https://github.com/edgi-govdata-archiving/overview/blob/master/CONTRIBUTING.md)'s._

View File

@ -9,6 +9,7 @@ Kiwix is an offline reader for Web content. One of its main purposes is to make
[![Build Status](https://travis-ci.org/kiwix/kiwix-android.svg?branch=master)](https://travis-ci.org/kiwix/kiwix-android)
[![IRC Web](https://img.shields.io/badge/chat-on%20freenode-brightgreen.svg)](http://chat.kiwix.org)
[![codecov](https://codecov.io/gh/kiwix/kiwix-android/branch/master/graph/badge.svg)](https://codecov.io/gh/kiwix/kiwix-android)
---
## Build Instructions
@ -22,16 +23,15 @@ We utilize different build variants (flavours) to build various different versio
## Libraries Used
- [Dagger 2](https://github.com/google/dagger) - A fast dependency injector for Android and Java
- [SquiDb](https://github.com/yahoo/squidb) - SquiDB is a SQLite database library for Android and iOS
- [Retrofit](http://square.github.io/retrofit/) - Retrofit turns your REST API into a Java interface
- [OkHttp](https://github.com/square/okhttp) - An HTTP+SPDY client for Android and Java applications
- [Butterknife](http://jakewharton.github.io/butterknife/) - View "injection" library for Android
- [Mockito](https://github.com/mockito/mockito) - Most popular Mocking framework for unit tests written in Java
- [Guava](https://github.com/google/guava) - Collections, caching, primitives support, concurrency libraries, common annotations, string processing, I/O, and so forth.
- [Apache](https://github.com/apache/commons-io) - The Apache Commons IO library contains utility classes, stream implementations, file filters, file comparators, endian transformation classes, and much more.
- [Mockito](https://github.com/mockito/mockito) - Most popular Mocking framework for unit tests written in Java
- [RxJava](https://github.com/ReactiveX/RxJava) - Reactive Extensions for the JVM a library for composing asynchronous and event-based programs using observable sequences for the Java VM.
- [ObjectBox] (https://github.com/objectbox/objectbox-java) - Reactive NoSQL Databse to replace SquiDb
- [MockK] (https://github.com/mockk/mockk) - Kotlin mocking library that allows mocking of final classes by default.
- [JUnit5] (https://github.com/junit-team/junit5/) - The next generation of JUnit
- [AssertJ] (https://github.com/joel-costigliola/assertj-core) - Fluent assertions for test code
## Contributing

View File

@ -1,13 +1,12 @@
import com.android.annotations.NonNull
import com.android.build.OutputFile
import com.android.builder.testing.api.TestServer
import com.testdroid.api.APIClient
import com.testdroid.api.APIKeyClient
import com.testdroid.api.model.APIProject
import com.testdroid.api.model.APIUser
import com.android.builder.testing.api.TestServer
import com.android.annotations.NonNull
import groovy.json.JsonSlurper
buildscript {
repositories {
google()
@ -19,13 +18,21 @@ buildscript {
classpath "com.android.tools.build:gradle:$androidGradlePluginVersion"
classpath "org.apache.httpcomponents:httpclient-android:4.3.3"
classpath "com.testdroid:testdroid-api:2.71"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
classpath "io.objectbox:objectbox-gradle-plugin:$objectboxVersion"
}
}
plugins {
id("com.android.application")
id("checkstyle")
id("com.github.triplet.play") version("2.2.1")
}
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt'
apply plugin: 'io.objectbox'
apply plugin: 'jacoco-android'
repositories {
google()
@ -36,14 +43,14 @@ repositories {
jcenter()
}
String[] archs = ["arm64-v8a", "armeabi", "mips", "mips64", "x86", "x86_64"]
String[] archs = ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']
dependencies {
// use jdk8 java.time backport, as long app < Build.VERSION_CODES.O
implementation("com.jakewharton.threetenabp:threetenabp:1.1.1")
// Get kiwixlib online if it is not populated locally
if (file("../kiwixlib/src/main").list().length == 1) {
implementation "org.kiwix.kiwixlib:kiwixlib:1.0.11"
implementation 'org.kiwix.kiwixlib:kiwixlib:1.0.12'
} else {
implementation project(":kiwixlib")
archs = file("../kiwixlib/src/main/jniLibs").list()
@ -58,27 +65,26 @@ dependencies {
implementation "androidx.cardview:cardview:$cardViewVersion"
implementation "androidx.multidex:multidex:$multidexVersion"
implementation "androidx.constraintlayout:constraintlayout:$constraintLayoutVersion"
implementation "androidx.core:core-ktx:1.0.2"
implementation "androidx.fragment:fragment-ktx:1.0.0"
implementation "androidx.collection:collection-ktx:1.1.0"
implementation "androidx.test.espresso:espresso-idling-resource:$espressoVersion"
androidTestImplementation("androidx.test.espresso:espresso-core:$espressoVersion")
androidTestImplementation "androidx.test.espresso:espresso-web:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-intents:$espressoVersion"
androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion") {
exclude group: "androidx.legacy", module: "legacy-support-core-utils"
exclude group: "androidx.viewpager", module: "viewpager"
exclude group: "com.google.android.material", module: "material"
exclude group: "androidx.recyclerview", module: "recyclerview"
}
androidTestImplementation("com.schibsted.spain:barista:$baristaVersion") {
exclude group: "com.android.support"
}
androidTestImplementation("androidx.test.espresso:espresso-contrib:$espressoVersion")
androidTestImplementation "androidx.annotation:annotation:$annotationVersion"
androidTestImplementation "androidx.test.ext:junit:1.1.1"
androidTestImplementation "androidx.test:runner:1.2.0"
androidTestImplementation "androidx.test:rules:1.2.0"
androidTestImplementation "androidx.test:core:1.2.0"
androidTestImplementation "com.squareup.okhttp3:mockwebserver:3.6.0"
// Mockito
androidTestImplementation "org.mockito:mockito-android:$mockitoVersion"
// Tab indicator
implementation "com.pacioianu.david:ink-page-indicator:$inkPageIndicatorVersion"
@ -88,17 +94,14 @@ dependencies {
androidTestCompileOnly "javax.annotation:javax.annotation-api:$javaxAnnotationVersion"
implementation "com.google.dagger:dagger:$daggerVersion"
implementation "com.google.dagger:dagger-android:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
annotationProcessor "com.google.dagger:dagger-android-processor:$daggerVersion"
androidTestAnnotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
kapt "com.google.dagger:dagger-compiler:$daggerVersion"
kapt "com.google.dagger:dagger-android-processor:$daggerVersion"
kaptAndroidTest "com.google.dagger:dagger-compiler:$daggerVersion"
// SquiDB
implementation "com.yahoo.squidb:squidb:2.0.0"
implementation "com.yahoo.squidb:squidb-annotations:2.0.0"
annotationProcessor "com.yahoo.squidb:squidb-processor:2.0.0"
// Apache
androidTestImplementation "commons-io:commons-io:$apacheCommonsVersion"
implementation 'com.yahoo.squidb:squidb:2.0.0'
implementation 'com.yahoo.squidb:squidb-annotations:2.0.0'
kapt 'com.yahoo.squidb:squidb-processor:2.0.0'
// Square
implementation "com.squareup.okhttp3:okhttp:$okHttpVersion"
@ -110,31 +113,20 @@ dependencies {
exclude group: "stax", module: "stax-api"
exclude group: "stax", module: "stax"
}
androidTestImplementation "com.squareup.okhttp3:mockwebserver:3.6.0"
// ButterKnife
implementation "com.jakewharton:butterknife:$butterKnifeVersion"
annotationProcessor "com.jakewharton:butterknife-compiler:$butterKnifeVersion"
kapt "com.jakewharton:butterknife-compiler:$butterKnifeVersion"
// RxJava
implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion"
implementation "io.reactivex.rxjava2:rxjava:$rxJavaVersion"
// JUnit
testImplementation "junit:junit:$jUnitVersion"
androidTestImplementation "junit:junit:$jUnitVersion"
// Mockito
testImplementation "org.mockito:mockito-core:$mockitoVersion"
androidTestImplementation "org.mockito:mockito-android:$mockitoVersion"
// PowerMockito
testImplementation "org.powermock:powermock:$powerMockVersion"
testImplementation "org.powermock:powermock-module-junit4:$powerMockJUnitVersion"
testImplementation "org.powermock:powermock-api-mockito2:$powerMockJUnitVersion"
// Leak canary
implementation "com.squareup.leakcanary:leakcanary-android-no-op:1.5.4"
implementation 'com.squareup.leakcanary:leakcanary-android-no-op:1.6.3'
// Only enable leak canary in debug builds
configurations.all { config ->
if (config.name.contains("debug") || config.name.contains("Debug")) {
@ -147,6 +139,16 @@ dependencies {
}
}
}
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlinVersion"
implementation "android.arch.lifecycle:extensions:1.1.1"
implementation "io.objectbox:objectbox-kotlin:$objectboxVersion"
implementation "io.objectbox:objectbox-rxjava:$objectboxVersion"
testImplementation "org.junit.jupiter:junit-jupiter:5.4.2"
testImplementation "io.mockk:mockk:1.9"
testImplementation "org.assertj:assertj-core:3.11.1"
testImplementation 'com.jraska.livedata:testing-ktx:1.1.0'
testImplementation 'androidx.arch.core:core-testing:2.0.1'
}
// Set custom app import directory
@ -161,14 +163,56 @@ if (custom.listFiles()) {
custom.eachFile() { file ->
def fileName = file.getName()
if (fileName.startsWith(".") || fileName.contains("test") ||
fileName == "main" || fileName.contains("Test")) {
if (fileName.startsWith(".") ||
fileName.contains("test") ||
fileName == "main" ||
fileName.contains("Test")) {
return
}
map.put(fileName, file.getAbsolutePath())
}
}
jacoco {
toolVersion = "0.8.3"
}
tasks.withType(Test) {
jacoco.includeNoLocationClasses = true
}
def branchName = System.getenv('TRAVIS_PULL_REQUEST') ?: "false" == "false"
? System.getenv('TRAVIS_BRANCH') ?: "local"
: System.getenv('TRAVIS_PULL_REQUEST_BRANCH')
def buildNumber = System.getenv('TRAVIS_BUILD_NUMBER') ?: "dev"
ext {
versionMajor = 2
versionMinor = 5
versionPatch = 1
}
private String generateVersionName() {
"${ext.versionMajor}.${ext.versionMinor}.${ext.versionPatch}"
}
/*
* max version code: 210-0-00-00-00
* our template : UUU-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
* U = unused
*/
private Integer generateVersionCode() {
20 * 10000 +
(ext.versionMajor * 10000) +
(ext.versionMinor * 100) +
(ext.versionPatch)
}
android {
compileSdkVersion 28
testServer new TestDroidUpload()
@ -181,6 +225,7 @@ android {
testInstrumentationRunnerArguments.notClass = "com.android.dex.DexIndexOverflowException"
multiDexEnabled true
vectorDrawables.useSupportLibrary = true
archivesBaseName = "$buildNumber"
}
aaptOptions {
@ -204,18 +249,37 @@ android {
warning "InvalidPackage"
warning "StringFormatInvalid"
}
testOptions {
unitTests.returnDefaultValues = true
unitTests.all {
useJUnitPlatform()
testLogging {
events "passed", "skipped", "failed", "standardOut", "standardError"
outputs.upToDateWhen { false }
showStandardStreams = true
}
}
}
flavorDimensions "default"
signingConfigs {
release {
storeFile file("../kiwix-android.keystore")
storePassword System.getenv("KEY_STORE_PASSWORD") ?: "000000"
keyAlias System.getenv("KEY_ALIAS") ?: "keystore"
keyPassword System.getenv("KEY_PASSWORD") ?: "000000"
}
}
buildTypes {
// Main build type for debugging
debug {
buildConfigField "String", "KIWIX_DOWNLOAD_URL", "\"http://download.kiwix.org/\""
// True breaks local variables being shown in breakpoints
testCoverageEnabled false
// Needed for instrumentation tests on Pre 5.0
multiDexKeepProguard file("multidex-instrumentation-config.pro")
buildConfigField "String", "KIWIX_DOWNLOAD_URL", "\"http://mirror.download.kiwix.org/\""
buildConfigField "boolean", "KIWIX_ERROR_ACTIVITY", "false"
testCoverageEnabled true
}
mock_network {
@ -230,16 +294,11 @@ android {
matchingFallbacks = ["debug", "release"]
}
// Used to assess code coverage
coverage {
initWith debug
testCoverageEnabled true
matchingFallbacks = ["debug", "release"]
}
// Release Type
release {
buildConfigField "String", "KIWIX_DOWNLOAD_URL", "\"http://download.kiwix.org/\""
signingConfig signingConfigs.release
buildConfigField "String", "KIWIX_DOWNLOAD_URL", "\"http://mirror.download.kiwix.org/\""
buildConfigField "boolean", "KIWIX_ERROR_ACTIVITY", "true"
}
}
@ -260,18 +319,22 @@ android {
def version_code = project.property("version_code")
versionCode version_code.toInteger()
} else {
versionCode 55
versionCode generateVersionCode()
}
if (project.hasProperty("version_name")) {
versionName project.property("version_name")
} else {
versionName "2.4"
versionName generateVersionName()
}
}
// Custom apps built from a json file, zim file and icon set
map.each { name, directory ->
"$name" {
println "Configuring $name"
if (name == "kiwix") {
return
}
if (file(directory + "/build.gradle").exists()) {
apply from: directory + "/build.gradle"
}
@ -333,8 +396,8 @@ android {
buildConfigField "int", "CONTENT_VERSION_CODE", "$content_version_code"
} else if (parsedJson.content_version_code != null) {
buildConfigField "int", "CONTENT_VERSION_CODE", "$parsedJson.content_version_code"
} else if (project.hasProperty("version_code")) {
def version_code = project.property("version_code")
} else if (project.hasProperty('version_code')) {
def version_code = project.property('version_code')
buildConfigField "int", "CONTENT_VERSION_CODE", "$version_code"
} else if (parsedJson.version_code != null) {
buildConfigField "int", "CONTENT_VERSION_CODE", "$parsedJson.version_code"
@ -376,10 +439,38 @@ android {
}
}
*/
androidExtensions {
experimental = true
}
def abiCodes = ['arm64-v8a': 6, 'x86': 3, 'x86_64': 4, 'armeabi-v7a': 5]
splits {
abi {
enable true
reset()
include "x86", "x86_64", 'armeabi-v7a', "arm64-v8a"
universalApk buildNumber == "dev"
}
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
def baseAbiVersionCode = abiCodes.get(output.getFilter(OutputFile.ABI))
if (baseAbiVersionCode != null) {
output.versionCodeOverride = baseAbiVersionCode * 1000000 + variant.versionCode
}
}
}
}
play {
enabled = true
serviceAccountCredentials = file("../google.json")
track = "alpha"
releaseStatus = "draft"
resolutionStrategy = "fail"
}
class TestDroidUpload extends TestServer{
class TestDroidUpload extends TestServer {
def buildNumber = System.getenv("TRAVIS_BUILD_NUMBER")
def API_KEY = System.getenv("PUBLIC_TESTDROID_API_KEY")
def TESTDROID_SERVER = "https://cloud.testdroid.com"
@ -396,7 +487,8 @@ class TestDroidUpload extends TestServer{
APIUser.metaClass.shareFile { id, accessGroup ->
System.out.println(id)
try {
delegate.postResource(createUri(selfURI, "/files/" + id + "/share"), [accessGroupId: accessGroup], APIProject.class)
delegate.postResource(createUri(selfURI, "/files/" + id + "/share"),
[accessGroupId: accessGroup], APIProject.class)
} catch (Exception e) {
System.out.println(e.getLocalizedMessage())
}
@ -409,7 +501,8 @@ class TestDroidUpload extends TestServer{
String testedId = user.uploadFile(testedApk).getId()
user.shareFile(testedId, accessGroup)
new URL(RUNNER_GATEWAY + "?apk=" + testedId + "&test=" + testId + "&buildno=" + buildNumber).getText()
new URL(RUNNER_GATEWAY + "?apk=" + testedId + "&test=" + testId + "&buildno=" + buildNumber).
getText()
}
@Override

View File

@ -0,0 +1,304 @@
{
"_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.",
"_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.",
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
"entities": [
{
"id": "1:7257718270326155947",
"lastPropertyId": "17:8085320504542486236",
"name": "DownloadEntity",
"properties": [
{
"id": "1:2266566996008201697",
"name": "id"
},
{
"id": "2:1953917250527765737",
"name": "downloadId"
},
{
"id": "5:6575412958851693470",
"name": "bookId"
},
{
"id": "6:1075612111256674117",
"name": "title"
},
{
"id": "7:2831524841121029990",
"name": "description"
},
{
"id": "8:2334902404590133038",
"name": "language"
},
{
"id": "9:5087250349738158996",
"name": "creator"
},
{
"id": "10:6128960350043895299",
"name": "publisher"
},
{
"id": "11:3850323036475883785",
"name": "date"
},
{
"id": "12:5288623325038033644",
"name": "url"
},
{
"id": "13:2501711400901908648",
"name": "articleCount"
},
{
"id": "14:3550975911715416030",
"name": "mediaCount"
},
{
"id": "15:8949996430663588693",
"name": "size"
},
{
"id": "16:7554483297276446029",
"name": "name"
},
{
"id": "17:8085320504542486236",
"name": "favIcon"
}
],
"relations": []
},
{
"id": "3:5536749840871435068",
"lastPropertyId": "16:6142333908132117423",
"name": "BookOnDiskEntity",
"properties": [
{
"id": "1:4248832782795400383",
"name": "id"
},
{
"id": "2:2644395282642821815",
"name": "file"
},
{
"id": "4:3145196313443812205",
"name": "bookId"
},
{
"id": "5:597997298666253723",
"name": "title"
},
{
"id": "6:8028706022307902131",
"name": "description"
},
{
"id": "7:4257578632233656657",
"name": "language"
},
{
"id": "8:7771231471515752814",
"name": "creator"
},
{
"id": "9:892859866782486178",
"name": "publisher"
},
{
"id": "10:1925365063061602631",
"name": "date"
},
{
"id": "11:1111395522977944209",
"name": "url"
},
{
"id": "12:3765116904492031525",
"name": "articleCount"
},
{
"id": "13:5901922417972273396",
"name": "mediaCount"
},
{
"id": "14:1229023184984372602",
"name": "size"
},
{
"id": "15:6851856791814492874",
"name": "name"
},
{
"id": "16:6142333908132117423",
"name": "favIcon"
}
],
"relations": []
},
{
"id": "4:6278838675135543734",
"lastPropertyId": "4:8812214350305159407",
"name": "LanguageEntity",
"properties": [
{
"id": "1:7795244654012809404",
"name": "id"
},
{
"id": "2:9116495537035444904",
"name": "locale"
},
{
"id": "3:452531964346972307",
"name": "active"
},
{
"id": "4:8812214350305159407",
"name": "occurencesOfLanguage"
}
],
"relations": []
},
{
"id": "5:3222423958972105425",
"lastPropertyId": "10:8395372122440621469",
"name": "HistoryEntity",
"properties": [
{
"id": "1:4390013783965661495",
"name": "id"
},
{
"id": "2:6814436941523306636",
"name": "zimId"
},
{
"id": "3:3445023139891930306",
"name": "zimName"
},
{
"id": "4:1707638909668210783",
"name": "zimFilePath"
},
{
"id": "5:7291321834337975178",
"name": "favicon"
},
{
"id": "6:8790316103579116510",
"name": "historyUrl"
},
{
"id": "7:6718164131929659510",
"name": "historyTitle"
},
{
"id": "9:6094002746638656105",
"name": "timeStamp"
},
{
"id": "10:8395372122440621469",
"name": "dateString"
}
],
"relations": []
},
{
"id": "6:2737311997994502758",
"lastPropertyId": "7:3805929017981932900",
"name": "BookmarkEntity",
"properties": [
{
"id": "1:6627309171741917147",
"name": "id"
},
{
"id": "2:6862771806221961183",
"name": "zimId"
},
{
"id": "3:4312769031500860715",
"name": "zimName"
},
{
"id": "4:8187716343071473669",
"name": "zimFilePath"
},
{
"id": "5:5652763871458286201",
"name": "bookmarkUrl"
},
{
"id": "6:4537799665712767375",
"name": "bookmarkTitle"
},
{
"id": "7:3805929017981932900",
"name": "favicon"
}
],
"relations": []
},
{
"id": "7:7635075139296819361",
"lastPropertyId": "3:3320858395373055542",
"name": "RecentSearchEntity",
"properties": [
{
"id": "1:7759655437795315973",
"name": "id"
},
{
"id": "2:3924214186055484853",
"name": "searchTerm"
},
{
"id": "3:3320858395373055542",
"name": "zimId"
}
],
"relations": []
}
],
"lastEntityId": "7:7635075139296819361",
"lastIndexId": "4:4868787482832538530",
"lastRelationId": "0:0",
"lastSequenceId": "0:0",
"modelVersion": 4,
"modelVersionParserMinimum": 4,
"retiredEntityUids": [
349148274283701276
],
"retiredIndexUids": [
1293695782925933448,
3655049272366703856,
7576716732364166705,
4868787482832538530
],
"retiredPropertyUids": [
4712434661554562781,
1521665545502891268,
1831899651198481824,
8913656606098213241,
4745760836781949968,
9177466730609383913,
6985467229796102081,
4417830652027770707,
3485079785941052658,
2875347328622347138,
96906195091428769,
305997162787053035,
8804682238892773896,
3464301918251637220,
5620508895870653354,
7273406943564025911,
428251106490095982,
5162677841083528491
],
"retiredRelationUids": [],
"version": 1
}

View File

@ -0,0 +1,304 @@
{
"_note1": "KEEP THIS FILE! Check it into a version control system (VCS) like git.",
"_note2": "ObjectBox manages crucial IDs for your object model. See docs for details.",
"_note3": "If you have VCS merge conflicts, you must resolve them according to ObjectBox docs.",
"entities": [
{
"id": "1:7257718270326155947",
"lastPropertyId": "17:8085320504542486236",
"name": "DownloadEntity",
"properties": [
{
"id": "1:2266566996008201697",
"name": "id"
},
{
"id": "2:1953917250527765737",
"name": "downloadId"
},
{
"id": "5:6575412958851693470",
"name": "bookId"
},
{
"id": "6:1075612111256674117",
"name": "title"
},
{
"id": "7:2831524841121029990",
"name": "description"
},
{
"id": "8:2334902404590133038",
"name": "language"
},
{
"id": "9:5087250349738158996",
"name": "creator"
},
{
"id": "10:6128960350043895299",
"name": "publisher"
},
{
"id": "11:3850323036475883785",
"name": "date"
},
{
"id": "12:5288623325038033644",
"name": "url"
},
{
"id": "13:2501711400901908648",
"name": "articleCount"
},
{
"id": "14:3550975911715416030",
"name": "mediaCount"
},
{
"id": "15:8949996430663588693",
"name": "size"
},
{
"id": "16:7554483297276446029",
"name": "name"
},
{
"id": "17:8085320504542486236",
"name": "favIcon"
}
],
"relations": []
},
{
"id": "3:5536749840871435068",
"lastPropertyId": "16:6142333908132117423",
"name": "BookOnDiskEntity",
"properties": [
{
"id": "1:4248832782795400383",
"name": "id"
},
{
"id": "2:2644395282642821815",
"name": "file"
},
{
"id": "4:3145196313443812205",
"name": "bookId"
},
{
"id": "5:597997298666253723",
"name": "title"
},
{
"id": "6:8028706022307902131",
"name": "description"
},
{
"id": "7:4257578632233656657",
"name": "language"
},
{
"id": "8:7771231471515752814",
"name": "creator"
},
{
"id": "9:892859866782486178",
"name": "publisher"
},
{
"id": "10:1925365063061602631",
"name": "date"
},
{
"id": "11:1111395522977944209",
"name": "url"
},
{
"id": "12:3765116904492031525",
"name": "articleCount"
},
{
"id": "13:5901922417972273396",
"name": "mediaCount"
},
{
"id": "14:1229023184984372602",
"name": "size"
},
{
"id": "15:6851856791814492874",
"name": "name"
},
{
"id": "16:6142333908132117423",
"name": "favIcon"
}
],
"relations": []
},
{
"id": "4:6278838675135543734",
"lastPropertyId": "4:8812214350305159407",
"name": "LanguageEntity",
"properties": [
{
"id": "1:7795244654012809404",
"name": "id"
},
{
"id": "2:9116495537035444904",
"name": "locale"
},
{
"id": "3:452531964346972307",
"name": "active"
},
{
"id": "4:8812214350305159407",
"name": "occurencesOfLanguage"
}
],
"relations": []
},
{
"id": "5:3222423958972105425",
"lastPropertyId": "10:8395372122440621469",
"name": "HistoryEntity",
"properties": [
{
"id": "1:4390013783965661495",
"name": "id"
},
{
"id": "2:6814436941523306636",
"name": "zimId"
},
{
"id": "3:3445023139891930306",
"name": "zimName"
},
{
"id": "4:1707638909668210783",
"name": "zimFilePath"
},
{
"id": "5:7291321834337975178",
"name": "favicon"
},
{
"id": "6:8790316103579116510",
"name": "historyUrl"
},
{
"id": "7:6718164131929659510",
"name": "historyTitle"
},
{
"id": "9:6094002746638656105",
"name": "timeStamp"
},
{
"id": "10:8395372122440621469",
"name": "dateString"
}
],
"relations": []
},
{
"id": "6:2737311997994502758",
"lastPropertyId": "7:3805929017981932900",
"name": "BookmarkEntity",
"properties": [
{
"id": "1:6627309171741917147",
"name": "id"
},
{
"id": "2:6862771806221961183",
"name": "zimID"
},
{
"id": "3:4312769031500860715",
"name": "zimName"
},
{
"id": "4:8187716343071473669",
"name": "zimFilePath"
},
{
"id": "5:5652763871458286201",
"name": "bookmarkUrl"
},
{
"id": "6:4537799665712767375",
"name": "bookmarkTitle"
},
{
"id": "7:3805929017981932900",
"name": "favicon"
}
],
"relations": []
},
{
"id": "7:7635075139296819361",
"lastPropertyId": "3:3320858395373055542",
"name": "RecentSearchEntity",
"properties": [
{
"id": "1:7759655437795315973",
"name": "id"
},
{
"id": "2:3924214186055484853",
"name": "searchTerm"
},
{
"id": "3:3320858395373055542",
"name": "zimId"
}
],
"relations": []
}
],
"lastEntityId": "7:7635075139296819361",
"lastIndexId": "4:4868787482832538530",
"lastRelationId": "0:0",
"lastSequenceId": "0:0",
"modelVersion": 4,
"modelVersionParserMinimum": 4,
"retiredEntityUids": [
349148274283701276
],
"retiredIndexUids": [
1293695782925933448,
3655049272366703856,
7576716732364166705,
4868787482832538530
],
"retiredPropertyUids": [
4712434661554562781,
1521665545502891268,
1831899651198481824,
8913656606098213241,
4745760836781949968,
9177466730609383913,
6985467229796102081,
4417830652027770707,
3485079785941052658,
2875347328622347138,
96906195091428769,
305997162787053035,
8804682238892773896,
3464301918251637220,
5620508895870653354,
7273406943564025911,
428251106490095982,
5162677841083528491
],
"retiredRelationUids": [],
"version": 1
}

View File

@ -20,9 +20,9 @@
package org.kiwix.kiwixmobile.data.local;
import android.content.Context;
import androidx.test.platform.app.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
import com.yahoo.squidb.data.SquidCursor;
import com.yahoo.squidb.sql.Query;
import java.io.BufferedWriter;
@ -31,6 +31,7 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -50,7 +51,7 @@ public class KiwixDatabaseTest {
@Test
public void testMigrateDatabase() throws IOException {
KiwixDatabase kiwixDatabase = new KiwixDatabase(context);
KiwixDatabase kiwixDatabase = new KiwixDatabase(context, null, null);
kiwixDatabase.recreate();
String testId = "8ce5775a-10a9-bbf3-178a-9df69f23263c";
String[] testBookmarks = new String[] { "Test1", "Test2", "Test3" };
@ -60,7 +61,8 @@ public class KiwixDatabaseTest {
throw new IOException("Unable to create file for testing migration");
}
Writer writer =
new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName), "utf-8"));
new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName),
StandardCharsets.UTF_8));
for (String bookmark : testBookmarks) {
writer.write(bookmark + "\n");
}

View File

@ -61,7 +61,7 @@ public class BookDatabaseTest {
bookDao = new BookDao(kiwixDatabase);
// Create a temporary directory where all the test files will be saved
testDir = context.getDir("testDir", context.MODE_PRIVATE);
testDir = context.getDir("testDir", Context.MODE_PRIVATE);
}
//TODO : test books are saved after downloading the list of available zim files
@ -139,9 +139,9 @@ public class BookDatabaseTest {
ArrayList<Book> books = new ArrayList<>();
for (int i = 0; i < 9; i++) {
Book book = new Book();
book.bookName = "Test Copy " + Integer.toString(i);
book.id = "Test ID " + Integer.toString(i);
String fileName = baseFileName + Integer.toString(i);
book.bookName = "Test Copy " + i;
book.id = "Test ID " + i;
String fileName = baseFileName + i;
switch (i) {
case 0:
book.file = new File(fileName + ".zim");

View File

@ -17,6 +17,8 @@
*/
package org.kiwix.kiwixmobile.di.components;
import android.content.Context;
import dagger.BindsInstance;
import dagger.Component;
import javax.inject.Singleton;
import org.kiwix.kiwixmobile.data.DataModule;
@ -40,6 +42,14 @@ import org.kiwix.kiwixmobile.utils.TestNetworkInterceptor;
})
public interface TestComponent extends ApplicationComponent {
@Component.Builder
interface Builder {
@BindsInstance TestComponent.Builder context(Context context);
TestComponent build();
}
void inject(ZimTest zimTest);
void inject(NetworkTest networkTest);

View File

@ -19,7 +19,6 @@
package org.kiwix.kiwixmobile.language;
import android.Manifest;
import androidx.test.espresso.IdlingRegistry;
import androidx.test.espresso.ViewInteraction;
import androidx.test.espresso.intent.Intents;
import androidx.test.rule.GrantPermissionRule;
@ -27,11 +26,11 @@ import com.schibsted.spain.barista.interaction.BaristaSleepInteractions;
import com.schibsted.spain.barista.rule.BaristaRule;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.kiwix.kiwixmobile.R;
import org.kiwix.kiwixmobile.intro.IntroActivity;
import org.kiwix.kiwixmobile.zim_manager.library_view.LibraryFragment;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
import static androidx.test.espresso.Espresso.onView;
@ -73,6 +72,7 @@ public class LanguageActivityTest {
}
@Test
@Ignore("Broken in 2.5")//TODO: Fix in 3.0
public void testLanguageActivity() {
BaristaSleepInteractions.sleep(TEST_PAUSE_MS);
onView(withId(R.id.get_started)).perform(click());
@ -83,7 +83,7 @@ public class LanguageActivityTest {
onView(withText("Get Content")).perform(click());
BaristaSleepInteractions.sleep(TEST_PAUSE_MS);
ViewInteraction viewPager = onView(allOf(withId(R.id.container),
ViewInteraction viewPager = onView(allOf(withId(R.id.manageViewPager),
childAtPosition(allOf(withId(R.id.zim_manager_main_activity),
childAtPosition(withId(android.R.id.content), 0)), 1),
isDisplayed()));
@ -109,7 +109,7 @@ public class LanguageActivityTest {
childAtPosition(withId(R.id.toolbar_layout), 0)), 1), isDisplayed()));
// Make sure that the zim list has been loaded
IdlingRegistry.getInstance().register(LibraryFragment.IDLING_RESOURCE);
//IdlingRegistry.getInstance().register(LibraryFragment.IDLING_RESOURCE);
onView(allOf(isDisplayed(), withText("Selected languages:"))).check(matches(notNullValue()));
// Open the Language Activity
@ -274,7 +274,7 @@ public class LanguageActivityTest {
@After
public void endTest() {
IdlingRegistry.getInstance().unregister(LibraryFragment.IDLING_RESOURCE);
//IdlingRegistry.getInstance().unregister(LibraryFragment.IDLING_RESOURCE);
Intents.release();
}
}

View File

@ -33,6 +33,7 @@ import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@ -57,6 +58,7 @@ import static org.kiwix.kiwixmobile.testutils.TestUtils.getResourceString;
import static org.kiwix.kiwixmobile.testutils.TestUtils.withContent;
import static org.kiwix.kiwixmobile.utils.StandardActions.deleteZimIfExists;
@LargeTest
@RunWith(AndroidJUnit4.class)
public class DownloadTest {
@ -84,6 +86,7 @@ public class DownloadTest {
}
@Test
@Ignore("Broken in 2.5")//TODO: Fix in 3.0
public void downloadTest() {
BaristaSleepInteractions.sleep(TEST_PAUSE_MS);
BaristaMenuClickInteractions.clickMenu(getResourceString(R.string.menu_zim_manager));
@ -96,30 +99,24 @@ public class DownloadTest {
clickOn(R.string.remote_zims);
try {
clickOn(R.id.network_permission_button);
} catch (RuntimeException e) {
Log.d(KIWIX_DOWNLOAD_TEST, "Failed to click Network Permission Button", e);
}
captureAndSaveScreenshot("Before-checking-for-ZimManager-Main-Activity");
ViewInteraction viewPager2 = onView(
allOf(withId(R.id.container),
withParent(allOf(withId(R.id.zim_manager_main_activity),
withParent(withId(android.R.id.content)))),
isDisplayed()));
allOf(withId(R.id.manageViewPager),
withParent(allOf(withId(R.id.zim_manager_main_activity),
withParent(withId(android.R.id.content)))),
isDisplayed()));
captureAndSaveScreenshot("After-the-check-completed");
BaristaSleepInteractions.sleep(TEST_PAUSE_MS);
try {
onData(withContent("ray_charles")).inAdapterView(withId(R.id.library_list));
onData(withContent("ray_charles")).inAdapterView(withId(R.id.libraryList));
} catch (Exception e) {
fail("Couldn't find downloaded file 'ray_charles'\n\nOriginal Exception:\n" +
e.getLocalizedMessage() + "\n\n");
}
deleteZimIfExists("ray_charles", R.id.library_list);
deleteZimIfExists("ray_charles", R.id.libraryList);
assertDisplayed(R.string.local_zims);
clickOn(R.string.local_zims);

View File

@ -28,15 +28,19 @@ import com.schibsted.spain.barista.interaction.BaristaMenuClickInteractions;
import com.schibsted.spain.barista.interaction.BaristaSleepInteractions;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import okio.Buffer;
import org.apache.commons.io.IOUtils;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.kiwix.kiwixmobile.KiwixApplication;
@ -44,9 +48,9 @@ import org.kiwix.kiwixmobile.R;
import org.kiwix.kiwixmobile.data.ZimContentProvider;
import org.kiwix.kiwixmobile.di.components.DaggerTestComponent;
import org.kiwix.kiwixmobile.di.components.TestComponent;
import org.kiwix.kiwixmobile.di.modules.ApplicationModule;
import org.kiwix.kiwixmobile.main.MainActivity;
import org.kiwix.kiwixmobile.testutils.TestUtils;
import org.kiwix.kiwixmobile.utils.IOUtils;
import org.kiwix.kiwixmobile.utils.KiwixIdlingResource;
import static androidx.test.InstrumentationRegistry.getInstrumentation;
@ -92,11 +96,8 @@ public class NetworkTest {
@Before
public void setUp() {
TestComponent component = DaggerTestComponent.builder()
.applicationModule
(new ApplicationModule(
(KiwixApplication) getInstrumentation().getTargetContext().getApplicationContext()))
.build();
TestComponent component = DaggerTestComponent.builder().context(
getInstrumentation().getTargetContext().getApplicationContext()).build();
KiwixApplication.setApplicationComponent(component);
@ -122,6 +123,7 @@ public class NetworkTest {
}
@Test
@Ignore("Broken in 2.5")//TODO: Fix in 3.0
public void networkTest() {
mActivityTestRule.launchActivity(null);
@ -131,15 +133,7 @@ public class NetworkTest {
TestUtils.allowPermissionsIfNeeded();
try {
onView(withId(R.id.network_permission_button)).perform(click());
} catch (RuntimeException e) {
Log.i(NETWORK_TEST_TAG,
"Permission dialog was not shown, we probably already have required permissions");
}
onData(withContent("wikipedia_ab_all_2017-03")).inAdapterView(withId(R.id.library_list))
.perform(click());
onData(withContent("wikipedia_ab_all_2017-03")).inAdapterView(withId(R.id.libraryList)).perform(click());
try {
onView(withId(android.R.id.button1)).perform(click());

View File

@ -1,10 +1,10 @@
package org.kiwix.kiwixmobile.tests.activities;
import android.Manifest;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.rule.GrantPermissionRule;
import androidx.test.runner.AndroidJUnit4;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@ -0,0 +1,57 @@
package org.kiwix.kiwixmobile.utils;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/*
* Kiwix Android
* Copyright (C) 2018 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/>.
*/
public class IOUtils {
private IOUtils() {
//utility class
}
private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
private static final int EOF = -1;
public static byte[] toByteArray(final InputStream input) throws IOException {
try (final ByteArrayOutputStream output = new ByteArrayOutputStream()) {
copy(input, output);
return output.toByteArray();
}
}
private static int copy(final InputStream input, final OutputStream output) throws IOException {
final long count = copyLarge(input, output);
if (count > Integer.MAX_VALUE) {
return -1;
}
return (int) count;
}
private static long copyLarge(final InputStream input, final OutputStream output) throws IOException {
final byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
long count = 0;
int n;
while (EOF != (n = input.read(buffer))) {
output.write(buffer, 0, n);
count += n;
}
return count;
}
}

View File

@ -23,7 +23,7 @@ public class FileUtilsInstrumentationTest {
context = InstrumentationRegistry.getTargetContext();
// Create a temporary directory where all the test files will be saved
testDir = context.getDir("testDir", context.MODE_PRIVATE);
testDir = context.getDir("testDir", Context.MODE_PRIVATE);
}
@Test
@ -35,7 +35,7 @@ public class FileUtilsInstrumentationTest {
String fileName = testDir.getPath() + "/" + testId + "testfile.zim";
String fileNameWithExtension;
Random r = new Random();
boolean bool[] = new boolean[122];
boolean[] bool = new boolean[122];
// Creating the files for the test
int index = 0;

View File

@ -0,0 +1 @@
contact+android@kiwix.org

View File

@ -0,0 +1 @@
http://www.kiwix.org

View File

@ -0,0 +1 @@
en-US

View File

@ -0,0 +1,9 @@
Die ganze Wikipedia auf deinem Mobilgerät!
Kiwix ist eine Programm, daß das Lesen der Wikipedia und anderer Inhalte (Ubuntu Dokumentation, WikiLeaks, WikiVoyage, WikiSource, etc) ohne Internetverbindung erlaubt.
Sobald du die Inhaltsdateien heruntergeladen hast, die sehr groß sein können, benötigst du keine Internetverbindung um sie zu verwenden.
Siehe die Hilfe in der App und unsere Webseite für Informationen über verfügbare Inhalte.
Anmerkung: Kiwix existiert auch für PCs (Windows, Mac, Linux) verfügbar..

View File

@ -0,0 +1 @@
Die Wikipedia immer dabei; ohne Internetverbindung!

View File

@ -0,0 +1 @@
Kiwix, Wikipedia offline

View File

@ -0,0 +1,7 @@
The whole of Wikipedia on your device!
The app is a lightweight piece of software reading bigger files stored on your device or SD card: once it is installed, you can select which additional content you would like to download (Wikipedia, Wiktionary, TED talks, etc.) and be ready for when your internet connexion is bad (or need to be in airplane mode)!
Please read the instructions inside the App or on the website (www.kiwix.org) to learn about the various contents that are available for download.
Note: Kiwix is also available on regular computers (Windows, Mac, Linux).

Binary file not shown.

After

Width:  |  Height:  |  Size: 253 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 185 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 323 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

View File

@ -0,0 +1 @@
Wikipedia (and a lot more) at hand everywhere. No internet required!

View File

@ -0,0 +1 @@
Kiwix, Wikipedia offline

View File

@ -0,0 +1,11 @@
Tout Wikipédia dans votre mobile !
Kiwix est un lecteur de contenus hors-ligne qui peut être utilisé pour Wikipédia ainsi que d'autres contenus (Documentation Ubuntu, WikiLeaks, WikiVoyage, WikiSource, etc).
Une fois que vous avez téléchargé le fichier de contenu (potentiellement très gros), vous n'avez plus du tout besoin de connexion pour l'utiliser.
Kiwix est une application légère utilisant des fichiers ZIM que vous aurez préalablement téléchargé et stocké sur la mémoire externe (carte SD).
Merci de consulter les instructions d'utilisations dans l'application ainsi que sur le site web pour en savoir plus sur les contenus disponibles.
Note: Kiwix est aussi disponible sur ordinateur (Windows, Mac, Linux).

View File

@ -0,0 +1 @@
Emportez la Wikipédia partout avec vous ; sans connexion !

View File

@ -0,0 +1 @@
Kiwix, Wikipédia sans Internet

View File

@ -0,0 +1,11 @@
L'intera Wikipedia sempre con te!
Kiwix è un lettore non in linea di contenuti e siti di ogni genere, Wikipedia ma non solo (documentazione di Ubuntu, WikiLeaks, Wikisource, Wikivoyage ecc.).
Una volta scaricato l'archivio ZIM contenente il tutto (potenzialmente molto grande), non serve alcuna connessione a internet per navigarlo.
Kiwix è leggero e gli archivi ZIM si possono scaricare e conservare nel tuo apparecchio android o memoria esterna (scheda SD).
Controlla le istruzioni nell'applicazione e nel sito per sapere di più sui contenuti disponibili.
Nota, Kiwix è disponibile anche per computer normali (Windows, Mac e Linux).

View File

@ -0,0 +1 @@
Wikipedia sempre con te!

View File

@ -0,0 +1 @@
Kiwix

View File

@ -0,0 +1,5 @@
Vikipedi'nin tamamı cihazınızda!
Uygulama, cihazınızda veya SD kartta depolanan büyük dosyalar okuyan hafif bir yazılım parçasıdır: yükledikten sonra, hangi ek içerikler indirmek istediğinizi seçebilirsiniz (Vikipedi, Vikisözlük, TED Konferansları, v.b.) ve ne zaman internet bağlantınız kötü olsa, hazır olabilirsiniz (veya uçak modunda olmanız gerekiyorsa) !
Indirmek için hazır olan çeşitli içerikler hakkında bilgi edinmek için, lütfen uygulama içindeki veya web sitemizindeki talimatları okuyun (www.kiwix.org)

Binary file not shown.

After

Width:  |  Height:  |  Size: 379 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 809 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 278 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 670 KiB

View File

@ -0,0 +1 @@
Kiwix ile, Vikipedi tamamıyla telefonunuza veya tabletinize indirin

View File

@ -0,0 +1 @@
Kiwix - offline Vikipedi

View File

@ -0,0 +1,3 @@
NEW: Downloads are now using the DownloadManager
NEW: Downloads/Device/Library completely rewritten
+ Lots More

View File

@ -21,9 +21,10 @@
android:hardwareAccelerated="true"
android:icon="@mipmap/kiwix_icon"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:supportsRtl="true"
android:theme="@style/AppTheme"
android:networkSecurityConfig="@xml/network_security_config">
android:theme="@style/AppTheme">
<activity
android:name=".splash.SplashActivity"
android:label="@string/app_name"
@ -138,8 +139,8 @@
</activity>
<activity
android:name=".zim_manager.ZimManageActivity"
android:label="@string/choose_file">
android:label="@string/choose_file"
android:launchMode="singleTop">
<!-- TODO -->
<intent-filter>
<action android:name="android.intent.action.GET_CONTENT"/>
@ -179,8 +180,6 @@
android:resource="@xml/kiwix_widget_provider_info"/>
</receiver>
<service android:name=".downloader.DownloadService"/>
<activity
android:name=".error.ErrorActivity"
android:process=":error_activity"/>
@ -195,6 +194,7 @@
android:resource="@xml/provider_paths"/>
</provider>
<activity android:name=".intro.IntroActivity"/>
<activity android:name=".language.LanguageActivity"/>
<activity android:name=".history.HistoryActivity"/>
@ -203,6 +203,11 @@
android:name="android.support.PARENT_ACTIVITY"
android:value="main.MainActivity"/>
</activity>
</application>
<receiver android:name=".zim_manager.DownloadNotificationClickedReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/>
</intent-filter>
</receiver>
</application>
</manifest>

View File

@ -17,6 +17,8 @@
</style>
</head>
<body class="content">

View File

@ -23,6 +23,7 @@ import android.os.Environment;
import android.util.Log;
import androidx.appcompat.app.AppCompatDelegate;
import androidx.multidex.MultiDexApplication;
import com.jakewharton.threetenabp.AndroidThreeTen;
import com.squareup.leakcanary.LeakCanary;
import dagger.android.AndroidInjector;
import dagger.android.DispatchingAndroidInjector;
@ -32,8 +33,6 @@ import java.io.IOException;
import javax.inject.Inject;
import org.kiwix.kiwixmobile.di.components.ApplicationComponent;
import org.kiwix.kiwixmobile.di.components.DaggerApplicationComponent;
import com.jakewharton.threetenabp.AndroidThreeTen;
import org.kiwix.kiwixmobile.di.modules.ApplicationModule;
public class KiwixApplication extends MultiDexApplication implements HasActivityInjector {
@ -65,13 +64,18 @@ public class KiwixApplication extends MultiDexApplication implements HasActivity
super.attachBaseContext(base);
application = this;
setApplicationComponent(DaggerApplicationComponent.builder()
.applicationModule(new ApplicationModule(this))
.context(this)
.build());
}
@Override
public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
AndroidThreeTen.init(this);
if (isExternalStorageWritable()) {
File appDirectory = new File(Environment.getExternalStorageDirectory() + "/Kiwix");
@ -103,13 +107,7 @@ public class KiwixApplication extends MultiDexApplication implements HasActivity
}
Log.d("KIWIX", "Started KiwixApplication");
applicationComponent.inject(this);
if (LeakCanary.isInAnalyzerProcess(this)) {
// This process is dedicated to LeakCanary for heap analysis.
// You should not init your app in this process.
return;
}
LeakCanary.install(this);
}

View File

@ -0,0 +1,57 @@
package org.kiwix.kiwixmobile;
import androidx.lifecycle.ViewModel;
import androidx.lifecycle.ViewModelProvider;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
/*
* Kiwix Android
* Copyright (C) 2018 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/>.
*/
@Singleton
public class KiwixViewModelFactory implements ViewModelProvider.Factory {
private final Map<Class<? extends ViewModel>, Provider<ViewModel>> creators;
@Inject
public KiwixViewModelFactory(Map<Class<? extends ViewModel>, Provider<ViewModel>> creators) {
this.creators = creators;
}
@SuppressWarnings("unchecked")
@Override
public <T extends ViewModel> T create(Class<T> modelClass) {
Provider<? extends ViewModel> creator = creators.get(modelClass);
if (creator == null) {
for (Map.Entry<Class<? extends ViewModel>, Provider<ViewModel>> entry : creators.entrySet()) {
if (modelClass.isAssignableFrom(entry.getKey())) {
creator = entry.getValue();
break;
}
}
}
if (creator == null) {
throw new IllegalArgumentException("unknown model class " + modelClass);
}
try {
return (T) creator.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@ -1,31 +0,0 @@
package org.kiwix.kiwixmobile.base;
import android.app.Activity;
import android.content.Context;
import android.os.Build;
import androidx.fragment.app.Fragment;
import org.kiwix.kiwixmobile.KiwixApplication;
/**
* All fragments should inherit from this fragment.
*/
public abstract class BaseFragment extends Fragment {
@Override
public void onAttach(Context context) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
KiwixApplication.getApplicationComponent().inject(this);
}
super.onAttach(context);
}
@SuppressWarnings("deprecation")
@Override
public void onAttach(Activity activity) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
KiwixApplication.getApplicationComponent().inject(this);
}
super.onAttach(activity);
}
}

View File

@ -0,0 +1,24 @@
package org.kiwix.kiwixmobile.base
import android.content.Context
import androidx.fragment.app.Fragment
import org.kiwix.kiwixmobile.KiwixApplication
import org.kiwix.kiwixmobile.di.components.ActivityComponent
/**
* All fragments should inherit from this fragment.
*/
abstract class BaseFragment : Fragment() {
override fun onAttach(context: Context?) {
super.onAttach(context)
inject(
KiwixApplication.getApplicationComponent().activityComponent()
.activity(activity!!)
.build()
)
}
abstract fun inject(activityComponent: ActivityComponent)
}

View File

@ -0,0 +1,39 @@
package org.kiwix.kiwixmobile.bookmark
import org.kiwix.kiwixmobile.data.ZimContentProvider
import org.kiwix.kiwixmobile.database.newdb.entities.BookmarkEntity
data class BookmarkItem(
val databaseId: Long = 0L,
val zimId: String,
val zimName: String,
val zimFilePath: String,
val bookmarkUrl: String,
val bookmarkTitle: String,
val favicon: String
) {
constructor(entity: BookmarkEntity) : this(
entity.id,
entity.zimId,
entity.zimName,
entity.zimFilePath,
entity.bookmarkUrl,
entity.bookmarkTitle,
entity.favicon
)
companion object {
@JvmStatic fun fromZimContentProvider(
title: String,
url: String
) = BookmarkItem(
zimId = ZimContentProvider.getId(),
zimName = ZimContentProvider.getName(),
zimFilePath = ZimContentProvider.getZimFile(),
bookmarkUrl = url,
bookmarkTitle = title,
favicon = ZimContentProvider.getFavicon()
)
}
}

View File

@ -21,19 +21,18 @@ import javax.inject.Inject;
import org.kiwix.kiwixmobile.R;
import org.kiwix.kiwixmobile.base.BaseActivity;
import org.kiwix.kiwixmobile.data.ZimContentProvider;
import org.kiwix.kiwixmobile.data.local.entity.Bookmark;
import org.kiwix.kiwixmobile.extensions.ImageViewExtensionsKt;
import org.kiwix.kiwixmobile.main.MainActivity;
import static org.kiwix.kiwixmobile.library.LibraryAdapter.createBitmapFromEncodedString;
import static org.kiwix.kiwixmobile.utils.Constants.EXTRA_CHOSE_X_TITLE;
import static org.kiwix.kiwixmobile.utils.Constants.EXTRA_CHOSE_X_URL;
public class BookmarksActivity extends BaseActivity implements BookmarksContract.View,
BookmarksAdapter.OnItemClickListener {
private final List<Bookmark> bookmarksList = new ArrayList<>();
private final List<Bookmark> allBookmarks = new ArrayList<>();
private final List<Bookmark> deleteList = new ArrayList<>();
private final List<BookmarkItem> bookmarksList = new ArrayList<>();
private final List<BookmarkItem> allBookmarks = new ArrayList<>();
private final List<BookmarkItem> deleteList = new ArrayList<>();
@BindView(R.id.toolbar)
Toolbar toolbar;
@ -64,7 +63,7 @@ public class BookmarksActivity extends BaseActivity implements BookmarksContract
switch (item.getItemId()) {
case R.id.menu_context_delete:
allBookmarks.removeAll(deleteList);
for (Bookmark bookmark : deleteList) {
for (BookmarkItem bookmark : deleteList) {
int position = bookmarksList.indexOf(bookmark);
bookmarksList.remove(bookmark);
bookmarksAdapter.notifyItemRemoved(position);
@ -163,21 +162,21 @@ public class BookmarksActivity extends BaseActivity implements BookmarksContract
}
@Override
public void updateBookmarksList(List<Bookmark> bookmarksList) {
public void updateBookmarksList(List<BookmarkItem> bookmarksList) {
allBookmarks.clear();
allBookmarks.addAll(bookmarksList);
notifyBookmarksListFiltered(bookmarksList);
}
@Override
public void notifyBookmarksListFiltered(List<Bookmark> bookmarksList) {
public void notifyBookmarksListFiltered(List<BookmarkItem> bookmarksList) {
this.bookmarksList.clear();
this.bookmarksList.addAll(bookmarksList);
bookmarksAdapter.notifyDataSetChanged();
}
@Override
public void onItemClick(ImageView favicon, Bookmark bookmark) {
public void onItemClick(ImageView favicon, BookmarkItem bookmark) {
if (actionMode == null) {
Intent intent = new Intent(this, MainActivity.class);
if ("null".equals(bookmark.getBookmarkUrl())) {
@ -202,7 +201,7 @@ public class BookmarksActivity extends BaseActivity implements BookmarksContract
}
@Override
public boolean onItemLongClick(ImageView favicon, Bookmark bookmark) {
public boolean onItemLongClick(ImageView favicon, BookmarkItem bookmark) {
if (actionMode != null) {
return false;
}
@ -212,9 +211,9 @@ public class BookmarksActivity extends BaseActivity implements BookmarksContract
return true;
}
private void toggleSelection(ImageView favicon, Bookmark bookmark) {
private void toggleSelection(ImageView favicon, BookmarkItem bookmark) {
if (deleteList.remove(bookmark)) {
favicon.setImageBitmap(createBitmapFromEncodedString(bookmark.getFavicon(), this));
ImageViewExtensionsKt.setBitmapFromString(favicon, bookmark.getFavicon());
} else {
favicon.setImageDrawable(
ContextCompat.getDrawable(this, R.drawable.ic_check_circle_blue_24dp));

View File

@ -12,16 +12,14 @@ import butterknife.BindView;
import butterknife.ButterKnife;
import java.util.List;
import org.kiwix.kiwixmobile.R;
import org.kiwix.kiwixmobile.data.local.entity.Bookmark;
import static org.kiwix.kiwixmobile.library.LibraryAdapter.createBitmapFromEncodedString;
import org.kiwix.kiwixmobile.extensions.ImageViewExtensionsKt;
class BookmarksAdapter extends RecyclerView.Adapter<BookmarksAdapter.Item> {
private final List<Bookmark> bookmarkList;
private final List<BookmarkItem> bookmarkList;
private final OnItemClickListener itemClickListener;
private final List<Bookmark> deleteList;
private final List<BookmarkItem> deleteList;
BookmarksAdapter(List<Bookmark> bookmarkList, List<Bookmark> deleteList,
BookmarksAdapter(List<BookmarkItem> bookmarkList, List<BookmarkItem> deleteList,
OnItemClickListener itemClickListener) {
this.bookmarkList = bookmarkList;
this.deleteList = deleteList;
@ -38,14 +36,13 @@ class BookmarksAdapter extends RecyclerView.Adapter<BookmarksAdapter.Item> {
@Override
public void onBindViewHolder(@NonNull Item holder, int position) {
Bookmark bookmark = bookmarkList.get(position);
BookmarkItem bookmark = bookmarkList.get(position);
holder.title.setText(bookmark.getBookmarkTitle());
if (deleteList.contains(bookmark)) {
holder.favicon.setImageDrawable(ContextCompat.getDrawable(holder.favicon.getContext(),
R.drawable.ic_check_circle_blue_24dp));
} else {
holder.favicon.setImageBitmap(createBitmapFromEncodedString(bookmark.getFavicon(),
holder.favicon.getContext()));
ImageViewExtensionsKt.setBitmapFromString(holder.favicon, bookmark.getFavicon());
}
holder.itemView.setOnClickListener(
v -> itemClickListener.onItemClick(holder.favicon, bookmark));
@ -59,9 +56,9 @@ class BookmarksAdapter extends RecyclerView.Adapter<BookmarksAdapter.Item> {
}
interface OnItemClickListener {
void onItemClick(ImageView favicon, Bookmark bookmark);
void onItemClick(ImageView favicon, BookmarkItem bookmark);
boolean onItemLongClick(ImageView favicon, Bookmark bookmark);
boolean onItemLongClick(ImageView favicon, BookmarkItem bookmark);
}
class Item extends RecyclerView.ViewHolder {

View File

@ -2,20 +2,19 @@ package org.kiwix.kiwixmobile.bookmark;
import java.util.List;
import org.kiwix.kiwixmobile.base.BaseContract;
import org.kiwix.kiwixmobile.data.local.entity.Bookmark;
interface BookmarksContract {
interface View extends BaseContract.View<Presenter> {
void updateBookmarksList(List<Bookmark> bookmarks);
void updateBookmarksList(List<BookmarkItem> bookmarks);
void notifyBookmarksListFiltered(List<Bookmark> bookmarks);
void notifyBookmarksListFiltered(List<BookmarkItem> bookmarks);
}
interface Presenter extends BaseContract.Presenter<View> {
void loadBookmarks(boolean showBookmarksCurrentBook);
void filterBookmarks(List<Bookmark> bookmarksList, String newText);
void filterBookmarks(List<BookmarkItem> bookmarksList, String newText);
void deleteBookmarks(List<Bookmark> deleteList);
void deleteBookmarks(List<BookmarkItem> deleteList);
}
}

View File

@ -34,7 +34,7 @@ class BookmarksPresenter extends BasePresenter<BookmarksContract.View>
@Override
public void loadBookmarks(boolean showFromCurrentBookmarks) {
dataSource.getBookmarks(showFromCurrentBookmarks)
.subscribe(new SingleObserver<List<Bookmark>>() {
.subscribe(new SingleObserver<List<BookmarkItem>>() {
@Override
public void onSubscribe(Disposable d) {
if (disposable != null && !disposable.isDisposed()) {
@ -45,7 +45,7 @@ class BookmarksPresenter extends BasePresenter<BookmarksContract.View>
}
@Override
public void onSuccess(List<Bookmark> bookmarks) {
public void onSuccess(List<BookmarkItem> bookmarks) {
view.updateBookmarksList(bookmarks);
}
@ -57,21 +57,21 @@ class BookmarksPresenter extends BasePresenter<BookmarksContract.View>
}
@Override
public void filterBookmarks(List<Bookmark> bookmarks, String newText) {
public void filterBookmarks(List<BookmarkItem> bookmarks, String newText) {
Observable.fromIterable(bookmarks)
.filter(
bookmark -> bookmark.getBookmarkTitle().toLowerCase().contains(newText.toLowerCase()))
.toList()
.subscribeOn(computation)
.observeOn(mainThread)
.subscribe(new SingleObserver<List<Bookmark>>() {
.subscribe(new SingleObserver<List<BookmarkItem>>() {
@Override
public void onSubscribe(Disposable d) {
compositeDisposable.add(d);
}
@Override
public void onSuccess(List<Bookmark> bookmarkList) {
public void onSuccess(List<BookmarkItem> bookmarkList) {
view.notifyBookmarksListFiltered(bookmarkList);
}
@ -83,7 +83,7 @@ class BookmarksPresenter extends BasePresenter<BookmarksContract.View>
}
@Override
public void deleteBookmarks(List<Bookmark> deleteList) {
public void deleteBookmarks(List<BookmarkItem> deleteList) {
dataSource.deleteBookmarks(deleteList)
.subscribe(new CompletableObserver() {
@Override

View File

@ -1,43 +1,46 @@
package org.kiwix.kiwixmobile.data;
import io.reactivex.Completable;
import io.reactivex.Flowable;
import io.reactivex.Single;
import java.util.List;
import org.kiwix.kiwixmobile.bookmark.BookmarkItem;
import org.kiwix.kiwixmobile.data.local.entity.Bookmark;
import org.kiwix.kiwixmobile.data.local.entity.History;
import org.kiwix.kiwixmobile.history.HistoryListItem;
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity;
import org.kiwix.kiwixmobile.models.Language;
import org.kiwix.kiwixmobile.zim_manager.Language;
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem;
/**
* Defines the set of methods which are required to provide the presenter with the requisite data.
*/
public interface DataSource {
Single<List<LibraryNetworkEntity.Book>> getLanguageCategorizedBooks();
Single<List<BooksOnDiskListItem>> getLanguageCategorizedBooks();
Completable saveBook(LibraryNetworkEntity.Book book);
Completable saveBook(BooksOnDiskListItem.BookOnDisk book);
Completable saveBooks(List<LibraryNetworkEntity.Book> book);
Completable deleteBook(LibraryNetworkEntity.Book book);
Completable saveBooks(List<BooksOnDiskListItem.BookOnDisk> book);
Completable saveLanguages(List<Language> languages);
Single<List<History>> getDateCategorizedHistory(boolean showHistoryCurrentBook);
Single<List<HistoryListItem>> getDateCategorizedHistory(boolean showHistoryCurrentBook);
Completable saveHistory(History history);
Completable saveHistory(HistoryListItem.HistoryItem history);
Completable deleteHistory(List<History> historyList);
Completable deleteHistory(List<HistoryListItem> historyList);
Completable clearHistory();
Single<List<Bookmark>> getBookmarks(boolean showFromCurrentBook);
Single<List<BookmarkItem>> getBookmarks(boolean showFromCurrentBook);
Single<List<String>> getCurrentZimBookmarksUrl();
Completable saveBookmark(Bookmark bookmark);
Completable saveBookmark(BookmarkItem bookmark);
Completable deleteBookmarks(List<Bookmark> bookmarks);
Completable deleteBookmarks(List<BookmarkItem> bookmarks);
Completable deleteBookmark(Bookmark bookmark);
Completable deleteBookmark(BookmarkItem bookmark);
Flowable<List<BooksOnDiskListItem>> booksOnDiskAsListItems();
}

View File

@ -1,181 +0,0 @@
package org.kiwix.kiwixmobile.data;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Scheduler;
import io.reactivex.Single;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.kiwix.kiwixmobile.data.local.dao.BookDao;
import org.kiwix.kiwixmobile.data.local.dao.BookmarksDao;
import org.kiwix.kiwixmobile.data.local.dao.HistoryDao;
import org.kiwix.kiwixmobile.data.local.dao.NetworkLanguageDao;
import org.kiwix.kiwixmobile.data.local.dao.RecentSearchDao;
import org.kiwix.kiwixmobile.data.local.entity.Bookmark;
import org.kiwix.kiwixmobile.data.local.entity.History;
import org.kiwix.kiwixmobile.di.qualifiers.IO;
import org.kiwix.kiwixmobile.di.qualifiers.MainThread;
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity;
import org.kiwix.kiwixmobile.models.Language;
/**
* A central repository of data which should provide the presenters with the required data.
*/
@Singleton
public class Repository implements DataSource {
private final BookDao bookDao;
private final BookmarksDao bookmarksDao;
private final HistoryDao historyDao;
private final NetworkLanguageDao languageDao;
private final RecentSearchDao recentSearchDao;
private final Scheduler io;
private final Scheduler mainThread;
@Inject Repository(@IO Scheduler io, @MainThread Scheduler mainThread,
BookDao bookDao,
BookmarksDao bookmarksDao,
HistoryDao historyDao,
NetworkLanguageDao languageDao,
RecentSearchDao recentSearchDao) {
this.io = io;
this.mainThread = mainThread;
this.bookDao = bookDao;
this.languageDao = languageDao;
this.bookmarksDao = bookmarksDao;
this.historyDao = historyDao;
this.recentSearchDao = recentSearchDao;
}
@Override
public Single<List<LibraryNetworkEntity.Book>> getLanguageCategorizedBooks() {
return Observable.fromIterable(bookDao.getBooks())
.toSortedList(
(book1, book2) -> book1.getLanguage().compareToIgnoreCase(book2.getLanguage()) == 0 ?
book1.getTitle().compareToIgnoreCase(book2.getTitle()) :
book1.getLanguage().compareToIgnoreCase(book2.getLanguage()))
.map(books -> {
LibraryNetworkEntity.Book book = null;
if (books.size() >= 1) {
book = books.get(0);
books.add(0, null);
}
for (int position = 2; position < books.size(); position++) {
if (book != null && books.get(position) != null &&
!new Locale(books.get(position).getLanguage()).getDisplayName()
.equalsIgnoreCase(new Locale(book.getLanguage()).getDisplayName())) {
books.add(position, null);
}
book = books.get(position);
}
return books;
})
.subscribeOn(io)
.observeOn(mainThread);
}
@Override
public Completable saveBooks(List<LibraryNetworkEntity.Book> books) {
return Completable.fromAction(
() -> bookDao.saveBooks((ArrayList<LibraryNetworkEntity.Book>) books))
.subscribeOn(io);
}
@Override
public Completable saveBook(LibraryNetworkEntity.Book book) {
return Completable.fromAction(() -> bookDao.saveBook(book))
.subscribeOn(io);
}
@Override
public Completable deleteBook(LibraryNetworkEntity.Book book) {
return Completable.fromAction(() -> bookDao.deleteBook(book.getId()))
.subscribeOn(io);
}
@Override
public Completable saveLanguages(List<Language> languages) {
return Completable.fromAction(() -> languageDao.saveFilteredLanguages(languages))
.subscribeOn(io);
}
@Override
public Single<List<History>> getDateCategorizedHistory(boolean showHistoryCurrentBook) {
return Single.just(historyDao.getHistoryList(showHistoryCurrentBook))
.map(histories -> {
History history = null;
if (histories.size() >= 1) {
history = histories.get(0);
histories.add(0, null);
}
for (int position = 2; position < histories.size(); position++) {
if (history != null && histories.get(position) != null &&
!history.getDate().equals(histories.get(position).getDate())) {
histories.add(position, null);
}
history = histories.get(position);
}
return histories;
})
.subscribeOn(io)
.observeOn(mainThread);
}
@Override
public Completable saveHistory(History history) {
return Completable.fromAction(() -> historyDao.saveHistory(history))
.subscribeOn(io);
}
@Override
public Completable deleteHistory(List<History> historyList) {
return Completable.fromAction(() -> historyDao.deleteHistory(historyList))
.subscribeOn(io);
}
@Override
public Completable clearHistory() {
return Completable.fromAction(() -> {
historyDao.deleteHistory(historyDao.getHistoryList(false));
recentSearchDao.deleteSearchHistory();
})
.subscribeOn(io);
}
@Override
public Single<List<Bookmark>> getBookmarks(boolean fromCurrentBook) {
return Single.just(bookmarksDao.getBookmarks(fromCurrentBook))
.subscribeOn(io)
.observeOn(mainThread);
}
@Override
public Single<List<String>> getCurrentZimBookmarksUrl() {
return Single.just(bookmarksDao.getCurrentZimBookmarksUrl())
.subscribeOn(io)
.observeOn(mainThread);
}
@Override
public Completable saveBookmark(Bookmark bookmark) {
return Completable.fromAction(() -> bookmarksDao.saveBookmark(bookmark))
.subscribeOn(io);
}
@Override
public Completable deleteBookmarks(List<Bookmark> bookmarks) {
return Completable.fromAction(() -> bookmarksDao.deleteBookmarks(bookmarks))
.subscribeOn(io);
}
@Override
public Completable deleteBookmark(Bookmark bookmark) {
return Completable.fromAction(() -> bookmarksDao.deleteBookmark(bookmark))
.subscribeOn(io);
}
}

View File

@ -0,0 +1,137 @@
package org.kiwix.kiwixmobile.data
import io.reactivex.Completable
import io.reactivex.Flowable
import io.reactivex.Scheduler
import io.reactivex.Single
import org.kiwix.kiwixmobile.bookmark.BookmarkItem
import org.kiwix.kiwixmobile.data.local.dao.BookmarksDao
import org.kiwix.kiwixmobile.data.local.dao.RecentSearchDao
import org.kiwix.kiwixmobile.data.local.entity.Bookmark
import org.kiwix.kiwixmobile.database.newdb.dao.HistoryDao
import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao
import org.kiwix.kiwixmobile.database.newdb.dao.NewBookmarksDao
import org.kiwix.kiwixmobile.database.newdb.dao.NewLanguagesDao
import org.kiwix.kiwixmobile.database.newdb.dao.NewRecentSearchDao
import org.kiwix.kiwixmobile.di.qualifiers.IO
import org.kiwix.kiwixmobile.di.qualifiers.MainThread
import org.kiwix.kiwixmobile.history.HistoryListItem
import org.kiwix.kiwixmobile.history.HistoryListItem.DateItem
import org.kiwix.kiwixmobile.history.HistoryListItem.HistoryItem
import org.kiwix.kiwixmobile.zim_manager.Language
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.LanguageItem
import javax.inject.Inject
import javax.inject.Singleton
/**
* A central repository of data which should provide the presenters with the required data.
*/
@Singleton
class Repository @Inject internal constructor(
@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
) : DataSource {
override fun getLanguageCategorizedBooks() =
booksOnDiskAsListItems()
.first(emptyList())
.subscribeOn(io)
.observeOn(mainThread)
override fun booksOnDiskAsListItems(): Flowable<List<BooksOnDiskListItem>> = bookDao.books()
.map { it.sortedBy { bookOnDisk -> bookOnDisk.book.language + bookOnDisk.book.title } }
.map {
foldOverAddingHeaders(
it,
{ bookOnDisk -> LanguageItem(bookOnDisk.locale) },
{ current, next -> current.locale.displayName != next.locale.displayName })
}
.map { it.toList() }
override fun saveBooks(books: List<BookOnDisk>) =
Completable.fromAction { bookDao.insert(books) }
.subscribeOn(io)
override fun saveBook(book: BookOnDisk) =
Completable.fromAction { bookDao.insert(listOf(book)) }
.subscribeOn(io)
override fun saveLanguages(languages: List<Language>) =
Completable.fromAction { languageDao.insert(languages) }
.subscribeOn(io)
override fun getDateCategorizedHistory(showHistoryCurrentBook: Boolean) =
Single.just(historyDao.getHistoryList(showHistoryCurrentBook))
.map {
foldOverAddingHeaders(
it,
{ historyItem -> DateItem(historyItem.dateString) },
{ current, next -> current.dateString != next.dateString })
}
.subscribeOn(io)
.observeOn(mainThread)
override fun saveHistory(history: HistoryItem) =
Completable.fromAction { historyDao.saveHistory(history) }
.subscribeOn(io)
override fun deleteHistory(historyList: List<HistoryListItem>) =
Completable.fromAction {
historyDao.deleteHistory(historyList.filterIsInstance(HistoryItem::class.java))
}
.subscribeOn(io)
override fun clearHistory() = Completable.fromAction {
historyDao.deleteHistory(historyDao.getHistoryList(false))
recentSearchDao.deleteSearchHistory()
}
override fun getBookmarks(fromCurrentBook: Boolean): Single<List<BookmarkItem>> =
Single.just(bookmarksDao.getBookmarks(fromCurrentBook))
.subscribeOn(io)
.observeOn(mainThread)
override fun getCurrentZimBookmarksUrl() =
Single.just(bookmarksDao.getCurrentZimBookmarksUrl())
.subscribeOn(io)
.observeOn(mainThread)
override fun saveBookmark(bookmark: BookmarkItem) =
Completable.fromAction { bookmarksDao.saveBookmark(bookmark) }
.subscribeOn(io)
override fun deleteBookmarks(bookmarks: List<BookmarkItem>) =
Completable.fromAction { bookmarksDao.deleteBookmarks(bookmarks) }
.subscribeOn(io)
override fun deleteBookmark(bookmark: BookmarkItem) =
Completable.fromAction { bookmarksDao.deleteBookmark(bookmark) }
.subscribeOn(io)
private fun <SUPERTYPE, ITEM : SUPERTYPE, HEADER : SUPERTYPE> foldOverAddingHeaders(
it: List<ITEM>,
headerConstructor: (ITEM) -> HEADER,
criteriaToAddHeader: (ITEM, ITEM) -> Boolean
): MutableList<SUPERTYPE> = it.foldIndexed(mutableListOf(),
{ index, acc, currentItem ->
if (index == 0) {
acc.add(headerConstructor.invoke(currentItem))
}
acc.add(currentItem)
if (index < it.size - 1) {
val nextItem = it[index + 1]
if (criteriaToAddHeader.invoke(currentItem, nextItem)) {
acc.add(headerConstructor.invoke(nextItem))
}
}
acc
}
)
}

View File

@ -35,12 +35,14 @@ import javax.inject.Singleton;
import org.kiwix.kiwixmobile.data.ZimContentProvider;
import org.kiwix.kiwixmobile.data.local.dao.BookDao;
import org.kiwix.kiwixmobile.data.local.dao.BookmarksDao;
import org.kiwix.kiwixmobile.data.local.dao.NetworkLanguageDao;
import org.kiwix.kiwixmobile.data.local.entity.BookDatabaseEntity;
import org.kiwix.kiwixmobile.data.local.entity.Bookmark;
import org.kiwix.kiwixmobile.data.local.entity.History;
import org.kiwix.kiwixmobile.data.local.entity.LibraryDatabaseEntity;
import org.kiwix.kiwixmobile.data.local.entity.NetworkLanguageDatabaseEntity;
import org.kiwix.kiwixmobile.data.local.entity.RecentSearch;
import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao;
import org.kiwix.kiwixmobile.database.newdb.dao.NewLanguagesDao;
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity;
import org.kiwix.kiwixmobile.utils.UpdateUtils;
@ -51,11 +53,15 @@ public class KiwixDatabase extends SquidDatabase {
private static final int VERSION = 17;
private final Context context;
private final NewBookDao bookDao;
private final NewLanguagesDao languagesDao;
@Inject
public KiwixDatabase(Context context) {
public KiwixDatabase(Context context, NewBookDao bookDao, NewLanguagesDao languagesDao) {
super(context);
this.context = context;
this.bookDao = bookDao;
this.languagesDao = languagesDao;
}
@Override
@ -66,17 +72,25 @@ public class KiwixDatabase extends SquidDatabase {
@Override
protected Table[] getTables() {
return new Table[] {
BookDatabaseEntity.TABLE,
LibraryDatabaseEntity.TABLE,
RecentSearch.TABLE,
Bookmark.TABLE,
NetworkLanguageDatabaseEntity.TABLE,
History.TABLE
};
}
@Override
protected boolean onUpgrade(SQLiteDatabaseWrapper db, int oldVersion, int newVersion) {
if (newVersion >= 16) { //2.5 attempt reading values from old db before they get dropped
try {
bookDao.migrationInsert(new BookDao(this).getBooks());
} catch (Exception e) {
e.printStackTrace();
}
try {
languagesDao.insert(new NetworkLanguageDao(this).getFilteredLanguages());
} catch (Exception e) {
e.printStackTrace();
}
}
switch (oldVersion) {
case 1:
case 2:
@ -117,13 +131,16 @@ public class KiwixDatabase extends SquidDatabase {
tryDropTable(BookDatabaseEntity.TABLE);
tryCreateTable(BookDatabaseEntity.TABLE);
case 14:
tryCreateTable(History.TABLE);
case 15:
tryAddColumn(Bookmark.ZIM_FILE_PATH);
tryAddColumn(Bookmark.FAVICON);
migrateBookmarksVersion16();
tryDropTable(BookDatabaseEntity.TABLE);
tryDropTable(NetworkLanguageDatabaseEntity.TABLE);
tryDropTable(LibraryDatabaseEntity.TABLE);
case 16:
new BookmarksDao(this).processBookmark(UpdateUtils::reformatProviderUrl);
//TODO MIGRATIONS BEFORE 3.0
}
return true;
}

View File

@ -31,6 +31,7 @@ import org.kiwix.kiwixmobile.utils.files.FileUtils;
* Dao class for books
*/
@Deprecated
public class BookDao {
private final KiwixDatabase kiwixDatabase;
@ -55,24 +56,6 @@ public class BookDao {
book.bookName = bookCursor.get(BookDatabaseEntity.NAME);
}
private void setBookDatabaseEntity(Book book, BookDatabaseEntity bookDatabaseEntity) {
bookDatabaseEntity.setBookId(book.getId());
bookDatabaseEntity.setTitle(book.getTitle());
bookDatabaseEntity.setDescription(book.getDescription());
bookDatabaseEntity.setLanguage(book.getLanguage());
bookDatabaseEntity.setBookCreator(book.getCreator());
bookDatabaseEntity.setPublisher(book.getPublisher());
bookDatabaseEntity.setDate(book.getDate());
bookDatabaseEntity.setUrl(book.file.getPath());
bookDatabaseEntity.setArticleCount(book.getArticleCount());
bookDatabaseEntity.setMediaCount(book.getMediaCount());
bookDatabaseEntity.setSize(book.getSize());
bookDatabaseEntity.setFavicon(book.getFavicon());
bookDatabaseEntity.setName(book.getName());
kiwixDatabase.deleteWhere(BookDatabaseEntity.class,
BookDatabaseEntity.BOOK_ID.eq(book.getId()));
kiwixDatabase.persist(bookDatabaseEntity);
}
public ArrayList<Book> getBooks() {
ArrayList<Book> books = new ArrayList<>();
@ -101,39 +84,4 @@ public class BookDao {
}
return filteredBookList;
}
public ArrayList<Book> getDownloadingBooks() {
ArrayList<Book> books = new ArrayList<>();
try (SquidCursor<BookDatabaseEntity> bookCursor = kiwixDatabase.query(BookDatabaseEntity.class,
Query.select())) {
while (bookCursor.moveToNext()) {
Book book = new Book();
setBookDetails(book, bookCursor);
book.remoteUrl = bookCursor.get(BookDatabaseEntity.REMOTE_URL);
if (FileUtils.hasPart(book.file)) {
books.add(book);
}
}
}
return books;
}
public void saveBooks(ArrayList<Book> books) {
for (Book book : books) {
if (book != null) {
BookDatabaseEntity bookDatabaseEntity = new BookDatabaseEntity();
setBookDatabaseEntity(book, bookDatabaseEntity);
}
}
}
public void saveBook(Book book) {
BookDatabaseEntity bookDatabaseEntity = new BookDatabaseEntity();
bookDatabaseEntity.setRemoteUrl(book.remoteUrl);
setBookDatabaseEntity(book, bookDatabaseEntity);
}
public void deleteBook(String id) {
kiwixDatabase.deleteWhere(BookDatabaseEntity.class, BookDatabaseEntity.BOOK_ID.eq(id));
}
}

View File

@ -31,6 +31,7 @@ import org.kiwix.kiwixmobile.data.local.entity.Bookmark;
* Dao class for bookmarks.
*/
@Deprecated
public class BookmarksDao {
private final KiwixDatabase kiwixDatabase;

View File

@ -1,73 +0,0 @@
package org.kiwix.kiwixmobile.data.local.dao;
import android.content.Context;
import com.yahoo.squidb.data.SquidCursor;
import com.yahoo.squidb.sql.Query;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.inject.Inject;
import org.kiwix.kiwixmobile.data.ZimContentProvider;
import org.kiwix.kiwixmobile.data.local.KiwixDatabase;
import org.kiwix.kiwixmobile.data.local.entity.History;
import static org.kiwix.kiwixmobile.utils.LanguageUtils.getCurrentLocale;
public class HistoryDao {
private final Context context;
private final KiwixDatabase kiwixDatabase;
@Inject HistoryDao(Context context, KiwixDatabase kiwixDatabase) {
this.context = context;
this.kiwixDatabase = kiwixDatabase;
}
public void saveHistory(History history) {
SimpleDateFormat sdf = new SimpleDateFormat("d MMM yyyy", getCurrentLocale(context));
String date = sdf.format(new Date(history.getTimeStamp()));
kiwixDatabase.deleteWhere(History.class, History.HISTORY_URL.eq(history.getHistoryUrl())
.and(History.DATE.eq(date)).and(History.ZIM_ID.eq(history.getZimId())));
kiwixDatabase.persist(new History()
.setZimId(history.getZimId())
.setZimName(history.getZimName())
.setZimFilePath(history.getZimFilePath())
.setFavicon(history.getFavicon())
.setHistoryUrl(history.getHistoryUrl())
.setHistoryTitle(history.getHistoryTitle())
.setDate(date)
.setTimeStamp(history.getTimeStamp()));
}
public List<History> getHistoryList(boolean showHistoryCurrentBook) {
ArrayList<History> histories = new ArrayList<>();
Query query = Query.select();
if (showHistoryCurrentBook) {
query = query.where(History.ZIM_FILE_PATH.eq(ZimContentProvider.getZimFile()));
}
try (SquidCursor<History> historySquidCursor = kiwixDatabase
.query(History.class, query.orderBy(History.TIME_STAMP.desc()))) {
while (historySquidCursor.moveToNext()) {
History history = new History();
history.setDate(historySquidCursor.get(History.DATE))
.setFavicon(historySquidCursor.get(History.FAVICON))
.setHistoryTitle(historySquidCursor.get(History.HISTORY_TITLE))
.setHistoryUrl(historySquidCursor.get(History.HISTORY_URL))
.setTimeStamp(historySquidCursor.get(History.TIME_STAMP))
.setZimFilePath(historySquidCursor.get(History.ZIM_FILE_PATH))
.setZimName(historySquidCursor.get(History.ZIM_NAME))
.setZimId(historySquidCursor.get(History.ZIM_ID));
histories.add(history);
}
}
return histories;
}
public void deleteHistory(List<History> historyList) {
for (History history : historyList) {
if (history != null) {
kiwixDatabase.deleteWhere(History.class, History.TIME_STAMP.eq(history.getTimeStamp()));
}
}
}
}

View File

@ -22,13 +22,12 @@ package org.kiwix.kiwixmobile.data.local.dao;
import com.yahoo.squidb.data.SquidCursor;
import com.yahoo.squidb.sql.Query;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.inject.Inject;
import org.kiwix.kiwixmobile.data.local.KiwixDatabase;
import org.kiwix.kiwixmobile.data.local.entity.NetworkLanguageDatabaseEntity;
import org.kiwix.kiwixmobile.models.Language;
import org.kiwix.kiwixmobile.zim_manager.Language;
@Deprecated
public class NetworkLanguageDao {
private KiwixDatabase mDb;
@ -45,21 +44,9 @@ public class NetworkLanguageDao {
while (languageCursor.moveToNext()) {
String languageCode = languageCursor.get(NetworkLanguageDatabaseEntity.LANGUAGE_I_S_O_3);
boolean enabled = languageCursor.get(NetworkLanguageDatabaseEntity.ENABLED);
result.add(new Language(languageCode, enabled));
result.add(new Language(languageCode, enabled, 0));
}
}
return result;
}
public void saveFilteredLanguages(List<Language> languages) {
mDb.deleteAll(NetworkLanguageDatabaseEntity.class);
Collections.sort(languages, (language, t1) -> language.language.compareTo(t1.language));
for (Language language : languages) {
NetworkLanguageDatabaseEntity networkLanguageDatabaseEntity =
new NetworkLanguageDatabaseEntity();
networkLanguageDatabaseEntity.setLanguageISO3(language.languageCode);
networkLanguageDatabaseEntity.setIsEnabled(language.active);
mDb.persist(networkLanguageDatabaseEntity);
}
}
}

View File

@ -29,6 +29,7 @@ import org.kiwix.kiwixmobile.data.local.entity.RecentSearch;
/**
* Dao class for recent searches.
*/
@Deprecated
public class RecentSearchDao {
private static final int NUM_RECENT_RESULTS = 5;

View File

@ -51,6 +51,4 @@ public class BookDataSource {
public String favicon;
public String name;
public boolean downloaded;
}

View File

@ -1,15 +0,0 @@
package org.kiwix.kiwixmobile.data.local.entity;
import com.yahoo.squidb.annotations.TableModelSpec;
@TableModelSpec(className = "History", tableName = "History")
public class HistorySpec {
public String zimId;
public String zimName;
public String zimFilePath;
public String favicon;
public String historyUrl;
public String historyTitle;
public String date;
public long timeStamp;
}

View File

@ -25,4 +25,5 @@ import com.yahoo.squidb.annotations.TableModelSpec;
public class NetworkLanguageSpec {
public String languageISO3;
public boolean enabled;
public int numberOfOccurences;
}

View File

@ -18,6 +18,7 @@
package org.kiwix.kiwixmobile.data.remote;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
import okhttp3.OkHttpClient;
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity;
@ -29,7 +30,7 @@ import retrofit2.http.GET;
import retrofit2.http.Url;
public interface KiwixService {
@GET("/library/library_zim.xml") Observable<LibraryNetworkEntity> getLibrary();
@GET("/library/library_zim.xml") Single<LibraryNetworkEntity> getLibrary();
@GET Observable<MetaLinkNetworkEntity> getMetaLinks(@Url String url);

View File

@ -0,0 +1,62 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.database.newdb.dao
import io.objectbox.Box
import io.objectbox.kotlin.query
import org.kiwix.kiwixmobile.KiwixApplication
import org.kiwix.kiwixmobile.data.ZimContentProvider
import org.kiwix.kiwixmobile.database.newdb.entities.HistoryEntity
import org.kiwix.kiwixmobile.database.newdb.entities.HistoryEntity_
import org.kiwix.kiwixmobile.history.HistoryListItem.HistoryItem
import org.kiwix.kiwixmobile.utils.LanguageUtils.getCurrentLocale
import java.text.SimpleDateFormat
import java.util.Date
import javax.inject.Inject
class HistoryDao @Inject constructor(val box: Box<HistoryEntity>) {
fun history() = box.asFlowable()
.map { it.map(::HistoryItem) }
fun saveHistory(historyItem: HistoryItem) {
box.store.callInTx {
box
.query {
equal(HistoryEntity_.historyUrl, historyItem.historyUrl).and()
.equal(HistoryEntity_.dateString, historyItem.dateString)
}
.remove()
box.put(HistoryEntity(historyItem))
}
}
fun getHistoryList(showHistoryCurrentBook: Boolean) = box
.query {
if (showHistoryCurrentBook) {
equal(HistoryEntity_.zimFilePath, ZimContentProvider.getZimFile())
}
orderDesc(HistoryEntity_.timeStamp)
}
.find()
.map(::HistoryItem)
fun deleteHistory(historyList: List<HistoryItem>) {
box.remove(historyList.map(::HistoryEntity))
}
}

View File

@ -0,0 +1,56 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.database.newdb.dao
import io.objectbox.Box
import io.objectbox.kotlin.inValues
import io.objectbox.kotlin.query
import org.kiwix.kiwixmobile.database.newdb.entities.BookOnDiskEntity
import org.kiwix.kiwixmobile.database.newdb.entities.BookOnDiskEntity_
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity.Book
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
import java.util.ArrayList
import javax.inject.Inject
class NewBookDao @Inject constructor(private val box: Box<BookOnDiskEntity>) {
fun books() = box.asFlowable()
.map { it.map(::BookOnDisk) }
fun getBooks() = box.all.map(::BookOnDisk)
fun insert(booksOnDisk: List<BookOnDisk>) {
box.store.callInTx {
box
.query {
inValues(BookOnDiskEntity_.bookId, booksOnDisk.map { it.book.id }.toTypedArray())
}
.remove()
box.put(booksOnDisk.map(::BookOnDiskEntity))
}
}
fun delete(databaseId: Long) {
box.remove(databaseId)
}
fun migrationInsert(books: ArrayList<Book>) {
insert(books.map { BookOnDisk(book = it, file = it.file) })
}
}

View File

@ -0,0 +1,63 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.database.newdb.dao
import io.objectbox.Box
import io.objectbox.kotlin.query
import org.kiwix.kiwixmobile.bookmark.BookmarkItem
import org.kiwix.kiwixmobile.data.ZimContentProvider
import org.kiwix.kiwixmobile.database.newdb.entities.BookmarkEntity
import org.kiwix.kiwixmobile.database.newdb.entities.BookmarkEntity_
import javax.inject.Inject
class NewBookmarksDao @Inject constructor(val box: Box<BookmarkEntity>) {
fun getBookmarks(fromCurrentBook: Boolean): List<BookmarkItem> {
return box
.query {
if (fromCurrentBook) {
equal(BookmarkEntity_.zimId, ZimContentProvider.getId() ?: "")
}
order(BookmarkEntity_.bookmarkTitle)
}
.find()
.map { BookmarkItem(it) }
}
fun getCurrentZimBookmarksUrl() = box.query {
equal(BookmarkEntity_.zimId, ZimContentProvider.getId() ?: "")
.or()
.equal(BookmarkEntity_.zimName, ZimContentProvider.getName() ?: "")
order(BookmarkEntity_.bookmarkTitle)
}
.property(BookmarkEntity_.bookmarkUrl)
.findStrings()
.toList()
.distinct()
fun saveBookmark(bookmarkItem: BookmarkItem) {
box.put(BookmarkEntity(bookmarkItem))
}
fun deleteBookmarks(bookmarks: List<BookmarkItem>) {
box.remove(bookmarks.map(::BookmarkEntity))
}
fun deleteBookmark(bookmark: BookmarkItem) {
box.remove(BookmarkEntity(bookmark))
}
}

View File

@ -0,0 +1,42 @@
package org.kiwix.kiwixmobile.database.newdb.dao
import io.objectbox.Box
import io.objectbox.kotlin.inValues
import io.objectbox.kotlin.query
import org.kiwix.kiwixmobile.database.newdb.entities.DownloadEntity
import org.kiwix.kiwixmobile.database.newdb.entities.DownloadEntity_
import org.kiwix.kiwixmobile.downloader.model.DownloadModel
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity.Book
import javax.inject.Inject
class NewDownloadDao @Inject constructor(private val box: Box<DownloadEntity>) {
fun downloads() = box.asFlowable()
.map { it.map(DownloadEntity::toDownloadModel) }
fun delete(vararg downloadIds: Long) {
box
.query {
inValues(DownloadEntity_.downloadId, downloadIds)
}
.remove()
}
fun containsAny(vararg downloadIds: Long) =
box
.query {
inValues(DownloadEntity_.downloadId, downloadIds)
}
.count() > 0
fun doesNotAlreadyExist(book: Book) =
box
.query {
equal(DownloadEntity_.bookId, book.id)
}
.count() == 0L
fun insert(downloadModel: DownloadModel) {
box.put(DownloadEntity(downloadModel))
}
}

View File

@ -0,0 +1,42 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.database.newdb.dao
import io.objectbox.Box
import io.objectbox.kotlin.query
import io.objectbox.rx.RxQuery
import io.reactivex.BackpressureStrategy
import io.reactivex.BackpressureStrategy.LATEST
import org.kiwix.kiwixmobile.database.newdb.entities.LanguageEntity
import org.kiwix.kiwixmobile.zim_manager.Language
import javax.inject.Inject
class NewLanguagesDao @Inject constructor(private val box: Box<LanguageEntity>) {
fun languages() = box.asFlowable()
.map { it.map(LanguageEntity::toLanguageModel) }
fun insert(languages: List<Language>) {
box.store.callInTx {
box.removeAll()
box.put(languages.map(::LanguageEntity))
}
}
}
internal fun <T> Box<T>.asFlowable(backpressureStrategy: BackpressureStrategy = LATEST) =
RxQuery.observable(query {}).toFlowable(backpressureStrategy)

View File

@ -0,0 +1,57 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.database.newdb.dao
import io.objectbox.Box
import io.objectbox.kotlin.query
import org.kiwix.kiwixmobile.data.ZimContentProvider
import org.kiwix.kiwixmobile.database.newdb.entities.RecentSearchEntity
import org.kiwix.kiwixmobile.database.newdb.entities.RecentSearchEntity_
import javax.inject.Inject
class NewRecentSearchDao @Inject constructor(val box: Box<RecentSearchEntity>) {
fun getRecentSearches() = box
.query {
equal(RecentSearchEntity_.zimId, ZimContentProvider.getId() ?: "")
orderDesc(RecentSearchEntity_.id)
}
.find()
.distinctBy { it.searchTerm }
.take(NUM_RECENT_RESULTS)
.map { it.searchTerm }
fun saveSearch(title: String) {
box.put(RecentSearchEntity(title))
}
fun deleteSearchString(searchTerm: String) {
box
.query {
equal(RecentSearchEntity_.searchTerm, searchTerm)
}
.remove()
}
fun deleteSearchHistory() {
box.removeAll()
}
companion object {
const val NUM_RECENT_RESULTS = 5
}
}

View File

@ -0,0 +1,71 @@
package org.kiwix.kiwixmobile.database.newdb.entities
import io.objectbox.annotation.Convert
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import io.objectbox.converter.PropertyConverter
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.adapter.BooksOnDiskListItem.BookOnDisk
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity.Book
import java.io.File
@Entity
data class BookOnDiskEntity(
@Id var id: Long = 0,
@Convert(converter = StringToFileConverter::class, dbType = String::class)
val file: File = File(""),
val bookId: String,
val title: String,
val description: String,
val language: String,
val creator: String,
val publisher: String,
val date: String,
val url: String?,
val articleCount: String?,
val mediaCount: String?,
val size: String,
val name: String?,
val favIcon: String
) {
constructor(bookOnDisk: BookOnDisk) : this(
0,
bookOnDisk.file,
bookOnDisk.book.getId(),
bookOnDisk.book.getTitle(),
bookOnDisk.book.getDescription(),
bookOnDisk.book.getLanguage(),
bookOnDisk.book.getCreator(),
bookOnDisk.book.getPublisher(),
bookOnDisk.book.getDate(),
bookOnDisk.book.getUrl(),
bookOnDisk.book.getArticleCount(),
bookOnDisk.book.getMediaCount(),
bookOnDisk.book.getSize(),
bookOnDisk.book.getName(),
bookOnDisk.book.getFavicon()
)
fun toBook() = Book().apply {
id = this@BookOnDiskEntity.bookId
title = this@BookOnDiskEntity.title
description = this@BookOnDiskEntity.description
language = this@BookOnDiskEntity.language
creator = this@BookOnDiskEntity.creator
publisher = this@BookOnDiskEntity.publisher
date = this@BookOnDiskEntity.date
url = this@BookOnDiskEntity.url
articleCount = this@BookOnDiskEntity.articleCount
mediaCount = this@BookOnDiskEntity.mediaCount
size = this@BookOnDiskEntity.size
bookName = this@BookOnDiskEntity.name
favicon = this@BookOnDiskEntity.favIcon
}
}
class StringToFileConverter : PropertyConverter<File, String> {
override fun convertToDatabaseValue(entityProperty: File?) = entityProperty?.path ?: ""
override fun convertToEntityProperty(databaseValue: String?) = File(databaseValue ?: "")
}

View File

@ -0,0 +1,43 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.database.newdb.entities
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import org.kiwix.kiwixmobile.bookmark.BookmarkItem
@Entity
data class BookmarkEntity(
@Id var id: Long = 0,
val zimId: String,
var zimName: String,
var zimFilePath: String,
var bookmarkUrl: String,
var bookmarkTitle: String,
var favicon: String
) {
constructor(item: BookmarkItem) : this(
item.databaseId,
item.zimId,
item.zimName,
item.zimFilePath,
item.bookmarkUrl,
item.bookmarkTitle,
item.favicon
)
}

View File

@ -0,0 +1,78 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.database.newdb.entities
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import org.kiwix.kiwixmobile.downloader.model.DownloadModel
import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity.Book
@Entity
data class DownloadEntity(
@Id var id: Long = 0,
val downloadId: Long,
val bookId: String,
val title: String,
val description: String,
val language: String,
val creator: String,
val publisher: String,
val date: String,
val url: String?,
val articleCount: String?,
val mediaCount: String?,
val size: String,
val name: String?,
val favIcon: String
) {
constructor(downloadModel: DownloadModel) : this(
0,
downloadModel.downloadId,
downloadModel.book.getId(),
downloadModel.book.getTitle(),
downloadModel.book.getDescription(),
downloadModel.book.getLanguage(),
downloadModel.book.getCreator(),
downloadModel.book.getPublisher(),
downloadModel.book.getDate(),
downloadModel.book.getUrl(),
downloadModel.book.getArticleCount(),
downloadModel.book.getMediaCount(),
downloadModel.book.getSize(),
downloadModel.book.getName(),
downloadModel.book.getFavicon()
)
fun toDownloadModel() = DownloadModel(id, downloadId, toBook())
private fun toBook() = Book().apply {
id = this@DownloadEntity.bookId
title = this@DownloadEntity.title
description = this@DownloadEntity.description
language = this@DownloadEntity.language
creator = this@DownloadEntity.creator
publisher = this@DownloadEntity.publisher
date = this@DownloadEntity.date
url = this@DownloadEntity.url
articleCount = this@DownloadEntity.articleCount
mediaCount = this@DownloadEntity.mediaCount
size = this@DownloadEntity.size
bookName = this@DownloadEntity.name
favicon = this@DownloadEntity.favIcon
}
}

View File

@ -0,0 +1,48 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.database.newdb.entities
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import org.kiwix.kiwixmobile.history.HistoryListItem.HistoryItem
@Entity
data class HistoryEntity(
@Id var id: Long = 0L,
val zimId: String,
val zimName: String,
val zimFilePath: String,
val favicon: String,
val historyUrl: String,
val historyTitle: String,
val dateString: String,
val timeStamp: Long
) {
constructor(historyItem: HistoryItem) : this(
historyItem.databaseId,
historyItem.zimId,
historyItem.zimName,
historyItem.zimFilePath,
historyItem.favicon,
historyItem.historyUrl,
historyItem.historyTitle,
historyItem.dateString,
historyItem.timeStamp
)
}

View File

@ -0,0 +1,37 @@
package org.kiwix.kiwixmobile.database.newdb.entities
import io.objectbox.annotation.Convert
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import io.objectbox.converter.PropertyConverter
import org.kiwix.kiwixmobile.zim_manager.Language
import java.util.Locale
@Entity
data class LanguageEntity(
@Id var id: Long = 0,
@Convert(converter = StringToLocaleConverter::class, dbType = String::class)
val locale: Locale = Locale.ENGLISH,
val active: Boolean = false,
val occurencesOfLanguage: Int = 0
) {
constructor(language: Language) : this(
0,
Locale(language.languageCode),
language.active,
language.occurencesOfLanguage
)
fun toLanguageModel() =
Language(locale, active, occurencesOfLanguage)
}
class StringToLocaleConverter : PropertyConverter<Locale, String> {
override fun convertToDatabaseValue(entityProperty: Locale?) =
entityProperty?.isO3Language ?: Locale.ENGLISH.isO3Language
override fun convertToEntityProperty(databaseValue: String?) =
databaseValue?.let(::Locale) ?: Locale.ENGLISH
}

View File

@ -0,0 +1,34 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.database.newdb.entities
import io.objectbox.annotation.Entity
import io.objectbox.annotation.Id
import org.kiwix.kiwixmobile.data.ZimContentProvider
@Entity
data class RecentSearchEntity(
@Id var id: Long = 0L,
val searchTerm: String,
val zimId: String
) {
constructor(searchTerm: String) : this(
searchTerm = searchTerm,
zimId = ZimContentProvider.getId()
)
}

View File

@ -0,0 +1,34 @@
package org.kiwix.kiwixmobile.di;
import androidx.lifecycle.ViewModel;
import dagger.MapKey;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/*
* Kiwix Android
* Copyright (C) 2018 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/>.
*/
@Documented
@Target({ ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@MapKey
public @interface ViewModelKey {
Class<? extends ViewModel> value();
}

View File

@ -0,0 +1,43 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.di.components
import android.app.Activity
import dagger.BindsInstance
import dagger.Subcomponent
import org.kiwix.kiwixmobile.di.modules.ActivityModule
import org.kiwix.kiwixmobile.downloader.DownloadFragment
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.ZimFileSelectFragment
import org.kiwix.kiwixmobile.zim_manager.library_view.LibraryFragment
@Subcomponent(modules = [ActivityModule::class])
interface ActivityComponent {
fun inject(downloadFragment: DownloadFragment)
fun inject(libraryFragment: LibraryFragment)
fun inject(zimFileSelectFragment: ZimFileSelectFragment)
@Subcomponent.Builder
interface Builder {
@BindsInstance fun activity(activity: Activity): Builder
fun build(): ActivityComponent
}
}

View File

@ -17,22 +17,21 @@
*/
package org.kiwix.kiwixmobile.di.components;
import android.content.Context;
import dagger.BindsInstance;
import dagger.Component;
import javax.inject.Singleton;
import org.kiwix.kiwixmobile.KiwixApplication;
import org.kiwix.kiwixmobile.base.BaseFragment;
import org.kiwix.kiwixmobile.data.DataModule;
import org.kiwix.kiwixmobile.data.ZimContentProvider;
import org.kiwix.kiwixmobile.di.modules.ApplicationModule;
import org.kiwix.kiwixmobile.di.modules.JNIModule;
import org.kiwix.kiwixmobile.di.modules.NetworkModule;
import org.kiwix.kiwixmobile.downloader.DownloadService;
import org.kiwix.kiwixmobile.library.LibraryAdapter;
import org.kiwix.kiwixmobile.main.KiwixWebView;
import org.kiwix.kiwixmobile.search.AutoCompleteAdapter;
import org.kiwix.kiwixmobile.settings.KiwixSettingsActivity;
import org.kiwix.kiwixmobile.zim_manager.fileselect_view.ZimFileSelectFragment;
import org.kiwix.kiwixmobile.zim_manager.library_view.LibraryFragment;
import org.kiwix.kiwixmobile.zim_manager.DownloadNotificationClickedReceiver;
@Singleton
@Component(modules = {
@ -42,23 +41,28 @@ import org.kiwix.kiwixmobile.zim_manager.library_view.LibraryFragment;
DataModule.class
})
public interface ApplicationComponent {
@Component.Builder
interface Builder {
@BindsInstance Builder context(Context context);
ApplicationComponent build();
}
ActivityComponent.Builder activityComponent();
void inject(KiwixApplication application);
void inject(DownloadService service);
void inject(LibraryFragment libraryFragment);
void inject(BaseFragment baseFragment);
void inject(ZimFileSelectFragment zimFileSelectFragment);
void inject(ZimContentProvider zimContentProvider);
void inject(LibraryAdapter libraryAdapter);
void inject(KiwixWebView kiwixWebView);
void inject(KiwixSettingsActivity.PrefsFragment prefsFragment);
void inject(AutoCompleteAdapter autoCompleteAdapter);
void inject(DownloadNotificationClickedReceiver downloadNotificationClickedReceiver);
}

View File

@ -0,0 +1,29 @@
/*
* Kiwix Android
* Copyright (C) 2018 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.di.modules
import dagger.Binds
import dagger.Module
import org.kiwix.kiwixmobile.utils.AlertDialogShower
import org.kiwix.kiwixmobile.utils.DialogShower
@Module
abstract class ActivityModule {
@Binds
abstract fun bindDialogShower(alertDialogShower: AlertDialogShower): DialogShower
}

Some files were not shown because too many files have changed in this diff Show More