mirror of
https://github.com/mihonapp/mihon.git
synced 2024-11-29 20:23:23 -05:00
Improve MAL support (UI is very simple yet).
This commit is contained in:
parent
a1d67c0fce
commit
8dca7fe79a
30 changed files with 569 additions and 392 deletions
|
@ -52,7 +52,7 @@
|
||||||
<service android:name=".data.download.DownloadService"
|
<service android:name=".data.download.DownloadService"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<service android:name=".data.chaptersync.UpdateChapterSyncService"
|
<service android:name=".data.sync.UpdateMangaSyncService"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package eu.kanade.mangafeed.data.chaptersync;
|
|
||||||
|
|
||||||
import com.squareup.okhttp.Response;
|
|
||||||
|
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
|
||||||
import rx.Observable;
|
|
||||||
|
|
||||||
public abstract class BaseChapterSync {
|
|
||||||
|
|
||||||
// Name of the chapter sync service to display
|
|
||||||
public abstract String getName();
|
|
||||||
|
|
||||||
// Id of the sync service (must be declared and obtained from ChapterSyncManager to avoid conflicts)
|
|
||||||
public abstract int getId();
|
|
||||||
|
|
||||||
public abstract Observable<Boolean> login(String username, String password);
|
|
||||||
|
|
||||||
public abstract boolean isLogged();
|
|
||||||
|
|
||||||
public abstract Observable<Response> update(ChapterSync chapter);
|
|
||||||
}
|
|
|
@ -1,163 +0,0 @@
|
||||||
package eu.kanade.mangafeed.data.chaptersync;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.util.Xml;
|
|
||||||
|
|
||||||
import com.squareup.okhttp.Credentials;
|
|
||||||
import com.squareup.okhttp.FormEncodingBuilder;
|
|
||||||
import com.squareup.okhttp.Headers;
|
|
||||||
import com.squareup.okhttp.Response;
|
|
||||||
|
|
||||||
import org.jsoup.Jsoup;
|
|
||||||
import org.xmlpull.v1.XmlSerializer;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
|
|
||||||
import eu.kanade.mangafeed.App;
|
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
|
||||||
import eu.kanade.mangafeed.data.network.NetworkHelper;
|
|
||||||
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
|
||||||
import rx.Observable;
|
|
||||||
|
|
||||||
public class MyAnimeList extends BaseChapterSync {
|
|
||||||
|
|
||||||
@Inject PreferencesHelper preferences;
|
|
||||||
@Inject NetworkHelper networkService;
|
|
||||||
|
|
||||||
private Headers headers;
|
|
||||||
|
|
||||||
public static final String BASE_URL = "http://myanimelist.net";
|
|
||||||
|
|
||||||
private static final String ENTRY = "entry";
|
|
||||||
private static final String CHAPTER = "chapter";
|
|
||||||
|
|
||||||
public MyAnimeList(Context context) {
|
|
||||||
App.get(context).getComponent().inject(this);
|
|
||||||
|
|
||||||
String username = preferences.getChapterSyncUsername(this);
|
|
||||||
String password = preferences.getChapterSyncPassword(this);
|
|
||||||
|
|
||||||
if (!username.isEmpty() && !password.isEmpty()) {
|
|
||||||
createHeaders(username, password);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
return "MyAnimeList";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getId() {
|
|
||||||
return ChapterSyncManager.MYANIMELIST;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getLoginUrl() {
|
|
||||||
return Uri.parse(BASE_URL).buildUpon()
|
|
||||||
.appendEncodedPath("api/account/verify_credentials.xml")
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable<Boolean> login(String username, String password) {
|
|
||||||
createHeaders(username, password);
|
|
||||||
return networkService.getResponse(getLoginUrl(), headers, null)
|
|
||||||
.map(response -> response.code() == 200);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isLogged() {
|
|
||||||
return !preferences.getChapterSyncUsername(this).isEmpty()
|
|
||||||
&& !preferences.getChapterSyncPassword(this).isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getSearchUrl(String query) {
|
|
||||||
return Uri.parse(BASE_URL).buildUpon()
|
|
||||||
.appendEncodedPath("api/manga/search.xml")
|
|
||||||
.appendQueryParameter("q", query)
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable<List<ChapterSync>> search(String query) {
|
|
||||||
return networkService.getStringResponse(getSearchUrl(query), headers, null)
|
|
||||||
.map(Jsoup::parse)
|
|
||||||
.flatMap(doc -> Observable.from(doc.select("entry")))
|
|
||||||
.map(entry -> {
|
|
||||||
ChapterSync chapter = ChapterSync.create(this);
|
|
||||||
chapter.title = entry.select("title").first().text();
|
|
||||||
chapter.remote_id = Integer.parseInt(entry.select("id").first().text());
|
|
||||||
return chapter;
|
|
||||||
})
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getListUrl(String username) {
|
|
||||||
return Uri.parse(BASE_URL).buildUpon()
|
|
||||||
.appendPath("malappinfo.php")
|
|
||||||
.appendQueryParameter("u", username)
|
|
||||||
.appendQueryParameter("status", "all")
|
|
||||||
.appendQueryParameter("type", "manga")
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable<List<ChapterSync>> getList(String username) {
|
|
||||||
return networkService.getStringResponse(getListUrl(username), headers, null)
|
|
||||||
.map(Jsoup::parse)
|
|
||||||
.flatMap(doc -> Observable.from(doc.select("manga")))
|
|
||||||
.map(entry -> {
|
|
||||||
ChapterSync chapter = ChapterSync.create(this);
|
|
||||||
chapter.title = entry.select("series_title").first().text();
|
|
||||||
chapter.remote_id = Integer.parseInt(
|
|
||||||
entry.select("series_mangadb_id").first().text());
|
|
||||||
chapter.last_chapter_read = Integer.parseInt(
|
|
||||||
entry.select("my_read_chapters").first().text());
|
|
||||||
return chapter;
|
|
||||||
})
|
|
||||||
.toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getUpdateUrl(ChapterSync chapter) {
|
|
||||||
return Uri.parse(BASE_URL).buildUpon()
|
|
||||||
.appendEncodedPath("api/mangalist/update")
|
|
||||||
.appendPath(chapter.remote_id + ".xml")
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Observable<Response> update(ChapterSync chapter) {
|
|
||||||
XmlSerializer xml = Xml.newSerializer();
|
|
||||||
StringWriter writer = new StringWriter();
|
|
||||||
try {
|
|
||||||
xml.setOutput(writer);
|
|
||||||
xml.startDocument("UTF-8", false);
|
|
||||||
xml.startTag("", ENTRY);
|
|
||||||
xml.startTag("", CHAPTER);
|
|
||||||
xml.text(chapter.last_chapter_read + "");
|
|
||||||
xml.endTag("", CHAPTER);
|
|
||||||
xml.endTag("", ENTRY);
|
|
||||||
xml.endDocument();
|
|
||||||
} catch (IOException e) {
|
|
||||||
return Observable.error(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
FormEncodingBuilder form = new FormEncodingBuilder();
|
|
||||||
form.add("data", writer.toString());
|
|
||||||
|
|
||||||
return networkService.postData(getUpdateUrl(chapter), form.build(), headers);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void createHeaders(String username, String password) {
|
|
||||||
Headers.Builder builder = new Headers.Builder();
|
|
||||||
builder.add("Authorization", Credentials.basic(username, password));
|
|
||||||
// builder.add("User-Agent", "");
|
|
||||||
setHeaders(builder.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHeaders(Headers headers) {
|
|
||||||
this.headers = headers;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -16,21 +16,21 @@ import com.pushtorefresh.storio.sqlite.queries.RawQuery;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.data.chaptersync.BaseChapterSync;
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
|
import eu.kanade.mangafeed.data.mangasync.base.BaseMangaSync;
|
||||||
import eu.kanade.mangafeed.data.database.models.Chapter;
|
import eu.kanade.mangafeed.data.database.models.Chapter;
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterStorIOSQLiteDeleteResolver;
|
import eu.kanade.mangafeed.data.database.models.ChapterStorIOSQLiteDeleteResolver;
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterStorIOSQLiteGetResolver;
|
import eu.kanade.mangafeed.data.database.models.ChapterStorIOSQLiteGetResolver;
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterStorIOSQLitePutResolver;
|
import eu.kanade.mangafeed.data.database.models.ChapterStorIOSQLitePutResolver;
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSyncStorIOSQLiteDeleteResolver;
|
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSyncStorIOSQLiteGetResolver;
|
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSyncStorIOSQLitePutResolver;
|
|
||||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLiteDeleteResolver;
|
import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLiteDeleteResolver;
|
||||||
import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLiteGetResolver;
|
import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLiteGetResolver;
|
||||||
import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLitePutResolver;
|
import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLitePutResolver;
|
||||||
|
import eu.kanade.mangafeed.data.database.models.MangaSyncStorIOSQLiteDeleteResolver;
|
||||||
|
import eu.kanade.mangafeed.data.database.models.MangaSyncStorIOSQLiteGetResolver;
|
||||||
|
import eu.kanade.mangafeed.data.database.models.MangaSyncStorIOSQLitePutResolver;
|
||||||
import eu.kanade.mangafeed.data.database.resolvers.MangaWithUnreadGetResolver;
|
import eu.kanade.mangafeed.data.database.resolvers.MangaWithUnreadGetResolver;
|
||||||
import eu.kanade.mangafeed.data.database.tables.ChapterSyncTable;
|
import eu.kanade.mangafeed.data.database.tables.MangaSyncTable;
|
||||||
import eu.kanade.mangafeed.data.database.tables.ChapterTable;
|
import eu.kanade.mangafeed.data.database.tables.ChapterTable;
|
||||||
import eu.kanade.mangafeed.data.database.tables.MangaTable;
|
import eu.kanade.mangafeed.data.database.tables.MangaTable;
|
||||||
import eu.kanade.mangafeed.util.ChapterRecognition;
|
import eu.kanade.mangafeed.util.ChapterRecognition;
|
||||||
|
@ -55,10 +55,10 @@ public class DatabaseHelper {
|
||||||
.getResolver(new ChapterStorIOSQLiteGetResolver())
|
.getResolver(new ChapterStorIOSQLiteGetResolver())
|
||||||
.deleteResolver(new ChapterStorIOSQLiteDeleteResolver())
|
.deleteResolver(new ChapterStorIOSQLiteDeleteResolver())
|
||||||
.build())
|
.build())
|
||||||
.addTypeMapping(ChapterSync.class, SQLiteTypeMapping.<ChapterSync>builder()
|
.addTypeMapping(MangaSync.class, SQLiteTypeMapping.<MangaSync>builder()
|
||||||
.putResolver(new ChapterSyncStorIOSQLitePutResolver())
|
.putResolver(new MangaSyncStorIOSQLitePutResolver())
|
||||||
.getResolver(new ChapterSyncStorIOSQLiteGetResolver())
|
.getResolver(new MangaSyncStorIOSQLiteGetResolver())
|
||||||
.deleteResolver(new ChapterSyncStorIOSQLiteDeleteResolver())
|
.deleteResolver(new MangaSyncStorIOSQLiteDeleteResolver())
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ public class DatabaseHelper {
|
||||||
.prepare();
|
.prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreparedGetListOfObjects<Manga> getMangasWithUnread() {
|
public PreparedGetListOfObjects<Manga> getFavoriteMangasWithUnread() {
|
||||||
return db.get()
|
return db.get()
|
||||||
.listOfObjects(Manga.class)
|
.listOfObjects(Manga.class)
|
||||||
.withQuery(RawQuery.builder()
|
.withQuery(RawQuery.builder()
|
||||||
|
@ -301,30 +301,30 @@ public class DatabaseHelper {
|
||||||
.prepare();
|
.prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chapter sync related queries
|
// Manga sync related queries
|
||||||
|
|
||||||
public PreparedGetListOfObjects<ChapterSync> getChapterSync(Manga manga, BaseChapterSync sync) {
|
public PreparedGetListOfObjects<MangaSync> getMangaSync(Manga manga, BaseMangaSync sync) {
|
||||||
|
|
||||||
return db.get()
|
return db.get()
|
||||||
.listOfObjects(ChapterSync.class)
|
.listOfObjects(MangaSync.class)
|
||||||
.withQuery(Query.builder()
|
.withQuery(Query.builder()
|
||||||
.table(ChapterSyncTable.TABLE)
|
.table(MangaSyncTable.TABLE)
|
||||||
.where(ChapterSyncTable.COLUMN_MANGA_ID + "=? AND " +
|
.where(MangaSyncTable.COLUMN_MANGA_ID + "=? AND " +
|
||||||
ChapterSyncTable.COLUMN_SYNC_ID + "=?")
|
MangaSyncTable.COLUMN_SYNC_ID + "=?")
|
||||||
.whereArgs(manga.id, sync.getId())
|
.whereArgs(manga.id, sync.getId())
|
||||||
.build())
|
.build())
|
||||||
.prepare();
|
.prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreparedPutObject<ChapterSync> insertChapterSync(ChapterSync chapter) {
|
public PreparedPutObject<MangaSync> insertMangaSync(MangaSync manga) {
|
||||||
return db.put()
|
return db.put()
|
||||||
.object(chapter)
|
.object(manga)
|
||||||
.prepare();
|
.prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PreparedDeleteObject<ChapterSync> deleteChapterSync(ChapterSync chapter) {
|
public PreparedDeleteObject<MangaSync> deleteMangaSync(MangaSync manga) {
|
||||||
return db.delete()
|
return db.delete()
|
||||||
.object(chapter)
|
.object(manga)
|
||||||
.prepare();
|
.prepare();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,14 @@ import android.database.sqlite.SQLiteDatabase;
|
||||||
import android.database.sqlite.SQLiteOpenHelper;
|
import android.database.sqlite.SQLiteOpenHelper;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.data.database.tables.ChapterSyncTable;
|
import eu.kanade.mangafeed.data.database.tables.MangaSyncTable;
|
||||||
import eu.kanade.mangafeed.data.database.tables.ChapterTable;
|
import eu.kanade.mangafeed.data.database.tables.ChapterTable;
|
||||||
import eu.kanade.mangafeed.data.database.tables.MangaTable;
|
import eu.kanade.mangafeed.data.database.tables.MangaTable;
|
||||||
|
|
||||||
public class DbOpenHelper extends SQLiteOpenHelper {
|
public class DbOpenHelper extends SQLiteOpenHelper {
|
||||||
|
|
||||||
public static final String DATABASE_NAME = "mangafeed.db";
|
public static final String DATABASE_NAME = "mangafeed.db";
|
||||||
public static final int DATABASE_VERSION = 2;
|
public static final int DATABASE_VERSION = 3;
|
||||||
|
|
||||||
public DbOpenHelper(@NonNull Context context) {
|
public DbOpenHelper(@NonNull Context context) {
|
||||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
|
@ -22,13 +22,13 @@ public class DbOpenHelper extends SQLiteOpenHelper {
|
||||||
public void onCreate(@NonNull SQLiteDatabase db) {
|
public void onCreate(@NonNull SQLiteDatabase db) {
|
||||||
db.execSQL(MangaTable.getCreateTableQuery());
|
db.execSQL(MangaTable.getCreateTableQuery());
|
||||||
db.execSQL(ChapterTable.getCreateTableQuery());
|
db.execSQL(ChapterTable.getCreateTableQuery());
|
||||||
db.execSQL(ChapterSyncTable.getCreateTableQuery());
|
db.execSQL(MangaSyncTable.getCreateTableQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
if (oldVersion == 1)
|
if (oldVersion < 3)
|
||||||
db.execSQL(ChapterSyncTable.getCreateTableQuery());
|
db.execSQL(MangaSyncTable.getCreateTableQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
package eu.kanade.mangafeed.data.database.models;
|
|
||||||
|
|
||||||
import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteColumn;
|
|
||||||
import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteType;
|
|
||||||
|
|
||||||
import eu.kanade.mangafeed.data.chaptersync.BaseChapterSync;
|
|
||||||
import eu.kanade.mangafeed.data.database.tables.ChapterSyncTable;
|
|
||||||
|
|
||||||
@StorIOSQLiteType(table = ChapterSyncTable.TABLE)
|
|
||||||
public class ChapterSync {
|
|
||||||
|
|
||||||
@StorIOSQLiteColumn(name = ChapterSyncTable.COLUMN_ID, key = true)
|
|
||||||
public long id;
|
|
||||||
|
|
||||||
@StorIOSQLiteColumn(name = ChapterSyncTable.COLUMN_MANGA_ID)
|
|
||||||
public long manga_id;
|
|
||||||
|
|
||||||
@StorIOSQLiteColumn(name = ChapterSyncTable.COLUMN_SYNC_ID)
|
|
||||||
public int sync_id;
|
|
||||||
|
|
||||||
@StorIOSQLiteColumn(name = ChapterSyncTable.COLUMN_REMOTE_ID)
|
|
||||||
public int remote_id;
|
|
||||||
|
|
||||||
@StorIOSQLiteColumn(name = ChapterSyncTable.COLUMN_TITLE)
|
|
||||||
public String title;
|
|
||||||
|
|
||||||
@StorIOSQLiteColumn(name = ChapterSyncTable.COLUMN_LAST_CHAPTER_READ)
|
|
||||||
public int last_chapter_read;
|
|
||||||
|
|
||||||
public static ChapterSync create(BaseChapterSync sync) {
|
|
||||||
ChapterSync chapter = new ChapterSync();
|
|
||||||
chapter.sync_id = sync.getId();
|
|
||||||
return chapter;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package eu.kanade.mangafeed.data.database.models;
|
||||||
|
|
||||||
|
import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteColumn;
|
||||||
|
import com.pushtorefresh.storio.sqlite.annotations.StorIOSQLiteType;
|
||||||
|
|
||||||
|
import eu.kanade.mangafeed.data.mangasync.base.BaseMangaSync;
|
||||||
|
import eu.kanade.mangafeed.data.database.tables.MangaSyncTable;
|
||||||
|
|
||||||
|
@StorIOSQLiteType(table = MangaSyncTable.TABLE)
|
||||||
|
public class MangaSync {
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = MangaSyncTable.COLUMN_ID, key = true)
|
||||||
|
public Long id;
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = MangaSyncTable.COLUMN_MANGA_ID)
|
||||||
|
public long manga_id;
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = MangaSyncTable.COLUMN_SYNC_ID)
|
||||||
|
public int sync_id;
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = MangaSyncTable.COLUMN_REMOTE_ID)
|
||||||
|
public int remote_id;
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = MangaSyncTable.COLUMN_TITLE)
|
||||||
|
public String title;
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = MangaSyncTable.COLUMN_LAST_CHAPTER_READ)
|
||||||
|
public int last_chapter_read;
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = MangaSyncTable.COLUMN_SCORE)
|
||||||
|
public float score;
|
||||||
|
|
||||||
|
@StorIOSQLiteColumn(name = MangaSyncTable.COLUMN_STATUS)
|
||||||
|
public int status;
|
||||||
|
|
||||||
|
public static MangaSync create(BaseMangaSync service) {
|
||||||
|
MangaSync mangasync = new MangaSync();
|
||||||
|
mangasync.sync_id = service.getId();
|
||||||
|
return mangasync;
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,9 @@ package eu.kanade.mangafeed.data.database.tables;
|
||||||
|
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
public class ChapterSyncTable {
|
public class MangaSyncTable {
|
||||||
|
|
||||||
public static final String TABLE = "chapter_sync";
|
public static final String TABLE = "manga_sync";
|
||||||
|
|
||||||
public static final String COLUMN_ID = "_id";
|
public static final String COLUMN_ID = "_id";
|
||||||
|
|
||||||
|
@ -18,6 +18,10 @@ public class ChapterSyncTable {
|
||||||
|
|
||||||
public static final String COLUMN_LAST_CHAPTER_READ = "last_chapter_read";
|
public static final String COLUMN_LAST_CHAPTER_READ = "last_chapter_read";
|
||||||
|
|
||||||
|
public static final String COLUMN_STATUS = "status";
|
||||||
|
|
||||||
|
public static final String COLUMN_SCORE = "score";
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
public static String getCreateTableQuery() {
|
public static String getCreateTableQuery() {
|
||||||
return "CREATE TABLE " + TABLE + "("
|
return "CREATE TABLE " + TABLE + "("
|
||||||
|
@ -27,6 +31,8 @@ public class ChapterSyncTable {
|
||||||
+ COLUMN_REMOTE_ID + " INTEGER NOT NULL, "
|
+ COLUMN_REMOTE_ID + " INTEGER NOT NULL, "
|
||||||
+ COLUMN_TITLE + " TEXT NOT NULL, "
|
+ COLUMN_TITLE + " TEXT NOT NULL, "
|
||||||
+ COLUMN_LAST_CHAPTER_READ + " INTEGER NOT NULL, "
|
+ COLUMN_LAST_CHAPTER_READ + " INTEGER NOT NULL, "
|
||||||
|
+ COLUMN_STATUS + " INTEGER NOT NULL, "
|
||||||
|
+ COLUMN_SCORE + " FLOAT NOT NULL, "
|
||||||
+ "FOREIGN KEY(" + COLUMN_MANGA_ID + ") REFERENCES " + MangaTable.TABLE + "(" + MangaTable.COLUMN_ID + ") "
|
+ "FOREIGN KEY(" + COLUMN_MANGA_ID + ") REFERENCES " + MangaTable.TABLE + "(" + MangaTable.COLUMN_ID + ") "
|
||||||
+ "ON DELETE CASCADE"
|
+ "ON DELETE CASCADE"
|
||||||
+ ");";
|
+ ");";
|
|
@ -1,18 +1,21 @@
|
||||||
package eu.kanade.mangafeed.data.chaptersync;
|
package eu.kanade.mangafeed.data.mangasync;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ChapterSyncManager {
|
import eu.kanade.mangafeed.data.mangasync.base.BaseMangaSync;
|
||||||
|
import eu.kanade.mangafeed.data.mangasync.services.MyAnimeList;
|
||||||
|
|
||||||
private List<BaseChapterSync> services;
|
public class MangaSyncManager {
|
||||||
|
|
||||||
|
private List<BaseMangaSync> services;
|
||||||
private MyAnimeList myAnimeList;
|
private MyAnimeList myAnimeList;
|
||||||
|
|
||||||
public static final int MYANIMELIST = 1;
|
public static final int MYANIMELIST = 1;
|
||||||
|
|
||||||
public ChapterSyncManager(Context context) {
|
public MangaSyncManager(Context context) {
|
||||||
services = new ArrayList<>();
|
services = new ArrayList<>();
|
||||||
myAnimeList = new MyAnimeList(context);
|
myAnimeList = new MyAnimeList(context);
|
||||||
services.add(myAnimeList);
|
services.add(myAnimeList);
|
||||||
|
@ -22,11 +25,11 @@ public class ChapterSyncManager {
|
||||||
return myAnimeList;
|
return myAnimeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<BaseChapterSync> getChapterSyncServices() {
|
public List<BaseMangaSync> getSyncServices() {
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|
||||||
public BaseChapterSync getSyncService(int id) {
|
public BaseMangaSync getSyncService(int id) {
|
||||||
switch (id) {
|
switch (id) {
|
||||||
case MYANIMELIST:
|
case MYANIMELIST:
|
||||||
return myAnimeList;
|
return myAnimeList;
|
|
@ -0,0 +1,28 @@
|
||||||
|
package eu.kanade.mangafeed.data.mangasync.base;
|
||||||
|
|
||||||
|
import com.squareup.okhttp.Response;
|
||||||
|
|
||||||
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
|
import rx.Observable;
|
||||||
|
|
||||||
|
public abstract class BaseMangaSync {
|
||||||
|
|
||||||
|
// Name of the manga sync service to display
|
||||||
|
public abstract String getName();
|
||||||
|
|
||||||
|
// Id of the sync service (must be declared and obtained from MangaSyncManager to avoid conflicts)
|
||||||
|
public abstract int getId();
|
||||||
|
|
||||||
|
public abstract Observable<Boolean> login(String username, String password);
|
||||||
|
|
||||||
|
public abstract boolean isLogged();
|
||||||
|
|
||||||
|
public abstract Observable<Response> update(MangaSync manga);
|
||||||
|
|
||||||
|
public abstract Observable<Response> add(MangaSync manga);
|
||||||
|
|
||||||
|
public abstract Observable<Response> bind(MangaSync manga);
|
||||||
|
|
||||||
|
public abstract String getStatus(int status);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,256 @@
|
||||||
|
package eu.kanade.mangafeed.data.mangasync.services;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.util.Xml;
|
||||||
|
|
||||||
|
import com.squareup.okhttp.Credentials;
|
||||||
|
import com.squareup.okhttp.FormEncodingBuilder;
|
||||||
|
import com.squareup.okhttp.Headers;
|
||||||
|
import com.squareup.okhttp.RequestBody;
|
||||||
|
import com.squareup.okhttp.Response;
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup;
|
||||||
|
import org.xmlpull.v1.XmlSerializer;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import eu.kanade.mangafeed.App;
|
||||||
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
|
import eu.kanade.mangafeed.data.mangasync.MangaSyncManager;
|
||||||
|
import eu.kanade.mangafeed.data.mangasync.base.BaseMangaSync;
|
||||||
|
import eu.kanade.mangafeed.data.network.NetworkHelper;
|
||||||
|
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
||||||
|
import rx.Observable;
|
||||||
|
|
||||||
|
public class MyAnimeList extends BaseMangaSync {
|
||||||
|
|
||||||
|
@Inject PreferencesHelper preferences;
|
||||||
|
@Inject NetworkHelper networkService;
|
||||||
|
|
||||||
|
private Headers headers;
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
public static final String BASE_URL = "http://myanimelist.net";
|
||||||
|
|
||||||
|
private static final String ENTRY_TAG = "entry";
|
||||||
|
private static final String CHAPTER_TAG = "chapter";
|
||||||
|
private static final String SCORE_TAG = "score";
|
||||||
|
private static final String STATUS_TAG = "status";
|
||||||
|
|
||||||
|
public static final int NOT_IN_LIST = 0;
|
||||||
|
public static final int READING = 1;
|
||||||
|
public static final int COMPLETED = 2;
|
||||||
|
public static final int ON_HOLD = 3;
|
||||||
|
public static final int DROPPED = 4;
|
||||||
|
public static final int PLAN_TO_READ = 6;
|
||||||
|
|
||||||
|
public static final int DEFAULT_STATUS = READING;
|
||||||
|
public static final int DEFAULT_SCORE = 0;
|
||||||
|
|
||||||
|
public MyAnimeList(Context context) {
|
||||||
|
App.get(context).getComponent().inject(this);
|
||||||
|
|
||||||
|
String username = preferences.getMangaSyncUsername(this);
|
||||||
|
String password = preferences.getMangaSyncPassword(this);
|
||||||
|
|
||||||
|
if (!username.isEmpty() && !password.isEmpty()) {
|
||||||
|
createHeaders(username, password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "MyAnimeList";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() {
|
||||||
|
return MangaSyncManager.MYANIMELIST;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLoginUrl() {
|
||||||
|
return Uri.parse(BASE_URL).buildUpon()
|
||||||
|
.appendEncodedPath("api/account/verify_credentials.xml")
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Observable<Boolean> login(String username, String password) {
|
||||||
|
createHeaders(username, password);
|
||||||
|
return networkService.getResponse(getLoginUrl(), headers, null)
|
||||||
|
.map(response -> response.code() == 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLogged() {
|
||||||
|
return !preferences.getMangaSyncUsername(this).isEmpty()
|
||||||
|
&& !preferences.getMangaSyncPassword(this).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSearchUrl(String query) {
|
||||||
|
return Uri.parse(BASE_URL).buildUpon()
|
||||||
|
.appendEncodedPath("api/manga/search.xml")
|
||||||
|
.appendQueryParameter("q", query)
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Observable<List<MangaSync>> search(String query) {
|
||||||
|
return networkService.getStringResponse(getSearchUrl(query), headers, null)
|
||||||
|
.map(Jsoup::parse)
|
||||||
|
.flatMap(doc -> Observable.from(doc.select("entry")))
|
||||||
|
.map(entry -> {
|
||||||
|
MangaSync manga = MangaSync.create(this);
|
||||||
|
manga.title = entry.select("title").first().text();
|
||||||
|
manga.remote_id = Integer.parseInt(entry.select("id").first().text());
|
||||||
|
return manga;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getListUrl(String username) {
|
||||||
|
return Uri.parse(BASE_URL).buildUpon()
|
||||||
|
.appendPath("malappinfo.php")
|
||||||
|
.appendQueryParameter("u", username)
|
||||||
|
.appendQueryParameter("status", "all")
|
||||||
|
.appendQueryParameter("type", "manga")
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Observable<List<MangaSync>> getList(String username) {
|
||||||
|
// TODO cache this list for a few minutes
|
||||||
|
return networkService.getStringResponse(getListUrl(username), headers, null)
|
||||||
|
.map(Jsoup::parse)
|
||||||
|
.flatMap(doc -> Observable.from(doc.select("manga")))
|
||||||
|
.map(entry -> {
|
||||||
|
MangaSync manga = MangaSync.create(this);
|
||||||
|
manga.title = entry.select("series_title").first().text();
|
||||||
|
manga.remote_id = Integer.parseInt(
|
||||||
|
entry.select("series_mangadb_id").first().text());
|
||||||
|
manga.last_chapter_read = Integer.parseInt(
|
||||||
|
entry.select("my_read_chapters").first().text());
|
||||||
|
manga.status = Integer.parseInt(
|
||||||
|
entry.select("my_status").first().text());
|
||||||
|
// MAL doesn't support score with decimals
|
||||||
|
manga.score = Integer.parseInt(
|
||||||
|
entry.select("my_score").first().text());
|
||||||
|
return manga;
|
||||||
|
})
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUpdateUrl(MangaSync manga) {
|
||||||
|
return Uri.parse(BASE_URL).buildUpon()
|
||||||
|
.appendEncodedPath("api/mangalist/update")
|
||||||
|
.appendPath(manga.remote_id + ".xml")
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Observable<Response> update(MangaSync manga) {
|
||||||
|
try {
|
||||||
|
RequestBody payload = getMangaPostPayload(manga);
|
||||||
|
return networkService.postData(getUpdateUrl(manga), payload, headers);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return Observable.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddUrl(MangaSync manga) {
|
||||||
|
return Uri.parse(BASE_URL).buildUpon()
|
||||||
|
.appendEncodedPath("api/mangalist/add")
|
||||||
|
.appendPath(manga.remote_id + ".xml")
|
||||||
|
.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Observable<Response> add(MangaSync manga) {
|
||||||
|
try {
|
||||||
|
RequestBody payload = getMangaPostPayload(manga);
|
||||||
|
return networkService.postData(getAddUrl(manga), payload, headers);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return Observable.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private RequestBody getMangaPostPayload(MangaSync manga) throws IOException {
|
||||||
|
XmlSerializer xml = Xml.newSerializer();
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
|
xml.setOutput(writer);
|
||||||
|
xml.startDocument("UTF-8", false);
|
||||||
|
xml.startTag("", ENTRY_TAG);
|
||||||
|
|
||||||
|
// Last chapter read
|
||||||
|
if (manga.last_chapter_read != 0) {
|
||||||
|
xml.startTag("", CHAPTER_TAG);
|
||||||
|
xml.text(manga.last_chapter_read + "");
|
||||||
|
xml.endTag("", CHAPTER_TAG);
|
||||||
|
}
|
||||||
|
// Manga status in the list
|
||||||
|
xml.startTag("", STATUS_TAG);
|
||||||
|
xml.text(manga.status + "");
|
||||||
|
xml.endTag("", STATUS_TAG);
|
||||||
|
// Manga score
|
||||||
|
xml.startTag("", SCORE_TAG);
|
||||||
|
xml.text(manga.score + "");
|
||||||
|
xml.endTag("", SCORE_TAG);
|
||||||
|
|
||||||
|
xml.endTag("", ENTRY_TAG);
|
||||||
|
xml.endDocument();
|
||||||
|
|
||||||
|
FormEncodingBuilder form = new FormEncodingBuilder();
|
||||||
|
form.add("data", writer.toString());
|
||||||
|
return form.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Observable<Response> bind(MangaSync manga) {
|
||||||
|
return getList(username)
|
||||||
|
.flatMap(list -> {
|
||||||
|
manga.sync_id = getId();
|
||||||
|
for (MangaSync remoteManga : list) {
|
||||||
|
if (remoteManga.remote_id == manga.remote_id) {
|
||||||
|
// Manga is already in the list
|
||||||
|
manga.score = remoteManga.score;
|
||||||
|
manga.status = remoteManga.status;
|
||||||
|
manga.last_chapter_read = remoteManga.last_chapter_read;
|
||||||
|
return update(manga);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Set default fields if it's not found in the list
|
||||||
|
manga.score = DEFAULT_SCORE;
|
||||||
|
manga.status = DEFAULT_STATUS;
|
||||||
|
return add(manga);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStatus(int status) {
|
||||||
|
switch (status) {
|
||||||
|
case READING:
|
||||||
|
return "Reading";
|
||||||
|
case COMPLETED:
|
||||||
|
return "Completed";
|
||||||
|
case ON_HOLD:
|
||||||
|
return "On hold";
|
||||||
|
case DROPPED:
|
||||||
|
return "Dropped";
|
||||||
|
case PLAN_TO_READ:
|
||||||
|
return "Plan to read";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createHeaders(String username, String password) {
|
||||||
|
this.username = username;
|
||||||
|
Headers.Builder builder = new Headers.Builder();
|
||||||
|
builder.add("Authorization", Credentials.basic(username, password));
|
||||||
|
builder.add("User-Agent", "api-indiv-9F93C52A963974CF674325391990191C");
|
||||||
|
setHeaders(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeaders(Headers headers) {
|
||||||
|
this.headers = headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,7 +11,7 @@ import com.f2prateek.rx.preferences.RxSharedPreferences;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.BaseChapterSync;
|
import eu.kanade.mangafeed.data.mangasync.base.BaseMangaSync;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
|
|
||||||
|
@ -23,8 +23,8 @@ public class PreferencesHelper {
|
||||||
|
|
||||||
private static final String SOURCE_ACCOUNT_USERNAME = "pref_source_username_";
|
private static final String SOURCE_ACCOUNT_USERNAME = "pref_source_username_";
|
||||||
private static final String SOURCE_ACCOUNT_PASSWORD = "pref_source_password_";
|
private static final String SOURCE_ACCOUNT_PASSWORD = "pref_source_password_";
|
||||||
private static final String CHAPTERSYNC_ACCOUNT_USERNAME = "pref_chaptersync_username_";
|
private static final String MANGASYNC_ACCOUNT_USERNAME = "pref_mangasync_username_";
|
||||||
private static final String CHAPTERSYNC_ACCOUNT_PASSWORD = "pref_chaptersync_password_";
|
private static final String MANGASYNC_ACCOUNT_PASSWORD = "pref_mangasync_password_";
|
||||||
|
|
||||||
private File defaultDownloadsDir;
|
private File defaultDownloadsDir;
|
||||||
|
|
||||||
|
@ -102,18 +102,18 @@ public class PreferencesHelper {
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getChapterSyncUsername(BaseChapterSync sync) {
|
public String getMangaSyncUsername(BaseMangaSync sync) {
|
||||||
return prefs.getString(CHAPTERSYNC_ACCOUNT_USERNAME + sync.getId(), "");
|
return prefs.getString(MANGASYNC_ACCOUNT_USERNAME + sync.getId(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getChapterSyncPassword(BaseChapterSync sync) {
|
public String getMangaSyncPassword(BaseMangaSync sync) {
|
||||||
return prefs.getString(CHAPTERSYNC_ACCOUNT_PASSWORD + sync.getId(), "");
|
return prefs.getString(MANGASYNC_ACCOUNT_PASSWORD + sync.getId(), "");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChapterSyncCredentials(BaseChapterSync sync, String username, String password) {
|
public void setMangaSyncCredentials(BaseMangaSync sync, String username, String password) {
|
||||||
prefs.edit()
|
prefs.edit()
|
||||||
.putString(CHAPTERSYNC_ACCOUNT_USERNAME + sync.getId(), username)
|
.putString(MANGASYNC_ACCOUNT_USERNAME + sync.getId(), username)
|
||||||
.putString(CHAPTERSYNC_ACCOUNT_PASSWORD + sync.getId(), password)
|
.putString(MANGASYNC_ACCOUNT_PASSWORD + sync.getId(), password)
|
||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,12 +127,11 @@ public class PreferencesHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDownloadThreads() {
|
public int getDownloadThreads() {
|
||||||
return Integer.parseInt(prefs.getString(getKey(R.string.pref_download_threads_key), "1"));
|
return prefs.getInt(getKey(R.string.pref_download_slots_key), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Observable<Integer> getDownloadTheadsObservable() {
|
public Observable<Integer> getDownloadTheadsObservable() {
|
||||||
return rxPrefs.getString(getKey(R.string.pref_download_threads_key), "1")
|
return rxPrefs.getInteger(getKey(R.string.pref_download_slots_key), 1).asObservable();
|
||||||
.asObservable().map(Integer::parseInt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package eu.kanade.mangafeed.data.chaptersync;
|
package eu.kanade.mangafeed.data.sync;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -10,24 +10,24 @@ import javax.inject.Inject;
|
||||||
import de.greenrobot.event.EventBus;
|
import de.greenrobot.event.EventBus;
|
||||||
import eu.kanade.mangafeed.App;
|
import eu.kanade.mangafeed.App;
|
||||||
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
import eu.kanade.mangafeed.data.network.NetworkHelper;
|
import eu.kanade.mangafeed.data.mangasync.MangaSyncManager;
|
||||||
import eu.kanade.mangafeed.event.UpdateChapterSyncEvent;
|
import eu.kanade.mangafeed.data.mangasync.base.BaseMangaSync;
|
||||||
|
import eu.kanade.mangafeed.event.UpdateMangaSyncEvent;
|
||||||
import eu.kanade.mangafeed.util.EventBusHook;
|
import eu.kanade.mangafeed.util.EventBusHook;
|
||||||
import rx.android.schedulers.AndroidSchedulers;
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
import rx.schedulers.Schedulers;
|
import rx.schedulers.Schedulers;
|
||||||
import rx.subscriptions.CompositeSubscription;
|
import rx.subscriptions.CompositeSubscription;
|
||||||
|
|
||||||
public class UpdateChapterSyncService extends Service {
|
public class UpdateMangaSyncService extends Service {
|
||||||
|
|
||||||
@Inject ChapterSyncManager syncManager;
|
@Inject MangaSyncManager syncManager;
|
||||||
@Inject NetworkHelper networkManager;
|
|
||||||
@Inject DatabaseHelper db;
|
@Inject DatabaseHelper db;
|
||||||
|
|
||||||
private CompositeSubscription subscriptions;
|
private CompositeSubscription subscriptions;
|
||||||
|
|
||||||
public static void start(Context context) {
|
public static void start(Context context) {
|
||||||
context.startService(new Intent(context, UpdateChapterSyncService.class));
|
context.startService(new Intent(context, UpdateMangaSyncService.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -56,15 +56,15 @@ public class UpdateChapterSyncService extends Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventBusHook
|
@EventBusHook
|
||||||
public void onEventMainThread(UpdateChapterSyncEvent event) {
|
public void onEventMainThread(UpdateMangaSyncEvent event) {
|
||||||
updateLastChapteRead(event.getChapterSync());
|
updateLastChapteRead(event.getMangaSync());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLastChapteRead(ChapterSync chapterSync) {
|
private void updateLastChapteRead(MangaSync mangaSync) {
|
||||||
BaseChapterSync sync = syncManager.getSyncService(chapterSync.sync_id);
|
BaseMangaSync sync = syncManager.getSyncService(mangaSync.sync_id);
|
||||||
|
|
||||||
subscriptions.add(sync.update(chapterSync)
|
subscriptions.add(sync.update(mangaSync)
|
||||||
.flatMap(response -> db.insertChapterSync(chapterSync).createObservable())
|
.flatMap(response -> db.insertMangaSync(mangaSync).createObservable())
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(result -> {
|
.subscribe(result -> {
|
|
@ -1,17 +0,0 @@
|
||||||
package eu.kanade.mangafeed.event;
|
|
||||||
|
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
|
||||||
|
|
||||||
public class UpdateChapterSyncEvent {
|
|
||||||
|
|
||||||
private ChapterSync chapterSync;
|
|
||||||
|
|
||||||
public UpdateChapterSyncEvent(ChapterSync chapterSync) {
|
|
||||||
this.chapterSync = chapterSync;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChapterSync getChapterSync() {
|
|
||||||
return chapterSync;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
package eu.kanade.mangafeed.event;
|
||||||
|
|
||||||
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
|
|
||||||
|
public class UpdateMangaSyncEvent {
|
||||||
|
|
||||||
|
private MangaSync mangaSync;
|
||||||
|
|
||||||
|
public UpdateMangaSyncEvent(MangaSync mangaSync) {
|
||||||
|
this.mangaSync = mangaSync;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MangaSync getMangaSync() {
|
||||||
|
return mangaSync;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -5,8 +5,8 @@ import android.app.Application;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import dagger.Component;
|
import dagger.Component;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.MyAnimeList;
|
import eu.kanade.mangafeed.data.mangasync.services.MyAnimeList;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.UpdateChapterSyncService;
|
import eu.kanade.mangafeed.data.sync.UpdateMangaSyncService;
|
||||||
import eu.kanade.mangafeed.data.download.DownloadService;
|
import eu.kanade.mangafeed.data.download.DownloadService;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
import eu.kanade.mangafeed.data.sync.LibraryUpdateService;
|
import eu.kanade.mangafeed.data.sync.LibraryUpdateService;
|
||||||
|
@ -56,7 +56,7 @@ public interface AppComponent {
|
||||||
|
|
||||||
void inject(LibraryUpdateService libraryUpdateService);
|
void inject(LibraryUpdateService libraryUpdateService);
|
||||||
void inject(DownloadService downloadService);
|
void inject(DownloadService downloadService);
|
||||||
void inject(UpdateChapterSyncService updateChapterSyncService);
|
void inject(UpdateMangaSyncService updateMangaSyncService);
|
||||||
|
|
||||||
Application application();
|
Application application();
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import dagger.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
import eu.kanade.mangafeed.data.cache.CacheManager;
|
import eu.kanade.mangafeed.data.cache.CacheManager;
|
||||||
import eu.kanade.mangafeed.data.cache.CoverCache;
|
import eu.kanade.mangafeed.data.cache.CoverCache;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager;
|
import eu.kanade.mangafeed.data.mangasync.MangaSyncManager;
|
||||||
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
||||||
import eu.kanade.mangafeed.data.download.DownloadManager;
|
import eu.kanade.mangafeed.data.download.DownloadManager;
|
||||||
import eu.kanade.mangafeed.data.network.NetworkHelper;
|
import eu.kanade.mangafeed.data.network.NetworkHelper;
|
||||||
|
@ -66,8 +66,8 @@ public class DataModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
ChapterSyncManager provideChapterSyncManager(Application app) {
|
MangaSyncManager provideMangaSyncManager(Application app) {
|
||||||
return new ChapterSyncManager(app);
|
return new MangaSyncManager(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -28,7 +28,7 @@ public class LibraryPresenter extends BasePresenter<LibraryFragment> {
|
||||||
super.onCreate(savedState);
|
super.onCreate(savedState);
|
||||||
|
|
||||||
restartableLatestCache(GET_MANGAS,
|
restartableLatestCache(GET_MANGAS,
|
||||||
() -> db.getMangasWithUnread().createObservable()
|
() -> db.getFavoriteMangasWithUnread().createObservable()
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread()),
|
.observeOn(AndroidSchedulers.mainThread()),
|
||||||
LibraryFragment::onNextMangas);
|
LibraryFragment::onNextMangas);
|
||||||
|
|
|
@ -17,7 +17,7 @@ import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import eu.kanade.mangafeed.App;
|
import eu.kanade.mangafeed.App;
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager;
|
import eu.kanade.mangafeed.data.mangasync.MangaSyncManager;
|
||||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
||||||
import eu.kanade.mangafeed.ui.base.activity.BaseRxActivity;
|
import eu.kanade.mangafeed.ui.base.activity.BaseRxActivity;
|
||||||
|
@ -34,7 +34,7 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
||||||
@Bind(R.id.view_pager) ViewPager view_pager;
|
@Bind(R.id.view_pager) ViewPager view_pager;
|
||||||
|
|
||||||
@Inject PreferencesHelper preferences;
|
@Inject PreferencesHelper preferences;
|
||||||
@Inject ChapterSyncManager chapterSyncManager;
|
@Inject MangaSyncManager mangaSyncManager;
|
||||||
|
|
||||||
private MangaDetailAdapter adapter;
|
private MangaDetailAdapter adapter;
|
||||||
private long manga_id;
|
private long manga_id;
|
||||||
|
@ -116,7 +116,7 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
||||||
};
|
};
|
||||||
|
|
||||||
pageCount = 2;
|
pageCount = 2;
|
||||||
if (chapterSyncManager.getMyAnimeList().isLogged())
|
if (!is_online && mangaSyncManager.getMyAnimeList().isLogged())
|
||||||
pageCount++;
|
pageCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import java.util.List;
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
import uk.co.ribot.easyadapter.EasyAdapter;
|
import uk.co.ribot.easyadapter.EasyAdapter;
|
||||||
import uk.co.ribot.easyadapter.ItemViewHolder;
|
import uk.co.ribot.easyadapter.ItemViewHolder;
|
||||||
import uk.co.ribot.easyadapter.PositionInfo;
|
import uk.co.ribot.easyadapter.PositionInfo;
|
||||||
|
@ -29,60 +29,60 @@ public class MyAnimeListDialogFragment extends DialogFragment {
|
||||||
@Bind(R.id.myanimelist_search_button) Button searchButton;
|
@Bind(R.id.myanimelist_search_button) Button searchButton;
|
||||||
@Bind(R.id.myanimelist_search_results) ListView searchResults;
|
@Bind(R.id.myanimelist_search_results) ListView searchResults;
|
||||||
|
|
||||||
private EasyAdapter<ChapterSync> adapter;
|
private EasyAdapter<MangaSync> adapter;
|
||||||
private MyAnimeListFragment fragment;
|
private MyAnimeListFragment fragment;
|
||||||
private ChapterSync selectedItem;
|
private MyAnimeListPresenter presenter;
|
||||||
|
private MangaSync selectedItem;
|
||||||
|
|
||||||
public static MyAnimeListDialogFragment newInstance(MyAnimeListFragment parentFragment) {
|
public static MyAnimeListDialogFragment newInstance(MyAnimeListFragment parentFragment) {
|
||||||
MyAnimeListDialogFragment dialog = new MyAnimeListDialogFragment();
|
MyAnimeListDialogFragment dialog = new MyAnimeListDialogFragment();
|
||||||
dialog.setParentFragment(parentFragment);
|
dialog.fragment = parentFragment;
|
||||||
|
dialog.presenter = parentFragment.getPresenter();
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(Bundle savedState) {
|
public Dialog onCreateDialog(Bundle savedState) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
// Inflate and bind view
|
||||||
|
|
||||||
LayoutInflater inflater = getActivity().getLayoutInflater();
|
LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||||
|
|
||||||
View view = inflater.inflate(R.layout.dialog_myanimelist_search, null);
|
View view = inflater.inflate(R.layout.dialog_myanimelist_search, null);
|
||||||
ButterKnife.bind(this, view);
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
|
// Build dialog
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
builder.setView(view)
|
builder.setView(view)
|
||||||
.setPositiveButton(R.string.button_ok, (dialog, which) -> onPositiveButtonClick())
|
.setPositiveButton(R.string.button_ok, (dialog, which) -> onPositiveButtonClick())
|
||||||
.setNegativeButton(R.string.button_cancel, (dialog, which) -> {});
|
.setNegativeButton(R.string.button_cancel, (dialog, which) -> {});
|
||||||
|
|
||||||
|
// Create adapter
|
||||||
|
adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class);
|
||||||
|
searchResults.setAdapter(adapter);
|
||||||
|
|
||||||
|
// Set listeners
|
||||||
searchButton.setOnClickListener(v ->
|
searchButton.setOnClickListener(v ->
|
||||||
fragment.getPresenter().searchManga(searchText.getText().toString()));
|
presenter.searchManga(searchText.getText().toString()));
|
||||||
|
|
||||||
searchResults.setOnItemClickListener((parent, viewList, position, id) ->
|
searchResults.setOnItemClickListener((parent, viewList, position, id) ->
|
||||||
selectedItem = adapter.getItem(position));
|
selectedItem = adapter.getItem(position));
|
||||||
|
|
||||||
adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class);
|
// Do an initial search based on the manga's title
|
||||||
|
presenter.searchManga(presenter.manga.title);
|
||||||
searchResults.setAdapter(adapter);
|
|
||||||
|
|
||||||
return builder.create();
|
return builder.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onPositiveButtonClick() {
|
private void onPositiveButtonClick() {
|
||||||
if (adapter != null && selectedItem != null) {
|
if (adapter != null && selectedItem != null) {
|
||||||
fragment.getPresenter().registerManga(selectedItem);
|
presenter.registerManga(selectedItem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResults(List<ChapterSync> results) {
|
public void setResults(List<MangaSync> results) {
|
||||||
selectedItem = null;
|
selectedItem = null;
|
||||||
adapter.setItems(results);
|
adapter.setItems(results);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setParentFragment(MyAnimeListFragment fragment) {
|
|
||||||
this.fragment = fragment;
|
|
||||||
}
|
|
||||||
|
|
||||||
@LayoutId(R.layout.dialog_myanimelist_search_item)
|
@LayoutId(R.layout.dialog_myanimelist_search_item)
|
||||||
public static class ResultViewHolder extends ItemViewHolder<ChapterSync> {
|
public static class ResultViewHolder extends ItemViewHolder<MangaSync> {
|
||||||
|
|
||||||
@ViewId(R.id.myanimelist_result_title) TextView title;
|
@ViewId(R.id.myanimelist_result_title) TextView title;
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ public class MyAnimeListDialogFragment extends DialogFragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSetValues(ChapterSync chapter, PositionInfo positionInfo) {
|
public void onSetValues(MangaSync chapter, PositionInfo positionInfo) {
|
||||||
title.setText(chapter.title);
|
title.setText(chapter.title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,12 +11,13 @@ import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.text.DecimalFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
import eu.kanade.mangafeed.ui.base.fragment.BaseRxFragment;
|
||||||
import nucleus.factory.RequiresPresenter;
|
import nucleus.factory.RequiresPresenter;
|
||||||
|
|
||||||
|
@ -24,11 +25,15 @@ import nucleus.factory.RequiresPresenter;
|
||||||
public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> {
|
public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> {
|
||||||
|
|
||||||
@Bind(R.id.myanimelist_title) TextView title;
|
@Bind(R.id.myanimelist_title) TextView title;
|
||||||
@Bind(R.id.myanimelist_last_chapter_read) EditText lastChapterRead;
|
@Bind(R.id.last_chapter_read) EditText lastChapterRead;
|
||||||
|
@Bind(R.id.score) TextView score;
|
||||||
|
@Bind(R.id.status) TextView status;
|
||||||
@Bind(R.id.update_button) Button updateButton;
|
@Bind(R.id.update_button) Button updateButton;
|
||||||
|
|
||||||
private MyAnimeListDialogFragment dialog;
|
private MyAnimeListDialogFragment dialog;
|
||||||
|
|
||||||
|
private DecimalFormat decimalFormat = new DecimalFormat("#.##");
|
||||||
|
|
||||||
public static MyAnimeListFragment newInstance() {
|
public static MyAnimeListFragment newInstance() {
|
||||||
return new MyAnimeListFragment();
|
return new MyAnimeListFragment();
|
||||||
}
|
}
|
||||||
|
@ -66,9 +71,11 @@ public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> {
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setChapterSync(ChapterSync chapterSync) {
|
public void setMangaSync(MangaSync mangaSync) {
|
||||||
title.setText(chapterSync.title);
|
title.setText(mangaSync.title);
|
||||||
lastChapterRead.setText(chapterSync.last_chapter_read + "");
|
lastChapterRead.setText(mangaSync.last_chapter_read + "");
|
||||||
|
score.setText(decimalFormat.format(mangaSync.score));
|
||||||
|
status.setText(getPresenter().myAnimeList.getStatus(mangaSync.status));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showSearchDialog() {
|
private void showSearchDialog() {
|
||||||
|
@ -78,7 +85,7 @@ public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> {
|
||||||
dialog.show(getActivity().getSupportFragmentManager(), "search");
|
dialog.show(getActivity().getSupportFragmentManager(), "search");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSearchResults(List<ChapterSync> results) {
|
public void onSearchResults(List<MangaSync> results) {
|
||||||
if (dialog != null)
|
if (dialog != null)
|
||||||
dialog.setResults(results);
|
dialog.setResults(results);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,13 +4,14 @@ import android.os.Bundle;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager;
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.MyAnimeList;
|
import eu.kanade.mangafeed.data.mangasync.MangaSyncManager;
|
||||||
|
import eu.kanade.mangafeed.data.mangasync.services.MyAnimeList;
|
||||||
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
|
||||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||||
import eu.kanade.mangafeed.util.EventBusHook;
|
import eu.kanade.mangafeed.util.EventBusHook;
|
||||||
|
import eu.kanade.mangafeed.util.ToastUtil;
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
import rx.Subscription;
|
import rx.Subscription;
|
||||||
import rx.android.schedulers.AndroidSchedulers;
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
|
@ -20,11 +21,11 @@ import timber.log.Timber;
|
||||||
public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
||||||
|
|
||||||
@Inject DatabaseHelper db;
|
@Inject DatabaseHelper db;
|
||||||
@Inject ChapterSyncManager syncManager;
|
@Inject MangaSyncManager syncManager;
|
||||||
|
|
||||||
private MyAnimeList myAnimeList;
|
protected MyAnimeList myAnimeList;
|
||||||
private Manga manga;
|
protected Manga manga;
|
||||||
private ChapterSync chapterSync;
|
private MangaSync mangaSync;
|
||||||
|
|
||||||
private String query;
|
private String query;
|
||||||
|
|
||||||
|
@ -37,15 +38,19 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
||||||
protected void onCreate(Bundle savedState) {
|
protected void onCreate(Bundle savedState) {
|
||||||
super.onCreate(savedState);
|
super.onCreate(savedState);
|
||||||
|
|
||||||
|
if (savedState != null) {
|
||||||
|
onProcessRestart();
|
||||||
|
}
|
||||||
|
|
||||||
myAnimeList = syncManager.getMyAnimeList();
|
myAnimeList = syncManager.getMyAnimeList();
|
||||||
|
|
||||||
restartableLatestCache(GET_CHAPTER_SYNC,
|
restartableLatestCache(GET_CHAPTER_SYNC,
|
||||||
() -> db.getChapterSync(manga, myAnimeList).createObservable()
|
() -> db.getMangaSync(manga, myAnimeList).createObservable()
|
||||||
.flatMap(Observable::from)
|
.flatMap(Observable::from)
|
||||||
.doOnNext(chapterSync -> this.chapterSync = chapterSync)
|
.doOnNext(mangaSync -> this.mangaSync = mangaSync)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread()),
|
.observeOn(AndroidSchedulers.mainThread()),
|
||||||
MyAnimeListFragment::setChapterSync);
|
MyAnimeListFragment::setMangaSync);
|
||||||
|
|
||||||
restartableLatestCache(GET_SEARCH_RESULTS,
|
restartableLatestCache(GET_SEARCH_RESULTS,
|
||||||
() -> myAnimeList.search(query)
|
() -> myAnimeList.search(query)
|
||||||
|
@ -59,6 +64,11 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void onProcessRestart() {
|
||||||
|
stop(GET_CHAPTER_SYNC);
|
||||||
|
stop(GET_SEARCH_RESULTS);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onTakeView(MyAnimeListFragment view) {
|
protected void onTakeView(MyAnimeListFragment view) {
|
||||||
super.onTakeView(view);
|
super.onTakeView(view);
|
||||||
|
@ -81,10 +91,10 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
||||||
if (updateSubscription != null)
|
if (updateSubscription != null)
|
||||||
remove(updateSubscription);
|
remove(updateSubscription);
|
||||||
|
|
||||||
chapterSync.last_chapter_read = chapterNumber;
|
mangaSync.last_chapter_read = chapterNumber;
|
||||||
|
|
||||||
add(updateSubscription = myAnimeList.update(chapterSync)
|
add(updateSubscription = myAnimeList.update(mangaSync)
|
||||||
.flatMap(response -> db.insertChapterSync(chapterSync).createObservable())
|
.flatMap(response -> db.insertMangaSync(mangaSync).createObservable())
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(response -> {},
|
.subscribe(response -> {},
|
||||||
|
@ -99,8 +109,19 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
||||||
start(GET_SEARCH_RESULTS);
|
start(GET_SEARCH_RESULTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerManga(ChapterSync selectedManga) {
|
public void registerManga(MangaSync manga) {
|
||||||
selectedManga.manga_id = manga.id;
|
manga.manga_id = this.manga.id;
|
||||||
db.insertChapterSync(selectedManga).executeAsBlocking();
|
add(myAnimeList.bind(manga)
|
||||||
|
.flatMap(response -> {
|
||||||
|
if (response.code() == 200 || response.code() == 201)
|
||||||
|
return Observable.just(manga);
|
||||||
|
return Observable.error(new Exception("Could not add manga"));
|
||||||
|
})
|
||||||
|
.flatMap(manga2 -> db.insertMangaSync(manga2).createObservable())
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(manga2 -> {},
|
||||||
|
error -> ToastUtil.showShort(getContext(), error.getMessage())));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,12 +8,12 @@ import java.util.List;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
import de.greenrobot.event.EventBus;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager;
|
import eu.kanade.mangafeed.data.mangasync.MangaSyncManager;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.MyAnimeList;
|
import eu.kanade.mangafeed.data.mangasync.services.MyAnimeList;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.UpdateChapterSyncService;
|
import eu.kanade.mangafeed.data.sync.UpdateMangaSyncService;
|
||||||
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
import eu.kanade.mangafeed.data.database.DatabaseHelper;
|
||||||
import eu.kanade.mangafeed.data.database.models.Chapter;
|
import eu.kanade.mangafeed.data.database.models.Chapter;
|
||||||
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
import eu.kanade.mangafeed.data.database.models.MangaSync;
|
||||||
import eu.kanade.mangafeed.data.database.models.Manga;
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
import eu.kanade.mangafeed.data.download.DownloadManager;
|
import eu.kanade.mangafeed.data.download.DownloadManager;
|
||||||
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
||||||
|
@ -21,7 +21,7 @@ import eu.kanade.mangafeed.data.source.SourceManager;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
import eu.kanade.mangafeed.data.source.model.Page;
|
import eu.kanade.mangafeed.data.source.model.Page;
|
||||||
import eu.kanade.mangafeed.event.ReaderEvent;
|
import eu.kanade.mangafeed.event.ReaderEvent;
|
||||||
import eu.kanade.mangafeed.event.UpdateChapterSyncEvent;
|
import eu.kanade.mangafeed.event.UpdateMangaSyncEvent;
|
||||||
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||||
import eu.kanade.mangafeed.util.EventBusHook;
|
import eu.kanade.mangafeed.util.EventBusHook;
|
||||||
import icepick.State;
|
import icepick.State;
|
||||||
|
@ -37,7 +37,7 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
||||||
@Inject PreferencesHelper prefs;
|
@Inject PreferencesHelper prefs;
|
||||||
@Inject DatabaseHelper db;
|
@Inject DatabaseHelper db;
|
||||||
@Inject DownloadManager downloadManager;
|
@Inject DownloadManager downloadManager;
|
||||||
@Inject ChapterSyncManager syncManager;
|
@Inject MangaSyncManager syncManager;
|
||||||
@Inject SourceManager sourceManager;
|
@Inject SourceManager sourceManager;
|
||||||
|
|
||||||
@State Manga manga;
|
@State Manga manga;
|
||||||
|
@ -235,7 +235,7 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
||||||
chapter.last_page_read = currentPage;
|
chapter.last_page_read = currentPage;
|
||||||
if (isChapterFinished()) {
|
if (isChapterFinished()) {
|
||||||
chapter.read = true;
|
chapter.read = true;
|
||||||
updateChapterSyncLastChapterRead();
|
updateMangaSyncLastChapterRead();
|
||||||
}
|
}
|
||||||
db.insertChapter(chapter).executeAsBlocking();
|
db.insertChapter(chapter).executeAsBlocking();
|
||||||
}
|
}
|
||||||
|
@ -245,26 +245,26 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
||||||
return !chapter.read && currentPage == pageList.size() - 1;
|
return !chapter.read && currentPage == pageList.size() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateChapterSyncLastChapterRead() {
|
private void updateMangaSyncLastChapterRead() {
|
||||||
// TODO don't use MAL methods for possible alternatives to MAL
|
// TODO don't use MAL methods for possible alternatives to MAL
|
||||||
MyAnimeList mal = syncManager.getMyAnimeList();
|
MyAnimeList mal = syncManager.getMyAnimeList();
|
||||||
|
|
||||||
if (!mal.isLogged())
|
if (!mal.isLogged())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
List<ChapterSync> result = db.getChapterSync(manga, mal).executeAsBlocking();
|
List<MangaSync> result = db.getMangaSync(manga, mal).executeAsBlocking();
|
||||||
if (result.isEmpty())
|
if (result.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ChapterSync chapterSync = result.get(0);
|
MangaSync mangaSync = result.get(0);
|
||||||
|
|
||||||
int lastChapterReadLocal = (int) Math.floor(chapter.chapter_number);
|
int lastChapterReadLocal = (int) Math.floor(chapter.chapter_number);
|
||||||
int lastChapterReadRemote = chapterSync.last_chapter_read;
|
int lastChapterReadRemote = mangaSync.last_chapter_read;
|
||||||
|
|
||||||
if (lastChapterReadLocal > lastChapterReadRemote) {
|
if (lastChapterReadLocal > lastChapterReadRemote) {
|
||||||
chapterSync.last_chapter_read = lastChapterReadLocal;
|
mangaSync.last_chapter_read = lastChapterReadLocal;
|
||||||
EventBus.getDefault().postSticky(new UpdateChapterSyncEvent(chapterSync));
|
EventBus.getDefault().postSticky(new UpdateMangaSyncEvent(mangaSync));
|
||||||
UpdateChapterSyncService.start(getContext());
|
UpdateMangaSyncService.start(getContext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,18 +12,18 @@ import java.util.List;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.App;
|
import eu.kanade.mangafeed.App;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.BaseChapterSync;
|
import eu.kanade.mangafeed.data.mangasync.base.BaseMangaSync;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager;
|
import eu.kanade.mangafeed.data.mangasync.MangaSyncManager;
|
||||||
import eu.kanade.mangafeed.data.source.SourceManager;
|
import eu.kanade.mangafeed.data.source.SourceManager;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
import eu.kanade.mangafeed.ui.setting.preference.ChapterSyncLoginDialog;
|
import eu.kanade.mangafeed.ui.setting.preference.MangaSyncLoginDialog;
|
||||||
import eu.kanade.mangafeed.ui.setting.preference.SourceLoginDialog;
|
import eu.kanade.mangafeed.ui.setting.preference.SourceLoginDialog;
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
|
|
||||||
public class SettingsAccountsFragment extends SettingsNestedFragment {
|
public class SettingsAccountsFragment extends SettingsNestedFragment {
|
||||||
|
|
||||||
@Inject SourceManager sourceManager;
|
@Inject SourceManager sourceManager;
|
||||||
@Inject ChapterSyncManager syncManager;
|
@Inject MangaSyncManager syncManager;
|
||||||
|
|
||||||
public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) {
|
public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) {
|
||||||
SettingsNestedFragment fragment = new SettingsAccountsFragment();
|
SettingsNestedFragment fragment = new SettingsAccountsFragment();
|
||||||
|
@ -56,16 +56,16 @@ public class SettingsAccountsFragment extends SettingsNestedFragment {
|
||||||
sourceCategory.addPreference(dialog);
|
sourceCategory.addPreference(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferenceCategory chapterSyncCategory = new PreferenceCategory(screen.getContext());
|
PreferenceCategory mangaSyncCategory = new PreferenceCategory(screen.getContext());
|
||||||
chapterSyncCategory.setTitle("Sync");
|
mangaSyncCategory.setTitle("Sync");
|
||||||
screen.addPreference(chapterSyncCategory);
|
screen.addPreference(mangaSyncCategory);
|
||||||
|
|
||||||
for (BaseChapterSync sync : syncManager.getChapterSyncServices()) {
|
for (BaseMangaSync sync : syncManager.getSyncServices()) {
|
||||||
ChapterSyncLoginDialog dialog = new ChapterSyncLoginDialog(
|
MangaSyncLoginDialog dialog = new MangaSyncLoginDialog(
|
||||||
screen.getContext(), preferences, sync);
|
screen.getContext(), preferences, sync);
|
||||||
dialog.setTitle(sync.getName());
|
dialog.setTitle(sync.getName());
|
||||||
|
|
||||||
chapterSyncCategory.addPreference(dialog);
|
mangaSyncCategory.addPreference(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
|
|
|
@ -5,17 +5,17 @@ import android.content.DialogInterface;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.chaptersync.BaseChapterSync;
|
import eu.kanade.mangafeed.data.mangasync.base.BaseMangaSync;
|
||||||
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
||||||
import eu.kanade.mangafeed.util.ToastUtil;
|
import eu.kanade.mangafeed.util.ToastUtil;
|
||||||
import rx.android.schedulers.AndroidSchedulers;
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
import rx.schedulers.Schedulers;
|
import rx.schedulers.Schedulers;
|
||||||
|
|
||||||
public class ChapterSyncLoginDialog extends LoginDialogPreference {
|
public class MangaSyncLoginDialog extends LoginDialogPreference {
|
||||||
|
|
||||||
private BaseChapterSync sync;
|
private BaseMangaSync sync;
|
||||||
|
|
||||||
public ChapterSyncLoginDialog(Context context, PreferencesHelper preferences, BaseChapterSync sync) {
|
public MangaSyncLoginDialog(Context context, PreferencesHelper preferences, BaseMangaSync sync) {
|
||||||
super(context, preferences);
|
super(context, preferences);
|
||||||
this.sync = sync;
|
this.sync = sync;
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,8 @@ public class ChapterSyncLoginDialog extends LoginDialogPreference {
|
||||||
|
|
||||||
title.setText(getContext().getString(R.string.accounts_login_title, sync.getName()));
|
title.setText(getContext().getString(R.string.accounts_login_title, sync.getName()));
|
||||||
|
|
||||||
username.setText(preferences.getChapterSyncUsername(sync));
|
username.setText(preferences.getMangaSyncUsername(sync));
|
||||||
password.setText(preferences.getChapterSyncPassword(sync));
|
password.setText(preferences.getMangaSyncPassword(sync));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -35,7 +35,7 @@ public class ChapterSyncLoginDialog extends LoginDialogPreference {
|
||||||
super.onDialogClosed(positiveResult);
|
super.onDialogClosed(positiveResult);
|
||||||
|
|
||||||
if (positiveResult) {
|
if (positiveResult) {
|
||||||
preferences.setChapterSyncCredentials(sync,
|
preferences.setMangaSyncCredentials(sync,
|
||||||
username.getText().toString(),
|
username.getText().toString(),
|
||||||
password.getText().toString());
|
password.getText().toString());
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ public class ChapterSyncLoginDialog extends LoginDialogPreference {
|
||||||
dialog.dismiss();
|
dialog.dismiss();
|
||||||
ToastUtil.showShort(context, R.string.login_success);
|
ToastUtil.showShort(context, R.string.login_success);
|
||||||
} else {
|
} else {
|
||||||
preferences.setChapterSyncCredentials(sync, "", "");
|
preferences.setMangaSyncCredentials(sync, "", "");
|
||||||
loginBtn.setProgress(-1);
|
loginBtn.setProgress(-1);
|
||||||
}
|
}
|
||||||
}, error -> {
|
}, error -> {
|
|
@ -35,7 +35,7 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:inputType="number"
|
android:inputType="number"
|
||||||
android:ems="10"
|
android:ems="10"
|
||||||
android:id="@+id/myanimelist_last_chapter_read"/>
|
android:id="@+id/last_chapter_read"/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
@ -45,5 +45,40 @@
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Score"
|
||||||
|
android:layout_marginRight="10dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/score"/>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Status"
|
||||||
|
android:layout_marginRight="10dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/status"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
|
@ -22,7 +22,7 @@
|
||||||
<item>@string/webtoon_viewer</item>
|
<item>@string/webtoon_viewer</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
<string-array name="download_threads">
|
<string-array name="download_slots">
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
<item>2</item>
|
<item>2</item>
|
||||||
<item>3</item>
|
<item>3</item>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<string name="pref_custom_brightness_value_key">pref_custom_brightness_value_key</string>
|
<string name="pref_custom_brightness_value_key">pref_custom_brightness_value_key</string>
|
||||||
|
|
||||||
<string name="pref_download_directory_key">pref_download_directory_key</string>
|
<string name="pref_download_directory_key">pref_download_directory_key</string>
|
||||||
<string name="pref_download_threads_key">pref_download_threads_key</string>
|
<string name="pref_download_slots_key">pref_download_slots_key</string>
|
||||||
|
|
||||||
<string name="pref_chapter_cache_size_key">pref_chapter_cache_size_key</string>
|
<string name="pref_chapter_cache_size_key">pref_chapter_cache_size_key</string>
|
||||||
<string name="pref_clear_chapter_cache_key">pref_clear_chapter_cache_key</string>
|
<string name="pref_clear_chapter_cache_key">pref_clear_chapter_cache_key</string>
|
||||||
|
|
|
@ -56,7 +56,7 @@
|
||||||
|
|
||||||
<!-- Downloads section -->
|
<!-- Downloads section -->
|
||||||
<string name="pref_download_directory">Downloads directory</string>
|
<string name="pref_download_directory">Downloads directory</string>
|
||||||
<string name="pref_download_threads">Download threads</string>
|
<string name="pref_download_slots">Simultaneous downloads</string>
|
||||||
|
|
||||||
<!-- Cache section -->
|
<!-- Cache section -->
|
||||||
<string name="pref_chapter_cache_size">Chapters cache size</string>
|
<string name="pref_chapter_cache_size">Chapters cache size</string>
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
android:title="@string/pref_download_directory"
|
android:title="@string/pref_download_directory"
|
||||||
android:key="@string/pref_download_directory_key"/>
|
android:key="@string/pref_download_directory_key"/>
|
||||||
|
|
||||||
<ListPreference
|
<eu.kanade.mangafeed.ui.setting.preference.IntListPreference
|
||||||
android:title="@string/pref_download_threads"
|
android:title="@string/pref_download_slots"
|
||||||
android:key="@string/pref_download_threads_key"
|
android:key="@string/pref_download_slots_key"
|
||||||
android:entries="@array/download_threads"
|
android:entries="@array/download_slots"
|
||||||
android:entryValues="@array/download_threads"
|
android:entryValues="@array/download_slots"
|
||||||
android:defaultValue="1"
|
android:defaultValue="1"
|
||||||
android:summary="%s"/>
|
android:summary="%s"/>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue