From 5e79e04e2f1606c18deb3bed78c51922705bf116 Mon Sep 17 00:00:00 2001 From: unravel22 Date: Fri, 8 Dec 2017 13:17:34 +0200 Subject: [PATCH 001/192] Update gradle config --- app/app.iml | 79 ++++++++++++------------ app/build.gradle | 49 ++++++++++----- build.gradle | 2 +- gradle/wrapper/gradle-wrapper.properties | 4 +- 4 files changed, 74 insertions(+), 60 deletions(-) diff --git a/app/app.iml b/app/app.iml index a9a90d89..1f23bb59 100644 --- a/app/app.iml +++ b/app/app.iml @@ -49,6 +49,13 @@ + + + + + + + @@ -63,13 +70,6 @@ - - - - - - - @@ -77,27 +77,26 @@ + + + + + + + - - - - - - - + - - @@ -105,30 +104,30 @@ - + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 236e46ae..5a92b34e 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,18 +1,22 @@ apply plugin: 'com.android.application' +def gitCommits = 'git rev-list --all --count'.execute([], rootDir).text.trim().toInteger() +def majorVersion = "4.3" + android { - compileSdkVersion 26 - buildToolsVersion "26.0.2" + compileSdkVersion 27 + buildToolsVersion "27.0.2" defaultConfig { applicationId "org.nv95.openmanga" minSdkVersion 14 - targetSdkVersion 26 - versionCode 1115 - versionName "preview build" + targetSdkVersion 27 + versionCode gitCommits + versionName "$majorVersion-$gitCommits" buildConfigField "boolean", "SELFUPDATE_ENABLED", "true" buildConfigField "String", "SELFUPDATE_URL", "\"http://anibreak.ru/v.0.3/get/openmanga/version\"" buildConfigField "String", "SYNC_URL", "\"http://46.36.36.38:5000/api/v1\"" + buildConfigField "String", "MAJOR_VERSION", "\"$majorVersion\"" } signingConfigs { @@ -29,13 +33,24 @@ android { minifyEnabled false shrinkResources false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + setProperty("archivesBaseName", "OpenManga-v${defaultConfig.versionName}") } + fdroid { + minifyEnabled false + shrinkResources false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + buildConfigField "boolean", "SELFUPDATE_ENABLED", "false" + versionNameSuffix="-fdroid" + } + debug { applicationIdSuffix ".debug" - minifyEnabled false - shrinkResources false - signingConfig signingConfigs.debug + versionNameSuffix="-debug" + minifyEnabled false + shrinkResources false + signingConfig signingConfigs.debug + setProperty("archivesBaseName", "OpenManga-v${defaultConfig.versionName}-debug") } } lintOptions { @@ -53,13 +68,13 @@ android { dependencies { - compile 'com.android.support:design:26.1.0' - compile 'com.android.support:recyclerview-v7:26.1.0' - compile 'com.android.support:cardview-v7:26.1.0' - compile 'org.jsoup:jsoup:1.10.3' - compile 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0' - compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' - compile 'com.soundcloud.android:android-crop:1.0.1@aar' - compile 'com.getkeepsafe.taptargetview:taptargetview:1.9.1' - compile 'info.guardianproject.netcipher:netcipher:2.0.0-alpha1' + implementation 'com.android.support:design:27.0.2' + implementation 'com.android.support:recyclerview-v7:27.0.2' + implementation 'com.android.support:cardview-v7:27.0.2' + implementation 'org.jsoup:jsoup:1.10.3' + implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.6.0' + implementation 'com.nostra13.universalimageloader:universal-image-loader:1.9.5' + implementation 'com.soundcloud.android:android-crop:1.0.1@aar' + implementation 'com.getkeepsafe.taptargetview:taptargetview:1.9.1' + implementation 'info.guardianproject.netcipher:netcipher:2.0.0-alpha1' } diff --git a/build.gradle b/build.gradle index 03bae593..17481913 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ buildscript { google() } dependencies { - classpath 'com.android.tools.build:gradle:3.0.0-beta7' + classpath 'com.android.tools.build:gradle:3.1.0-alpha05' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ca5ea296..108d310c 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Wed Sep 13 13:11:21 EEST 2017 +#Fri Dec 08 13:09:46 EET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip +distributionUrl=https\://services.gradle.org/distributions-snapshots/gradle-4.4-20171031235950+0000-all.zip From c6bceaac64bfde058b20533b4011c2a600f2f12d Mon Sep 17 00:00:00 2001 From: unravel22 Date: Fri, 8 Dec 2017 13:23:52 +0200 Subject: [PATCH 002/192] Fix desu.me chapters order --- app/app.iml | 10 ++++++++++ .../org/nv95/openmanga/providers/DesuMeProvider.java | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/app/app.iml b/app/app.iml index 1f23bb59..9eff24fb 100644 --- a/app/app.iml +++ b/app/app.iml @@ -86,17 +86,27 @@ + + + + + + + + + + diff --git a/app/src/main/java/org/nv95/openmanga/providers/DesuMeProvider.java b/app/src/main/java/org/nv95/openmanga/providers/DesuMeProvider.java index 077c889d..9005dd31 100644 --- a/app/src/main/java/org/nv95/openmanga/providers/DesuMeProvider.java +++ b/app/src/main/java/org/nv95/openmanga/providers/DesuMeProvider.java @@ -99,7 +99,7 @@ public MangaSummary getDetailedInfo(MangaInfo mangaInfo) { chapter.name = jo.isNull("title") ? "Chapter " + (i + 1) : jo.getString("title"); chapter.readLink = summary.path + "/chapter/" + jo.getInt("id"); chapter.provider = summary.provider; - summary.chapters.add(chapter); + summary.chapters.add(0, chapter); } return summary; } catch (Exception e) { From 081e276b6603fa3e3bf8cd4915827ceedf04bcd1 Mon Sep 17 00:00:00 2001 From: unravel22 Date: Fri, 8 Dec 2017 13:29:10 +0200 Subject: [PATCH 003/192] Fix changelog --- app/build.gradle | 1 + .../java/org/nv95/openmanga/activities/WelcomeActivity.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/build.gradle b/app/build.gradle index 5a92b34e..af6c165b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,6 +17,7 @@ android { buildConfigField "String", "SELFUPDATE_URL", "\"http://anibreak.ru/v.0.3/get/openmanga/version\"" buildConfigField "String", "SYNC_URL", "\"http://46.36.36.38:5000/api/v1\"" buildConfigField "String", "MAJOR_VERSION", "\"$majorVersion\"" + buildConfigField "boolean", "HAS_CHANGELOG", "false" } signingConfigs { diff --git a/app/src/main/java/org/nv95/openmanga/activities/WelcomeActivity.java b/app/src/main/java/org/nv95/openmanga/activities/WelcomeActivity.java index 62a7b600..b55477ae 100755 --- a/app/src/main/java/org/nv95/openmanga/activities/WelcomeActivity.java +++ b/app/src/main/java/org/nv95/openmanga/activities/WelcomeActivity.java @@ -62,7 +62,7 @@ public static boolean show(Activity context) { REQUEST_ONBOARDING ); } else if (lastVersion < version) { - if (version % 2 == 0 && prefs.getBoolean("showChangelog", true)) { + if (BuildConfig.HAS_CHANGELOG && prefs.getBoolean("showChangelog", true)) { context.startActivity( new Intent(context, WelcomeActivity.class) .putExtra("mode", WELCOME_CHANGELOG) From 42e39946530636952d63fe914566ec4697a1ef73 Mon Sep 17 00:00:00 2001 From: unravel22 Date: Fri, 8 Dec 2017 13:32:29 +0200 Subject: [PATCH 004/192] Fix #39 --- .../main/java/org/nv95/openmanga/components/RatingView.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/src/main/java/org/nv95/openmanga/components/RatingView.java b/app/src/main/java/org/nv95/openmanga/components/RatingView.java index bf32a52c..2f4504d9 100644 --- a/app/src/main/java/org/nv95/openmanga/components/RatingView.java +++ b/app/src/main/java/org/nv95/openmanga/components/RatingView.java @@ -49,6 +49,11 @@ private void init(Context context) { @SuppressLint("DefaultLocale") public void setRating(byte value) { + if (value == 0) { + setVisibility(GONE); + } else { + setVisibility(VISIBLE); + } int a = value / 10; int b = value % 10; setText(String.format("%d.%d", a, b)); From 214aae7f4a09def2b5288a933ca03256626ca38f Mon Sep 17 00:00:00 2001 From: unravel22 Date: Fri, 8 Dec 2017 13:43:18 +0200 Subject: [PATCH 005/192] Update travis --- .travis.yml | 4 +- app/src/main/AndroidManifest.xml | 174 ++++++++++++++++--------------- 2 files changed, 90 insertions(+), 88 deletions(-) diff --git a/.travis.yml b/.travis.yml index d49abf21..5f48fc2a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,8 +4,8 @@ android: components: - platform-tools - tools - - build-tools-26.0.2 - - android-26 + - build-tools-27.0.2 + - android-27 - extra-android-m2repository jdk: - oraclejdk8 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f1cc58c4..5677e687 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,95 +1,97 @@ + xmlns:tools="http://schemas.android.com/tools" + package="org.nv95.openmanga"> - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + - - - - - - - + + + + - + + + + + From b53c47dc7ec69d0b9c39d93085b7c82a661e209f Mon Sep 17 00:00:00 2001 From: unravel22 Date: Fri, 8 Dec 2017 14:09:25 +0200 Subject: [PATCH 006/192] Update gradle config --- app/app.iml | 1 + app/build.gradle | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/app/app.iml b/app/app.iml index 9eff24fb..fc3a9a40 100644 --- a/app/app.iml +++ b/app/app.iml @@ -112,6 +112,7 @@ + diff --git a/app/build.gradle b/app/build.gradle index af6c165b..1334123b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -6,6 +6,7 @@ def majorVersion = "4.3" android { compileSdkVersion 27 buildToolsVersion "27.0.2" + flavorDimensions "default" defaultConfig { applicationId "org.nv95.openmanga" @@ -13,6 +14,7 @@ android { targetSdkVersion 27 versionCode gitCommits versionName "$majorVersion-$gitCommits" + resConfigs "en", "ru", "tr", "uk" buildConfigField "boolean", "SELFUPDATE_ENABLED", "true" buildConfigField "String", "SELFUPDATE_URL", "\"http://anibreak.ru/v.0.3/get/openmanga/version\"" buildConfigField "String", "SYNC_URL", "\"http://46.36.36.38:5000/api/v1\"" @@ -38,20 +40,18 @@ android { } fdroid { - minifyEnabled false - shrinkResources false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' + initWith release buildConfigField "boolean", "SELFUPDATE_ENABLED", "false" versionNameSuffix="-fdroid" } - debug { + + debug { applicationIdSuffix ".debug" versionNameSuffix="-debug" minifyEnabled false shrinkResources false signingConfig signingConfigs.debug - setProperty("archivesBaseName", "OpenManga-v${defaultConfig.versionName}-debug") } } lintOptions { From 494ed169d6ab69f5fdeb903597c0d4ea7f41e4d1 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 11 Dec 2017 11:33:29 +0200 Subject: [PATCH 007/192] Change sync server --- OpenManga.iml | 1 + app/app.iml | 17 ++++++++--------- app/build.gradle | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/OpenManga.iml b/OpenManga.iml index c15cda03..d6c923ad 100644 --- a/OpenManga.iml +++ b/OpenManga.iml @@ -12,6 +12,7 @@ + diff --git a/app/app.iml b/app/app.iml index fc3a9a40..2f8359c9 100644 --- a/app/app.iml +++ b/app/app.iml @@ -49,13 +49,6 @@ - - - - - - - @@ -63,6 +56,13 @@ + + + + + + + @@ -94,12 +94,11 @@ - + - diff --git a/app/build.gradle b/app/build.gradle index 1334123b..d34b753a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -17,7 +17,7 @@ android { resConfigs "en", "ru", "tr", "uk" buildConfigField "boolean", "SELFUPDATE_ENABLED", "true" buildConfigField "String", "SELFUPDATE_URL", "\"http://anibreak.ru/v.0.3/get/openmanga/version\"" - buildConfigField "String", "SYNC_URL", "\"http://46.36.36.38:5000/api/v1\"" + buildConfigField "String", "SYNC_URL", "\"http://openmanga.pythonanywhere.com/api/v1\"" buildConfigField "String", "MAJOR_VERSION", "\"$majorVersion\"" buildConfigField "boolean", "HAS_CHANGELOG", "false" } From 74b30a85f47cbda00ab031cd619313d77499137f Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 11 Dec 2017 11:41:49 +0200 Subject: [PATCH 008/192] Fix webtton mode crash --- OpenManga.iml | 1 - .../nv95/openmanga/components/reader/OverscrollDetector.java | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenManga.iml b/OpenManga.iml index d6c923ad..c15cda03 100644 --- a/OpenManga.iml +++ b/OpenManga.iml @@ -12,7 +12,6 @@ - diff --git a/app/src/main/java/org/nv95/openmanga/components/reader/OverscrollDetector.java b/app/src/main/java/org/nv95/openmanga/components/reader/OverscrollDetector.java index 767975c0..b66b8447 100644 --- a/app/src/main/java/org/nv95/openmanga/components/reader/OverscrollDetector.java +++ b/app/src/main/java/org/nv95/openmanga/components/reader/OverscrollDetector.java @@ -47,6 +47,7 @@ else if (mCanScrollBottom) mStartPoint = new PointF(motionEvent.getX(), motionEvent.getY()); return true; case MotionEvent.ACTION_MOVE: + if (mStartPoint == null) return false; int dY = (int) (mStartPoint.y - motionEvent.getY()); int dX = (int) (mStartPoint.x - motionEvent.getX()); if (mCanScrollTop && dY < 0) @@ -61,6 +62,7 @@ else if (mCanScrollRight && dX > 0) return true; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: + if (mStartPoint == null) return false; dY = (int) (mStartPoint.y - motionEvent.getY()); dX = (int) (mStartPoint.x - motionEvent.getX()); From 59af51d6a63fbbab314441e1cdc4651f214a2a1e Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 11 Dec 2017 11:45:11 +0200 Subject: [PATCH 009/192] Update changelog --- app/build.gradle | 4 ++-- app/src/main/res/raw-ru/changelog | 14 ++------------ app/src/main/res/raw/changelog | 14 ++------------ 3 files changed, 6 insertions(+), 26 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d34b753a..8351f0f9 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,7 +1,7 @@ apply plugin: 'com.android.application' def gitCommits = 'git rev-list --all --count'.execute([], rootDir).text.trim().toInteger() -def majorVersion = "4.3" +def majorVersion = "4.3.1" android { compileSdkVersion 27 @@ -19,7 +19,7 @@ android { buildConfigField "String", "SELFUPDATE_URL", "\"http://anibreak.ru/v.0.3/get/openmanga/version\"" buildConfigField "String", "SYNC_URL", "\"http://openmanga.pythonanywhere.com/api/v1\"" buildConfigField "String", "MAJOR_VERSION", "\"$majorVersion\"" - buildConfigField "boolean", "HAS_CHANGELOG", "false" + buildConfigField "boolean", "HAS_CHANGELOG", "true" } signingConfigs { diff --git a/app/src/main/res/raw-ru/changelog b/app/src/main/res/raw-ru/changelog index ed00f8cf..6dfec0ac 100644 --- a/app/src/main/res/raw-ru/changelog +++ b/app/src/main/res/raw-ru/changelog @@ -1,15 +1,5 @@

Примечания к выпуску

- + Синхронизация истории и избранного
- + Поддержка Tor proxy
- + Создание ярлыков на домашнем экране
- + Открытие читалки прямо из списка
- + Новый каклог манги: ScanFR
- + Экспорт сохранённой манги в CBZ файлы
- + Параллельная загрузка манги, отображение скорости загрузки
- + Множественное выделение в результатах поиска
- + Сохранение глав прямо из списка (глав)
- + Отображение последней манги по долгому нажатию «Продолжить»
- * Обновлённый пользовательский интерфейс
- * Множество исправлений и оптимизация
+ * Изменён адрес сервера синхронизации
+ * Исправления

\ No newline at end of file diff --git a/app/src/main/res/raw/changelog b/app/src/main/res/raw/changelog index 03818269..5a6356a5 100644 --- a/app/src/main/res/raw/changelog +++ b/app/src/main/res/raw/changelog @@ -1,15 +1,5 @@

Changelog

- + Synchronization: you can synchronize favourites and history across devices
- + Tor proxy support
- + Creating home screen shortcuts for manga
- + Opening reader directly from lists
- + New manga catalogue: ScanFR
- + Exporting saved manga to CBZ files
- + Saving multiple manga parallel and showing downloading speed
- + Multiple selection in search results
- + Saving chapters directly from chapters list
- + Showing recent manga by long tap on «Quick read» button
- * Updated UI
- * Lot of fixes and optimization
+ * Change synchronization server address
+ * Other fixes

\ No newline at end of file From 6ba3133ed8a9001dfe3484972c04c612d8cca30a Mon Sep 17 00:00:00 2001 From: unravel22 Date: Mon, 18 Dec 2017 16:07:56 +0200 Subject: [PATCH 010/192] Sync authenticator --- app/app.iml | 17 +- app/src/main/AndroidManifest.xml | 17 ++ .../settings/SettingsActivity2.java | 3 +- .../nv95/openmanga/helpers/SyncHelper.java | 5 + .../openmanga/sync/AppCompatAuthActivity.java | 133 ++++++++++ .../openmanga/sync/SyncAccountService.java | 20 ++ .../nv95/openmanga/sync/SyncAuthActivity.java | 234 ++++++++++++++++++ .../openmanga/sync/SyncAuthenticator.java | 97 ++++++++ .../nv95/openmanga/utils/WeakAsyncTask.java | 17 +- app/src/main/res/drawable/ic_arrow_left.xml | 9 + app/src/main/res/layout/activity_syncauth.xml | 117 +++++++++ app/src/main/res/values/strings.xml | 3 + app/src/main/res/xml/authenticator.xml | 7 + 13 files changed, 666 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/org/nv95/openmanga/sync/AppCompatAuthActivity.java create mode 100644 app/src/main/java/org/nv95/openmanga/sync/SyncAccountService.java create mode 100644 app/src/main/java/org/nv95/openmanga/sync/SyncAuthActivity.java create mode 100644 app/src/main/java/org/nv95/openmanga/sync/SyncAuthenticator.java create mode 100644 app/src/main/res/drawable/ic_arrow_left.xml create mode 100644 app/src/main/res/layout/activity_syncauth.xml create mode 100644 app/src/main/res/xml/authenticator.xml diff --git a/app/app.iml b/app/app.iml index 2f8359c9..fc3a9a40 100644 --- a/app/app.iml +++ b/app/app.iml @@ -49,13 +49,6 @@ - - - - - - - @@ -63,6 +56,13 @@ + + + + + + + @@ -94,11 +94,12 @@ + - + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5677e687..e63ddb2d 100755 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -11,6 +11,9 @@ + + + + + @@ -80,6 +88,15 @@ + + + + + + + + instanceRef = new WeakReference<>(null); @@ -381,4 +382,8 @@ private void noauthBroadcast() { intent.putExtra("what", SyncService.MSG_UNAUTHORIZED); mContext.sendBroadcast(intent); } + + public String getToken() { + return mToken; + } } diff --git a/app/src/main/java/org/nv95/openmanga/sync/AppCompatAuthActivity.java b/app/src/main/java/org/nv95/openmanga/sync/AppCompatAuthActivity.java new file mode 100644 index 00000000..2fbe75d4 --- /dev/null +++ b/app/src/main/java/org/nv95/openmanga/sync/AppCompatAuthActivity.java @@ -0,0 +1,133 @@ +package org.nv95.openmanga.sync; + +import android.accounts.AccountAuthenticatorActivity; +import android.content.res.Configuration; +import android.os.Bundle; +import android.support.annotation.LayoutRes; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.v7.app.ActionBar; +import android.support.v7.app.AppCompatDelegate; +import android.support.v7.widget.Toolbar; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; +import android.view.ViewGroup; + +import org.nv95.openmanga.activities.BaseAppActivity; +import org.nv95.openmanga.utils.LayoutUtils; + +/** + * Created by koitharu on 18.12.17. + */ + +public abstract class AppCompatAuthActivity extends AccountAuthenticatorActivity { + + private int mTheme = 0; + private AppCompatDelegate mDelegate; + + @Override + protected void onCreate(Bundle savedInstanceState) { + getDelegate().installViewFactory(); + getDelegate().onCreate(savedInstanceState); + super.onCreate(savedInstanceState); + mTheme = LayoutUtils.getAppTheme(this); + setTheme(LayoutUtils.getAppThemeRes(mTheme)); + } + + @Override + protected void onPostCreate(Bundle savedInstanceState) { + super.onPostCreate(savedInstanceState); + getDelegate().onPostCreate(savedInstanceState); + } + + public ActionBar getSupportActionBar() { + return getDelegate().getSupportActionBar(); + } + + public void setSupportActionBar(@Nullable Toolbar toolbar) { + getDelegate().setSupportActionBar(toolbar); + } + + @Override + @NonNull + public MenuInflater getMenuInflater() { + return getDelegate().getMenuInflater(); + } + + @Override + public void setContentView(@LayoutRes int layoutResID) { + getDelegate().setContentView(layoutResID); + } + + @Override + public void setContentView(View view) { + getDelegate().setContentView(view); + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().setContentView(view, params); + } + + @Override + public void addContentView(View view, ViewGroup.LayoutParams params) { + getDelegate().addContentView(view, params); + } + + @Override + protected void onPostResume() { + super.onPostResume(); + getDelegate().onPostResume(); + } + + @Override + protected void onTitleChanged(CharSequence title, int color) { + super.onTitleChanged(title, color); + getDelegate().setTitle(title); + } + + @Override + public void onConfigurationChanged(Configuration newConfig) { + super.onConfigurationChanged(newConfig); + getDelegate().onConfigurationChanged(newConfig); + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + if (item.getItemId() == android.R.id.home) { + finish(); + } + return super.onOptionsItemSelected(item); + } + + @Override + protected void onStop() { + super.onStop(); + getDelegate().onStop(); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + getDelegate().onDestroy(); + } + + public void invalidateOptionsMenu() { + getDelegate().invalidateOptionsMenu(); + } + + private AppCompatDelegate getDelegate() { + if (mDelegate == null) { + mDelegate = AppCompatDelegate.create(this, null); + } + return mDelegate; + } + + public void enableHomeAsUp() { + final ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } + } +} diff --git a/app/src/main/java/org/nv95/openmanga/sync/SyncAccountService.java b/app/src/main/java/org/nv95/openmanga/sync/SyncAccountService.java new file mode 100644 index 00000000..8c381413 --- /dev/null +++ b/app/src/main/java/org/nv95/openmanga/sync/SyncAccountService.java @@ -0,0 +1,20 @@ +package org.nv95.openmanga.sync; + +import android.app.Service; +import android.content.Intent; +import android.os.IBinder; +import android.support.annotation.Nullable; + +/** + * Created by koitharu on 18.12.17. + */ + +public class SyncAccountService extends Service { + + @Nullable + @Override + public IBinder onBind(Intent intent) { + SyncAuthenticator authenticator = new SyncAuthenticator(this); + return authenticator.getIBinder(); + } +} diff --git a/app/src/main/java/org/nv95/openmanga/sync/SyncAuthActivity.java b/app/src/main/java/org/nv95/openmanga/sync/SyncAuthActivity.java new file mode 100644 index 00000000..e2fbd42b --- /dev/null +++ b/app/src/main/java/org/nv95/openmanga/sync/SyncAuthActivity.java @@ -0,0 +1,234 @@ +package org.nv95.openmanga.sync; + +import android.accounts.Account; +import android.accounts.AccountManager; +import android.animation.Animator; +import android.animation.AnimatorListenerAdapter; +import android.content.Intent; +import android.os.AsyncTask; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.design.widget.TextInputEditText; +import android.support.design.widget.TextInputLayout; +import android.support.v7.widget.Toolbar; +import android.text.TextUtils; +import android.view.KeyEvent; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.Button; +import android.widget.TextView; + +import org.json.JSONException; +import org.nv95.openmanga.BuildConfig; +import org.nv95.openmanga.R; +import org.nv95.openmanga.items.RESTResponse; +import org.nv95.openmanga.utils.AppHelper; +import org.nv95.openmanga.utils.NetworkUtils; +import org.nv95.openmanga.utils.WeakAsyncTask; + +/** + * Created by koitharu on 18.12.17. + */ + +public class SyncAuthActivity extends AppCompatAuthActivity implements View.OnClickListener { + + private UserLoginTask mAuthTask = null; + private TextInputLayout mLayoutPassword; + private TextInputEditText mEditLogin; + private TextInputEditText mEditPassword; + private Button mButtonSignIn; + private Button mButtonRegisterMode; + private Button mButtonRegister; + private Button mButtonBack; + private View mViewProgress; + private View mViewForm; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_syncauth); + setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); + enableHomeAsUp(); + + mEditLogin = findViewById(R.id.editLogin); + mEditPassword = findViewById(R.id.editPassword); + mLayoutPassword = findViewById(R.id.inputLayoutPassword); + mButtonSignIn = findViewById(R.id.buttonLogin); + mButtonRegister = findViewById(R.id.buttonRegister); + mButtonRegisterMode = findViewById(R.id.buttonRegisterMode); + mButtonBack = findViewById(R.id.buttonBack); + + mEditPassword.setOnEditorActionListener(new TextView.OnEditorActionListener() { + + @Override + public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) { + if (id == EditorInfo.IME_ACTION_DONE || id == EditorInfo.IME_NULL) { + attemptLogin(mButtonRegister.getVisibility() == View.VISIBLE); + return true; + } + return false; + } + }); + + mButtonRegister.setOnClickListener(this); + mButtonSignIn.setOnClickListener(this); + mButtonRegisterMode.setOnClickListener(this); + mButtonBack.setOnClickListener(this); + + mViewForm = findViewById(R.id.login_form); + mViewProgress = findViewById(R.id.login_progress); + } + + @Override + public void onClick(View view) { + switch (view.getId()) { + case R.id.buttonLogin: + attemptLogin(false); + break; + case R.id.buttonRegister: + attemptLogin(true); + break; + case R.id.buttonRegisterMode: + mButtonSignIn.setVisibility(View.GONE); + mButtonRegister.setVisibility(View.VISIBLE); + mButtonRegisterMode.setVisibility(View.GONE); + mButtonBack.setVisibility(View.VISIBLE); + break; + case R.id.buttonBack: + mButtonSignIn.setVisibility(View.VISIBLE); + mButtonRegister.setVisibility(View.GONE); + mButtonRegisterMode.setVisibility(View.VISIBLE); + mButtonBack.setVisibility(View.GONE); + break; + } + } + + private void attemptLogin(boolean wantRegister) { + if (mAuthTask != null) { + return; + } + mEditLogin.setError(null); + mEditPassword.setError(null); + mLayoutPassword.setError(null); + + String login = mEditLogin.getText().toString().trim(); + String password = mEditPassword.getText().toString(); + + boolean cancel = false; + View focusView = null; + + if (wantRegister && !TextUtils.isEmpty(password) && password.length() < 4) { + mLayoutPassword.setError(getString(R.string.password_too_short)); + focusView = mEditPassword; + cancel = true; + } + + if (TextUtils.isEmpty(login)) { + mEditLogin.setError(getString(R.string.login_required)); + focusView = mEditLogin; + cancel = true; + } + + if (cancel) { + if (focusView != null) { + focusView.requestFocus(); + } + } else { + showProgress(true); + mAuthTask = new UserLoginTask(this, login, password, wantRegister); + mAuthTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + } + + private void showProgress(final boolean show) { + + int shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime); + + mViewForm.setVisibility(show ? View.GONE : View.VISIBLE); + mViewForm.animate().setDuration(shortAnimTime).alpha( + show ? 0 : 1).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mViewForm.setVisibility(show ? View.GONE : View.VISIBLE); + } + }); + + mViewProgress.setVisibility(show ? View.VISIBLE : View.GONE); + mViewProgress.animate().setDuration(shortAnimTime).alpha( + show ? 1 : 0).setListener(new AnimatorListenerAdapter() { + @Override + public void onAnimationEnd(Animator animation) { + mViewProgress.setVisibility(show ? View.VISIBLE : View.GONE); + } + }); + } + + private void finishLogin(String login, String password, String token) { + final AccountManager accountManager = AccountManager.get(this); + final Intent intent = new Intent(); + intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, login); + intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, SyncAuthenticator.ACCOUNT_TYPE); + intent.putExtra(AccountManager.KEY_AUTHTOKEN, token); + final Account account = new Account(login, SyncAuthenticator.ACCOUNT_TYPE); + accountManager.addAccountExplicitly(account, password, null); + accountManager.setAuthToken(account, SyncAuthenticator.TOKEN_DEFAULT, token); + setAccountAuthenticatorResult(intent.getExtras()); + setResult(RESULT_OK, intent); + finish(); + } + + + public static class UserLoginTask extends WeakAsyncTask { + + private final String mLogin; + private final String mPassword; + private final boolean mWantRegister; + + UserLoginTask(SyncAuthActivity authActivity, String login, String password, boolean wantRegister) { + super(authActivity); + mLogin = login; + mPassword = password; + mWantRegister = wantRegister; + } + + @Override + protected RESTResponse doInBackground(Void... params) { + return NetworkUtils.restQuery( + BuildConfig.SYNC_URL + "/user", + null, + mWantRegister ? NetworkUtils.HTTP_PUT : NetworkUtils.HTTP_POST, + "login", mLogin, + "password", mPassword, + "device", + AppHelper.getDeviceSummary() + ); + } + + @Override + protected void onPostExecute(@NonNull SyncAuthActivity authActivity, RESTResponse response) { + authActivity.mAuthTask = null; + authActivity.showProgress(false); + + if (response.isSuccess()) { + try { + final String token = response.getData().getString("token"); + authActivity.finishLogin(mLogin, mPassword, token); + } catch (JSONException e) { + e.printStackTrace(); + authActivity.mLayoutPassword.setError(authActivity.getString(R.string.error)); + authActivity.mEditPassword.requestFocus(); + } + } else { + authActivity.mLayoutPassword.setError(response.getMessage()); + authActivity.mEditPassword.requestFocus(); + } + } + + + @Override + protected void onTaskCancelled(@NonNull SyncAuthActivity authActivity) { + authActivity.mAuthTask = null; + authActivity.showProgress(false); + } + } +} diff --git a/app/src/main/java/org/nv95/openmanga/sync/SyncAuthenticator.java b/app/src/main/java/org/nv95/openmanga/sync/SyncAuthenticator.java new file mode 100644 index 00000000..f67717a3 --- /dev/null +++ b/app/src/main/java/org/nv95/openmanga/sync/SyncAuthenticator.java @@ -0,0 +1,97 @@ +package org.nv95.openmanga.sync; + +import android.accounts.AbstractAccountAuthenticator; +import android.accounts.Account; +import android.accounts.AccountAuthenticatorResponse; +import android.accounts.AccountManager; +import android.accounts.NetworkErrorException; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.text.TextUtils; + +import org.nv95.openmanga.BuildConfig; +import org.nv95.openmanga.activities.settings.SettingsActivity2; +import org.nv95.openmanga.helpers.SyncHelper; + +/** + * Created by koitharu on 18.12.17. + */ + +public class SyncAuthenticator extends AbstractAccountAuthenticator { + + static final String ACCOUNT_TYPE = "org.nv95.openmanga.SYNC"; + static final String TOKEN_DEFAULT = "default"; + + private final Context mContext; + + public SyncAuthenticator(Context context) { + super(context); + mContext = context; + } + + @Override + public Bundle editProperties(AccountAuthenticatorResponse accountAuthenticatorResponse, String s) { + return null; + } + + @Override + public Bundle addAccount(AccountAuthenticatorResponse response, String accountType, String authTokenType, String[] requiredFeatures, Bundle options) throws NetworkErrorException { + final Intent intent = new Intent(mContext, SyncAuthActivity.class); + intent.putExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE, response); + final Bundle bundle = new Bundle(); + bundle.putParcelable(AccountManager.KEY_INTENT, intent); + return bundle; + } + + @Override + public Bundle confirmCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, Bundle bundle) throws NetworkErrorException { + return null; + } + + @Override + public Bundle getAuthToken(AccountAuthenticatorResponse response, Account account, String authTokenType, Bundle options) throws NetworkErrorException { + + // Extract the username and password from the Account Manager, and ask + // the server for an appropriate AuthToken. + final AccountManager am = AccountManager.get(mContext); + + String authToken = am.peekAuthToken(account, authTokenType); + + // Lets give another try to authenticate the user + if (TextUtils.isEmpty(authToken)) { + final String password = am.getPassword(account); + if (password != null) { + SyncHelper.get(mContext).authorize(account.name, password); + authToken = SyncHelper.get(mContext).getToken(); + } + } + + // If we get an authToken - we return it + if (!TextUtils.isEmpty(authToken)) { + final Bundle result = new Bundle(); + result.putString(AccountManager.KEY_ACCOUNT_NAME, account.name); + result.putString(AccountManager.KEY_ACCOUNT_TYPE, account.type); + result.putString(AccountManager.KEY_AUTHTOKEN, authToken); + return result; + } + + return addAccount(response, account.type, authTokenType, new String[0], options); + } + + + @Override + public String getAuthTokenLabel(String s) { + return null; + } + + @Override + public Bundle updateCredentials(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String s, Bundle bundle) throws NetworkErrorException { + return null; + } + + @Override + public Bundle hasFeatures(AccountAuthenticatorResponse accountAuthenticatorResponse, Account account, String[] strings) throws NetworkErrorException { + return null; + } +} diff --git a/app/src/main/java/org/nv95/openmanga/utils/WeakAsyncTask.java b/app/src/main/java/org/nv95/openmanga/utils/WeakAsyncTask.java index b0130ca7..91553e71 100644 --- a/app/src/main/java/org/nv95/openmanga/utils/WeakAsyncTask.java +++ b/app/src/main/java/org/nv95/openmanga/utils/WeakAsyncTask.java @@ -26,7 +26,7 @@ protected Obj getObject() { } @Override - protected void onPostExecute(Result result) { + protected final void onPostExecute(Result result) { super.onPostExecute(result); Obj obj = getObject(); if (obj != null) { @@ -35,7 +35,7 @@ protected void onPostExecute(Result result) { } @Override - protected void onPreExecute() { + protected final void onPreExecute() { super.onPreExecute(); Obj obj = getObject(); if (obj != null) { @@ -44,7 +44,7 @@ protected void onPreExecute() { } @Override - protected void onProgressUpdate(Progress[] values) { + protected final void onProgressUpdate(Progress[] values) { super.onProgressUpdate(values); Obj obj = getObject(); if (obj != null) { @@ -52,6 +52,15 @@ protected void onProgressUpdate(Progress[] values) { } } + @Override + protected final void onCancelled() { + super.onCancelled(); + Obj obj = getObject(); + if (obj != null) { + onTaskCancelled(obj); + } + } + @SafeVarargs public final void start(Param... params) { this.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, params); @@ -72,6 +81,8 @@ protected void onPreExecute(@NonNull Obj obj) {} protected void onPostExecute(@NonNull Obj obj, Result result) {} + protected void onTaskCancelled(@NonNull Obj obj) {} + public static void cancel(@Nullable WeakReference weakReference, boolean mayInterruptIfRunning) { if (weakReference == null) return; AsyncTask task = weakReference.get(); diff --git a/app/src/main/res/drawable/ic_arrow_left.xml b/app/src/main/res/drawable/ic_arrow_left.xml new file mode 100644 index 00000000..0783aa49 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_left.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_syncauth.xml b/app/src/main/res/layout/activity_syncauth.xml new file mode 100644 index 00000000..83fc23e8 --- /dev/null +++ b/app/src/main/res/layout/activity_syncauth.xml @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + +