Browse Source

Initial support for sources' login. Upgrade support library version.

inorichi 9 years ago
parent
commit
0e9e80b081

+ 5 - 1
app/build.gradle

@@ -4,6 +4,10 @@ apply plugin: 'com.zeroturnaround.jrebel.android'
 apply plugin: 'com.neenbedankt.android-apt'
 apply plugin: 'me.tatarka.retrolambda'
 
+retrolambda {
+    jvmArgs '-noverify'
+}
+
 android {
     compileSdkVersion 23
     buildToolsVersion "23.0.1"
@@ -45,7 +49,7 @@ android {
 }
 
 dependencies {
-    final SUPPORT_LIBRARY_VERSION = '23.0.1'
+    final SUPPORT_LIBRARY_VERSION = '23.1.0'
     final DAGGER_VERSION = '2.0.1'
     final HAMCREST_VERSION = '1.3'
     final MOCKITO_VERSION = '1.10.19'

+ 27 - 5
app/src/main/java/eu/kanade/mangafeed/data/helpers/PreferencesHelper.java

@@ -5,30 +5,52 @@ import android.content.SharedPreferences;
 import android.preference.PreferenceManager;
 
 import eu.kanade.mangafeed.R;
+import eu.kanade.mangafeed.sources.Source;
 
 public class PreferencesHelper {
 
     private static SharedPreferences mPref;
+    private Context context;
 
-    private static final String PREF_HIDE_STATUS_BAR = "hide_status_bar";
-    private static final String PREF_DEFAULT_VIEWER = "default_viewer";
+    private static final String SOURCE_ACCOUNT_USERNAME = "pref_source_username_";
+    private static final String SOURCE_ACCOUNT_PASSWORD = "pref_source_password_";
 
     public PreferencesHelper(Context context) {
-        PreferenceManager.setDefaultValues(context, R.xml.preferences, false);
+        this.context = context;
+        PreferenceManager.setDefaultValues(context, R.xml.pref_reader, false);
 
         mPref = PreferenceManager.getDefaultSharedPreferences(context);
     }
 
+    private String getKey(int keyResource) {
+        return context.getString(keyResource);
+    }
+
     public void clear() {
         mPref.edit().clear().apply();
     }
 
     public boolean hideStatusBarSet() {
-        return mPref.getBoolean(PREF_HIDE_STATUS_BAR, false);
+        return mPref.getBoolean(getKey(R.string.pref_hide_status_bar_key), false);
     }
 
     public int getDefaultViewer() {
-        return Integer.parseInt(mPref.getString(PREF_DEFAULT_VIEWER, "1"));
+        return Integer.parseInt(mPref.getString(getKey(R.string.pref_default_viewer_key), "1"));
+    }
+
+    public String getSourceUsername(Source source) {
+        return mPref.getString(SOURCE_ACCOUNT_USERNAME + source.getSourceId(), "");
+    }
+
+    public String getSourcePassword(Source source) {
+        return mPref.getString(SOURCE_ACCOUNT_PASSWORD + source.getSourceId(), "");
+    }
+
+    public void setSourceCredentials(Source source, String username, String password) {
+        mPref.edit()
+                .putString(SOURCE_ACCOUNT_USERNAME + source.getSourceId(), username)
+                .putString(SOURCE_ACCOUNT_PASSWORD + source.getSourceId(), password)
+                .apply();
     }
 
 }

+ 2 - 0
app/src/main/java/eu/kanade/mangafeed/injection/component/AppComponent.java

@@ -15,6 +15,7 @@ import eu.kanade.mangafeed.presenter.MangaInfoPresenter;
 import eu.kanade.mangafeed.presenter.ReaderPresenter;
 import eu.kanade.mangafeed.presenter.SourcePresenter;
 import eu.kanade.mangafeed.ui.activity.ReaderActivity;
+import eu.kanade.mangafeed.ui.fragment.SettingsAccountsFragment;
 
 @Singleton
 @Component(
@@ -34,6 +35,7 @@ public interface AppComponent {
     void inject(ReaderPresenter readerPresenter);
 
     void inject(ReaderActivity readerActivity);
+    void inject(SettingsAccountsFragment settingsAccountsFragment);
 
     Application application();
 

+ 5 - 0
app/src/main/java/eu/kanade/mangafeed/sources/Batoto.java

@@ -98,6 +98,11 @@ public class Batoto extends Source {
         return SourceManager.BATOTO;
     }
 
+    @Override
+    public boolean isLoginRequired() {
+        return true;
+    }
+
     @Override
     protected String getUrlFromPageNumber(int page) {
         return INITIAL_UPDATE_URL + page;

+ 5 - 0
app/src/main/java/eu/kanade/mangafeed/sources/Source.java

@@ -33,6 +33,11 @@ public abstract class Source {
     protected abstract List<String> parseHtmlToPageUrls(String unparsedHtml);
     protected abstract String parseHtmlToImageUrl(String unparsedHtml);
 
+    // True if the source requires a login
+    public boolean isLoginRequired() {
+        return false;
+    }
+
     // Get the URL to the details of a manga, useful if the source provides some kind of API or fast calls
     protected String getMangaUrl(String defaultMangaUrl) {
         return defaultMangaUrl;

+ 18 - 8
app/src/main/java/eu/kanade/mangafeed/ui/activity/SettingsActivity.java

@@ -1,13 +1,14 @@
 package eu.kanade.mangafeed.ui.activity;
 
 import android.os.Bundle;
-import android.preference.PreferenceFragment;
 import android.support.v7.widget.Toolbar;
+import android.view.MenuItem;
 
 import butterknife.Bind;
 import butterknife.ButterKnife;
 import eu.kanade.mangafeed.R;
 import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
+import eu.kanade.mangafeed.ui.fragment.SettingsMainFragment;
 
 public class SettingsActivity extends BaseActivity {
 
@@ -21,16 +22,25 @@ public class SettingsActivity extends BaseActivity {
 
         setupToolbar(toolbar);
 
-        getFragmentManager().beginTransaction().replace(R.id.settings_content,
-                new MyPreferenceFragment()).commit();
+        if (savedInstanceState == null)
+            getFragmentManager().beginTransaction().replace(R.id.settings_content,
+                    new SettingsMainFragment())
+                    .commit();
     }
 
-    public static class MyPreferenceFragment extends PreferenceFragment {
-        @Override
-        public void onCreate(final Bundle savedInstanceState) {
-            super.onCreate(savedInstanceState);
-            addPreferencesFromResource(R.xml.preferences);
+    @Override
+    public void onBackPressed() {
+        if( !getFragmentManager().popBackStackImmediate() ) super.onBackPressed();
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                onBackPressed();
+                return true;
         }
+        return super.onOptionsItemSelected(item);
     }
 
 }

+ 120 - 0
app/src/main/java/eu/kanade/mangafeed/ui/fragment/SettingsAccountsFragment.java

@@ -0,0 +1,120 @@
+package eu.kanade.mangafeed.ui.fragment;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.preference.DialogPreference;
+import android.preference.PreferenceFragment;
+import android.preference.PreferenceScreen;
+import android.text.method.PasswordTransformationMethod;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.CheckBox;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import butterknife.Bind;
+import butterknife.ButterKnife;
+import eu.kanade.mangafeed.App;
+import eu.kanade.mangafeed.R;
+import eu.kanade.mangafeed.data.helpers.PreferencesHelper;
+import eu.kanade.mangafeed.data.helpers.SourceManager;
+import eu.kanade.mangafeed.sources.Source;
+import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
+import rx.Observable;
+
+public class SettingsAccountsFragment extends PreferenceFragment {
+
+    @Inject SourceManager sourceManager;
+    @Inject PreferencesHelper preferences;
+
+    public static SettingsAccountsFragment newInstance() {
+        return new SettingsAccountsFragment();
+    }
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        App.get(getActivity()).getComponent().inject(this);
+
+        addPreferencesFromResource(R.xml.pref_accounts);
+
+        PreferenceScreen screen = getPreferenceScreen();
+
+        List<Source> sourceAccounts = getSourcesWithLogin();
+
+        for (Source source : sourceAccounts) {
+            LoginDialogPreference dialog = new LoginDialogPreference(
+                    screen.getContext(), null, source);
+            dialog.setTitle(source.getName());
+
+            screen.addPreference(dialog);
+        }
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        ((BaseActivity)getActivity())
+                .setToolbarTitle(getString(R.string.pref_category_accounts));
+    }
+
+    private List<Source> getSourcesWithLogin() {
+        return Observable.from(sourceManager.getSources())
+                .filter(Source::isLoginRequired)
+                .toList()
+                .toBlocking()
+                .single();
+    }
+
+    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;
+
+        private Source source;
+
+        public LoginDialogPreference(Context context, AttributeSet attrs, Source source) {
+            super(context, attrs);
+            this.source = source;
+
+            setDialogLayoutResource(R.layout.pref_account_login);
+        }
+
+        @Override
+        protected void onBindDialogView(View view) {
+            ButterKnife.bind(this, view);
+
+            title.setText(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());
+            });
+
+            super.onBindDialogView(view);
+        }
+
+        @Override
+        protected void onDialogClosed(boolean positiveResult) {
+            if(!positiveResult)
+                return;
+
+            preferences.setSourceCredentials(source,
+                    username.getText().toString(),
+                    password.getText().toString());
+
+            super.onDialogClosed(true);
+        }
+
+    }
+
+}

+ 41 - 0
app/src/main/java/eu/kanade/mangafeed/ui/fragment/SettingsMainFragment.java

@@ -0,0 +1,41 @@
+package eu.kanade.mangafeed.ui.fragment;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+import eu.kanade.mangafeed.R;
+import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
+
+public class SettingsMainFragment extends PreferenceFragment {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(R.xml.pref_main);
+
+        registerSubpreference(R.string.pref_category_reader_key,
+                SettingsNestedFragment.newInstance(
+                        R.xml.pref_reader, R.string.pref_category_reader));
+
+        registerSubpreference(R.string.pref_category_accounts_key,
+                SettingsAccountsFragment.newInstance());
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        ((BaseActivity)getActivity())
+                .setToolbarTitle(getString(R.string.settings_title));
+    }
+
+    private void registerSubpreference(int preferenceResource, PreferenceFragment fragment) {
+        findPreference(getString(preferenceResource))
+                .setOnPreferenceClickListener(preference -> {
+                    getFragmentManager().beginTransaction()
+                            .replace(R.id.settings_content, fragment)
+                            .addToBackStack(fragment.getClass().getSimpleName()).commit();
+                    return true;
+                });
+    }
+
+}

+ 36 - 0
app/src/main/java/eu/kanade/mangafeed/ui/fragment/SettingsNestedFragment.java

@@ -0,0 +1,36 @@
+package eu.kanade.mangafeed.ui.fragment;
+
+import android.os.Bundle;
+import android.preference.PreferenceFragment;
+
+import eu.kanade.mangafeed.ui.activity.base.BaseActivity;
+
+public class SettingsNestedFragment extends PreferenceFragment {
+
+    private static final String RESOURCE_FILE = "resource_file";
+    private static final String TOOLBAR_TITLE = "toolbar_title";
+
+    public static SettingsNestedFragment newInstance(int resourcePreference, int resourceTitle) {
+        SettingsNestedFragment fragment = new SettingsNestedFragment();
+        Bundle args = new Bundle();
+        args.putInt(RESOURCE_FILE, resourcePreference);
+        args.putInt(TOOLBAR_TITLE, resourceTitle);
+        fragment.setArguments(args);
+        return fragment;
+    }
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        addPreferencesFromResource(getArguments().getInt(RESOURCE_FILE));
+
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        ((BaseActivity)getActivity())
+                .setToolbarTitle(getString(getArguments().getInt(TOOLBAR_TITLE)));
+    }
+
+}

+ 53 - 0
app/src/main/res/layout/pref_account_login.xml

@@ -0,0 +1,53 @@
+<?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="24dp">
+
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/accounts_login_title"
+        android:id="@+id/accounts_login"
+        android:textStyle="bold"
+        android:textSize="16sp"
+        android:layout_gravity="center_horizontal" />
+
+    <View android:id="@+id/titleDivider"
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="@color/line_grey"
+        android:layout_marginTop="6dp"
+        android:layout_marginBottom="24dp"/>
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="@string/username"/>
+
+    <EditText
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:id="@+id/username" />
+
+    <TextView
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="16dp"
+        android:text="@string/password"/>
+
+    <EditText
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:inputType="textPassword"
+        android:ems="10"
+        android:id="@+id/password" />
+
+    <CheckBox
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/show_password"
+        android:id="@+id/show_password"
+        android:layout_marginTop="10dp"/>
+
+</LinearLayout>

+ 7 - 0
app/src/main/res/values/keys.xml

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="pref_category_reader_key">pref_category_reader_key</string>
+    <string name="pref_category_accounts_key">pref_category_accounts_key</string>
+    <string name="pref_hide_status_bar_key">pref_hide_status_bar_key</string>
+    <string name="pref_default_viewer_key">pref_default_viewer_key</string>
+</resources>

+ 12 - 0
app/src/main/res/values/strings.xml

@@ -46,13 +46,25 @@
     <string name="manga_detail_tab">Info</string>
     <string name="manga_chapters_tab">Chapters</string>
     <string name="title_activity_viewer">ViewerActivity</string>
+
+    <!-- Preferences -->
+
     <string name="title_activity_settings">Settings</string>
+    <string name="pref_category_reader">Reader</string>
+    <string name="pref_category_accounts">Accounts</string>
+
     <string name="pref_hide_status_bar">Hide status bar</string>
     <string name="pref_hide_status_bar_summary">This option will hide the status bar while reading</string>
+
     <string name="pref_viewer_type">Default viewer</string>
     <string name="left_to_right_viewer">Left to right</string>
     <string name="right_to_left_viewer">Right to left</string>
     <string name="vertical_viewer">Vertical</string>
     <string name="webtoon_viewer">Webtoon (experimental)</string>
 
+    <string name="accounts_login_title">Login for %1$s</string>
+    <string name="username">Username</string>
+    <string name="password">Password</string>
+    <string name="show_password">Show password</string>
+
 </resources>

+ 5 - 0
app/src/main/res/xml/pref_accounts.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orderingFromXml="true">
+
+</PreferenceScreen>

+ 14 - 0
app/src/main/res/xml/pref_main.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
+
+    <Preference
+        android:key="@string/pref_category_reader_key"
+        android:persistent="false"
+        android:title="@string/pref_category_reader" />
+
+    <Preference
+        android:key="@string/pref_category_accounts_key"
+        android:persistent="false"
+        android:title="@string/pref_category_accounts" />
+
+</PreferenceScreen>

+ 3 - 3
app/src/main/res/xml/preferences.xml → app/src/main/res/xml/pref_reader.xml

@@ -2,12 +2,12 @@
 <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
 
     <CheckBoxPreference android:title="@string/pref_hide_status_bar"
+        android:key="pref_hide_status_bar_key"
         android:defaultValue="false"
-        android:summary="@string/pref_hide_status_bar_summary"
-        android:key="hide_status_bar" />
+        android:summary="@string/pref_hide_status_bar_summary" />
 
     <ListPreference android:title="@string/pref_viewer_type"
-        android:key="default_viewer"
+        android:key="pref_default_viewer_key"
         android:entries="@array/viewers"
         android:entryValues="@array/viewers_values"
         android:defaultValue="1"/>