mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-22 05:41:51 +01:00
Merge remote-tracking branch 'inorichi/master'
This commit is contained in:
commit
df70ecce72
@ -1,6 +1,4 @@
|
|||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
// This does not break the build when Android Studio is missing the JRebel for Android plugin.
|
|
||||||
apply plugin: 'com.zeroturnaround.jrebel.android'
|
|
||||||
apply plugin: 'com.neenbedankt.android-apt'
|
apply plugin: 'com.neenbedankt.android-apt'
|
||||||
apply plugin: 'me.tatarka.retrolambda'
|
apply plugin: 'me.tatarka.retrolambda'
|
||||||
|
|
||||||
@ -65,8 +63,8 @@ dependencies {
|
|||||||
compile "com.android.support:design:$SUPPORT_LIBRARY_VERSION"
|
compile "com.android.support:design:$SUPPORT_LIBRARY_VERSION"
|
||||||
compile "com.android.support:recyclerview-v7:$SUPPORT_LIBRARY_VERSION"
|
compile "com.android.support:recyclerview-v7:$SUPPORT_LIBRARY_VERSION"
|
||||||
compile "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION"
|
compile "com.android.support:support-annotations:$SUPPORT_LIBRARY_VERSION"
|
||||||
compile 'com.squareup.okhttp:okhttp-urlconnection:2.5.0'
|
compile 'com.squareup.okhttp:okhttp-urlconnection:2.6.0'
|
||||||
compile 'com.squareup.okhttp:okhttp:2.5.0'
|
compile 'com.squareup.okhttp:okhttp:2.6.0'
|
||||||
compile 'com.squareup.okio:okio:1.6.0'
|
compile 'com.squareup.okio:okio:1.6.0'
|
||||||
compile 'com.google.code.gson:gson:2.4'
|
compile 'com.google.code.gson:gson:2.4'
|
||||||
compile 'com.jakewharton:disklrucache:2.0.2'
|
compile 'com.jakewharton:disklrucache:2.0.2'
|
||||||
|
@ -46,6 +46,9 @@
|
|||||||
<service android:name=".data.download.DownloadService"
|
<service android:name=".data.download.DownloadService"
|
||||||
android:exported="false"/>
|
android:exported="false"/>
|
||||||
|
|
||||||
|
<service android:name=".data.chaptersync.UpdateChapterSyncService"
|
||||||
|
android:exported="false"/>
|
||||||
|
|
||||||
<receiver
|
<receiver
|
||||||
android:name=".data.sync.LibraryUpdateService$SyncOnConnectionAvailable"
|
android:name=".data.sync.LibraryUpdateService$SyncOnConnectionAvailable"
|
||||||
android:enabled="false">
|
android:enabled="false">
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
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);
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package eu.kanade.mangafeed.data.chaptersync;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ChapterSyncManager {
|
||||||
|
|
||||||
|
private List<BaseChapterSync> services;
|
||||||
|
private MyAnimeList myAnimeList;
|
||||||
|
|
||||||
|
public static final int MYANIMELIST = 1;
|
||||||
|
|
||||||
|
public ChapterSyncManager(Context context) {
|
||||||
|
services = new ArrayList<>();
|
||||||
|
myAnimeList = new MyAnimeList(context);
|
||||||
|
services.add(myAnimeList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MyAnimeList getMyAnimeList() {
|
||||||
|
return myAnimeList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BaseChapterSync> getChapterSyncServices() {
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BaseChapterSync getSyncService(int id) {
|
||||||
|
switch (id) {
|
||||||
|
case MYANIMELIST:
|
||||||
|
return myAnimeList;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,163 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
package eu.kanade.mangafeed.data.chaptersync;
|
||||||
|
|
||||||
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.IBinder;
|
||||||
|
|
||||||
|
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.util.EventBusHook;
|
||||||
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
|
import rx.schedulers.Schedulers;
|
||||||
|
import rx.subscriptions.CompositeSubscription;
|
||||||
|
|
||||||
|
public class UpdateChapterSyncService extends Service {
|
||||||
|
|
||||||
|
@Inject ChapterSyncManager syncManager;
|
||||||
|
@Inject NetworkHelper networkManager;
|
||||||
|
@Inject DatabaseHelper db;
|
||||||
|
|
||||||
|
private CompositeSubscription subscriptions;
|
||||||
|
|
||||||
|
public static void start(Context context) {
|
||||||
|
context.startService(new Intent(context, UpdateChapterSyncService.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate() {
|
||||||
|
super.onCreate();
|
||||||
|
App.get(this).getComponent().inject(this);
|
||||||
|
subscriptions = new CompositeSubscription();
|
||||||
|
EventBus.getDefault().registerSticky(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int onStartCommand(Intent intent, int flags, int startId) {
|
||||||
|
return START_STICKY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
EventBus.getDefault().unregister(this);
|
||||||
|
subscriptions.unsubscribe();
|
||||||
|
super.onDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBinder onBind(Intent intent) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventBusHook
|
||||||
|
public void onEventMainThread(UpdateChapterSyncEvent event) {
|
||||||
|
updateLastChapteRead(event.getChapterSync());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLastChapteRead(ChapterSync chapterSync) {
|
||||||
|
BaseChapterSync sync = syncManager.getSyncService(chapterSync.sync_id);
|
||||||
|
|
||||||
|
subscriptions.add(sync.update(chapterSync)
|
||||||
|
.flatMap(response -> db.insertChapterSync(chapterSync).createObservable())
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(result -> {
|
||||||
|
stopSelf();
|
||||||
|
}, error -> {
|
||||||
|
stopSelf();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -16,14 +16,20 @@ 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.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.MangaStorIOSQLitePutResolver;
|
import eu.kanade.mangafeed.data.database.models.MangaStorIOSQLitePutResolver;
|
||||||
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.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;
|
||||||
@ -48,6 +54,11 @@ public class DatabaseHelper {
|
|||||||
.getResolver(new ChapterStorIOSQLiteGetResolver())
|
.getResolver(new ChapterStorIOSQLiteGetResolver())
|
||||||
.deleteResolver(new ChapterStorIOSQLiteDeleteResolver())
|
.deleteResolver(new ChapterStorIOSQLiteDeleteResolver())
|
||||||
.build())
|
.build())
|
||||||
|
.addTypeMapping(ChapterSync.class, SQLiteTypeMapping.<ChapterSync>builder()
|
||||||
|
.putResolver(new ChapterSyncStorIOSQLitePutResolver())
|
||||||
|
.getResolver(new ChapterSyncStorIOSQLiteGetResolver())
|
||||||
|
.deleteResolver(new ChapterSyncStorIOSQLiteDeleteResolver())
|
||||||
|
.build())
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,4 +274,31 @@ public class DatabaseHelper {
|
|||||||
.objects(chapters)
|
.objects(chapters)
|
||||||
.prepare();
|
.prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Chapter sync related queries
|
||||||
|
|
||||||
|
public PreparedGetListOfObjects<ChapterSync> getChapterSync(Manga manga, BaseChapterSync sync) {
|
||||||
|
|
||||||
|
return db.get()
|
||||||
|
.listOfObjects(ChapterSync.class)
|
||||||
|
.withQuery(Query.builder()
|
||||||
|
.table(ChapterSyncTable.TABLE)
|
||||||
|
.where(ChapterSyncTable.COLUMN_MANGA_ID + "=? AND " +
|
||||||
|
ChapterSyncTable.COLUMN_SYNC_ID + "=?")
|
||||||
|
.whereArgs(manga.id, sync.getId())
|
||||||
|
.build())
|
||||||
|
.prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PreparedPutObject<ChapterSync> insertChapterSync(ChapterSync chapter) {
|
||||||
|
return db.put()
|
||||||
|
.object(chapter)
|
||||||
|
.prepare();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PreparedDeleteObject<ChapterSync> deleteChapterSync(ChapterSync chapter) {
|
||||||
|
return db.delete()
|
||||||
|
.object(chapter)
|
||||||
|
.prepare();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,13 +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.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 = 1;
|
public static final int DATABASE_VERSION = 2;
|
||||||
|
|
||||||
public DbOpenHelper(@NonNull Context context) {
|
public DbOpenHelper(@NonNull Context context) {
|
||||||
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
super(context, DATABASE_NAME, null, DATABASE_VERSION);
|
||||||
@ -21,11 +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());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
public void onUpgrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||||
// no impl
|
if (oldVersion == 1)
|
||||||
|
db.execSQL(ChapterSyncTable.getCreateTableQuery());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
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,35 @@
|
|||||||
|
package eu.kanade.mangafeed.data.database.tables;
|
||||||
|
|
||||||
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
|
public class ChapterSyncTable {
|
||||||
|
|
||||||
|
public static final String TABLE = "chapter_sync";
|
||||||
|
|
||||||
|
public static final String COLUMN_ID = "_id";
|
||||||
|
|
||||||
|
public static final String COLUMN_MANGA_ID = "manga_id";
|
||||||
|
|
||||||
|
public static final String COLUMN_SYNC_ID = "sync_id";
|
||||||
|
|
||||||
|
public static final String COLUMN_REMOTE_ID = "remote_id";
|
||||||
|
|
||||||
|
public static final String COLUMN_TITLE = "title";
|
||||||
|
|
||||||
|
public static final String COLUMN_LAST_CHAPTER_READ = "last_chapter_read";
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static String getCreateTableQuery() {
|
||||||
|
return "CREATE TABLE " + TABLE + "("
|
||||||
|
+ COLUMN_ID + " INTEGER NOT NULL PRIMARY KEY, "
|
||||||
|
+ COLUMN_MANGA_ID + " INTEGER NOT NULL, "
|
||||||
|
+ COLUMN_SYNC_ID + " INTEGER NOT NULL, "
|
||||||
|
+ COLUMN_REMOTE_ID + " INTEGER NOT NULL, "
|
||||||
|
+ COLUMN_TITLE + " TEXT NOT NULL, "
|
||||||
|
+ COLUMN_LAST_CHAPTER_READ + " INTEGER NOT NULL, "
|
||||||
|
+ "FOREIGN KEY(" + COLUMN_MANGA_ID + ") REFERENCES " + MangaTable.TABLE + "(" + MangaTable.COLUMN_ID + ") "
|
||||||
|
+ "ON DELETE CASCADE"
|
||||||
|
+ ");";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -8,6 +8,7 @@ import com.f2prateek.rx.preferences.Preference;
|
|||||||
import com.f2prateek.rx.preferences.RxSharedPreferences;
|
import com.f2prateek.rx.preferences.RxSharedPreferences;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
|
import eu.kanade.mangafeed.data.chaptersync.BaseChapterSync;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
import eu.kanade.mangafeed.util.DiskUtils;
|
import eu.kanade.mangafeed.util.DiskUtils;
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
@ -20,6 +21,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 CHAPTERSYNC_ACCOUNT_PASSWORD = "pref_chaptersync_password_";
|
||||||
|
|
||||||
public PreferencesHelper(Context context) {
|
public PreferencesHelper(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
@ -84,6 +87,21 @@ public class PreferencesHelper {
|
|||||||
.apply();
|
.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getChapterSyncUsername(BaseChapterSync sync) {
|
||||||
|
return prefs.getString(CHAPTERSYNC_ACCOUNT_USERNAME + sync.getId(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChapterSyncPassword(BaseChapterSync sync) {
|
||||||
|
return prefs.getString(CHAPTERSYNC_ACCOUNT_PASSWORD + sync.getId(), "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChapterSyncCredentials(BaseChapterSync sync, String username, String password) {
|
||||||
|
prefs.edit()
|
||||||
|
.putString(CHAPTERSYNC_ACCOUNT_USERNAME + sync.getId(), username)
|
||||||
|
.putString(CHAPTERSYNC_ACCOUNT_PASSWORD + sync.getId(), password)
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
public String getDownloadsDirectory() {
|
public String getDownloadsDirectory() {
|
||||||
return prefs.getString(getKey(R.string.pref_download_directory_key),
|
return prefs.getString(getKey(R.string.pref_download_directory_key),
|
||||||
DiskUtils.getStorageDirectories(context)[0]);
|
DiskUtils.getStorageDirectories(context)[0]);
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -5,6 +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.chaptersync.UpdateChapterSyncService;
|
||||||
import eu.kanade.mangafeed.data.download.DownloadService;
|
import eu.kanade.mangafeed.data.download.DownloadService;
|
||||||
import eu.kanade.mangafeed.data.sync.LibraryUpdateService;
|
import eu.kanade.mangafeed.data.sync.LibraryUpdateService;
|
||||||
import eu.kanade.mangafeed.injection.module.AppModule;
|
import eu.kanade.mangafeed.injection.module.AppModule;
|
||||||
@ -12,9 +14,11 @@ import eu.kanade.mangafeed.injection.module.DataModule;
|
|||||||
import eu.kanade.mangafeed.ui.catalogue.CataloguePresenter;
|
import eu.kanade.mangafeed.ui.catalogue.CataloguePresenter;
|
||||||
import eu.kanade.mangafeed.ui.download.DownloadPresenter;
|
import eu.kanade.mangafeed.ui.download.DownloadPresenter;
|
||||||
import eu.kanade.mangafeed.ui.library.LibraryPresenter;
|
import eu.kanade.mangafeed.ui.library.LibraryPresenter;
|
||||||
|
import eu.kanade.mangafeed.ui.manga.MangaActivity;
|
||||||
import eu.kanade.mangafeed.ui.manga.MangaPresenter;
|
import eu.kanade.mangafeed.ui.manga.MangaPresenter;
|
||||||
import eu.kanade.mangafeed.ui.manga.chapter.ChaptersPresenter;
|
import eu.kanade.mangafeed.ui.manga.chapter.ChaptersPresenter;
|
||||||
import eu.kanade.mangafeed.ui.manga.info.MangaInfoPresenter;
|
import eu.kanade.mangafeed.ui.manga.info.MangaInfoPresenter;
|
||||||
|
import eu.kanade.mangafeed.ui.manga.myanimelist.MyAnimeListPresenter;
|
||||||
import eu.kanade.mangafeed.ui.reader.ReaderPresenter;
|
import eu.kanade.mangafeed.ui.reader.ReaderPresenter;
|
||||||
import eu.kanade.mangafeed.ui.catalogue.SourcePresenter;
|
import eu.kanade.mangafeed.ui.catalogue.SourcePresenter;
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
@ -39,15 +43,20 @@ public interface AppComponent {
|
|||||||
void inject(ChaptersPresenter chaptersPresenter);
|
void inject(ChaptersPresenter chaptersPresenter);
|
||||||
void inject(ReaderPresenter readerPresenter);
|
void inject(ReaderPresenter readerPresenter);
|
||||||
void inject(DownloadPresenter downloadPresenter);
|
void inject(DownloadPresenter downloadPresenter);
|
||||||
|
void inject(MyAnimeListPresenter myAnimeListPresenter);
|
||||||
|
|
||||||
void inject(ReaderActivity readerActivity);
|
void inject(ReaderActivity readerActivity);
|
||||||
|
void inject(MangaActivity mangaActivity);
|
||||||
void inject(SettingsAccountsFragment settingsAccountsFragment);
|
void inject(SettingsAccountsFragment settingsAccountsFragment);
|
||||||
void inject(SettingsDownloadsFragment settingsDownloadsFragment);
|
void inject(SettingsDownloadsFragment settingsDownloadsFragment);
|
||||||
|
|
||||||
void inject(Source source);
|
void inject(Source source);
|
||||||
|
|
||||||
|
void inject(MyAnimeList myAnimeList);
|
||||||
|
|
||||||
void inject(LibraryUpdateService libraryUpdateService);
|
void inject(LibraryUpdateService libraryUpdateService);
|
||||||
void inject(DownloadService downloadService);
|
void inject(DownloadService downloadService);
|
||||||
|
void inject(UpdateChapterSyncService updateChapterSyncService);
|
||||||
|
|
||||||
Application application();
|
Application application();
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import javax.inject.Singleton;
|
|||||||
import dagger.Module;
|
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.chaptersync.ChapterSyncManager;
|
||||||
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;
|
||||||
@ -56,4 +57,10 @@ public class DataModule {
|
|||||||
return new DownloadManager(app, sourceManager, preferences);
|
return new DownloadManager(app, sourceManager, preferences);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
ChapterSyncManager provideChapterSyncManager(Application app) {
|
||||||
|
return new ChapterSyncManager(app);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ import android.os.Bundle;
|
|||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.App;
|
import eu.kanade.mangafeed.App;
|
||||||
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||||
import nucleus.factory.PresenterFactory;
|
import nucleus.factory.PresenterFactory;
|
||||||
import nucleus.factory.ReflectionPresenterFactory;
|
import nucleus.factory.ReflectionPresenterFactory;
|
||||||
import nucleus.presenter.Presenter;
|
import nucleus.presenter.Presenter;
|
||||||
@ -60,7 +60,9 @@ public abstract class BaseRxActivity<P extends Presenter> extends BaseActivity i
|
|||||||
final PresenterFactory<P> superFactory = getPresenterFactory();
|
final PresenterFactory<P> superFactory = getPresenterFactory();
|
||||||
setPresenterFactory(() -> {
|
setPresenterFactory(() -> {
|
||||||
P presenter = superFactory.createPresenter();
|
P presenter = superFactory.createPresenter();
|
||||||
((App)getApplication()).getComponentReflection().inject(presenter);
|
App app = (App) getApplication();
|
||||||
|
app.getComponentReflection().inject(presenter);
|
||||||
|
((BasePresenter)presenter).setContext(app.getApplicationContext());
|
||||||
return presenter;
|
return presenter;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ package eu.kanade.mangafeed.ui.base.fragment;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import eu.kanade.mangafeed.App;
|
import eu.kanade.mangafeed.App;
|
||||||
import eu.kanade.mangafeed.ui.base.fragment.BaseFragment;
|
import eu.kanade.mangafeed.ui.base.presenter.BasePresenter;
|
||||||
import nucleus.factory.PresenterFactory;
|
import nucleus.factory.PresenterFactory;
|
||||||
import nucleus.factory.ReflectionPresenterFactory;
|
import nucleus.factory.ReflectionPresenterFactory;
|
||||||
import nucleus.presenter.Presenter;
|
import nucleus.presenter.Presenter;
|
||||||
@ -57,7 +57,9 @@ public abstract class BaseRxFragment<P extends Presenter> extends BaseFragment i
|
|||||||
final PresenterFactory<P> superFactory = getPresenterFactory();
|
final PresenterFactory<P> superFactory = getPresenterFactory();
|
||||||
setPresenterFactory(() -> {
|
setPresenterFactory(() -> {
|
||||||
P presenter = superFactory.createPresenter();
|
P presenter = superFactory.createPresenter();
|
||||||
((App)getActivity().getApplication()).getComponentReflection().inject(presenter);
|
App app = (App) getActivity().getApplication();
|
||||||
|
app.getComponentReflection().inject(presenter);
|
||||||
|
((BasePresenter)presenter).setContext(app.getApplicationContext());
|
||||||
return presenter;
|
return presenter;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package eu.kanade.mangafeed.ui.base.presenter;
|
package eu.kanade.mangafeed.ui.base.presenter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
|
|
||||||
@ -10,6 +11,8 @@ import nucleus.view.ViewWithPresenter;
|
|||||||
|
|
||||||
public class BasePresenter<V extends ViewWithPresenter> extends RxPresenter<V> {
|
public class BasePresenter<V extends ViewWithPresenter> extends RxPresenter<V> {
|
||||||
|
|
||||||
|
private Context context;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedState) {
|
protected void onCreate(Bundle savedState) {
|
||||||
super.onCreate(savedState);
|
super.onCreate(savedState);
|
||||||
@ -33,4 +36,13 @@ public class BasePresenter<V extends ViewWithPresenter> extends RxPresenter<V> {
|
|||||||
public void unregisterForEvents() {
|
public void unregisterForEvents() {
|
||||||
EventBus.getDefault().unregister(this);
|
EventBus.getDefault().unregister(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setContext(Context applicationContext) {
|
||||||
|
context = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Context getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,19 @@ import android.support.v4.app.FragmentPagerAdapter;
|
|||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import butterknife.Bind;
|
import butterknife.Bind;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
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.database.models.Manga;
|
import eu.kanade.mangafeed.data.database.models.Manga;
|
||||||
|
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
||||||
import eu.kanade.mangafeed.ui.base.activity.BaseRxActivity;
|
import eu.kanade.mangafeed.ui.base.activity.BaseRxActivity;
|
||||||
import eu.kanade.mangafeed.ui.manga.chapter.ChaptersFragment;
|
import eu.kanade.mangafeed.ui.manga.chapter.ChaptersFragment;
|
||||||
import eu.kanade.mangafeed.ui.manga.info.MangaInfoFragment;
|
import eu.kanade.mangafeed.ui.manga.info.MangaInfoFragment;
|
||||||
|
import eu.kanade.mangafeed.ui.manga.myanimelist.MyAnimeListFragment;
|
||||||
import nucleus.factory.RequiresPresenter;
|
import nucleus.factory.RequiresPresenter;
|
||||||
|
|
||||||
@RequiresPresenter(MangaPresenter.class)
|
@RequiresPresenter(MangaPresenter.class)
|
||||||
@ -27,6 +33,9 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
|||||||
@Bind(R.id.tabs) TabLayout tabs;
|
@Bind(R.id.tabs) TabLayout tabs;
|
||||||
@Bind(R.id.view_pager) ViewPager view_pager;
|
@Bind(R.id.view_pager) ViewPager view_pager;
|
||||||
|
|
||||||
|
@Inject PreferencesHelper preferences;
|
||||||
|
@Inject ChapterSyncManager chapterSyncManager;
|
||||||
|
|
||||||
private MangaDetailAdapter adapter;
|
private MangaDetailAdapter adapter;
|
||||||
private long manga_id;
|
private long manga_id;
|
||||||
private boolean is_online;
|
private boolean is_online;
|
||||||
@ -43,6 +52,7 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
|||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
App.get(this).getComponent().inject(this);
|
||||||
setContentView(R.layout.activity_manga_detail);
|
setContentView(R.layout.activity_manga_detail);
|
||||||
ButterKnife.bind(this);
|
ButterKnife.bind(this);
|
||||||
|
|
||||||
@ -88,25 +98,31 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
|||||||
|
|
||||||
class MangaDetailAdapter extends FragmentPagerAdapter {
|
class MangaDetailAdapter extends FragmentPagerAdapter {
|
||||||
|
|
||||||
final int PAGE_COUNT = 2;
|
private int pageCount;
|
||||||
private String tab_titles[];
|
private String tabTitles[];
|
||||||
private Context context;
|
private Context context;
|
||||||
|
|
||||||
final static int INFO_FRAGMENT = 0;
|
final static int INFO_FRAGMENT = 0;
|
||||||
final static int CHAPTERS_FRAGMENT = 1;
|
final static int CHAPTERS_FRAGMENT = 1;
|
||||||
|
final static int MYANIMELIST_FRAGMENT = 2;
|
||||||
|
|
||||||
public MangaDetailAdapter(FragmentManager fm, Context context) {
|
public MangaDetailAdapter(FragmentManager fm, Context context) {
|
||||||
super(fm);
|
super(fm);
|
||||||
this.context = context;
|
this.context = context;
|
||||||
tab_titles = new String[]{
|
tabTitles = new String[]{
|
||||||
context.getString(R.string.manga_detail_tab),
|
context.getString(R.string.manga_detail_tab),
|
||||||
context.getString(R.string.manga_chapters_tab)
|
context.getString(R.string.manga_chapters_tab),
|
||||||
|
"MAL"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pageCount = 2;
|
||||||
|
if (chapterSyncManager.getMyAnimeList().isLogged())
|
||||||
|
pageCount++;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getCount() {
|
public int getCount() {
|
||||||
return PAGE_COUNT;
|
return pageCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -116,7 +132,8 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
|||||||
return MangaInfoFragment.newInstance();
|
return MangaInfoFragment.newInstance();
|
||||||
case CHAPTERS_FRAGMENT:
|
case CHAPTERS_FRAGMENT:
|
||||||
return ChaptersFragment.newInstance();
|
return ChaptersFragment.newInstance();
|
||||||
|
case MYANIMELIST_FRAGMENT:
|
||||||
|
return MyAnimeListFragment.newInstance();
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -125,7 +142,7 @@ public class MangaActivity extends BaseRxActivity<MangaPresenter> {
|
|||||||
@Override
|
@Override
|
||||||
public CharSequence getPageTitle(int position) {
|
public CharSequence getPageTitle(int position) {
|
||||||
// Generate title based on item position
|
// Generate title based on item position
|
||||||
return tab_titles[position];
|
return tabTitles[position];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,10 +2,6 @@ package eu.kanade.mangafeed.ui.manga.info;
|
|||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
@ -52,28 +48,12 @@ public class MangaInfoFragment extends BaseRxFragment<MangaInfoPresenter> {
|
|||||||
// Inflate the layout for this fragment
|
// Inflate the layout for this fragment
|
||||||
View view = inflater.inflate(R.layout.fragment_manga_info, container, false);
|
View view = inflater.inflate(R.layout.fragment_manga_info, container, false);
|
||||||
ButterKnife.bind(this, view);
|
ButterKnife.bind(this, view);
|
||||||
favoriteBtn.setOnTouchListener((v, event) -> {
|
|
||||||
if (event.getAction() == MotionEvent.ACTION_DOWN) {
|
|
||||||
getPresenter().toggleFavorite();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
favoriteBtn.setOnClickListener(v -> {
|
||||||
|
getPresenter().toggleFavorite();
|
||||||
});
|
});
|
||||||
getPresenter().initFavoriteText();
|
|
||||||
return view;
|
return view;
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
|
||||||
super.onCreateOptionsMenu(menu, inflater);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setMangaInfo(Manga manga) {
|
public void setMangaInfo(Manga manga) {
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
package eu.kanade.mangafeed.ui.manga.myanimelist;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.DialogFragment;
|
||||||
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.ListView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import eu.kanade.mangafeed.R;
|
||||||
|
import eu.kanade.mangafeed.data.database.models.ChapterSync;
|
||||||
|
import uk.co.ribot.easyadapter.EasyAdapter;
|
||||||
|
import uk.co.ribot.easyadapter.ItemViewHolder;
|
||||||
|
import uk.co.ribot.easyadapter.PositionInfo;
|
||||||
|
import uk.co.ribot.easyadapter.annotations.LayoutId;
|
||||||
|
import uk.co.ribot.easyadapter.annotations.ViewId;
|
||||||
|
|
||||||
|
public class MyAnimeListDialogFragment extends DialogFragment {
|
||||||
|
|
||||||
|
@Bind(R.id.myanimelist_search_field) EditText searchText;
|
||||||
|
@Bind(R.id.myanimelist_search_button) Button searchButton;
|
||||||
|
@Bind(R.id.myanimelist_search_results) ListView searchResults;
|
||||||
|
|
||||||
|
private EasyAdapter<ChapterSync> adapter;
|
||||||
|
private MyAnimeListFragment fragment;
|
||||||
|
private ChapterSync selectedItem;
|
||||||
|
|
||||||
|
public static MyAnimeListDialogFragment newInstance(MyAnimeListFragment parentFragment) {
|
||||||
|
MyAnimeListDialogFragment dialog = new MyAnimeListDialogFragment();
|
||||||
|
dialog.setParentFragment(parentFragment);
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(Bundle savedState) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||||
|
|
||||||
|
LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||||
|
|
||||||
|
View view = inflater.inflate(R.layout.dialog_myanimelist_search, null);
|
||||||
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
|
|
||||||
|
builder.setView(view)
|
||||||
|
.setPositiveButton(R.string.button_ok, (dialog, which) -> onPositiveButtonClick())
|
||||||
|
.setNegativeButton(R.string.button_cancel, (dialog, which) -> {});
|
||||||
|
|
||||||
|
searchButton.setOnClickListener(v ->
|
||||||
|
fragment.getPresenter().searchManga(searchText.getText().toString()));
|
||||||
|
|
||||||
|
searchResults.setOnItemClickListener((parent, viewList, position, id) ->
|
||||||
|
selectedItem = adapter.getItem(position));
|
||||||
|
|
||||||
|
adapter = new EasyAdapter<>(getActivity(), ResultViewHolder.class);
|
||||||
|
|
||||||
|
searchResults.setAdapter(adapter);
|
||||||
|
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onPositiveButtonClick() {
|
||||||
|
if (adapter != null && selectedItem != null) {
|
||||||
|
fragment.getPresenter().registerManga(selectedItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResults(List<ChapterSync> 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> {
|
||||||
|
|
||||||
|
@ViewId(R.id.myanimelist_result_title) TextView title;
|
||||||
|
|
||||||
|
public ResultViewHolder(View view) {
|
||||||
|
super(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSetValues(ChapterSync chapter, PositionInfo positionInfo) {
|
||||||
|
title.setText(chapter.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package eu.kanade.mangafeed.ui.manga.myanimelist;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
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.ui.base.fragment.BaseRxFragment;
|
||||||
|
import nucleus.factory.RequiresPresenter;
|
||||||
|
|
||||||
|
@RequiresPresenter(MyAnimeListPresenter.class)
|
||||||
|
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.update_button) Button updateButton;
|
||||||
|
|
||||||
|
private MyAnimeListDialogFragment dialog;
|
||||||
|
|
||||||
|
public static MyAnimeListFragment newInstance() {
|
||||||
|
return new MyAnimeListFragment();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle bundle) {
|
||||||
|
super.onCreate(bundle);
|
||||||
|
setHasOptionsMenu(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(R.layout.fragment_myanimelist, container, false);
|
||||||
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
|
updateButton.setOnClickListener(v -> getPresenter().updateLastChapter(
|
||||||
|
Integer.parseInt(lastChapterRead.getText().toString())));
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
inflater.inflate(R.menu.myanimelist, menu);
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.myanimelist_edit:
|
||||||
|
showSearchDialog();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChapterSync(ChapterSync chapterSync) {
|
||||||
|
title.setText(chapterSync.title);
|
||||||
|
lastChapterRead.setText(chapterSync.last_chapter_read + "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showSearchDialog() {
|
||||||
|
if (dialog == null)
|
||||||
|
dialog = MyAnimeListDialogFragment.newInstance(this);
|
||||||
|
|
||||||
|
dialog.show(getActivity().getSupportFragmentManager(), "search");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSearchResults(List<ChapterSync> results) {
|
||||||
|
if (dialog != null)
|
||||||
|
dialog.setResults(results);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
package eu.kanade.mangafeed.ui.manga.myanimelist;
|
||||||
|
|
||||||
|
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.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 rx.Observable;
|
||||||
|
import rx.Subscription;
|
||||||
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
|
import rx.schedulers.Schedulers;
|
||||||
|
import timber.log.Timber;
|
||||||
|
|
||||||
|
public class MyAnimeListPresenter extends BasePresenter<MyAnimeListFragment> {
|
||||||
|
|
||||||
|
@Inject DatabaseHelper db;
|
||||||
|
@Inject ChapterSyncManager syncManager;
|
||||||
|
|
||||||
|
private MyAnimeList myAnimeList;
|
||||||
|
private Manga manga;
|
||||||
|
private ChapterSync chapterSync;
|
||||||
|
|
||||||
|
private String query;
|
||||||
|
|
||||||
|
private Subscription updateSubscription;
|
||||||
|
|
||||||
|
private static final int GET_CHAPTER_SYNC = 1;
|
||||||
|
private static final int GET_SEARCH_RESULTS = 2;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedState) {
|
||||||
|
super.onCreate(savedState);
|
||||||
|
|
||||||
|
myAnimeList = syncManager.getMyAnimeList();
|
||||||
|
|
||||||
|
restartableLatestCache(GET_CHAPTER_SYNC,
|
||||||
|
() -> db.getChapterSync(manga, myAnimeList).createObservable()
|
||||||
|
.flatMap(Observable::from)
|
||||||
|
.doOnNext(chapterSync -> this.chapterSync = chapterSync)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread()),
|
||||||
|
MyAnimeListFragment::setChapterSync);
|
||||||
|
|
||||||
|
restartableLatestCache(GET_SEARCH_RESULTS,
|
||||||
|
() -> myAnimeList.search(query)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread()),
|
||||||
|
(view, results) -> {
|
||||||
|
view.onSearchResults(results);
|
||||||
|
}, (view, error) -> {
|
||||||
|
Timber.e(error.getMessage());
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onTakeView(MyAnimeListFragment view) {
|
||||||
|
super.onTakeView(view);
|
||||||
|
registerForStickyEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDropView() {
|
||||||
|
unregisterForEvents();
|
||||||
|
super.onDropView();
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventBusHook
|
||||||
|
public void onEventMainThread(Manga manga) {
|
||||||
|
this.manga = manga;
|
||||||
|
start(GET_CHAPTER_SYNC);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateLastChapter(int chapterNumber) {
|
||||||
|
if (updateSubscription != null)
|
||||||
|
remove(updateSubscription);
|
||||||
|
|
||||||
|
chapterSync.last_chapter_read = chapterNumber;
|
||||||
|
|
||||||
|
add(updateSubscription = myAnimeList.update(chapterSync)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(response -> {},
|
||||||
|
error -> {
|
||||||
|
Timber.e(error.getMessage());
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void searchManga(String query) {
|
||||||
|
this.query = query;
|
||||||
|
start(GET_SEARCH_RESULTS);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerManga(ChapterSync selectedManga) {
|
||||||
|
selectedManga.manga_id = manga.id;
|
||||||
|
db.insertChapterSync(selectedManga).executeAsBlocking();
|
||||||
|
}
|
||||||
|
}
|
@ -8,8 +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.chaptersync.MyAnimeList;
|
||||||
|
import eu.kanade.mangafeed.data.chaptersync.UpdateChapterSyncService;
|
||||||
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.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;
|
||||||
@ -17,6 +21,7 @@ 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.RetryPageEvent;
|
import eu.kanade.mangafeed.event.RetryPageEvent;
|
||||||
import eu.kanade.mangafeed.event.SourceMangaChapterEvent;
|
import eu.kanade.mangafeed.event.SourceMangaChapterEvent;
|
||||||
|
import eu.kanade.mangafeed.event.UpdateChapterSyncEvent;
|
||||||
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;
|
||||||
@ -32,6 +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;
|
||||||
|
|
||||||
private Source source;
|
private Source source;
|
||||||
private Manga manga;
|
private Manga manga;
|
||||||
@ -135,10 +141,47 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void onChapterChange() {
|
private void onChapterChange() {
|
||||||
if (pageList != null) {
|
if (pageList == null)
|
||||||
if (!isDownloaded)
|
return;
|
||||||
source.savePageList(chapter.url, pageList);
|
|
||||||
saveChapterProgress();
|
// Cache page list for online chapters to allow a faster reopen
|
||||||
|
if (!isDownloaded)
|
||||||
|
source.savePageList(chapter.url, pageList);
|
||||||
|
|
||||||
|
// Save current progress of the chapter. Mark as read if the chapter is finished
|
||||||
|
// and update progress in remote services (like MyAnimeList)
|
||||||
|
chapter.last_page_read = currentPage;
|
||||||
|
if (isChapterFinished()) {
|
||||||
|
chapter.read = true;
|
||||||
|
updateChapterSyncLastChapterRead();
|
||||||
|
}
|
||||||
|
db.insertChapter(chapter).executeAsBlocking();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isChapterFinished() {
|
||||||
|
return !chapter.read && currentPage == pageList.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateChapterSyncLastChapterRead() {
|
||||||
|
// 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();
|
||||||
|
if (result.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
ChapterSync chapterSync = result.get(0);
|
||||||
|
|
||||||
|
int lastChapterReadLocal = (int) Math.floor(chapter.chapter_number);
|
||||||
|
int lastChapterReadRemote = chapterSync.last_chapter_read;
|
||||||
|
|
||||||
|
if (lastChapterReadLocal > lastChapterReadRemote) {
|
||||||
|
chapterSync.last_chapter_read = lastChapterReadLocal;
|
||||||
|
EventBus.getDefault().postSticky(new UpdateChapterSyncEvent(chapterSync));
|
||||||
|
UpdateChapterSyncService.start(getContext());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,14 +229,6 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
|
|||||||
this.currentPage = currentPage;
|
this.currentPage = currentPage;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveChapterProgress() {
|
|
||||||
chapter.last_page_read = currentPage;
|
|
||||||
if (currentPage == pageList.size() - 1) {
|
|
||||||
chapter.read = true;
|
|
||||||
}
|
|
||||||
db.insertChapter(chapter).executeAsBlocking();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void getAdjacentChapters() {
|
private void getAdjacentChapters() {
|
||||||
if (nextChapterSubscription != null)
|
if (nextChapterSubscription != null)
|
||||||
remove(nextChapterSubscription);
|
remove(nextChapterSubscription);
|
||||||
|
@ -1,124 +0,0 @@
|
|||||||
package eu.kanade.mangafeed.ui.setting;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.DialogInterface;
|
|
||||||
import android.os.Bundle;
|
|
||||||
import android.preference.DialogPreference;
|
|
||||||
import android.text.method.PasswordTransformationMethod;
|
|
||||||
import android.view.View;
|
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.EditText;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.dd.processbutton.iml.ActionProcessButton;
|
|
||||||
|
|
||||||
import butterknife.Bind;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import eu.kanade.mangafeed.R;
|
|
||||||
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
|
||||||
import eu.kanade.mangafeed.data.source.base.Source;
|
|
||||||
import eu.kanade.mangafeed.util.ToastUtil;
|
|
||||||
import rx.Subscription;
|
|
||||||
import rx.android.schedulers.AndroidSchedulers;
|
|
||||||
import rx.schedulers.Schedulers;
|
|
||||||
|
|
||||||
public class LoginDialogPreference extends DialogPreference {
|
|
||||||
|
|
||||||
@Bind(R.id.accounts_login) TextView title;
|
|
||||||
@Bind(R.id.username) EditText username;
|
|
||||||
@Bind(R.id.password) EditText password;
|
|
||||||
@Bind(R.id.show_password) CheckBox showPassword;
|
|
||||||
@Bind(R.id.login) ActionProcessButton loginBtn;
|
|
||||||
|
|
||||||
private PreferencesHelper preferences;
|
|
||||||
private Source source;
|
|
||||||
private AlertDialog dialog;
|
|
||||||
private Subscription requestSubscription;
|
|
||||||
private Context context;
|
|
||||||
|
|
||||||
public LoginDialogPreference(Context context, PreferencesHelper preferences, Source source) {
|
|
||||||
super(context, null);
|
|
||||||
this.context = context;
|
|
||||||
this.preferences = preferences;
|
|
||||||
this.source = source;
|
|
||||||
|
|
||||||
setDialogLayoutResource(R.layout.pref_account_login);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
|
||||||
// Hide positive button
|
|
||||||
builder.setPositiveButton("", this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onBindDialogView(View view) {
|
|
||||||
ButterKnife.bind(this, view);
|
|
||||||
|
|
||||||
title.setText(getContext().getString(R.string.accounts_login_title, source.getName()));
|
|
||||||
|
|
||||||
username.setText(preferences.getSourceUsername(source));
|
|
||||||
password.setText(preferences.getSourcePassword(source));
|
|
||||||
showPassword.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
|
||||||
if (isChecked)
|
|
||||||
password.setTransformationMethod(null);
|
|
||||||
else
|
|
||||||
password.setTransformationMethod(new PasswordTransformationMethod());
|
|
||||||
});
|
|
||||||
|
|
||||||
loginBtn.setMode(ActionProcessButton.Mode.ENDLESS);
|
|
||||||
loginBtn.setOnClickListener(click -> checkLogin());
|
|
||||||
|
|
||||||
super.onBindDialogView(view);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void showDialog(Bundle state) {
|
|
||||||
super.showDialog(state);
|
|
||||||
dialog = ((AlertDialog) getDialog());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onDialogClosed(boolean positiveResult) {
|
|
||||||
if (requestSubscription != null)
|
|
||||||
requestSubscription.unsubscribe();
|
|
||||||
|
|
||||||
if(!positiveResult)
|
|
||||||
return;
|
|
||||||
|
|
||||||
preferences.setSourceCredentials(source,
|
|
||||||
username.getText().toString(),
|
|
||||||
password.getText().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkLogin() {
|
|
||||||
if (requestSubscription != null)
|
|
||||||
requestSubscription.unsubscribe();
|
|
||||||
|
|
||||||
if (username.getText().length() == 0 || password.getText().length() == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
loginBtn.setProgress(1);
|
|
||||||
|
|
||||||
requestSubscription = source
|
|
||||||
.login(username.getText().toString(), password.getText().toString())
|
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
|
||||||
.subscribe(logged -> {
|
|
||||||
if (logged) {
|
|
||||||
// Simulate a positive button click and dismiss the dialog
|
|
||||||
onClick(dialog, DialogInterface.BUTTON_POSITIVE);
|
|
||||||
dialog.dismiss();
|
|
||||||
ToastUtil.showShort(context, R.string.login_success);
|
|
||||||
} else {
|
|
||||||
loginBtn.setProgress(-1);
|
|
||||||
}
|
|
||||||
}, throwable -> {
|
|
||||||
loginBtn.setProgress(-1);
|
|
||||||
loginBtn.setText(R.string.unknown_error);
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,6 +1,7 @@
|
|||||||
package eu.kanade.mangafeed.ui.setting;
|
package eu.kanade.mangafeed.ui.setting;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.preference.PreferenceCategory;
|
||||||
import android.preference.PreferenceFragment;
|
import android.preference.PreferenceFragment;
|
||||||
import android.preference.PreferenceScreen;
|
import android.preference.PreferenceScreen;
|
||||||
|
|
||||||
@ -10,16 +11,21 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
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.BaseChapterSync;
|
||||||
|
import eu.kanade.mangafeed.data.chaptersync.ChapterSyncManager;
|
||||||
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
||||||
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.base.activity.BaseActivity;
|
import eu.kanade.mangafeed.ui.base.activity.BaseActivity;
|
||||||
|
import eu.kanade.mangafeed.ui.setting.dialog.ChapterSyncLoginDialog;
|
||||||
|
import eu.kanade.mangafeed.ui.setting.dialog.SourceLoginDialog;
|
||||||
import rx.Observable;
|
import rx.Observable;
|
||||||
|
|
||||||
public class SettingsAccountsFragment extends PreferenceFragment {
|
public class SettingsAccountsFragment extends PreferenceFragment {
|
||||||
|
|
||||||
@Inject SourceManager sourceManager;
|
|
||||||
@Inject PreferencesHelper preferences;
|
@Inject PreferencesHelper preferences;
|
||||||
|
@Inject SourceManager sourceManager;
|
||||||
|
@Inject ChapterSyncManager syncManager;
|
||||||
|
|
||||||
public static SettingsAccountsFragment newInstance() {
|
public static SettingsAccountsFragment newInstance() {
|
||||||
return new SettingsAccountsFragment();
|
return new SettingsAccountsFragment();
|
||||||
@ -35,13 +41,30 @@ public class SettingsAccountsFragment extends PreferenceFragment {
|
|||||||
|
|
||||||
List<Source> sourceAccounts = getSourcesWithLogin();
|
List<Source> sourceAccounts = getSourcesWithLogin();
|
||||||
|
|
||||||
|
PreferenceCategory sourceCategory = new PreferenceCategory(screen.getContext());
|
||||||
|
sourceCategory.setTitle("Sources");
|
||||||
|
screen.addPreference(sourceCategory);
|
||||||
|
|
||||||
for (Source source : sourceAccounts) {
|
for (Source source : sourceAccounts) {
|
||||||
LoginDialogPreference dialog = new LoginDialogPreference(
|
SourceLoginDialog dialog = new SourceLoginDialog(
|
||||||
screen.getContext(), preferences, source);
|
screen.getContext(), preferences, source);
|
||||||
dialog.setTitle(source.getName());
|
dialog.setTitle(source.getName());
|
||||||
|
|
||||||
screen.addPreference(dialog);
|
sourceCategory.addPreference(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PreferenceCategory chapterSyncCategory = new PreferenceCategory(screen.getContext());
|
||||||
|
chapterSyncCategory.setTitle("Sync");
|
||||||
|
screen.addPreference(chapterSyncCategory);
|
||||||
|
|
||||||
|
for (BaseChapterSync sync : syncManager.getChapterSyncServices()) {
|
||||||
|
ChapterSyncLoginDialog dialog = new ChapterSyncLoginDialog(
|
||||||
|
screen.getContext(), preferences, sync);
|
||||||
|
dialog.setTitle(sync.getName());
|
||||||
|
|
||||||
|
chapterSyncCategory.addPreference(dialog);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,74 @@
|
|||||||
|
package eu.kanade.mangafeed.ui.setting.dialog;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
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.preference.PreferencesHelper;
|
||||||
|
import eu.kanade.mangafeed.util.ToastUtil;
|
||||||
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
|
import rx.schedulers.Schedulers;
|
||||||
|
|
||||||
|
public class ChapterSyncLoginDialog extends LoginDialogPreference {
|
||||||
|
|
||||||
|
private BaseChapterSync sync;
|
||||||
|
|
||||||
|
public ChapterSyncLoginDialog(Context context, PreferencesHelper preferences, BaseChapterSync sync) {
|
||||||
|
super(context, preferences);
|
||||||
|
this.sync = sync;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBindDialogView(View view) {
|
||||||
|
super.onBindDialogView(view);
|
||||||
|
|
||||||
|
title.setText(getContext().getString(R.string.accounts_login_title, sync.getName()));
|
||||||
|
|
||||||
|
username.setText(preferences.getChapterSyncUsername(sync));
|
||||||
|
password.setText(preferences.getChapterSyncPassword(sync));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDialogClosed(boolean positiveResult) {
|
||||||
|
super.onDialogClosed(positiveResult);
|
||||||
|
|
||||||
|
if (positiveResult) {
|
||||||
|
preferences.setChapterSyncCredentials(sync,
|
||||||
|
username.getText().toString(),
|
||||||
|
password.getText().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkLogin() {
|
||||||
|
if (requestSubscription != null)
|
||||||
|
requestSubscription.unsubscribe();
|
||||||
|
|
||||||
|
if (username.getText().length() == 0 || password.getText().length() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
loginBtn.setProgress(1);
|
||||||
|
|
||||||
|
requestSubscription = sync
|
||||||
|
.login(username.getText().toString(), password.getText().toString())
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(logged -> {
|
||||||
|
if (logged) {
|
||||||
|
// Simulate a positive button click and dismiss the dialog
|
||||||
|
onClick(dialog, DialogInterface.BUTTON_POSITIVE);
|
||||||
|
dialog.dismiss();
|
||||||
|
ToastUtil.showShort(context, R.string.login_success);
|
||||||
|
} else {
|
||||||
|
preferences.setChapterSyncCredentials(sync, "", "");
|
||||||
|
loginBtn.setProgress(-1);
|
||||||
|
}
|
||||||
|
}, error -> {
|
||||||
|
loginBtn.setProgress(-1);
|
||||||
|
loginBtn.setText(R.string.unknown_error);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,78 @@
|
|||||||
|
package eu.kanade.mangafeed.ui.setting.dialog;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.preference.DialogPreference;
|
||||||
|
import android.text.method.PasswordTransformationMethod;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.CheckBox;
|
||||||
|
import android.widget.EditText;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.dd.processbutton.iml.ActionProcessButton;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import eu.kanade.mangafeed.R;
|
||||||
|
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
||||||
|
import rx.Subscription;
|
||||||
|
|
||||||
|
public abstract class LoginDialogPreference extends DialogPreference {
|
||||||
|
|
||||||
|
@Bind(R.id.accounts_login) TextView title;
|
||||||
|
@Bind(R.id.username) EditText username;
|
||||||
|
@Bind(R.id.password) EditText password;
|
||||||
|
@Bind(R.id.show_password) CheckBox showPassword;
|
||||||
|
@Bind(R.id.login) ActionProcessButton loginBtn;
|
||||||
|
|
||||||
|
protected PreferencesHelper preferences;
|
||||||
|
protected AlertDialog dialog;
|
||||||
|
protected Subscription requestSubscription;
|
||||||
|
protected Context context;
|
||||||
|
|
||||||
|
public LoginDialogPreference(Context context, PreferencesHelper preferences) {
|
||||||
|
super(context, null);
|
||||||
|
this.context = context;
|
||||||
|
this.preferences = preferences;
|
||||||
|
|
||||||
|
setDialogLayoutResource(R.layout.pref_account_login);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onPrepareDialogBuilder(AlertDialog.Builder builder) {
|
||||||
|
// Hide positive button
|
||||||
|
builder.setPositiveButton("", this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBindDialogView(View view) {
|
||||||
|
super.onBindDialogView(view);
|
||||||
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
|
showPassword.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||||
|
if (isChecked)
|
||||||
|
password.setTransformationMethod(null);
|
||||||
|
else
|
||||||
|
password.setTransformationMethod(new PasswordTransformationMethod());
|
||||||
|
});
|
||||||
|
|
||||||
|
loginBtn.setMode(ActionProcessButton.Mode.ENDLESS);
|
||||||
|
loginBtn.setOnClickListener(click -> checkLogin());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void showDialog(Bundle state) {
|
||||||
|
super.showDialog(state);
|
||||||
|
dialog = ((AlertDialog) getDialog());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDialogClosed(boolean positiveResult) {
|
||||||
|
if (requestSubscription != null)
|
||||||
|
requestSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void checkLogin();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
package eu.kanade.mangafeed.ui.setting.dialog;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import eu.kanade.mangafeed.R;
|
||||||
|
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
|
||||||
|
import eu.kanade.mangafeed.data.source.base.Source;
|
||||||
|
import eu.kanade.mangafeed.util.ToastUtil;
|
||||||
|
import rx.android.schedulers.AndroidSchedulers;
|
||||||
|
import rx.schedulers.Schedulers;
|
||||||
|
|
||||||
|
public class SourceLoginDialog extends LoginDialogPreference {
|
||||||
|
|
||||||
|
private Source source;
|
||||||
|
|
||||||
|
public SourceLoginDialog(Context context, PreferencesHelper preferences, Source source) {
|
||||||
|
super(context, preferences);
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onBindDialogView(View view) {
|
||||||
|
super.onBindDialogView(view);
|
||||||
|
|
||||||
|
title.setText(getContext().getString(R.string.accounts_login_title, source.getName()));
|
||||||
|
|
||||||
|
username.setText(preferences.getSourceUsername(source));
|
||||||
|
password.setText(preferences.getSourcePassword(source));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDialogClosed(boolean positiveResult) {
|
||||||
|
super.onDialogClosed(positiveResult);
|
||||||
|
|
||||||
|
if (positiveResult) {
|
||||||
|
preferences.setSourceCredentials(source,
|
||||||
|
username.getText().toString(),
|
||||||
|
password.getText().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void checkLogin() {
|
||||||
|
if (requestSubscription != null)
|
||||||
|
requestSubscription.unsubscribe();
|
||||||
|
|
||||||
|
if (username.getText().length() == 0 || password.getText().length() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
loginBtn.setProgress(1);
|
||||||
|
|
||||||
|
requestSubscription = source
|
||||||
|
.login(username.getText().toString(), password.getText().toString())
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe(logged -> {
|
||||||
|
if (logged) {
|
||||||
|
// Simulate a positive button click and dismiss the dialog
|
||||||
|
onClick(dialog, DialogInterface.BUTTON_POSITIVE);
|
||||||
|
dialog.dismiss();
|
||||||
|
ToastUtil.showShort(context, R.string.login_success);
|
||||||
|
} else {
|
||||||
|
preferences.setSourceCredentials(source, "", "");
|
||||||
|
loginBtn.setProgress(-1);
|
||||||
|
}
|
||||||
|
}, error -> {
|
||||||
|
loginBtn.setProgress(-1);
|
||||||
|
loginBtn.setText(R.string.unknown_error);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
BIN
app/src/main/res/drawable-hdpi/ic_create.png
Normal file
BIN
app/src/main/res/drawable-hdpi/ic_create.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 262 B |
BIN
app/src/main/res/drawable-ldpi/ic_create.png
Normal file
BIN
app/src/main/res/drawable-ldpi/ic_create.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 195 B |
BIN
app/src/main/res/drawable-mdpi/ic_create.png
Normal file
BIN
app/src/main/res/drawable-mdpi/ic_create.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 195 B |
BIN
app/src/main/res/drawable-xhdpi/ic_create.png
Normal file
BIN
app/src/main/res/drawable-xhdpi/ic_create.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 299 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_create.png
Normal file
BIN
app/src/main/res/drawable-xxhdpi/ic_create.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 415 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_create.png
Normal file
BIN
app/src/main/res/drawable-xxxhdpi/ic_create.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 501 B |
36
app/src/main/res/layout/dialog_myanimelist_search.xml
Normal file
36
app/src/main/res/layout/dialog_myanimelist_search.xml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:id="@+id/myanimelist_search_field"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/action_search"
|
||||||
|
android:id="@+id/myanimelist_search_button"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ListView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/myanimelist_search_results"
|
||||||
|
android:choiceMode="singleChoice"
|
||||||
|
android:listSelector="@color/list_choice_pressed_bg_light">
|
||||||
|
|
||||||
|
</ListView>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
13
app/src/main/res/layout/dialog_myanimelist_search_item.xml
Normal file
13
app/src/main/res/layout/dialog_myanimelist_search_item.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/myanimelist_result_title"
|
||||||
|
android:padding="10dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
49
app/src/main/res/layout/fragment_myanimelist.xml
Normal file
49
app/src/main/res/layout/fragment_myanimelist.xml
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:padding="10dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="MyAnimeList title:" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/myanimelist_title" />
|
||||||
|
|
||||||
|
</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="Last chapter read" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:layout_width="56dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:inputType="number"
|
||||||
|
android:ems="10"
|
||||||
|
android:id="@+id/myanimelist_last_chapter_read"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/action_update"
|
||||||
|
android:id="@+id/update_button"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
10
app/src/main/res/menu/myanimelist.xml
Normal file
10
app/src/main/res/menu/myanimelist.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item android:title="@string/action_edit"
|
||||||
|
android:id="@+id/myanimelist_edit"
|
||||||
|
android:icon="@drawable/ic_create"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
</menu>
|
@ -17,10 +17,17 @@
|
|||||||
<string name="action_mark_as_unread">Mark as unread</string>
|
<string name="action_mark_as_unread">Mark as unread</string>
|
||||||
<string name="action_download">Download</string>
|
<string name="action_download">Download</string>
|
||||||
<string name="action_delete">Delete</string>
|
<string name="action_delete">Delete</string>
|
||||||
|
<string name="action_update">Update</string>
|
||||||
|
<string name="action_edit">Edit</string>
|
||||||
<string name="action_sort_up">Sort up</string>
|
<string name="action_sort_up">Sort up</string>
|
||||||
<string name="action_sort_down">Sort down</string>
|
<string name="action_sort_down">Sort down</string>
|
||||||
<string name="action_show_unread">Show unread</string>
|
<string name="action_show_unread">Show unread</string>
|
||||||
|
|
||||||
|
<!-- Buttons -->
|
||||||
|
<string name="button_ok">Ok</string>
|
||||||
|
<string name="button_cancel">Cancel</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Preferences -->
|
<!-- Preferences -->
|
||||||
<!-- Subsections -->
|
<!-- Subsections -->
|
||||||
<string name="pref_category_reader">Reader</string>
|
<string name="pref_category_reader">Reader</string>
|
||||||
|
@ -15,7 +15,7 @@ public class ChapterRecognitionTest {
|
|||||||
Manga randomManga;
|
Manga randomManga;
|
||||||
|
|
||||||
private Chapter createChapter(String title) {
|
private Chapter createChapter(String title) {
|
||||||
Chapter chapter = new Chapter();
|
Chapter chapter = Chapter.create();
|
||||||
chapter.name = title;
|
chapter.name = title;
|
||||||
return chapter;
|
return chapter;
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,9 @@ apply plugin: 'com.github.ben-manes.versions'
|
|||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
repositories {
|
||||||
jcenter()
|
jcenter()
|
||||||
maven {
|
|
||||||
url 'https://repos.zeroturnaround.com/nexus/content/repositories/zt-public-releases'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:1.3.0'
|
classpath 'com.android.tools.build:gradle:1.3.0'
|
||||||
// This does not break the build when Android Studio is missing the JRebel for Android plugin.
|
|
||||||
classpath 'com.zeroturnaround.jrebel.android:jr-android-gradle:0.9.+'
|
|
||||||
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.7'
|
classpath 'com.neenbedankt.gradle.plugins:android-apt:1.7'
|
||||||
classpath 'me.tatarka:gradle-retrolambda:3.2.3'
|
classpath 'me.tatarka:gradle-retrolambda:3.2.3'
|
||||||
classpath 'com.github.ben-manes:gradle-versions-plugin:0.11.3'
|
classpath 'com.github.ben-manes:gradle-versions-plugin:0.11.3'
|
||||||
|
Loading…
Reference in New Issue
Block a user