Rename project

This commit is contained in:
inorichi
2016-01-15 15:18:19 +01:00
parent 1508bf42fb
commit 70f4c7fcc3
167 changed files with 647 additions and 654 deletions

View File

@@ -0,0 +1,68 @@
package eu.kanade.tachiyomi.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
public class AutofitRecyclerView extends RecyclerView {
private GridLayoutManager manager;
private int columnWidth = -1;
private int spanCount = 0;
public AutofitRecyclerView(Context context) {
super(context);
init(context, null);
}
public AutofitRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public AutofitRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
int[] attrsArray = {
android.R.attr.columnWidth
};
TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
columnWidth = array.getDimensionPixelSize(0, -1);
array.recycle();
}
manager = new GridLayoutManager(getContext(), 1);
setLayoutManager(manager);
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
if (spanCount == 0 && columnWidth > 0) {
int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
manager.setSpanCount(spanCount);
}
}
public void setSpanCount(int spanCount) {
this.spanCount = spanCount;
if (spanCount > 0) {
manager.setSpanCount(spanCount);
}
}
public int getSpanCount() {
return manager.getSpanCount();
}
public int getItemWidth() {
return getMeasuredWidth() / getSpanCount();
}
}

View File

@@ -0,0 +1,49 @@
package eu.kanade.tachiyomi.widget;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import rx.functions.Action0;
public class EndlessRecyclerScrollListener extends RecyclerView.OnScrollListener {
private int previousTotal = 0; // The total number of items in the dataset after the last load
private boolean loading = true; // True if we are still waiting for the last set of data to load.
private int visibleThreshold = 5; // The minimum amount of items to have below your current scroll position before loading more.
int firstVisibleItem, visibleItemCount, totalItemCount;
private GridLayoutManager layoutManager;
private Action0 requestNext;
public EndlessRecyclerScrollListener(GridLayoutManager layoutManager, Action0 requestNext) {
this.layoutManager = layoutManager;
this.requestNext = requestNext;
}
public void resetScroll() {
previousTotal = 0;
loading = true;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
visibleItemCount = recyclerView.getChildCount();
totalItemCount = layoutManager.getItemCount();
firstVisibleItem = layoutManager.findFirstVisibleItemPosition();
if (loading && (totalItemCount > previousTotal)) {
loading = false;
previousTotal = totalItemCount;
}
if (!loading && (totalItemCount - visibleItemCount)
<= (firstVisibleItem + visibleThreshold)) {
// End has been reached
requestNext.call();
loading = true;
}
}
}

View File

@@ -0,0 +1,61 @@
package eu.kanade.tachiyomi.widget;
import android.widget.AbsListView;
import rx.functions.Action0;
public class EndlessScrollListener implements AbsListView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
private Action0 requestNext;
public EndlessScrollListener(Action0 requestNext) {
this.requestNext = requestNext;
}
public void resetScroll() {
this.previousTotalItemCount = 0;
this.loading = true;
}
// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
// If the total item count is zero and the previous isn't, assume the
// list is invalidated and should be reset back to initial state
if (totalItemCount < previousTotalItemCount) {
this.previousTotalItemCount = totalItemCount;
if (totalItemCount == 0) { this.loading = true; }
}
// If its still loading, we check to see if the dataset count has
// changed, if so we conclude it has finished loading and update the current page
// number and total item count.
if (loading && (totalItemCount > previousTotalItemCount)) {
loading = false;
previousTotalItemCount = totalItemCount;
}
// If it isnt currently loading, we check to see if we have breached
// the visibleThreshold and need to reload more data.
// If we do need to reload some more data, we execute onLoadMore to fetch the data.
if (!loading && (totalItemCount - visibleItemCount)<=(firstVisibleItem + visibleThreshold)) {
requestNext.call();
loading = true;
}
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
// Don't take any action on changed
}
}

View File

@@ -0,0 +1,36 @@
package eu.kanade.tachiyomi.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.NumberPicker;
import eu.kanade.tachiyomi.R;
public class MinMaxNumberPicker extends NumberPicker{
public MinMaxNumberPicker(Context context) {
super(context);
}
public MinMaxNumberPicker(Context context, AttributeSet attrs) {
super(context, attrs);
processAttributeSet(context, attrs);
}
public MinMaxNumberPicker(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
processAttributeSet(context, attrs);
}
private void processAttributeSet(Context context, AttributeSet attrs) {
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MinMaxNumberPicker, 0, 0);
try {
setMinValue(ta.getInt(R.styleable.MinMaxNumberPicker_min, 0));
setMaxValue(ta.getInt(R.styleable.MinMaxNumberPicker_max, 0));
} finally {
ta.recycle();
}
}
}

View File

@@ -0,0 +1,60 @@
package eu.kanade.tachiyomi.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
import eu.kanade.tachiyomi.R;
public class PTSansTextView extends TextView {
private final static int PTSANS_NARROW = 0;
private final static int PTSANS_NARROW_BOLD = 1;
public PTSansTextView(Context c) {
super(c);
}
public PTSansTextView(Context c, AttributeSet attrs) {
super(c, attrs);
parseAttributes(c, attrs);
}
public PTSansTextView(Context c, AttributeSet attrs, int defStyle) {
super(c, attrs, defStyle);
parseAttributes(c, attrs);
}
private void parseAttributes(Context c, AttributeSet attrs) {
TypedArray values = c.obtainStyledAttributes(attrs, R.styleable.PTSansTextView);
//The value 0 is a default, but shouldn't ever be used since the attr is an enum
int typeface = values.getInt(R.styleable.PTSansTextView_typeface, 0);
switch(typeface) {
case PTSANS_NARROW:
//You can instantiate your typeface anywhere, I would suggest as a
//singleton somewhere to avoid unnecessary copies
setTypeface(Typeface.createFromAsset(c.getAssets(), "fonts/PTSans-Narrow.ttf"));
break;
case PTSANS_NARROW_BOLD:
setTypeface(Typeface.createFromAsset(c.getAssets(), "fonts/PTSans-NarrowBold.ttf"));
break;
default:
throw new IllegalArgumentException("Font not found " + typeface);
}
values.recycle();
}
@Override
public void draw(Canvas canvas) {
// Draw two times for a more visible shadow around the text
super.draw(canvas);
super.draw(canvas);
}
}

View File

@@ -0,0 +1,28 @@
package eu.kanade.tachiyomi.widget;
import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
public class PreCachingLayoutManager extends LinearLayoutManager {
private static final int DEFAULT_EXTRA_LAYOUT_SPACE = 600;
private int extraLayoutSpace = -1;
public PreCachingLayoutManager(Context context) {
super(context);
}
public void setExtraLayoutSpace(int extraLayoutSpace) {
this.extraLayoutSpace = extraLayoutSpace;
}
@Override
protected int getExtraLayoutSpace(RecyclerView.State state) {
if (extraLayoutSpace > 0) {
return extraLayoutSpace;
}
return DEFAULT_EXTRA_LAYOUT_SPACE;
}
}

View File

@@ -0,0 +1,35 @@
package eu.kanade.tachiyomi.widget.preference;
import android.content.Context;
import android.preference.ListPreference;
import android.util.AttributeSet;
public class IntListPreference extends ListPreference
{
public IntListPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public IntListPreference(Context context) {
super(context);
}
@Override
protected boolean persistString(String value) {
if(value == null) {
return false;
} else {
return persistInt(Integer.valueOf(value));
}
}
@Override
protected String getPersistedString(String defaultReturnValue) {
if(getSharedPreferences().contains(getKey())) {
int intValue = getPersistedInt(0);
return String.valueOf(intValue);
} else {
return defaultReturnValue;
}
}
}

View File

@@ -0,0 +1,80 @@
package eu.kanade.tachiyomi.widget.preference;
import android.content.Context;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.NumberPicker;
import butterknife.Bind;
import butterknife.ButterKnife;
import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.preference.PreferencesHelper;
public class LibraryColumnsDialog extends DialogPreference {
private Context context;
private PreferencesHelper preferences;
@Bind(R.id.portrait_columns) NumberPicker portraitColumns;
@Bind(R.id.landscape_columns) NumberPicker landscapeColumns;
public LibraryColumnsDialog(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public LibraryColumnsDialog(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
this.context = context;
setDialogLayoutResource(R.layout.pref_library_columns);
}
@Override
protected void onBindDialogView(View view) {
super.onBindDialogView(view);
ButterKnife.bind(this, view);
portraitColumns.setValue(preferences.portraitColumns().get());
landscapeColumns.setValue(preferences.landscapeColumns().get());
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
preferences.portraitColumns().set(portraitColumns.getValue());
preferences.landscapeColumns().set(landscapeColumns.getValue());
updateSummary();
}
}
private void updateSummary() {
setSummary(getColumnsSummary());
}
private String getColumnsSummary() {
return String.format("%s: %s, %s: %s",
context.getString(R.string.portrait),
getColumnValue(preferences.portraitColumns().get()),
context.getString(R.string.landscape),
getColumnValue(preferences.landscapeColumns().get()));
}
private String getColumnValue(int value) {
return value == 0 ? context.getString(R.string.default_columns) : value + "";
}
public void setPreferencesHelper(PreferencesHelper preferences) {
this.preferences = preferences;
// Set initial summary when the preferences helper is provided
updateSummary();
}
}

View File

@@ -0,0 +1,78 @@
package eu.kanade.tachiyomi.widget.preference;
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.tachiyomi.R;
import eu.kanade.tachiyomi.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();
}

View File

@@ -0,0 +1,74 @@
package eu.kanade.tachiyomi.widget.preference;
import android.content.Context;
import android.content.DialogInterface;
import android.view.View;
import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.mangasync.base.MangaSyncService;
import eu.kanade.tachiyomi.data.preference.PreferencesHelper;
import eu.kanade.tachiyomi.util.ToastUtil;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class MangaSyncLoginDialog extends LoginDialogPreference {
private MangaSyncService sync;
public MangaSyncLoginDialog(Context context, PreferencesHelper preferences, MangaSyncService 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.getMangaSyncUsername(sync));
password.setText(preferences.getMangaSyncPassword(sync));
}
@Override
protected void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
preferences.setMangaSyncCredentials(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.setMangaSyncCredentials(sync, "", "");
loginBtn.setProgress(-1);
}
}, error -> {
loginBtn.setProgress(-1);
loginBtn.setText(R.string.unknown_error);
});
}
}

View File

@@ -0,0 +1,74 @@
package eu.kanade.tachiyomi.widget.preference;
import android.content.Context;
import android.content.DialogInterface;
import android.view.View;
import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.preference.PreferencesHelper;
import eu.kanade.tachiyomi.data.source.base.Source;
import eu.kanade.tachiyomi.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);
});
}
}