mirror of
				https://github.com/mihonapp/mihon.git
				synced 2025-10-30 22:07:57 +01:00 
			
		
		
		
	Improve MAL support (UI is very simple yet).
This commit is contained in:
		| @@ -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 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.ChapterStorIOSQLiteDeleteResolver; | ||||
| import eu.kanade.mangafeed.data.database.models.ChapterStorIOSQLiteGetResolver; | ||||
| 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.MangaStorIOSQLiteDeleteResolver; | ||||
| import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLiteGetResolver; | ||||
| 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.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.MangaTable; | ||||
| import eu.kanade.mangafeed.util.ChapterRecognition; | ||||
| @@ -55,10 +55,10 @@ public class DatabaseHelper { | ||||
|                         .getResolver(new ChapterStorIOSQLiteGetResolver()) | ||||
|                         .deleteResolver(new ChapterStorIOSQLiteDeleteResolver()) | ||||
|                         .build()) | ||||
|                 .addTypeMapping(ChapterSync.class, SQLiteTypeMapping.<ChapterSync>builder() | ||||
|                         .putResolver(new ChapterSyncStorIOSQLitePutResolver()) | ||||
|                         .getResolver(new ChapterSyncStorIOSQLiteGetResolver()) | ||||
|                         .deleteResolver(new ChapterSyncStorIOSQLiteDeleteResolver()) | ||||
|                 .addTypeMapping(MangaSync.class, SQLiteTypeMapping.<MangaSync>builder() | ||||
|                         .putResolver(new MangaSyncStorIOSQLitePutResolver()) | ||||
|                         .getResolver(new MangaSyncStorIOSQLiteGetResolver()) | ||||
|                         .deleteResolver(new MangaSyncStorIOSQLiteDeleteResolver()) | ||||
|                         .build()) | ||||
|                 .build(); | ||||
|     } | ||||
| @@ -88,7 +88,7 @@ public class DatabaseHelper { | ||||
|                 .prepare(); | ||||
|     } | ||||
|  | ||||
|     public PreparedGetListOfObjects<Manga> getMangasWithUnread() { | ||||
|     public PreparedGetListOfObjects<Manga> getFavoriteMangasWithUnread() { | ||||
|         return db.get() | ||||
|                 .listOfObjects(Manga.class) | ||||
|                 .withQuery(RawQuery.builder() | ||||
| @@ -301,30 +301,30 @@ public class DatabaseHelper { | ||||
|                 .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() | ||||
|                 .listOfObjects(ChapterSync.class) | ||||
|                 .listOfObjects(MangaSync.class) | ||||
|                 .withQuery(Query.builder() | ||||
|                         .table(ChapterSyncTable.TABLE) | ||||
|                         .where(ChapterSyncTable.COLUMN_MANGA_ID + "=? AND " + | ||||
|                                 ChapterSyncTable.COLUMN_SYNC_ID + "=?") | ||||
|                         .table(MangaSyncTable.TABLE) | ||||
|                         .where(MangaSyncTable.COLUMN_MANGA_ID + "=? AND " + | ||||
|                                 MangaSyncTable.COLUMN_SYNC_ID + "=?") | ||||
|                         .whereArgs(manga.id, sync.getId()) | ||||
|                         .build()) | ||||
|                 .prepare(); | ||||
|     } | ||||
|  | ||||
|     public PreparedPutObject<ChapterSync> insertChapterSync(ChapterSync chapter) { | ||||
|     public PreparedPutObject<MangaSync> insertMangaSync(MangaSync manga) { | ||||
|         return db.put() | ||||
|                 .object(chapter) | ||||
|                 .object(manga) | ||||
|                 .prepare(); | ||||
|     } | ||||
|  | ||||
|     public PreparedDeleteObject<ChapterSync> deleteChapterSync(ChapterSync chapter) { | ||||
|     public PreparedDeleteObject<MangaSync> deleteMangaSync(MangaSync manga) { | ||||
|         return db.delete() | ||||
|                 .object(chapter) | ||||
|                 .object(manga) | ||||
|                 .prepare(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -5,14 +5,14 @@ import android.database.sqlite.SQLiteDatabase; | ||||
| import android.database.sqlite.SQLiteOpenHelper; | ||||
| 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.MangaTable; | ||||
|  | ||||
| public class DbOpenHelper extends SQLiteOpenHelper { | ||||
|  | ||||
|     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) { | ||||
|         super(context, DATABASE_NAME, null, DATABASE_VERSION); | ||||
| @@ -22,13 +22,13 @@ public class DbOpenHelper extends SQLiteOpenHelper { | ||||
|     public void onCreate(@NonNull SQLiteDatabase db) { | ||||
|         db.execSQL(MangaTable.getCreateTableQuery()); | ||||
|         db.execSQL(ChapterTable.getCreateTableQuery()); | ||||
|         db.execSQL(ChapterSyncTable.getCreateTableQuery()); | ||||
|         db.execSQL(MangaSyncTable.getCreateTableQuery()); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) { | ||||
|         if (oldVersion == 1) | ||||
|             db.execSQL(ChapterSyncTable.getCreateTableQuery()); | ||||
|         if (oldVersion < 3) | ||||
|             db.execSQL(MangaSyncTable.getCreateTableQuery()); | ||||
|     } | ||||
|  | ||||
|     @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; | ||||
| 
 | ||||
| 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"; | ||||
| 
 | ||||
| @@ -18,6 +18,10 @@ public class ChapterSyncTable { | ||||
| 
 | ||||
|     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 | ||||
|     public static String getCreateTableQuery() { | ||||
|         return "CREATE TABLE " + TABLE + "(" | ||||
| @@ -27,6 +31,8 @@ public class ChapterSyncTable { | ||||
|                 + COLUMN_REMOTE_ID + " INTEGER NOT NULL, " | ||||
|                 + COLUMN_TITLE + " TEXT 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 + ") " | ||||
|                 + "ON DELETE CASCADE" | ||||
|                 + ");"; | ||||
| @@ -1,18 +1,21 @@ | ||||
| package eu.kanade.mangafeed.data.chaptersync; | ||||
| package eu.kanade.mangafeed.data.mangasync; | ||||
| 
 | ||||
| import android.content.Context; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| 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; | ||||
| 
 | ||||
|     public static final int MYANIMELIST = 1; | ||||
| 
 | ||||
|     public ChapterSyncManager(Context context) { | ||||
|     public MangaSyncManager(Context context) { | ||||
|         services = new ArrayList<>(); | ||||
|         myAnimeList = new MyAnimeList(context); | ||||
|         services.add(myAnimeList); | ||||
| @@ -22,11 +25,11 @@ public class ChapterSyncManager { | ||||
|         return myAnimeList; | ||||
|     } | ||||
| 
 | ||||
|     public List<BaseChapterSync> getChapterSyncServices() { | ||||
|     public List<BaseMangaSync> getSyncServices() { | ||||
|         return services; | ||||
|     } | ||||
| 
 | ||||
|     public BaseChapterSync getSyncService(int id) { | ||||
|     public BaseMangaSync getSyncService(int id) { | ||||
|         switch (id) { | ||||
|             case 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 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 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_PASSWORD = "pref_source_password_"; | ||||
|     private static final String CHAPTERSYNC_ACCOUNT_USERNAME = "pref_chaptersync_username_"; | ||||
|     private static final String CHAPTERSYNC_ACCOUNT_PASSWORD = "pref_chaptersync_password_"; | ||||
|     private static final String MANGASYNC_ACCOUNT_USERNAME = "pref_mangasync_username_"; | ||||
|     private static final String MANGASYNC_ACCOUNT_PASSWORD = "pref_mangasync_password_"; | ||||
|  | ||||
|     private File defaultDownloadsDir; | ||||
|  | ||||
| @@ -102,18 +102,18 @@ public class PreferencesHelper { | ||||
|                 .apply(); | ||||
|     } | ||||
|  | ||||
|     public String getChapterSyncUsername(BaseChapterSync sync) { | ||||
|         return prefs.getString(CHAPTERSYNC_ACCOUNT_USERNAME + sync.getId(), ""); | ||||
|     public String getMangaSyncUsername(BaseMangaSync sync) { | ||||
|         return prefs.getString(MANGASYNC_ACCOUNT_USERNAME + sync.getId(), ""); | ||||
|     } | ||||
|  | ||||
|     public String getChapterSyncPassword(BaseChapterSync sync) { | ||||
|         return prefs.getString(CHAPTERSYNC_ACCOUNT_PASSWORD + sync.getId(), ""); | ||||
|     public String getMangaSyncPassword(BaseMangaSync sync) { | ||||
|         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() | ||||
|                 .putString(CHAPTERSYNC_ACCOUNT_USERNAME + sync.getId(), username) | ||||
|                 .putString(CHAPTERSYNC_ACCOUNT_PASSWORD + sync.getId(), password) | ||||
|                 .putString(MANGASYNC_ACCOUNT_USERNAME + sync.getId(), username) | ||||
|                 .putString(MANGASYNC_ACCOUNT_PASSWORD + sync.getId(), password) | ||||
|                 .apply(); | ||||
|     } | ||||
|  | ||||
| @@ -127,12 +127,11 @@ public class PreferencesHelper { | ||||
|     } | ||||
|  | ||||
|     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() { | ||||
|         return rxPrefs.getString(getKey(R.string.pref_download_threads_key), "1") | ||||
|                 .asObservable().map(Integer::parseInt); | ||||
|         return rxPrefs.getInteger(getKey(R.string.pref_download_slots_key), 1).asObservable(); | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| package eu.kanade.mangafeed.data.chaptersync; | ||||
| package eu.kanade.mangafeed.data.sync; | ||||
| 
 | ||||
| import android.app.Service; | ||||
| import android.content.Context; | ||||
| @@ -10,24 +10,24 @@ import javax.inject.Inject; | ||||
| import de.greenrobot.event.EventBus; | ||||
| import eu.kanade.mangafeed.App; | ||||
| import eu.kanade.mangafeed.data.database.DatabaseHelper; | ||||
| import eu.kanade.mangafeed.data.database.models.ChapterSync; | ||||
| import eu.kanade.mangafeed.data.network.NetworkHelper; | ||||
| import eu.kanade.mangafeed.event.UpdateChapterSyncEvent; | ||||
| 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.event.UpdateMangaSyncEvent; | ||||
| import eu.kanade.mangafeed.util.EventBusHook; | ||||
| import rx.android.schedulers.AndroidSchedulers; | ||||
| import rx.schedulers.Schedulers; | ||||
| import rx.subscriptions.CompositeSubscription; | ||||
| 
 | ||||
| public class UpdateChapterSyncService extends Service { | ||||
| public class UpdateMangaSyncService extends Service { | ||||
| 
 | ||||
|     @Inject ChapterSyncManager syncManager; | ||||
|     @Inject NetworkHelper networkManager; | ||||
|     @Inject MangaSyncManager syncManager; | ||||
|     @Inject DatabaseHelper db; | ||||
| 
 | ||||
|     private CompositeSubscription subscriptions; | ||||
| 
 | ||||
|     public static void start(Context context) { | ||||
|         context.startService(new Intent(context, UpdateChapterSyncService.class)); | ||||
|         context.startService(new Intent(context, UpdateMangaSyncService.class)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @@ -56,15 +56,15 @@ public class UpdateChapterSyncService extends Service { | ||||
|     } | ||||
| 
 | ||||
|     @EventBusHook | ||||
|     public void onEventMainThread(UpdateChapterSyncEvent event) { | ||||
|         updateLastChapteRead(event.getChapterSync()); | ||||
|     public void onEventMainThread(UpdateMangaSyncEvent event) { | ||||
|         updateLastChapteRead(event.getMangaSync()); | ||||
|     } | ||||
| 
 | ||||
|     private void updateLastChapteRead(ChapterSync chapterSync) { | ||||
|         BaseChapterSync sync = syncManager.getSyncService(chapterSync.sync_id); | ||||
|     private void updateLastChapteRead(MangaSync mangaSync) { | ||||
|         BaseMangaSync sync = syncManager.getSyncService(mangaSync.sync_id); | ||||
| 
 | ||||
|         subscriptions.add(sync.update(chapterSync) | ||||
|                 .flatMap(response -> db.insertChapterSync(chapterSync).createObservable()) | ||||
|         subscriptions.add(sync.update(mangaSync) | ||||
|                 .flatMap(response -> db.insertMangaSync(mangaSync).createObservable()) | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .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 dagger.Component; | ||||
| import eu.kanade.mangafeed.data.chaptersync.MyAnimeList; | ||||
| import eu.kanade.mangafeed.data.chaptersync.UpdateChapterSyncService; | ||||
| import eu.kanade.mangafeed.data.mangasync.services.MyAnimeList; | ||||
| import eu.kanade.mangafeed.data.sync.UpdateMangaSyncService; | ||||
| import eu.kanade.mangafeed.data.download.DownloadService; | ||||
| import eu.kanade.mangafeed.data.source.base.Source; | ||||
| import eu.kanade.mangafeed.data.sync.LibraryUpdateService; | ||||
| @@ -56,7 +56,7 @@ public interface AppComponent { | ||||
|  | ||||
|     void inject(LibraryUpdateService libraryUpdateService); | ||||
|     void inject(DownloadService downloadService); | ||||
|     void inject(UpdateChapterSyncService updateChapterSyncService); | ||||
|     void inject(UpdateMangaSyncService updateMangaSyncService); | ||||
|  | ||||
|     Application application(); | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import dagger.Module; | ||||
| import dagger.Provides; | ||||
| import eu.kanade.mangafeed.data.cache.CacheManager; | ||||
| 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.download.DownloadManager; | ||||
| import eu.kanade.mangafeed.data.network.NetworkHelper; | ||||
| @@ -66,8 +66,8 @@ public class DataModule { | ||||
|  | ||||
|     @Provides | ||||
|     @Singleton | ||||
|     ChapterSyncManager provideChapterSyncManager(Application app) { | ||||
|         return new ChapterSyncManager(app); | ||||
|     MangaSyncManager provideMangaSyncManager(Application app) { | ||||
|         return new MangaSyncManager(app); | ||||
|     } | ||||
|  | ||||
| } | ||||
| @@ -28,7 +28,7 @@ public class LibraryPresenter extends BasePresenter<LibraryFragment> { | ||||
|         super.onCreate(savedState); | ||||
|  | ||||
|         restartableLatestCache(GET_MANGAS, | ||||
|                 () -> db.getMangasWithUnread().createObservable() | ||||
|                 () -> db.getFavoriteMangasWithUnread().createObservable() | ||||
|                         .subscribeOn(Schedulers.io()) | ||||
|                         .observeOn(AndroidSchedulers.mainThread()), | ||||
|                 LibraryFragment::onNextMangas); | ||||
|   | ||||
| @@ -17,7 +17,7 @@ import butterknife.Bind; | ||||
| import butterknife.ButterKnife; | ||||
| import eu.kanade.mangafeed.App; | ||||
| 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.preference.PreferencesHelper; | ||||
| 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; | ||||
|  | ||||
|     @Inject PreferencesHelper preferences; | ||||
|     @Inject ChapterSyncManager chapterSyncManager; | ||||
|     @Inject MangaSyncManager mangaSyncManager; | ||||
|  | ||||
|     private MangaDetailAdapter adapter; | ||||
|     private long manga_id; | ||||
| @@ -116,7 +116,7 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> { | ||||
|             }; | ||||
|  | ||||
|             pageCount = 2; | ||||
|             if (chapterSyncManager.getMyAnimeList().isLogged()) | ||||
|             if (!is_online && mangaSyncManager.getMyAnimeList().isLogged()) | ||||
|                 pageCount++; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -16,7 +16,7 @@ import java.util.List; | ||||
| import butterknife.Bind; | ||||
| import butterknife.ButterKnife; | ||||
| 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.ItemViewHolder; | ||||
| 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_results) ListView searchResults; | ||||
|  | ||||
|     private EasyAdapter<ChapterSync> adapter; | ||||
|     private EasyAdapter<MangaSync> adapter; | ||||
|     private MyAnimeListFragment fragment; | ||||
|     private ChapterSync selectedItem; | ||||
|     private MyAnimeListPresenter presenter; | ||||
|     private MangaSync selectedItem; | ||||
|  | ||||
|     public static MyAnimeListDialogFragment newInstance(MyAnimeListFragment parentFragment) { | ||||
|         MyAnimeListDialogFragment dialog = new MyAnimeListDialogFragment(); | ||||
|         dialog.setParentFragment(parentFragment); | ||||
|         dialog.fragment = parentFragment; | ||||
|         dialog.presenter = parentFragment.getPresenter(); | ||||
|         return dialog; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public Dialog onCreateDialog(Bundle savedState) { | ||||
|         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); | ||||
|  | ||||
|         // Inflate and bind view | ||||
|         LayoutInflater inflater = getActivity().getLayoutInflater(); | ||||
|  | ||||
|         View view = inflater.inflate(R.layout.dialog_myanimelist_search, null); | ||||
|         ButterKnife.bind(this, view); | ||||
|  | ||||
|  | ||||
|         // Build dialog | ||||
|         AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); | ||||
|         builder.setView(view) | ||||
|                 .setPositiveButton(R.string.button_ok, (dialog, which) -> onPositiveButtonClick()) | ||||
|                 .setNegativeButton(R.string.button_cancel, (dialog, which) -> {}); | ||||
|  | ||||
|         // Create adapter | ||||
|         adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class); | ||||
|         searchResults.setAdapter(adapter); | ||||
|  | ||||
|         // Set listeners | ||||
|         searchButton.setOnClickListener(v -> | ||||
|                 fragment.getPresenter().searchManga(searchText.getText().toString())); | ||||
|                 presenter.searchManga(searchText.getText().toString())); | ||||
|  | ||||
|         searchResults.setOnItemClickListener((parent, viewList, position, id) -> | ||||
|                 selectedItem = adapter.getItem(position)); | ||||
|  | ||||
|         adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class); | ||||
|  | ||||
|         searchResults.setAdapter(adapter); | ||||
|  | ||||
|         // Do an initial search based on the manga's title | ||||
|         presenter.searchManga(presenter.manga.title); | ||||
|         return builder.create(); | ||||
|     } | ||||
|  | ||||
|     private void onPositiveButtonClick() { | ||||
|         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; | ||||
|         adapter.setItems(results); | ||||
|     } | ||||
|  | ||||
|     public void setParentFragment(MyAnimeListFragment fragment) { | ||||
|         this.fragment = fragment; | ||||
|     } | ||||
|  | ||||
|     @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; | ||||
|  | ||||
| @@ -91,7 +91,7 @@ public class MyAnimeListDialogFragment extends DialogFragment { | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public void onSetValues(ChapterSync chapter, PositionInfo positionInfo) { | ||||
|         public void onSetValues(MangaSync chapter, PositionInfo positionInfo) { | ||||
|             title.setText(chapter.title); | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -11,12 +11,13 @@ import android.widget.Button; | ||||
| import android.widget.EditText; | ||||
| import android.widget.TextView; | ||||
|  | ||||
| import java.text.DecimalFormat; | ||||
| import java.util.List; | ||||
|  | ||||
| import butterknife.Bind; | ||||
| import butterknife.ButterKnife; | ||||
| 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 nucleus.factory.RequiresPresenter; | ||||
|  | ||||
| @@ -24,11 +25,15 @@ import nucleus.factory.RequiresPresenter; | ||||
| public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> { | ||||
|  | ||||
|     @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; | ||||
|  | ||||
|     private MyAnimeListDialogFragment dialog; | ||||
|  | ||||
|     private DecimalFormat decimalFormat = new DecimalFormat("#.##"); | ||||
|  | ||||
|     public static MyAnimeListFragment newInstance() { | ||||
|         return new MyAnimeListFragment(); | ||||
|     } | ||||
| @@ -66,9 +71,11 @@ public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> { | ||||
|         return super.onOptionsItemSelected(item); | ||||
|     } | ||||
|  | ||||
|     public void setChapterSync(ChapterSync chapterSync) { | ||||
|         title.setText(chapterSync.title); | ||||
|         lastChapterRead.setText(chapterSync.last_chapter_read + ""); | ||||
|     public void setMangaSync(MangaSync mangaSync) { | ||||
|         title.setText(mangaSync.title); | ||||
|         lastChapterRead.setText(mangaSync.last_chapter_read + ""); | ||||
|         score.setText(decimalFormat.format(mangaSync.score)); | ||||
|         status.setText(getPresenter().myAnimeList.getStatus(mangaSync.status)); | ||||
|     } | ||||
|  | ||||
|     private void showSearchDialog() { | ||||
| @@ -78,7 +85,7 @@ public class MyAnimeListFragment extends BaseRxFragment<MyAnimeListPresenter> { | ||||
|         dialog.show(getActivity().getSupportFragmentManager(), "search"); | ||||
|     } | ||||
|  | ||||
|     public void onSearchResults(List<ChapterSync> results) { | ||||
|     public void onSearchResults(List<MangaSync> results) { | ||||
|         if (dialog != null) | ||||
|             dialog.setResults(results); | ||||
|     } | ||||
|   | ||||
| @@ -4,13 +4,14 @@ import android.os.Bundle; | ||||
|  | ||||
| import javax.inject.Inject; | ||||
|  | ||||
| import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager; | ||||
| import eu.kanade.mangafeed.data.chaptersync.MyAnimeList; | ||||
| import eu.kanade.mangafeed.data.database.models.MangaSync; | ||||
| 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.models.ChapterSync; | ||||
| import eu.kanade.mangafeed.data.database.models.Manga; | ||||
| import eu.kanade.mangafeed.ui.base.presenter.BasePresenter; | ||||
| import eu.kanade.mangafeed.util.EventBusHook; | ||||
| import eu.kanade.mangafeed.util.ToastUtil; | ||||
| import rx.Observable; | ||||
| import rx.Subscription; | ||||
| import rx.android.schedulers.AndroidSchedulers; | ||||
| @@ -20,11 +21,11 @@ import timber.log.Timber; | ||||
| public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> { | ||||
|  | ||||
|     @Inject DatabaseHelper db; | ||||
|     @Inject ChapterSyncManager syncManager; | ||||
|     @Inject MangaSyncManager syncManager; | ||||
|  | ||||
|     private MyAnimeList myAnimeList; | ||||
|     private Manga manga; | ||||
|     private ChapterSync chapterSync; | ||||
|     protected MyAnimeList myAnimeList; | ||||
|     protected Manga manga; | ||||
|     private MangaSync mangaSync; | ||||
|  | ||||
|     private String query; | ||||
|  | ||||
| @@ -37,15 +38,19 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> { | ||||
|     protected void onCreate(Bundle savedState) { | ||||
|         super.onCreate(savedState); | ||||
|  | ||||
|         if (savedState != null) { | ||||
|             onProcessRestart(); | ||||
|         } | ||||
|  | ||||
|         myAnimeList = syncManager.getMyAnimeList(); | ||||
|  | ||||
|         restartableLatestCache(GET_CHAPTER_SYNC, | ||||
|                 () -> db.getChapterSync(manga, myAnimeList).createObservable() | ||||
|                 () -> db.getMangaSync(manga, myAnimeList).createObservable() | ||||
|                         .flatMap(Observable::from) | ||||
|                         .doOnNext(chapterSync -> this.chapterSync = chapterSync) | ||||
|                         .doOnNext(mangaSync -> this.mangaSync = mangaSync) | ||||
|                         .subscribeOn(Schedulers.io()) | ||||
|                         .observeOn(AndroidSchedulers.mainThread()), | ||||
|                 MyAnimeListFragment::setChapterSync); | ||||
|                 MyAnimeListFragment::setMangaSync); | ||||
|  | ||||
|         restartableLatestCache(GET_SEARCH_RESULTS, | ||||
|                 () -> 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 | ||||
|     protected void onTakeView(MyAnimeListFragment view) { | ||||
|         super.onTakeView(view); | ||||
| @@ -81,10 +91,10 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> { | ||||
|         if (updateSubscription != null) | ||||
|             remove(updateSubscription); | ||||
|  | ||||
|         chapterSync.last_chapter_read = chapterNumber; | ||||
|         mangaSync.last_chapter_read = chapterNumber; | ||||
|  | ||||
|         add(updateSubscription = myAnimeList.update(chapterSync) | ||||
|                 .flatMap(response -> db.insertChapterSync(chapterSync).createObservable()) | ||||
|         add(updateSubscription = myAnimeList.update(mangaSync) | ||||
|                 .flatMap(response -> db.insertMangaSync(mangaSync).createObservable()) | ||||
|                 .subscribeOn(Schedulers.io()) | ||||
|                 .observeOn(AndroidSchedulers.mainThread()) | ||||
|                 .subscribe(response -> {}, | ||||
| @@ -99,8 +109,19 @@ public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> { | ||||
|         start(GET_SEARCH_RESULTS); | ||||
|     } | ||||
|  | ||||
|     public void registerManga(ChapterSync selectedManga) { | ||||
|         selectedManga.manga_id = manga.id; | ||||
|         db.insertChapterSync(selectedManga).executeAsBlocking(); | ||||
|     public void registerManga(MangaSync manga) { | ||||
|         manga.manga_id = this.manga.id; | ||||
|         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 de.greenrobot.event.EventBus; | ||||
| import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager; | ||||
| import eu.kanade.mangafeed.data.chaptersync.MyAnimeList; | ||||
| import eu.kanade.mangafeed.data.chaptersync.UpdateChapterSyncService; | ||||
| import eu.kanade.mangafeed.data.mangasync.MangaSyncManager; | ||||
| import eu.kanade.mangafeed.data.mangasync.services.MyAnimeList; | ||||
| import eu.kanade.mangafeed.data.sync.UpdateMangaSyncService; | ||||
| import eu.kanade.mangafeed.data.database.DatabaseHelper; | ||||
| 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.download.DownloadManager; | ||||
| 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.model.Page; | ||||
| 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.util.EventBusHook; | ||||
| import icepick.State; | ||||
| @@ -37,7 +37,7 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> { | ||||
|     @Inject PreferencesHelper prefs; | ||||
|     @Inject DatabaseHelper db; | ||||
|     @Inject DownloadManager downloadManager; | ||||
|     @Inject ChapterSyncManager syncManager; | ||||
|     @Inject MangaSyncManager syncManager; | ||||
|     @Inject SourceManager sourceManager; | ||||
|  | ||||
|     @State Manga manga; | ||||
| @@ -235,7 +235,7 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> { | ||||
|         chapter.last_page_read = currentPage; | ||||
|         if (isChapterFinished()) { | ||||
|             chapter.read = true; | ||||
|             updateChapterSyncLastChapterRead(); | ||||
|             updateMangaSyncLastChapterRead(); | ||||
|         } | ||||
|         db.insertChapter(chapter).executeAsBlocking(); | ||||
|     } | ||||
| @@ -245,26 +245,26 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> { | ||||
|         return !chapter.read && currentPage == pageList.size() - 1; | ||||
|     } | ||||
|  | ||||
|     private void updateChapterSyncLastChapterRead() { | ||||
|     private void updateMangaSyncLastChapterRead() { | ||||
|         // TODO don't use MAL methods for possible alternatives to MAL | ||||
|         MyAnimeList mal = syncManager.getMyAnimeList(); | ||||
|  | ||||
|         if (!mal.isLogged()) | ||||
|             return; | ||||
|  | ||||
|         List<ChapterSync> result = db.getChapterSync(manga, mal).executeAsBlocking(); | ||||
|         List<MangaSync> result = db.getMangaSync(manga, mal).executeAsBlocking(); | ||||
|         if (result.isEmpty()) | ||||
|             return; | ||||
|  | ||||
|         ChapterSync chapterSync = result.get(0); | ||||
|         MangaSync mangaSync = result.get(0); | ||||
|  | ||||
|         int lastChapterReadLocal = (int) Math.floor(chapter.chapter_number); | ||||
|         int lastChapterReadRemote = chapterSync.last_chapter_read; | ||||
|         int lastChapterReadRemote = mangaSync.last_chapter_read; | ||||
|  | ||||
|         if (lastChapterReadLocal > lastChapterReadRemote) { | ||||
|             chapterSync.last_chapter_read = lastChapterReadLocal; | ||||
|             EventBus.getDefault().postSticky(new UpdateChapterSyncEvent(chapterSync)); | ||||
|             UpdateChapterSyncService.start(getContext()); | ||||
|             mangaSync.last_chapter_read = lastChapterReadLocal; | ||||
|             EventBus.getDefault().postSticky(new UpdateMangaSyncEvent(mangaSync)); | ||||
|             UpdateMangaSyncService.start(getContext()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -12,18 +12,18 @@ import java.util.List; | ||||
| import javax.inject.Inject; | ||||
|  | ||||
| import eu.kanade.mangafeed.App; | ||||
| import eu.kanade.mangafeed.data.chaptersync.BaseChapterSync; | ||||
| import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager; | ||||
| import eu.kanade.mangafeed.data.mangasync.base.BaseMangaSync; | ||||
| import eu.kanade.mangafeed.data.mangasync.MangaSyncManager; | ||||
| import eu.kanade.mangafeed.data.source.SourceManager; | ||||
| 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 rx.Observable; | ||||
|  | ||||
| public class SettingsAccountsFragment extends SettingsNestedFragment { | ||||
|  | ||||
|     @Inject SourceManager sourceManager; | ||||
|     @Inject ChapterSyncManager syncManager; | ||||
|     @Inject MangaSyncManager syncManager; | ||||
|  | ||||
|     public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) { | ||||
|         SettingsNestedFragment fragment = new SettingsAccountsFragment(); | ||||
| @@ -56,16 +56,16 @@ public class SettingsAccountsFragment extends SettingsNestedFragment { | ||||
|             sourceCategory.addPreference(dialog); | ||||
|         } | ||||
|  | ||||
|         PreferenceCategory chapterSyncCategory = new PreferenceCategory(screen.getContext()); | ||||
|         chapterSyncCategory.setTitle("Sync"); | ||||
|         screen.addPreference(chapterSyncCategory); | ||||
|         PreferenceCategory mangaSyncCategory = new PreferenceCategory(screen.getContext()); | ||||
|         mangaSyncCategory.setTitle("Sync"); | ||||
|         screen.addPreference(mangaSyncCategory); | ||||
|  | ||||
|         for (BaseChapterSync sync : syncManager.getChapterSyncServices()) { | ||||
|             ChapterSyncLoginDialog dialog = new ChapterSyncLoginDialog( | ||||
|         for (BaseMangaSync sync : syncManager.getSyncServices()) { | ||||
|             MangaSyncLoginDialog dialog = new MangaSyncLoginDialog( | ||||
|                     screen.getContext(), preferences, sync); | ||||
|             dialog.setTitle(sync.getName()); | ||||
|  | ||||
|             chapterSyncCategory.addPreference(dialog); | ||||
|             mangaSyncCategory.addPreference(dialog); | ||||
|         } | ||||
|  | ||||
|         return view; | ||||
|   | ||||
| @@ -5,17 +5,17 @@ import android.content.DialogInterface; | ||||
| import android.view.View; | ||||
| 
 | ||||
| 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.util.ToastUtil; | ||||
| import rx.android.schedulers.AndroidSchedulers; | ||||
| 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); | ||||
|         this.sync = sync; | ||||
|     } | ||||
| @@ -26,8 +26,8 @@ public class ChapterSyncLoginDialog extends LoginDialogPreference { | ||||
| 
 | ||||
|         title.setText(getContext().getString(R.string.accounts_login_title, sync.getName())); | ||||
| 
 | ||||
|         username.setText(preferences.getChapterSyncUsername(sync)); | ||||
|         password.setText(preferences.getChapterSyncPassword(sync)); | ||||
|         username.setText(preferences.getMangaSyncUsername(sync)); | ||||
|         password.setText(preferences.getMangaSyncPassword(sync)); | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
| @@ -35,7 +35,7 @@ public class ChapterSyncLoginDialog extends LoginDialogPreference { | ||||
|         super.onDialogClosed(positiveResult); | ||||
| 
 | ||||
|         if (positiveResult) { | ||||
|             preferences.setChapterSyncCredentials(sync, | ||||
|             preferences.setMangaSyncCredentials(sync, | ||||
|                     username.getText().toString(), | ||||
|                     password.getText().toString()); | ||||
|         } | ||||
| @@ -61,7 +61,7 @@ public class ChapterSyncLoginDialog extends LoginDialogPreference { | ||||
|                         dialog.dismiss(); | ||||
|                         ToastUtil.showShort(context, R.string.login_success); | ||||
|                     } else { | ||||
|                         preferences.setChapterSyncCredentials(sync, "", ""); | ||||
|                         preferences.setMangaSyncCredentials(sync, "", ""); | ||||
|                         loginBtn.setProgress(-1); | ||||
|                     } | ||||
|                 }, error -> { | ||||
		Reference in New Issue
	
	Block a user