Merge changes.

Various changes.
This commit is contained in:
NerdNumber9 2016-10-18 21:58:00 -04:00
parent 3cafbd9141
commit 15b2bbc6d1
26 changed files with 169 additions and 215 deletions

View File

@ -0,0 +1,9 @@
- Upstream merge
- Fix auto-updater
- Add ability to delete page list
- Add crash reporting
- Increase retries in downloader
- Use integrated genre filtering
- Remove useless manga sync code
- General code cleanup
- Performance improvements

View File

@ -34,7 +34,7 @@ def includeUpdater() {
android { android {
compileSdkVersion 24 compileSdkVersion 24
buildToolsVersion "24.0.2" buildToolsVersion "24.0.3"
publishNonDefault true publishNonDefault true
defaultConfig { defaultConfig {
@ -48,7 +48,7 @@ android {
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\"" buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""
buildConfigField "String", "BUILD_TIME", "\"${getBuildTime()}\"" buildConfigField "String", "BUILD_TIME", "\"${getBuildTime()}\""
buildConfigField "boolean", "INCLUDE_UPDATER", "${includeUpdater()}" buildConfigField "boolean", "INCLUDE_UPDATER", "true"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
@ -60,7 +60,7 @@ android {
buildTypes { buildTypes {
debug { debug {
versionNameSuffix "-${getCommitCount()}" versionNameSuffix "-${getCommitCount()}"
applicationIdSuffix ".debug" // applicationIdSuffix ".debug"
multiDexEnabled true multiDexEnabled true
} }
release { release {
@ -108,7 +108,8 @@ dependencies {
compile 'com.android.support:multidex:1.0.1' compile 'com.android.support:multidex:1.0.1'
compile 'com.google.android.gms:play-services-gcm:9.6.1' //@9.2.1 to resolve firebase API init failure (hidden error in logcat)
compile 'com.google.android.gms:play-services-gcm:9.2.1'
// ReactiveX // ReactiveX
compile 'io.reactivex:rxandroid:1.2.1' compile 'io.reactivex:rxandroid:1.2.1'
@ -193,6 +194,11 @@ dependencies {
testCompile 'org.robolectric:shadows-play-services:3.1.2' testCompile 'org.robolectric:shadows-play-services:3.1.2'
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
//Firebase
compile 'com.google.firebase:firebase-core:9.2.1'
compile 'com.google.firebase:firebase-messaging:9.2.1'
compile 'com.google.firebase:firebase-crash:9.2.1'
} }
buildscript { buildscript {
@ -208,3 +214,5 @@ buildscript {
repositories { repositories {
mavenCentral() mavenCentral()
} }
//Firebase
apply plugin: 'com.google.gms.google-services'

View File

@ -60,9 +60,6 @@
<service android:name=".data.download.DownloadService" <service android:name=".data.download.DownloadService"
android:exported="false"/> android:exported="false"/>
<service android:name=".data.mangasync.UpdateMangaSyncService"
android:exported="false"/>
<service <service
android:name=".data.library.LibraryUpdateTrigger" android:name=".data.library.LibraryUpdateTrigger"
android:exported="true" android:exported="true"

View File

@ -1,12 +1,12 @@
package eu.kanade.tachiyomi package eu.kanade.tachiyomi
import android.app.Application import android.app.Application
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.gson.Gson import com.google.gson.Gson
import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.data.network.NetworkHelper import eu.kanade.tachiyomi.data.network.NetworkHelper
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.source.SourceManager import eu.kanade.tachiyomi.data.source.SourceManager
@ -32,10 +32,9 @@ class AppModule(val app: Application) : InjektModule {
addSingletonFactory { DownloadManager(app) } addSingletonFactory { DownloadManager(app) }
addSingletonFactory { MangaSyncManager(app) }
addSingletonFactory { Gson() } addSingletonFactory { Gson() }
addSingletonFactory { FirebaseAnalytics.getInstance(app) }
} }
} }

View File

@ -105,12 +105,6 @@ class BackupManager(private val db: DatabaseHelper) {
entry.add(CHAPTERS, gson.toJsonTree(chapters)) entry.add(CHAPTERS, gson.toJsonTree(chapters))
} }
// Backup manga sync
val mangaSync = db.getMangasSync(manga).executeAsBlocking()
if (!mangaSync.isEmpty()) {
entry.add(MANGA_SYNC, gson.toJsonTree(mangaSync))
}
// Backup categories for this manga // Backup categories for this manga
val categoriesForManga = db.getCategoriesForManga(manga).executeAsBlocking() val categoriesForManga = db.getCategoriesForManga(manga).executeAsBlocking()
if (!categoriesForManga.isEmpty()) { if (!categoriesForManga.isEmpty()) {
@ -332,33 +326,7 @@ class BackupManager(private val db: DatabaseHelper) {
* @param sync the sync to restore. * @param sync the sync to restore.
*/ */
private fun restoreSyncForManga(manga: Manga, sync: List<MangaSync>) { private fun restoreSyncForManga(manga: Manga, sync: List<MangaSync>) {
// Fix foreign keys with the current manga id //Sync disabled
for (mangaSync in sync) {
mangaSync.manga_id = manga.id!!
}
val dbSyncs = db.getMangasSync(manga).executeAsBlocking()
val syncToUpdate = ArrayList<MangaSync>()
for (backupSync in sync) {
// Try to find existing chapter in db
val pos = dbSyncs.indexOf(backupSync)
if (pos != -1) {
// The sync is already in the db, only update its fields
val dbSync = dbSyncs[pos]
// Mark the max chapter as read and nothing else
dbSync.last_chapter_read = Math.max(backupSync.last_chapter_read, dbSync.last_chapter_read)
syncToUpdate.add(dbSync)
} else {
// Insert new sync. Let the db assign the id
backupSync.id = null
syncToUpdate.add(backupSync)
}
}
// Update database
if (!syncToUpdate.isEmpty()) {
db.insertMangasSync(syncToUpdate).executeAsBlocking()
}
} }
} }

View File

@ -116,6 +116,15 @@ class ChapterCache(private val context: Context) {
} }
} }
fun removePageListFromCache(chapterUrl: String) {
// Get the key for the chapter.
val key = DiskUtils.hashKeyForDisk(chapterUrl)
try {
diskCache.remove(key)
} catch(e: IOException) {
}
}
/** /**
* Add page list to disk cache. * Add page list to disk cache.
* @param chapterUrl the url of the chapter. * @param chapterUrl the url of the chapter.

View File

@ -10,13 +10,12 @@ import eu.kanade.tachiyomi.data.database.queries.*
* This class provides operations to manage the database through its interfaces. * This class provides operations to manage the database through its interfaces.
*/ */
open class DatabaseHelper(context: Context) open class DatabaseHelper(context: Context)
: MangaQueries, ChapterQueries, MangaSyncQueries, CategoryQueries, MangaCategoryQueries, HistoryQueries { : MangaQueries, ChapterQueries, CategoryQueries, MangaCategoryQueries, HistoryQueries {
override val db = DefaultStorIOSQLite.builder() override val db = DefaultStorIOSQLite.builder()
.sqliteOpenHelper(DbOpenHelper(context)) .sqliteOpenHelper(DbOpenHelper(context))
.addTypeMapping(Manga::class.java, MangaTypeMapping()) .addTypeMapping(Manga::class.java, MangaTypeMapping())
.addTypeMapping(Chapter::class.java, ChapterTypeMapping()) .addTypeMapping(Chapter::class.java, ChapterTypeMapping())
.addTypeMapping(MangaSync::class.java, MangaSyncTypeMapping())
.addTypeMapping(Category::class.java, CategoryTypeMapping()) .addTypeMapping(Category::class.java, CategoryTypeMapping())
.addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping()) .addTypeMapping(MangaCategory::class.java, MangaCategoryTypeMapping())
.addTypeMapping(History::class.java, HistoryTypeMapping()) .addTypeMapping(History::class.java, HistoryTypeMapping())

View File

@ -273,7 +273,7 @@ class DownloadManager(
page page
} }
// Retry 3 times, waiting 2, 4 and 8 seconds between attempts. // Retry 3 times, waiting 2, 4 and 8 seconds between attempts.
.retryWhen(RetryWithDelay(3, { (2 shl it - 1) * 1000 }, Schedulers.trampoline())) .retryWhen(RetryWithDelay(5, { (2 shl it - 1) * 1000 }, Schedulers.trampoline()))
} }
// Public method to get the image from the filesystem. It does NOT provide any way to download the image // Public method to get the image from the filesystem. It does NOT provide any way to download the image

View File

@ -6,7 +6,6 @@ import android.preference.PreferenceManager
import com.f2prateek.rx.preferences.Preference import com.f2prateek.rx.preferences.Preference
import com.f2prateek.rx.preferences.RxSharedPreferences import com.f2prateek.rx.preferences.RxSharedPreferences
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.mangasync.MangaSyncService
import eu.kanade.tachiyomi.data.source.Source import eu.kanade.tachiyomi.data.source.Source
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
@ -103,17 +102,6 @@ class PreferencesHelper(context: Context) {
.apply() .apply()
} }
fun mangaSyncUsername(sync: MangaSyncService) = prefs.getString(keys.syncUsername(sync.id), "")
fun mangaSyncPassword(sync: MangaSyncService) = prefs.getString(keys.syncPassword(sync.id), "")
fun setMangaSyncCredentials(sync: MangaSyncService, username: String, password: String) {
prefs.edit()
.putString(keys.syncUsername(sync.id), username)
.putString(keys.syncPassword(sync.id), password)
.apply()
}
fun downloadsDirectory() = rxPrefs.getString(keys.downloadsDirectory, defaultDownloadsDir.absolutePath) fun downloadsDirectory() = rxPrefs.getString(keys.downloadsDirectory, defaultDownloadsDir.absolutePath)
fun downloadThreads() = rxPrefs.getInteger(keys.downloadThreads, 1) fun downloadThreads() = rxPrefs.getInteger(keys.downloadThreads, 1)

View File

@ -25,9 +25,9 @@ open class SourceManager(private val context: Context) {
private fun createOnlineSourceList(): List<Source> = private fun createOnlineSourceList(): List<Source> =
if (DialogLogin.isLoggedIn(context, false)) if (DialogLogin.isLoggedIn(context, false))
listOf(EHentai(1, false), EHentai(2, true)) listOf(EHentai(context, 1, false), EHentai(context, 2, true))
else else
listOf(EHentai(1, false)) listOf(EHentai(context, 1, false))
private fun createSources(): Map<Int, Source> = hashMapOf<Int, Source>().apply { private fun createSources(): Map<Int, Source> = hashMapOf<Int, Source>().apply {
createOnlineSourceList().forEach { put(it.id, it) } createOnlineSourceList().forEach { put(it.id, it) }

View File

@ -2,14 +2,12 @@ package eu.kanade.tachiyomi.data.source.online.english;
import android.app.Activity; import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.os.Handler; import android.os.Handler;
import android.os.Looper; import android.os.Looper;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.app.ShareCompat; import android.support.v4.app.ShareCompat;
import android.support.v7.app.AlertDialog;
import android.text.TextUtils; import android.text.TextUtils;
import android.widget.Toast; import android.widget.Toast;
@ -26,11 +24,10 @@ import java.net.URL;
import java.net.URLEncoder; import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set;
import eu.kanade.tachiyomi.data.database.models.Chapter; import eu.kanade.tachiyomi.data.database.models.Chapter;
import eu.kanade.tachiyomi.data.database.models.Manga; import eu.kanade.tachiyomi.data.database.models.Manga;
@ -38,16 +35,12 @@ import eu.kanade.tachiyomi.data.network.RequestsKt;
import eu.kanade.tachiyomi.data.preference.PreferencesHelper; import eu.kanade.tachiyomi.data.preference.PreferencesHelper;
import eu.kanade.tachiyomi.data.source.Language; import eu.kanade.tachiyomi.data.source.Language;
import eu.kanade.tachiyomi.data.source.LanguageKt; import eu.kanade.tachiyomi.data.source.LanguageKt;
import eu.kanade.tachiyomi.data.source.SourceManager;
import eu.kanade.tachiyomi.data.source.model.MangasPage; import eu.kanade.tachiyomi.data.source.model.MangasPage;
import eu.kanade.tachiyomi.data.source.model.Page; import eu.kanade.tachiyomi.data.source.model.Page;
import eu.kanade.tachiyomi.data.source.online.OnlineSource; import eu.kanade.tachiyomi.data.source.online.OnlineSource;
import eu.kanade.tachiyomi.ui.catalogue.CatalogueFragment;
import exh.DialogLogin; import exh.DialogLogin;
import exh.ExHentaiLoginPref;
import exh.NetworkManager; import exh.NetworkManager;
import exh.StringJoiner; import exh.StringJoiner;
import exh.Util;
import okhttp3.Headers; import okhttp3.Headers;
import okhttp3.Interceptor; import okhttp3.Interceptor;
import okhttp3.Request; import okhttp3.Request;
@ -68,9 +61,6 @@ public class EHentai extends OnlineSource {
"misc" "misc"
}; };
public static ArrayList<String> ENABLED_GENRES = null;
public static final String KEY_GENRE_FILTER = "exh_genre_filter";
public static final String QUERY_PREFIX = "?f_apply=Apply+Filter"; public static final String QUERY_PREFIX = "?f_apply=Apply+Filter";
public static String HOST = "http://g.e-hentai.org/"; public static String HOST = "http://g.e-hentai.org/";
@ -82,14 +72,14 @@ public class EHentai extends OnlineSource {
public static final String FAVORITES_PATH = "favorites.php"; public static final String FAVORITES_PATH = "favorites.php";
boolean isExhentai = false; private boolean isExhentai = false;
Context context; private Context context;
int id; private int id;
PreferencesHelper helper; private PreferencesHelper helper;
public EHentai(Context context, int id, boolean isExhentai) { public EHentai(Context context, int id, boolean isExhentai) {
super(context); super();
this.context = context.getApplicationContext(); this.context = context.getApplicationContext();
this.isExhentai = isExhentai; this.isExhentai = isExhentai;
helper = new PreferencesHelper(context); helper = new PreferencesHelper(context);
@ -98,82 +88,27 @@ public class EHentai extends OnlineSource {
// glideHeaders = glideHeadersBuilder().build(); // glideHeaders = glideHeadersBuilder().build();
} }
public static void saveGenreFilter(PreferencesHelper helper) { private static boolean isGenreEnabled(String genre, List<Filter> filters) {
Set<String> genreSet = new HashSet<>(); for(Filter filter : filters) {
genreSet.addAll(ENABLED_GENRES); if(filter.getId().equals(genre)) {
helper.getPrefs().edit().putStringSet(KEY_GENRE_FILTER, genreSet).commit(); return true;
} }
public static void loadGenreFilter(PreferencesHelper helper) {
Set<String> defaultSet = new HashSet<>();
defaultSet.addAll(Arrays.asList(GENRE_LIST));
ENABLED_GENRES.clear();
ENABLED_GENRES.addAll(helper.getPrefs().getStringSet(KEY_GENRE_FILTER, defaultSet));
}
public static List<String> getEnabledGenres(PreferencesHelper helper) {
if(ENABLED_GENRES == null) {
ENABLED_GENRES = new ArrayList<>();
loadGenreFilter(helper);
} }
return ENABLED_GENRES; return false;
} }
public static void launchGenreSelectionDialog(Context context, final CatalogueFragment catalogueFragment) { private static String buildGenreString(List<Filter> filters) {
final PreferencesHelper helper = new PreferencesHelper(context);
final boolean[] selectedGenres = new boolean[GENRE_LIST.length];
for (int i = 0; i < GENRE_LIST.length; i++) {
selectedGenres[i] = getEnabledGenres(helper).contains(GENRE_LIST[i]);
}
AlertDialog dialog = new AlertDialog.Builder(context)
.setTitle("Genre Filter")
.setMultiChoiceItems(GENRE_LIST, selectedGenres, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog1, int indexSelected, boolean isChecked) {
if (isChecked) {
selectedGenres[indexSelected] = true;
} else if (selectedGenres[indexSelected]) {
selectedGenres[indexSelected] = false;
}
}
}).setPositiveButton("Apply", new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog1, int id) {
dialog1.dismiss();
getEnabledGenres(helper).clear();
for (int i = 0; i < GENRE_LIST.length; i++) {
if (selectedGenres[i]) {
getEnabledGenres(helper).add(GENRE_LIST[i]);
}
}
//Save the new genre filter
saveGenreFilter(helper);
String originalQuery = catalogueFragment.getQuery();
if(originalQuery == null){
originalQuery = "";
}
//Force a new search event
catalogueFragment.onSearchEvent(originalQuery, true, true);
}
}).setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog1, int id) {
dialog1.dismiss();
}
}).create();
dialog.show();
}
public static String buildGenreString(PreferencesHelper helper) {
StringBuilder genreString = new StringBuilder(); StringBuilder genreString = new StringBuilder();
for (String genre : GENRE_LIST) { for (String genre : GENRE_LIST) {
genreString.append("&f_"); genreString.append("&f_");
genreString.append(genre); genreString.append(genre);
genreString.append("="); genreString.append("=");
genreString.append(getEnabledGenres(helper).contains(genre) ? "1" : "0"); genreString.append(filters.isEmpty() || isGenreEnabled(genre, filters) ? "1" : "0");
} }
return genreString.toString(); return genreString.toString();
} }
public static String getQualityMode(PreferencesHelper prefHelper) { private static String getQualityMode(PreferencesHelper prefHelper) {
return prefHelper.getPrefs().getString("ehentai_quality", "auto"); return prefHelper.getPrefs().getString("ehentai_quality", "auto");
} }
@ -207,14 +142,14 @@ public class EHentai extends OnlineSource {
@NonNull @NonNull
@Override protected String popularMangaInitialUrl() { @Override protected String popularMangaInitialUrl() {
return getBaseUrl() + QUERY_PREFIX + buildGenreString(helper); return getBaseUrl() + QUERY_PREFIX + buildGenreString(Collections.<Filter>emptyList());
} }
@NonNull @NotNull
@Override protected String searchMangaInitialUrl(@NonNull String query) { @Override protected String searchMangaInitialUrl(@NotNull String query, @NotNull List<Filter> filters) {
try { try {
log("Query: " + getBaseUrl() + QUERY_PREFIX + buildGenreString(helper) + "&f_search=" + URLEncoder.encode(query, "UTF-8")); log("Query: " + getBaseUrl() + QUERY_PREFIX + buildGenreString(filters) + "&f_search=" + URLEncoder.encode(query, "UTF-8"));
return getBaseUrl() + QUERY_PREFIX + buildGenreString(helper) + "&f_search=" + URLEncoder.encode(query, "UTF-8"); return getBaseUrl() + QUERY_PREFIX + buildGenreString(filters) + "&f_search=" + URLEncoder.encode(query, "UTF-8");
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
//How can this happen :/ //How can this happen :/
throw new RuntimeException(e); throw new RuntimeException(e);
@ -263,6 +198,28 @@ public class EHentai extends OnlineSource {
.startChooser(); .startChooser();
} }
@Override
public boolean getSupportsLatest() {
return true;
}
@Override
protected void searchMangaParse(@NotNull Response response, @NotNull MangasPage page, @NotNull String query, @NotNull List<Filter> filters) {
popularMangaParse(response, page);
}
@NotNull
@Override
protected String latestUpdatesInitialUrl() {
//TODO Change this when we actually parse the popular stuff!
return popularMangaInitialUrl();
}
@Override
protected void latestUpdatesParse(@NotNull Response response, @NotNull MangasPage page) {
popularMangaParse(response, page);
}
public static class FavoritesResponse { public static class FavoritesResponse {
public Map<String, List<Manga>> favs; public Map<String, List<Manga>> favs;
public List<String> favCategories; public List<String> favCategories;
@ -282,7 +239,8 @@ public class EHentai extends OnlineSource {
this.id = id; this.id = id;
} }
} }
public static BuildFavoritesBaseResponse buildFavoritesBase(Context context, SharedPreferences preferences) {
private static BuildFavoritesBaseResponse buildFavoritesBase(Context context, SharedPreferences preferences) {
String favoritesBase; String favoritesBase;
int id; int id;
if(DialogLogin.isLoggedIn(context, false)) { if(DialogLogin.isLoggedIn(context, false)) {
@ -334,7 +292,7 @@ public class EHentai extends OnlineSource {
public Map<String, List<Manga>> mangas; public Map<String, List<Manga>> mangas;
} }
public static ParsedMangaPage parseMangaPage(Response response, int id) { private static ParsedMangaPage parseMangaPage(Response response, int id) {
ParsedMangaPage mangaPage = new ParsedMangaPage(); ParsedMangaPage mangaPage = new ParsedMangaPage();
Map<String, List<Manga>> mangas = new HashMap<>(); Map<String, List<Manga>> mangas = new HashMap<>();
mangaPage.mangas = mangas; mangaPage.mangas = mangas;
@ -427,12 +385,6 @@ public class EHentai extends OnlineSource {
} }
} }
@Override
protected void searchMangaParse(@NotNull Response response, @NotNull MangasPage page, @NotNull String query) {
popularMangaParse(response, page);
}
protected static String parseNextSearchUrl(Document parsedHtml) { protected static String parseNextSearchUrl(Document parsedHtml) {
Elements buttons = parsedHtml.select("a[onclick=return false]"); Elements buttons = parsedHtml.select("a[onclick=return false]");
Element lastButton = buttons.last(); Element lastButton = buttons.last();
@ -559,15 +511,11 @@ public class EHentai extends OnlineSource {
} }
}); });
return false; return false;
// DialogLogin.requestLogin(context);
// if (!DialogLogin.isLoggedIn(context, true)) {
// return false;
// }
} }
return true; return true;
} }
String parseChapterPage(ArrayList<String> urls, String url) throws Exception { private String parseChapterPage(ArrayList<String> urls, String url) throws Exception {
log("Parsing chapter page: " + url); log("Parsing chapter page: " + url);
String source = getClient().newCall(RequestsKt.GET(getBaseUrl() + url, getHeaders(), RequestsKt.getDEFAULT_CACHE_CONTROL())) String source = getClient().newCall(RequestsKt.GET(getBaseUrl() + url, getHeaders(), RequestsKt.getDEFAULT_CACHE_CONTROL()))
.execute().body().string(); .execute().body().string();
@ -578,9 +526,6 @@ public class EHentai extends OnlineSource {
String pageUrl = next.attr("href"); String pageUrl = next.attr("href");
int pageNumber = Integer.parseInt(next.children().first().attr("alt")); int pageNumber = Integer.parseInt(next.children().first().attr("alt"));
log("Got page: " + pageNumber + ", " + pageUrl); log("Got page: " + pageNumber + ", " + pageUrl);
// List<Page> pages = c.getPages();
// if(pages == null) pages = new ArrayList<>();
// pages.add(new Page(pageNumber, pageUrl));
urls.add(pageUrl); urls.add(pageUrl);
} }
@ -728,6 +673,22 @@ public class EHentai extends OnlineSource {
return foundCookies; return foundCookies;
} }
private static List<Filter> filterList = createFilterList();
private static List<Filter> createFilterList() {
List<Filter> filters = new ArrayList<>();
for(String genre : GENRE_LIST) {
filters.add(new Filter(genre, genre));
}
return filters;
}
@NotNull
@Override
public List<Filter> getFilterList() {
return filterList;
}
private static void log(String string) { private static void log(String string) {
// Util.d("EHentai", string); // Util.d("EHentai", string);
} }

View File

@ -23,7 +23,7 @@ interface GithubService {
} }
} }
@GET("/repos/inorichi/tachiyomi/releases/latest") @GET("/repos/NerdNumber9/tachiyomi/releases/latest")
fun getLatestVersion(): Observable<GithubRelease> fun getLatestVersion(): Observable<GithubRelease>
} }

View File

@ -477,4 +477,4 @@ open class CatalogueFragment : BaseRxFragment<CataloguePresenter>(), FlexibleVie
.show() .show()
} }
} }

View File

@ -81,9 +81,8 @@ class MainActivity : BaseActivity() {
// Set start screen // Set start screen
setSelectedDrawerItem(startScreenId) setSelectedDrawerItem(startScreenId)
//Check for update // Show changelog if needed
val context = this ChangelogDialogFragment.show(preferences, supportFragmentManager)
Thread { ActivityAskUpdate.checkAndDoUpdateIfNeeded(context, true) }.start()
} }
} }

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.manga
import android.os.Bundle import android.os.Bundle
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.manga.info.ChapterCountEvent import eu.kanade.tachiyomi.ui.manga.info.ChapterCountEvent
import eu.kanade.tachiyomi.util.SharedData import eu.kanade.tachiyomi.util.SharedData
@ -21,11 +20,6 @@ class MangaPresenter : BasePresenter<MangaActivity>() {
*/ */
val db: DatabaseHelper by injectLazy() val db: DatabaseHelper by injectLazy()
/**
* Manga sync manager.
*/
val syncManager: MangaSyncManager by injectLazy()
/** /**
* Manga associated with this instance. * Manga associated with this instance.
*/ */

View File

@ -370,6 +370,11 @@ class ChaptersFragment : BaseRxFragment<ChaptersPresenter>(), ActionMode.Callbac
presenter.deleteChapters(chapters) presenter.deleteChapters(chapters)
} }
fun deletePageList(chapter: ChapterModel) {
destroyActionModeIfNeeded()
presenter.deletePageList(chapter)
}
fun onChaptersDeleted() { fun onChaptersDeleted() {
dismissDeletingDialog() dismissDeletingDialog()
adapter.notifyItemRangeChanged(0, adapter.itemCount) adapter.notifyItemRangeChanged(0, adapter.itemCount)

View File

@ -105,6 +105,7 @@ class ChaptersHolder(
R.id.action_mark_as_read -> markAsRead(chapterList) R.id.action_mark_as_read -> markAsRead(chapterList)
R.id.action_mark_as_unread -> markAsUnread(chapterList) R.id.action_mark_as_unread -> markAsUnread(chapterList)
R.id.action_mark_previous_as_read -> markPreviousAsRead(chapter) R.id.action_mark_previous_as_read -> markPreviousAsRead(chapter)
R.id.action_delete_page_list -> deletePageList(chapter)
} }
} }

View File

@ -1,6 +1,7 @@
package eu.kanade.tachiyomi.ui.manga.chapter package eu.kanade.tachiyomi.ui.manga.chapter
import android.os.Bundle import android.os.Bundle
import eu.kanade.tachiyomi.data.cache.ChapterCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
@ -47,6 +48,11 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
*/ */
val downloadManager: DownloadManager by injectLazy() val downloadManager: DownloadManager by injectLazy()
/**
* Chapter cache
*/
val chapterCache: ChapterCache by injectLazy()
/** /**
* Active manga. * Active manga.
*/ */
@ -338,6 +344,10 @@ class ChaptersPresenter : BasePresenter<ChaptersFragment>() {
chapter.download = null chapter.download = null
} }
fun deletePageList(chapter: ChapterModel) {
chapterCache.removePageListFromCache(chapter.url)
}
/** /**
* Reverses the sorting and requests an UI update. * Reverses the sorting and requests an UI update.
*/ */

View File

@ -8,8 +8,6 @@ import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaSync import eu.kanade.tachiyomi.data.database.models.MangaSync
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.mangasync.MangaSyncManager
import eu.kanade.tachiyomi.data.mangasync.UpdateMangaSyncService
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.source.SourceManager import eu.kanade.tachiyomi.data.source.SourceManager
import eu.kanade.tachiyomi.data.source.model.Page import eu.kanade.tachiyomi.data.source.model.Page
@ -46,11 +44,6 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
*/ */
val downloadManager: DownloadManager by injectLazy() val downloadManager: DownloadManager by injectLazy()
/**
* Sync manager.
*/
val syncManager: MangaSyncManager by injectLazy()
/** /**
* Source manager. * Source manager.
*/ */
@ -152,12 +145,6 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
Observable.just(manga) Observable.just(manga)
.subscribeLatestCache({ view, manga -> view.onMangaOpen(manga) }) .subscribeLatestCache({ view, manga -> view.onMangaOpen(manga) })
// Retrieve the sync list if auto syncing is enabled.
if (prefs.autoUpdateMangaSync()) {
add(db.getMangasSync(manga).asRxSingle()
.subscribe({ mangaSyncList = it }))
}
restartableLatestCache(LOAD_ACTIVE_CHAPTER, restartableLatestCache(LOAD_ACTIVE_CHAPTER,
{ loadChapterObservable(chapter) }, { loadChapterObservable(chapter) },
{ view, chapter -> view.onChapterReady(this.chapter) }, { view, chapter -> view.onChapterReady(this.chapter) },
@ -448,12 +435,7 @@ class ReaderPresenter : BasePresenter<ReaderActivity>() {
* Starts the service that updates the last chapter read in sync services * Starts the service that updates the last chapter read in sync services
*/ */
fun updateMangaSyncLastChapterRead() { fun updateMangaSyncLastChapterRead() {
mangaSyncList?.forEach { sync -> //Sync disabled
val service = syncManager.getService(sync.sync_id)
if (service != null && service.isLogged && sync.update) {
UpdateMangaSyncService.start(context, sync)
}
}
} }
/** /**

View File

@ -1,9 +1,11 @@
package eu.kanade.tachiyomi.ui.setting package eu.kanade.tachiyomi.ui.setting
import android.os.Bundle import android.os.Bundle
import android.support.v4.app.ShareCompat
import android.support.v7.preference.XpPreferenceFragment import android.support.v7.preference.XpPreferenceFragment
import android.view.View import android.view.View
import com.afollestad.materialdialogs.MaterialDialog import com.afollestad.materialdialogs.MaterialDialog
import com.google.firebase.iid.FirebaseInstanceId
import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.updater.GithubUpdateChecker import eu.kanade.tachiyomi.data.updater.GithubUpdateChecker
@ -48,14 +50,26 @@ class SettingsAboutFragment : SettingsFragment() {
val version = findPreference(getString(R.string.pref_version)) val version = findPreference(getString(R.string.pref_version))
val buildTime = findPreference(getString(R.string.pref_build_time)) val buildTime = findPreference(getString(R.string.pref_build_time))
findPreference("acra.enable").isEnabled = false;
val fcmRegToken = findPreference("pref_fcm_reg_token")
fcmRegToken.summary = FirebaseInstanceId.getInstance().token
fcmRegToken.setOnPreferenceClickListener {
ShareCompat.IntentBuilder
.from(activity)
.setText(FirebaseInstanceId.getInstance().token)
.setType("text/plain") // most general text sharing MIME type
.setChooserTitle("Share FCM Token")
.startChooser()
true
}
findPreference("acra.enable").isEnabled = false
version.summary = if (BuildConfig.DEBUG) version.summary = if (BuildConfig.DEBUG)
"r" + BuildConfig.COMMIT_COUNT "r" + BuildConfig.COMMIT_COUNT
else else
BuildConfig.VERSION_NAME BuildConfig.VERSION_NAME
if (!BuildConfig.DEBUG && BuildConfig.INCLUDE_UPDATER) { if (BuildConfig.INCLUDE_UPDATER) {
//Set onClickListener to check for new version //Set onClickListener to check for new version
version.setOnPreferenceClickListener { version.setOnPreferenceClickListener {
checkVersion() checkVersion()

View File

@ -19,6 +19,8 @@ import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.Toast; import android.widget.Toast;
import com.google.firebase.analytics.FirebaseAnalytics;
import java.io.IOException; import java.io.IOException;
import java.net.CookieStore; import java.net.CookieStore;
import java.net.HttpCookie; import java.net.HttpCookie;
@ -28,9 +30,11 @@ import java.util.concurrent.locks.ReentrantLock;
import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.R;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.Response; import okhttp3.Response;
import uy.kohesive.injekt.InjektKt;
public class DialogLogin extends AppCompatDialog { public class DialogLogin extends AppCompatDialog {
private FirebaseAnalytics analytics = InjektKt.getInjekt().getInstance(FirebaseAnalytics.class);
public static ReentrantLock DIALOG_LOCK = new ReentrantLock(); public static ReentrantLock DIALOG_LOCK = new ReentrantLock();
public DialogLogin(Context context) { public DialogLogin(Context context) {
@ -89,6 +93,21 @@ public class DialogLogin extends AppCompatDialog {
} }
} }
private void logLoginAttempt() {
Bundle params = new Bundle();
analytics.logEvent("login_try", params);
}
private void logLoginCancel() {
Bundle params = new Bundle();
analytics.logEvent("login_cancel", params);
}
private void logLoginSuccess() {
Bundle params = new Bundle();
analytics.logEvent("login_success", params);
}
public static boolean isLoggedIn(final Context context, boolean useWeb) { public static boolean isLoggedIn(final Context context, boolean useWeb) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
String ehCookieString = prefs.getString("eh_cookie_string", ""); String ehCookieString = prefs.getString("eh_cookie_string", "");
@ -125,6 +144,7 @@ public class DialogLogin extends AppCompatDialog {
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
DIALOG_LOCK.lock(); DIALOG_LOCK.lock();
logLoginAttempt();
setContentView(R.layout.activity_dialog_login); setContentView(R.layout.activity_dialog_login);
getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); getWindow().setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
final WebView wv = (WebView) findViewById(R.id.webView); final WebView wv = (WebView) findViewById(R.id.webView);
@ -132,6 +152,7 @@ public class DialogLogin extends AppCompatDialog {
findViewById(R.id.btnCancel).setOnClickListener(new View.OnClickListener() { findViewById(R.id.btnCancel).setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) { @Override public void onClick(View v) {
instance.dismiss(); instance.dismiss();
logLoginCancel();
} }
}); });
findViewById(R.id.btnAdvanced).setOnClickListener(new View.OnClickListener() { findViewById(R.id.btnAdvanced).setOnClickListener(new View.OnClickListener() {
@ -239,6 +260,7 @@ public class DialogLogin extends AppCompatDialog {
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(instance.getContext()); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(instance.getContext());
preferences.edit().putString("eh_cookie_string", "ipb_member_id=" + memberID + "; ipb_pass_hash=" + passHash + "; igneous=" + igneous + "; ").commit(); preferences.edit().putString("eh_cookie_string", "ipb_member_id=" + memberID + "; ipb_pass_hash=" + passHash + "; igneous=" + igneous + "; ").commit();
instance.dismiss(); instance.dismiss();
logLoginSuccess();
} else { } else {
Log.i("EHentai", "@ ExHentai but cookies not fully set, waiting..."); Log.i("EHentai", "@ ExHentai but cookies not fully set, waiting...");
} }

View File

@ -19,9 +19,4 @@
android:id="@+id/action_display_mode" android:id="@+id/action_display_mode"
android:title="@string/action_display_mode" android:title="@string/action_display_mode"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_genre_filter"
android:title="Modify Genre Filter"
app:showAsAction="ifRoom"/>
</menu> </menu>

View File

@ -18,5 +18,7 @@
<item android:id="@+id/action_mark_previous_as_read" <item android:id="@+id/action_mark_previous_as_read"
android:title="@string/action_mark_previous_as_read"/> android:title="@string/action_mark_previous_as_read"/>
<item android:id="@+id/action_delete_page_list"
android:title="Delete page list"/>
</menu> </menu>

View File

@ -29,7 +29,7 @@
</menu> </menu>
</item> </item>
<item <!--<item
android:id="@+id/action_update_library" android:id="@+id/action_update_library"
android:title="@string/action_update_library" android:title="@string/action_update_library"
android:icon="@drawable/ic_refresh_white_24dp" android:icon="@drawable/ic_refresh_white_24dp"

View File

@ -6,14 +6,8 @@
android:title="@string/pref_category_about" android:title="@string/pref_category_about"
android:persistent="false"> android:persistent="false">
<SwitchPreferenceCompat
android:key="acra.enable"
android:summary="@string/pref_acra_summary"
android:title="@string/pref_enable_acra"
android:defaultValue="false"/>
<SwitchPreference <SwitchPreference
android:defaultValue="false" android:defaultValue="ftrue"
android:key="@string/pref_enable_automatic_updates_key" android:key="@string/pref_enable_automatic_updates_key"
android:summary="@string/pref_enable_automatic_updates_summary" android:summary="@string/pref_enable_automatic_updates_summary"
android:title="@string/pref_enable_automatic_updates"/> android:title="@string/pref_enable_automatic_updates"/>
@ -28,15 +22,10 @@
android:persistent="false" android:persistent="false"
android:title="@string/build_time"/> android:title="@string/build_time"/>
<SwitchPreferenceCompat <Preference
android:key="auto_update" android:key="pref_fcm_reg_token"
android:defaultValue="true" android:persistent="false"
android:title="Auto Update" android:title="FCM Registration Token"/>
android:summary="Automatically check for updates on startup."/>
<exh.CheckUpdatePref
android:title="Check for Updates"
android:summary="Check for update right now."/>
</PreferenceScreen> </PreferenceScreen>
</PreferenceScreen> </PreferenceScreen>

View File

@ -10,6 +10,9 @@ buildscript {
classpath 'com.github.ben-manes:gradle-versions-plugin:0.13.0' classpath 'com.github.ben-manes:gradle-versions-plugin:0.13.0'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
//Firebase
classpath 'com.google.gms:google-services:3.0.0'
} }
} }