diff --git a/app/build.gradle b/app/build.gradle index 4121b731a..f7fbf6b5f 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -16,8 +16,10 @@ buildscript { apply plugin: 'com.android.application' apply plugin: 'kotlin-android' apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' apply plugin: 'checkstyle' apply plugin: 'testdroid' +apply plugin: 'io.objectbox' repositories { mavenCentral() @@ -29,7 +31,6 @@ repositories { } String[] archs = ['arm64-v8a', 'armeabi', 'mips', 'mips64', 'x86', 'x86_64'] - dependencies { // Get kiwixlib online if it is not populated locally @@ -79,14 +80,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' + kapt 'com.yahoo.squidb:squidb-processor:2.0.0' // Square implementation "com.squareup.okhttp3:okhttp:$okHttpVersion" @@ -102,7 +103,7 @@ dependencies { // Butterknife implementation 'com.jakewharton:butterknife:8.0.1' - annotationProcessor 'com.jakewharton:butterknife-compiler:8.0.1' + kapt 'com.jakewharton:butterknife-compiler:8.0.1' // RxJava implementation "io.reactivex.rxjava2:rxandroid:$rxAndroidVersion" @@ -133,6 +134,8 @@ dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation "android.arch.lifecycle:extensions:1.1.1" + implementation "io.objectbox:objectbox-kotlin:$objectboxVersion" + implementation "io.objectbox:objectbox-rxjava:$objectboxVersion" } // Set custom app import directory @@ -158,7 +161,7 @@ android { compileSdkVersion 27 defaultConfig { - minSdkVersion 14 + minSdkVersion 15 targetSdkVersion 27 testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" // See https://github.com/linkedin/dexmaker/issues/65 for why we need the following line. diff --git a/app/objectbox-models/default.json b/app/objectbox-models/default.json new file mode 100644 index 000000000..8eb30689a --- /dev/null +++ b/app/objectbox-models/default.json @@ -0,0 +1,203 @@ +{ + "_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": [] + } + ], + "lastEntityId": "4:6278838675135543734", + "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 + ], + "retiredRelationUids": [], + "version": 1 +} \ No newline at end of file diff --git a/app/objectbox-models/default.json.bak b/app/objectbox-models/default.json.bak new file mode 100644 index 000000000..5965b46c7 --- /dev/null +++ b/app/objectbox-models/default.json.bak @@ -0,0 +1,179 @@ +{ + "_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": [] + } + ], + "lastEntityId": "3:5536749840871435068", + "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 + ], + "retiredRelationUids": [], + "version": 1 +} \ No newline at end of file diff --git a/app/src/main/java/org/kiwix/kiwixmobile/KiwixErrorActivity.java b/app/src/main/java/org/kiwix/kiwixmobile/KiwixErrorActivity.java index 11585e807..6d0714514 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/KiwixErrorActivity.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/KiwixErrorActivity.java @@ -15,7 +15,7 @@ import java.io.File; import java.util.List; import javax.inject.Inject; import org.kiwix.kiwixmobile.base.BaseActivity; -import org.kiwix.kiwixmobile.database.BookDao; +import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao; import org.kiwix.kiwixmobile.downloader.model.BookOnDisk; import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity; import org.kiwix.kiwixmobile.utils.SplashActivity; @@ -25,7 +25,7 @@ import static org.kiwix.kiwixmobile.utils.LanguageUtils.getCurrentLocale; public class KiwixErrorActivity extends BaseActivity { @Inject - BookDao bookDao; + NewBookDao bookDao; @BindView(R.id.reportButton) Button reportButton; diff --git a/app/src/main/java/org/kiwix/kiwixmobile/database/DownloadDao.java b/app/src/main/java/org/kiwix/kiwixmobile/database/DownloadDao.java deleted file mode 100644 index e16eb5233..000000000 --- a/app/src/main/java/org/kiwix/kiwixmobile/database/DownloadDao.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Kiwix Android - * Copyright (C) 2018 Kiwix - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.kiwix.kiwixmobile.database; - -import com.yahoo.squidb.data.SquidCursor; -import com.yahoo.squidb.data.TableModel; -import com.yahoo.squidb.sql.Query; -import com.yahoo.squidb.sql.TableStatement; -import io.reactivex.Flowable; -import io.reactivex.processors.BehaviorProcessor; -import java.util.ArrayList; -import java.util.List; -import javax.inject.Inject; -import org.jetbrains.annotations.NotNull; -import org.kiwix.kiwixmobile.database.entity.DownloadDatabaseEntity; -import org.kiwix.kiwixmobile.downloader.model.DownloadModel; -import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity; - -public class DownloadDao extends BaseDao { - - private final BehaviorProcessor> downloadsProcessor = - BehaviorProcessor.create(); - - @Inject - public DownloadDao(KiwixDatabase kiwixDatabase) { - super(kiwixDatabase, DownloadDatabaseEntity.TABLE); - } - - @Override - protected void onUpdateToTable() { - downloadsProcessor.onNext(getDownloads()); - } - - public void insert(final DownloadModel downloadModel) { - kiwixDatabase.persistWithOnConflict(databaseEntity(downloadModel), - TableStatement.ConflictAlgorithm.REPLACE); - } - - public boolean doesNotAlreadyExist(LibraryNetworkEntity.Book book) { - return kiwixDatabase.count( - DownloadDatabaseEntity.class, - DownloadDatabaseEntity.BOOK_ID.eq(book.getId()) - ) == 0; - } - - public boolean containsAny(@NotNull Long[] downloadIds) { - return kiwixDatabase.count( - DownloadDatabaseEntity.class, - DownloadDatabaseEntity.DOWNLOAD_ID.in((Object[]) downloadIds) - ) > 0; - } - - public void delete(@NotNull Long... downloadIds) { - if (downloadIds.length > 0) { - kiwixDatabase.deleteWhere(DownloadDatabaseEntity.class, - DownloadDatabaseEntity.DOWNLOAD_ID.in((Object[]) downloadIds)); - } - } - - public Flowable> downloads() { - return downloadsProcessor; - } - - private TableModel databaseEntity(final DownloadModel downloadModel) { - final LibraryNetworkEntity.Book book = downloadModel.getBook(); - return new DownloadDatabaseEntity() - .setDownloadId(downloadModel.getDownloadId()) - .setBookId(book.getId()) - .setTitle(book.getTitle()) - .setDescription(book.getDescription()) - .setLanguage(book.getLanguage()) - .setBookCreator(book.getCreator()) - .setPublisher(book.getPublisher()) - .setDate(book.getDate()) - .setUrl(book.getUrl()) - .setArticleCount(book.getArticleCount()) - .setMediaCount(book.getMediaCount()) - .setSize(book.getSize()) - .setName(book.getName()) - .setFavIcon(book.getFavicon()); - } - - public List getDownloads() { - return toList(kiwixDatabase.query(DownloadDatabaseEntity.class, Query.select())); - } - - private List toList(final SquidCursor cursor) { - final ArrayList downloadModels = new ArrayList<>(); - final DownloadDatabaseEntity downloadDatabaseEntity = new DownloadDatabaseEntity(); - while (cursor.moveToNext()) { - downloadDatabaseEntity.readPropertiesFromCursor(cursor); - downloadModels.add(new DownloadModel( - downloadDatabaseEntity.getDownloadId(), - toBook(downloadDatabaseEntity) - )); - } - cursor.close(); - return downloadModels; - } - - private LibraryNetworkEntity.Book toBook(DownloadDatabaseEntity downloadDatabaseEntity) { - final LibraryNetworkEntity.Book book = new LibraryNetworkEntity.Book(); - book.id = downloadDatabaseEntity.getBookId(); - book.title = downloadDatabaseEntity.getTitle(); - book.description = downloadDatabaseEntity.getDescription(); - book.language = downloadDatabaseEntity.getLanguage(); - book.creator = downloadDatabaseEntity.getBookCreator(); - book.publisher = downloadDatabaseEntity.getPublisher(); - book.date = downloadDatabaseEntity.getDate(); - book.url = downloadDatabaseEntity.getUrl(); - book.articleCount = downloadDatabaseEntity.getArticleCount(); - book.mediaCount = downloadDatabaseEntity.getMediaCount(); - book.size = downloadDatabaseEntity.getSize(); - book.bookName = downloadDatabaseEntity.getName(); - book.favicon = downloadDatabaseEntity.getFavIcon(); - return book; - } -} diff --git a/app/src/main/java/org/kiwix/kiwixmobile/database/KiwixDatabase.java b/app/src/main/java/org/kiwix/kiwixmobile/database/KiwixDatabase.java index 57d07b45f..159b505cb 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/database/KiwixDatabase.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/database/KiwixDatabase.java @@ -34,7 +34,6 @@ import javax.inject.Singleton; import org.kiwix.kiwixmobile.ZimContentProvider; import org.kiwix.kiwixmobile.database.entity.BookDatabaseEntity; import org.kiwix.kiwixmobile.database.entity.Bookmarks; -import org.kiwix.kiwixmobile.database.entity.DownloadDatabaseEntity; import org.kiwix.kiwixmobile.database.entity.LibraryDatabaseEntity; import org.kiwix.kiwixmobile.database.entity.NetworkLanguageDatabaseEntity; import org.kiwix.kiwixmobile.database.entity.RecentSearch; @@ -67,7 +66,6 @@ public class KiwixDatabase extends SquidDatabase { RecentSearch.TABLE, Bookmarks.TABLE, NetworkLanguageDatabaseEntity.TABLE, - DownloadDatabaseEntity.TABLE }; } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/database/entity/DownloadsSpec.java b/app/src/main/java/org/kiwix/kiwixmobile/database/entity/DownloadsSpec.java deleted file mode 100644 index 1914024e2..000000000 --- a/app/src/main/java/org/kiwix/kiwixmobile/database/entity/DownloadsSpec.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Kiwix Android - * Copyright (C) 2018 Kiwix - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package org.kiwix.kiwixmobile.database.entity; - -import com.yahoo.squidb.annotations.TableModelSpec; - -@TableModelSpec(className = "DownloadDatabaseEntity", tableName = "downloads") -public class DownloadsSpec { - public Long downloadId; - public String bookId; - public String favIcon; - public String title; - public String description; - public String language; - public String bookCreator; - public String publisher; - public String date; - public String url; - public String articleCount; - public String mediaCount; - public String size; - public String name; -} diff --git a/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/dao/NewBookDao.kt b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/dao/NewBookDao.kt new file mode 100644 index 000000000..55b4a3d1c --- /dev/null +++ b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/dao/NewBookDao.kt @@ -0,0 +1,50 @@ +/* + * Kiwix Android + * Copyright (C) 2018 Kiwix + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.kiwix.kiwixmobile.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.downloader.model.BookOnDisk +import javax.inject.Inject + +class NewBookDao @Inject constructor(private val box: Box) { + + fun books() = box.asFlowable() + .map { it.map(::BookOnDisk) } + + fun getBooks() = box.all.map(::BookOnDisk) + + fun insert(booksOnDisk: List) { + 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) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/dao/NewDownloadDao.kt b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/dao/NewDownloadDao.kt new file mode 100644 index 000000000..66628c0d8 --- /dev/null +++ b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/dao/NewDownloadDao.kt @@ -0,0 +1,45 @@ +package org.kiwix.kiwixmobile.database.newdb.dao + +import android.util.Log +import io.objectbox.Box +import io.objectbox.kotlin.inValues +import io.objectbox.kotlin.query +import io.objectbox.rx.RxQuery +import io.reactivex.BackpressureStrategy.LATEST +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) { + + 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)) + } +} \ No newline at end of file diff --git a/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/dao/NewLanguagesDao.kt b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/dao/NewLanguagesDao.kt new file mode 100644 index 000000000..9b784fec9 --- /dev/null +++ b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/dao/NewLanguagesDao.kt @@ -0,0 +1,43 @@ +/* + * Kiwix Android + * Copyright (C) 2018 Kiwix + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.kiwix.kiwixmobile.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.library_view.adapter.Language +import javax.inject.Inject + +class NewLanguagesDao @Inject constructor(private val box: Box) { + fun languages() = box.asFlowable() + .map { it.map(LanguageEntity::toLanguageModel) } + + fun insert(languages: List) { + box.store.callInTx { + box.removeAll() + box.put(languages.map(::LanguageEntity)) + } + } + +} + +internal fun Box.asFlowable(backpressureStrategy: BackpressureStrategy = LATEST) = + RxQuery.observable(query {}).toFlowable(backpressureStrategy) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/entities/BookOnDiskEntity.kt b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/entities/BookOnDiskEntity.kt new file mode 100644 index 000000000..f09fa9d71 --- /dev/null +++ b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/entities/BookOnDiskEntity.kt @@ -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.downloader.model.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 { + override fun convertToDatabaseValue(entityProperty: File?) = entityProperty?.path ?: "" + + override fun convertToEntityProperty(databaseValue: String?) = File(databaseValue ?: "") + +} diff --git a/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/entities/DownloadEntity.kt b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/entities/DownloadEntity.kt new file mode 100644 index 000000000..ce8f0166e --- /dev/null +++ b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/entities/DownloadEntity.kt @@ -0,0 +1,78 @@ +/* + * Kiwix Android + * Copyright (C) 2018 Kiwix + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.kiwix.kiwixmobile.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 + } +} \ No newline at end of file diff --git a/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/entities/LanguageEntity.kt b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/entities/LanguageEntity.kt new file mode 100644 index 000000000..e6b34bf8b --- /dev/null +++ b/app/src/main/java/org/kiwix/kiwixmobile/database/newdb/entities/LanguageEntity.kt @@ -0,0 +1,36 @@ +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.library_view.adapter.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, + var active: Boolean = false, + var occurencesOfLanguage: Int = 0 +) { + + constructor(language: Language) : this( + 0, + Locale(language.languageCode), + language.active, + language.occurencesOfLanguage + ) + + fun toLanguageModel() = Language(locale, active, occurencesOfLanguage) +} + +class StringToLocaleConverter : PropertyConverter { + override fun convertToDatabaseValue(entityProperty: Locale?) = + entityProperty?.isO3Language ?: Locale.ENGLISH.isO3Language + + override fun convertToEntityProperty(databaseValue: String?) = + databaseValue?.let(::Locale) ?: Locale.ENGLISH + +} diff --git a/app/src/main/java/org/kiwix/kiwixmobile/di/modules/ApplicationModule.java b/app/src/main/java/org/kiwix/kiwixmobile/di/modules/ApplicationModule.java index 14acf2c98..794afc49b 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/di/modules/ApplicationModule.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/di/modules/ApplicationModule.java @@ -28,8 +28,11 @@ import javax.inject.Singleton; import org.kiwix.kiwixmobile.utils.BookUtils; @Module(includes = { - ActivityBindingModule.class, AndroidInjectionModule.class, DownloaderModule.class, - ViewModelModule.class + ActivityBindingModule.class, + AndroidInjectionModule.class, + DownloaderModule.class, + ViewModelModule.class, + DatabaseModule.class }) public class ApplicationModule { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/di/modules/DatabaseModule.kt b/app/src/main/java/org/kiwix/kiwixmobile/di/modules/DatabaseModule.kt new file mode 100644 index 000000000..70cbb398a --- /dev/null +++ b/app/src/main/java/org/kiwix/kiwixmobile/di/modules/DatabaseModule.kt @@ -0,0 +1,44 @@ +/* + * Kiwix Android + * Copyright (C) 2018 Kiwix + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package org.kiwix.kiwixmobile.di.modules + +import android.content.Context +import dagger.Module +import dagger.Provides +import io.objectbox.BoxStore +import io.objectbox.kotlin.boxFor +import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao +import org.kiwix.kiwixmobile.database.newdb.dao.NewDownloadDao +import org.kiwix.kiwixmobile.database.newdb.dao.NewLanguagesDao +import org.kiwix.kiwixmobile.database.newdb.entities.MyObjectBox +import javax.inject.Singleton + +@Module +class DatabaseModule { + @Provides @Singleton fun providesBoxStore(context: Context): BoxStore = + MyObjectBox.builder().androidContext(context.applicationContext).build() + + @Provides @Singleton fun providesNewDownloadDao(boxStore: BoxStore): NewDownloadDao = + NewDownloadDao(boxStore.boxFor()) + + @Provides @Singleton fun providesNewBookDao(boxStore: BoxStore): NewBookDao = + NewBookDao(boxStore.boxFor()) + + @Provides @Singleton fun providesNewLanguagesDao(boxStore: BoxStore): NewLanguagesDao = + NewLanguagesDao(boxStore.boxFor()) +} \ No newline at end of file diff --git a/app/src/main/java/org/kiwix/kiwixmobile/di/modules/NetworkModule.java b/app/src/main/java/org/kiwix/kiwixmobile/di/modules/NetworkModule.java index 62e831ba8..8e49fc995 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/di/modules/NetworkModule.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/di/modules/NetworkModule.java @@ -19,18 +19,16 @@ package org.kiwix.kiwixmobile.di.modules; import android.content.Context; import android.net.ConnectivityManager; - +import dagger.Module; +import dagger.Provides; +import java.util.concurrent.TimeUnit; +import javax.inject.Singleton; +import okhttp3.OkHttpClient; +import okhttp3.logging.HttpLoggingInterceptor; import org.kiwix.kiwixmobile.BuildConfig; import org.kiwix.kiwixmobile.network.KiwixService; import org.kiwix.kiwixmobile.network.UserAgentInterceptor; -import javax.inject.Singleton; - -import dagger.Module; -import dagger.Provides; -import okhttp3.OkHttpClient; -import okhttp3.logging.HttpLoggingInterceptor; - @Module public class NetworkModule { public static String KIWIX_DOWNLOAD_URL = BuildConfig.KIWIX_DOWNLOAD_URL; //"http://download.kiwix.org/"; @@ -41,6 +39,8 @@ import okhttp3.logging.HttpLoggingInterceptor; logging.setLevel(HttpLoggingInterceptor.Level.BASIC); return new OkHttpClient().newBuilder().followRedirects(true).followSslRedirects(true) + .connectTimeout(10, TimeUnit.SECONDS) + .readTimeout(10, TimeUnit.SECONDS) .addNetworkInterceptor(logging) .addNetworkInterceptor(new UserAgentInterceptor(useragent)).build(); } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/downloader/DownloadService.java b/app/src/main/java/org/kiwix/kiwixmobile/downloader/DownloadService.java index fcf2ea9d6..e3f91e271 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/downloader/DownloadService.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/downloader/DownloadService.java @@ -52,7 +52,7 @@ import okio.BufferedSource; import org.kiwix.kiwixmobile.KiwixApplication; import org.kiwix.kiwixmobile.KiwixMobileActivity; import org.kiwix.kiwixmobile.R; -import org.kiwix.kiwixmobile.database.BookDao; +import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao; import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity; import org.kiwix.kiwixmobile.network.KiwixService; import org.kiwix.kiwixmobile.utils.Constants; @@ -106,7 +106,7 @@ public class DownloadService extends Service { SharedPreferenceUtil sharedPreferenceUtil; @Inject - BookDao bookDao; + NewBookDao bookDao; public static void setDownloadFragment(DownloadFragment dFragment) { downloadFragment = dFragment; diff --git a/app/src/main/java/org/kiwix/kiwixmobile/downloader/DownloaderImpl.kt b/app/src/main/java/org/kiwix/kiwixmobile/downloader/DownloaderImpl.kt index 165fac5ca..0ba4c5a25 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/downloader/DownloaderImpl.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/downloader/DownloaderImpl.kt @@ -18,8 +18,7 @@ package org.kiwix.kiwixmobile.downloader -import io.reactivex.schedulers.Schedulers -import org.kiwix.kiwixmobile.database.DownloadDao +import org.kiwix.kiwixmobile.database.newdb.dao.NewDownloadDao import org.kiwix.kiwixmobile.downloader.model.DownloadItem import org.kiwix.kiwixmobile.downloader.model.DownloadModel import org.kiwix.kiwixmobile.downloader.model.DownloadRequest @@ -29,14 +28,12 @@ import javax.inject.Inject class DownloaderImpl @Inject constructor( private val downloadRequester: DownloadRequester, - private val downloadDao: DownloadDao, + private val downloadDao: NewDownloadDao, private val kiwixService: KiwixService ) : Downloader { override fun download(book: LibraryNetworkEntity.Book) { kiwixService.getMetaLinks(book.url) - .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.io()) .take(1) .subscribe( { @@ -45,7 +42,7 @@ class DownloaderImpl @Inject constructor( DownloadRequest(it, book) ) downloadDao.insert( - DownloadModel(downloadId, book) + DownloadModel(downloadId = downloadId, book = book) ) } }, diff --git a/app/src/main/java/org/kiwix/kiwixmobile/downloader/model/BookOnDisk.kt b/app/src/main/java/org/kiwix/kiwixmobile/downloader/model/BookOnDisk.kt index b511ddc16..a5076d04a 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/downloader/model/BookOnDisk.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/downloader/model/BookOnDisk.kt @@ -1,5 +1,6 @@ package org.kiwix.kiwixmobile.downloader.model +import org.kiwix.kiwixmobile.database.newdb.entities.BookOnDiskEntity import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity.Book import java.io.File @@ -7,4 +8,10 @@ data class BookOnDisk( val databaseId: Long? = null, val book: Book, val file: File -) +) { + constructor(bookOnDiskEntity: BookOnDiskEntity) : this( + bookOnDiskEntity.id, + bookOnDiskEntity.toBook(), + bookOnDiskEntity.file + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/kiwix/kiwixmobile/downloader/model/DownloadModel.kt b/app/src/main/java/org/kiwix/kiwixmobile/downloader/model/DownloadModel.kt index 64fdad581..8fdc34594 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/downloader/model/DownloadModel.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/downloader/model/DownloadModel.kt @@ -17,9 +17,12 @@ */ package org.kiwix.kiwixmobile.downloader.model +import android.view.WindowId +import org.kiwix.kiwixmobile.database.newdb.entities.DownloadEntity import org.kiwix.kiwixmobile.library.entity.LibraryNetworkEntity data class DownloadModel( + val databaseId: Long? = null, val downloadId: Long, val book: LibraryNetworkEntity.Book ) diff --git a/app/src/main/java/org/kiwix/kiwixmobile/utils/NetworkUtils.java b/app/src/main/java/org/kiwix/kiwixmobile/utils/NetworkUtils.java index f0c822635..e72e8d307 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/utils/NetworkUtils.java +++ b/app/src/main/java/org/kiwix/kiwixmobile/utils/NetworkUtils.java @@ -22,10 +22,8 @@ import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Build; import android.util.Log; - -import org.kiwix.kiwixmobile.R; - import java.util.UUID; +import org.kiwix.kiwixmobile.R; import static org.kiwix.kiwixmobile.utils.Constants.TAG_KIWIX; @@ -86,9 +84,11 @@ public class NetworkUtils { } public static String parseURL(Context context, String url) { - String details; + if (url == null) { + return ""; + } try { - details = url.substring(url.lastIndexOf("/") + 1); + String details = url.substring(url.lastIndexOf("/") + 1); int beginIndex = details.indexOf("_", details.indexOf("_") + 1) + 1; int endIndex = details.lastIndexOf("_"); if (beginIndex < 0 || endIndex > details.length() || beginIndex > endIndex) { diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/DownloadNotificationClickedReceiver.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/DownloadNotificationClickedReceiver.kt index 8473ea36d..40c937a6c 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/DownloadNotificationClickedReceiver.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/DownloadNotificationClickedReceiver.kt @@ -20,14 +20,15 @@ package org.kiwix.kiwixmobile.zim_manager import android.app.DownloadManager import android.content.Context import android.content.Intent +import android.os.Bundle import org.kiwix.kiwixmobile.KiwixApplication -import org.kiwix.kiwixmobile.database.DownloadDao +import org.kiwix.kiwixmobile.database.newdb.dao.NewDownloadDao import javax.inject.Inject class DownloadNotificationClickedReceiver : BaseBroadcastReceiver() { override val action: String = DownloadManager.ACTION_NOTIFICATION_CLICKED - @Inject lateinit var downloadDao: DownloadDao + @Inject lateinit var downloadDao: NewDownloadDao override fun onIntentWithActionReceived( context: Context, @@ -35,10 +36,7 @@ class DownloadNotificationClickedReceiver : BaseBroadcastReceiver() { ) { KiwixApplication.getApplicationComponent() .inject(this) - val longArray = - intent.extras?.getLongArray(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS) - ?: longArrayOf() - if (downloadDao.containsAny(longArray.toTypedArray())) { + if (downloadDao.containsAny(*longArrayFrom(intent.extras))) { context.startActivity( Intent(context, ZimManageActivity::class.java).apply { addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) @@ -47,4 +45,7 @@ class DownloadNotificationClickedReceiver : BaseBroadcastReceiver() { ) } } + + private fun longArrayFrom(extras: Bundle?) = + extras?.getLongArray(DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS) ?: longArrayOf() } diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageActivity.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageActivity.kt index abcf39e97..ce3eef4f2 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageActivity.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageActivity.kt @@ -41,7 +41,7 @@ import org.kiwix.kiwixmobile.R.layout import org.kiwix.kiwixmobile.R.string import org.kiwix.kiwixmobile.R.style import org.kiwix.kiwixmobile.base.BaseActivity -import org.kiwix.kiwixmobile.database.NetworkLanguageDao +import org.kiwix.kiwixmobile.database.newdb.dao.NewLanguagesDao import org.kiwix.kiwixmobile.extensions.toast import org.kiwix.kiwixmobile.settings.KiwixSettingsActivity import org.kiwix.kiwixmobile.utils.Constants.TAG_KIWIX @@ -68,7 +68,7 @@ class ZimManageActivity : BaseActivity() { @Inject lateinit var viewModelFactory: ViewModelProvider.Factory @Inject lateinit var sharedPreferenceUtil: SharedPreferenceUtil - @Inject lateinit var languagesDao: NetworkLanguageDao + @Inject lateinit var languagesDao: NewLanguagesDao override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -111,7 +111,7 @@ class ZimManageActivity : BaseActivity() { .apply { onOkClicked = { Flowable.fromCallable { - languagesDao.saveFilteredLanguages(it) + languagesDao.insert(it) } .subscribeOn(Schedulers.io()) .subscribe() diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageViewModel.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageViewModel.kt index e6f6dd649..1b4f6d776 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageViewModel.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/ZimManageViewModel.kt @@ -21,6 +21,7 @@ package org.kiwix.kiwixmobile.zim_manager import android.app.Application import android.arch.lifecycle.MutableLiveData import android.arch.lifecycle.ViewModel +import android.util.Log import io.reactivex.Flowable import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.Disposable @@ -30,9 +31,9 @@ import io.reactivex.processors.BehaviorProcessor import io.reactivex.processors.PublishProcessor import io.reactivex.schedulers.Schedulers import org.kiwix.kiwixmobile.R -import org.kiwix.kiwixmobile.database.BookDao -import org.kiwix.kiwixmobile.database.DownloadDao -import org.kiwix.kiwixmobile.database.NetworkLanguageDao +import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao +import org.kiwix.kiwixmobile.database.newdb.dao.NewDownloadDao +import org.kiwix.kiwixmobile.database.newdb.dao.NewLanguagesDao import org.kiwix.kiwixmobile.downloader.Downloader import org.kiwix.kiwixmobile.downloader.model.BookOnDisk import org.kiwix.kiwixmobile.downloader.model.DownloadItem @@ -62,9 +63,9 @@ import java.util.concurrent.TimeUnit.SECONDS import javax.inject.Inject class ZimManageViewModel @Inject constructor( - private val downloadDao: DownloadDao, - private val bookDao: BookDao, - private val languageDao: NetworkLanguageDao, + private val downloadDao: NewDownloadDao, + private val bookDao: NewBookDao, + private val languageDao: NewLanguagesDao, private val downloader: Downloader, private val storageObserver: StorageObserver, private val kiwixService: KiwixService, @@ -101,7 +102,7 @@ class ZimManageViewModel @Inject constructor( } private fun disposables(): Array { - val downloads: Flowable> = downloadDao.downloads() + val downloads = downloadDao.downloads() val downloadStatuses = downloadStatuses(downloads) val booksFromDao = books() val networkLibrary = PublishProcessor.create() @@ -131,20 +132,23 @@ class ZimManageViewModel @Inject constructor( .observeOn(Schedulers.io()) .subscribe( { - kiwixService.library.subscribe( - { library.onNext(it) }, - { - it.printStackTrace() - library.onNext(LibraryNetworkEntity().apply { book = LinkedList() }) - } - ) + kiwixService.library + .timeout(10, SECONDS) + .retry(5) + .subscribe( + { library.onNext(it) }, + { + it.printStackTrace() + library.onNext(LibraryNetworkEntity().apply { book = LinkedList() }) + } + ) }, Throwable::printStackTrace ) private fun removeNonExistingDownloadsFromDb( downloadStatuses: Flowable>, - downloads: Flowable> + downloads: Flowable> ) = downloadStatuses .withLatestFrom( downloads, @@ -154,17 +158,16 @@ class ZimManageViewModel @Inject constructor( .map(this::downloadIdsWithNoStatusesOverBufferPeriod) .subscribe( { - downloadDao.delete(*it.toTypedArray()) + downloadDao.delete(*it.toLongArray()) }, Throwable::printStackTrace ) - private fun downloadIdsWithNoStatusesOverBufferPeriod(it: List>) = - it.flatten() - .fold(mutableMapOf(), - { acc, id -> acc.increment(id) }) - .filter { (_, value) -> value == it.size } - .map { (key, _) -> key } + private fun downloadIdsWithNoStatusesOverBufferPeriod(noStatusIds: List>) = + noStatusIds.flatten() + .fold(mutableMapOf(), { acc, id -> acc.increment(id) }) + .filter { (_, count) -> count == noStatusIds.size } + .map { (id, _) -> id } private fun combineToDownloadsWithoutStatuses( statuses: List, @@ -183,7 +186,7 @@ class ZimManageViewModel @Inject constructor( } private fun updateLanguageItemsForDialog() = requestLanguagesDialog - .withLatestFrom(languageDao.allLanguages(), + .withLatestFrom(languageDao.languages(), BiFunction, List> { _, languages -> languages }) .subscribe( languageItems::postValue, @@ -197,12 +200,12 @@ class ZimManageViewModel @Inject constructor( private fun updateLibraryItems( booksFromDao: Flowable>, - downloads: Flowable>, + downloads: Flowable>, library: Flowable ) = Flowable.combineLatest( booksFromDao, downloads, - languageDao.allLanguages().filter { it.isNotEmpty() }, + languageDao.languages().filter { it.isNotEmpty() }, library, requestFiltering .doOnNext { libraryListIsRefreshing.postValue(true) } @@ -224,12 +227,12 @@ class ZimManageViewModel @Inject constructor( .subscribeOn(Schedulers.io()) .map { it.books } .withLatestFrom( - languageDao.allLanguages(), + languageDao.languages(), BiFunction(this::combineToLanguageList) ) .map { it.sortedBy(Language::language) } .subscribe( - languageDao::saveFilteredLanguages, + languageDao::insert, Throwable::printStackTrace ) @@ -334,14 +337,13 @@ class ZimManageViewModel @Inject constructor( books: List, sectionStringId: Int, sectionId: Long - ) = if (books.isNotEmpty()) { - arrayOf( - DividerItem(sectionId, context.getString(sectionStringId)), - *toBookItems(books) - ) - } else { - emptyArray() - } + ) = + if (books.isNotEmpty()) + arrayOf( + DividerItem(sectionId, context.getString(sectionStringId)), + *toBookItems(books) + ) + else emptyArray() private fun applyUserFilter( booksUnfilteredByLanguage: List, @@ -370,8 +372,9 @@ class ZimManageViewModel @Inject constructor( ) .onBackpressureDrop() .doOnNext { deviceListIsRefreshing.postValue(false) } + .filter { it.isNotEmpty() } .subscribe( - bookDao::saveBooks, + bookDao::insert, Throwable::printStackTrace ) @@ -405,11 +408,12 @@ class ZimManageViewModel @Inject constructor( .observeOn(Schedulers.io()) .subscribeOn(Schedulers.io()) .map { it.filter { status -> status.state == Successful } } + .filter { it.isNotEmpty() } .subscribe( { - bookDao.saveBooks(it.map { downloadStatus -> downloadStatus.toBookOnDisk() }) + bookDao.insert(it.map { downloadStatus -> downloadStatus.toBookOnDisk() }) downloadDao.delete( - *it.map { status -> status.downloadId }.toTypedArray() + *it.map { status -> status.downloadId }.toLongArray() ) }, Throwable::printStackTrace @@ -423,7 +427,7 @@ class ZimManageViewModel @Inject constructor( Throwable::printStackTrace ) - private fun downloadStatuses(downloads: Flowable>) = + private fun downloadStatuses(downloads: Flowable>) = Flowable.combineLatest( downloads, Flowable.interval(1, SECONDS), diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/StorageObserver.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/StorageObserver.kt index 4098254d1..9fd69e5c8 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/StorageObserver.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/StorageObserver.kt @@ -3,7 +3,8 @@ package org.kiwix.kiwixmobile.zim_manager.fileselect_view import android.content.Context import android.util.Log import io.reactivex.processors.PublishProcessor -import org.kiwix.kiwixmobile.database.DownloadDao +import io.reactivex.schedulers.Schedulers +import org.kiwix.kiwixmobile.database.newdb.dao.NewDownloadDao import org.kiwix.kiwixmobile.downloader.model.BookOnDisk import org.kiwix.kiwixmobile.downloader.model.DownloadModel import org.kiwix.kiwixmobile.utils.SharedPreferenceUtil @@ -14,14 +15,19 @@ import javax.inject.Inject class StorageObserver @Inject constructor( private val context: Context, private val sharedPreferenceUtil: SharedPreferenceUtil, - private val downloadDao: DownloadDao + private val downloadDao: NewDownloadDao ) { private val _booksOnFileSystem = PublishProcessor.create>() val booksOnFileSystem = _booksOnFileSystem.distinctUntilChanged() - .doOnSubscribe { scanFiles(downloadDao.downloads) } + .doOnSubscribe { + downloadDao.downloads() + .subscribeOn(Schedulers.io()) + .take(1) + .subscribe(this::scanFiles, Throwable::printStackTrace) + } - private fun scanFiles(downloads: MutableList) { + private fun scanFiles(downloads: List) { FileSearch(context, downloads, object : ResultListener { val foundBooks = mutableSetOf() diff --git a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/ZimFileSelectFragment.kt b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/ZimFileSelectFragment.kt index ad0e4a76c..b400f9078 100644 --- a/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/ZimFileSelectFragment.kt +++ b/app/src/main/java/org/kiwix/kiwixmobile/zim_manager/fileselect_view/ZimFileSelectFragment.kt @@ -38,7 +38,7 @@ import org.kiwix.kiwixmobile.R import org.kiwix.kiwixmobile.R.string import org.kiwix.kiwixmobile.ZimContentProvider import org.kiwix.kiwixmobile.base.BaseFragment -import org.kiwix.kiwixmobile.database.BookDao +import org.kiwix.kiwixmobile.database.newdb.dao.NewBookDao import org.kiwix.kiwixmobile.di.components.ActivityComponent import org.kiwix.kiwixmobile.downloader.model.BookOnDisk import org.kiwix.kiwixmobile.extensions.toast @@ -56,7 +56,7 @@ import javax.inject.Inject class ZimFileSelectFragment : BaseFragment() { @Inject lateinit var sharedPreferenceUtil: SharedPreferenceUtil - @Inject lateinit var bookDao: BookDao + @Inject lateinit var bookDao: NewBookDao @Inject lateinit var dialogShower: DialogShower @Inject lateinit var viewModelFactory: ViewModelProvider.Factory @Inject lateinit var bookUtils: BookUtils @@ -161,7 +161,7 @@ class ZimFileSelectFragment : BaseFragment() { if (file.exists()) { return false } - bookDao.deleteBook(book.databaseId) + bookDao.delete(book.databaseId!!) return true } } \ No newline at end of file diff --git a/build.gradle b/build.gradle index a47c7722e..a7e867e97 100644 --- a/build.gradle +++ b/build.gradle @@ -1,12 +1,14 @@ buildscript { ext.kotlin_version = '1.3.31' + ext.objectboxVersion = '2.3.4' repositories { jcenter() google() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0' + classpath 'com.android.tools.build:gradle:3.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "io.objectbox:objectbox-gradle-plugin:$objectboxVersion" // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files