diff --git a/app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java b/app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java index 3b4d4328e..8197163f4 100644 --- a/app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java +++ b/app/src/main/java/eu/kanade/mangafeed/data/preference/PreferencesHelper.java @@ -57,6 +57,14 @@ public class PreferencesHelper { return rxPrefs.getBoolean(getKey(R.string.pref_keep_screen_on_key), true); } + public Preference customBrightness() { + return rxPrefs.getBoolean(getKey(R.string.pref_custom_brightness_key), false); + } + + public Preference customBrightnessValue() { + return rxPrefs.getFloat(getKey(R.string.pref_custom_brightness_value_key), 0F); + } + public int getDefaultViewer() { return Integer.parseInt(prefs.getString(getKey(R.string.pref_default_viewer_key), "1")); } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderActivity.java b/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderActivity.java index a54154c76..acfa8f21e 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderActivity.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderActivity.java @@ -36,6 +36,7 @@ import eu.kanade.mangafeed.ui.reader.viewer.webtoon.WebtoonReader; import eu.kanade.mangafeed.util.ToastUtil; import icepick.Icepick; import nucleus.factory.RequiresPresenter; +import rx.Subscription; import rx.subscriptions.CompositeSubscription; @RequiresPresenter(ReaderPresenter.class) @@ -52,6 +53,7 @@ public class ReaderActivity extends BaseRxActivity { private int uiFlags; private CompositeSubscription subscriptions; + private Subscription customBrightnessSubscription; private static final int LEFT_TO_RIGHT = 1; private static final int RIGHT_TO_LEFT = 2; @@ -166,6 +168,10 @@ public class ReaderActivity extends BaseRxActivity { subscriptions.add(preferences.keepScreenOn() .asObservable() .subscribe(this::setKeepScreenOn)); + + subscriptions.add(preferences.customBrightness() + .asObservable() + .subscribe(this::setCustomBrightness)); } private void setOrientation(boolean locked) { @@ -205,6 +211,24 @@ public class ReaderActivity extends BaseRxActivity { } } + private void setCustomBrightness(boolean enabled) { + if (enabled) { + subscriptions.add(customBrightnessSubscription = preferences.customBrightnessValue() + .asObservable() + .subscribe(this::setCustomBrightnessValue)); + } else { + if (customBrightnessSubscription != null) + subscriptions.remove(customBrightnessSubscription); + setCustomBrightnessValue(-1); + } + } + + private void setCustomBrightnessValue(float value) { + WindowManager.LayoutParams layout = getWindow().getAttributes(); + layout.screenBrightness = value; + getWindow().setAttributes(layout); + } + private void setStatusBarVisibility(boolean hidden) { createUiHideFlags(hidden); setSystemUiVisibility(); diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderMenu.java b/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderMenu.java index 32f7f8851..fdf217454 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderMenu.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/reader/ReaderMenu.java @@ -40,12 +40,14 @@ public class ReaderMenu { @Bind(R.id.lock_orientation) ImageButton lockOrientation; @Bind(R.id.reader_selector) ImageButton readerSelector; @Bind(R.id.reader_extra_settings) ImageButton extraSettings; + @Bind(R.id.reader_brightness) ImageButton brightnessSettings; private ReaderActivity activity; private PreferencesHelper preferences; @State boolean showing; - private PopupWindow popupWindow; + private PopupWindow settingsPopup; + private PopupWindow brightnessPopup; private DecimalFormat decimalFormat; @@ -99,7 +101,8 @@ public class ReaderMenu { Animation bottomMenuAnimation = AnimationUtils.loadAnimation(activity, R.anim.exit_to_bottom); bottomMenu.startAnimation(bottomMenuAnimation); - popupWindow.dismiss(); + settingsPopup.dismiss(); + brightnessPopup.dismiss(); showing = false; } @@ -152,14 +155,26 @@ public class ReaderMenu { // Extra settings menu final View popupView = activity.getLayoutInflater().inflate(R.layout.reader_popup, null); - popupWindow = new SettingsPopupWindow(popupView); + settingsPopup = new SettingsPopupWindow(popupView); extraSettings.setOnClickListener(v -> { - if (!popupWindow.isShowing()) - popupWindow.showAtLocation(extraSettings, + if (!settingsPopup.isShowing()) + settingsPopup.showAtLocation(extraSettings, Gravity.BOTTOM | Gravity.RIGHT, 0, bottomMenu.getHeight()); else - popupWindow.dismiss(); + settingsPopup.dismiss(); + }); + + // Brightness popup + final View brightnessView = activity.getLayoutInflater().inflate(R.layout.reader_brightness, null); + brightnessPopup = new BrightnessPopupWindow(brightnessView); + + brightnessSettings.setOnClickListener(v -> { + if (!brightnessPopup.isShowing()) + brightnessPopup.showAtLocation(brightnessSettings, + Gravity.BOTTOM | Gravity.LEFT, 0, bottomMenu.getHeight()); + else + brightnessPopup.dismiss(); }); } @@ -208,7 +223,37 @@ public class ReaderMenu { keepScreenOn.setOnCheckedChangeListener((view, isChecked) -> preferences.keepScreenOn().set(isChecked)); + } + } + + class BrightnessPopupWindow extends PopupWindow { + + @Bind(R.id.custom_brightness) CheckBox customBrightness; + @Bind(R.id.brightness_seekbar) SeekBar brightnessSeekbar; + + public BrightnessPopupWindow(View view) { + super(view, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + setAnimationStyle(R.style.reader_brightness_popup_animation); + ButterKnife.bind(this, view); + initializePopupMenu(); + } + + private void initializePopupMenu() { + subscriptions.add(preferences.customBrightness() + .asObservable() + .subscribe(isEnabled -> { + customBrightness.setChecked(isEnabled); + brightnessSeekbar.setEnabled(isEnabled); + })); + + customBrightness.setOnCheckedChangeListener((view, isChecked) -> + preferences.customBrightness().set(isChecked)); + + brightnessSeekbar.setMax(100); + brightnessSeekbar.setProgress(Math.round( + preferences.customBrightnessValue().get() * brightnessSeekbar.getMax())); + brightnessSeekbar.setOnSeekBarChangeListener(new BrightnessSeekBarChangeListener()); } } @@ -229,6 +274,26 @@ public class ReaderMenu { public void onStopTrackingTouch(SeekBar seekBar) {} } + class BrightnessSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener { + + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (fromUser) { + preferences.customBrightnessValue().set((float) progress / seekBar.getMax()); + } + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + + } + } + class HideMenuAnimationListener implements Animation.AnimationListener { @Override diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/reader/viewer/vertical/VerticalReader.java b/app/src/main/java/eu/kanade/mangafeed/ui/reader/viewer/vertical/VerticalReader.java index 29ec85876..680195bc7 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/reader/viewer/vertical/VerticalReader.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/reader/viewer/vertical/VerticalReader.java @@ -12,6 +12,7 @@ import eu.kanade.mangafeed.data.source.model.Page; import eu.kanade.mangafeed.ui.reader.ReaderActivity; import eu.kanade.mangafeed.ui.reader.viewer.base.BaseReader; import eu.kanade.mangafeed.ui.reader.viewer.common.ViewPagerReaderAdapter; +import rx.Subscription; public class VerticalReader extends BaseReader { @@ -19,11 +20,17 @@ public class VerticalReader extends BaseReader { private ViewPagerReaderAdapter adapter; + private boolean transitions; + private Subscription transitionsSubscription; + public VerticalReader(ReaderActivity activity) { super(activity); activity.getLayoutInflater().inflate(R.layout.reader_vertical, container); ButterKnife.bind(this, container); + transitionsSubscription = activity.getPreferences().enableTransitions().asObservable() + .subscribe(value -> transitions = value); + viewPager.setOffscreenPageLimit(3); viewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override @@ -32,6 +39,33 @@ public class VerticalReader extends BaseReader { updatePageNumber(); } }); + viewPager.setOnChapterBoundariesOutListener(new VerticalViewPager.OnChapterBoundariesOutListener() { + @Override + public void onFirstPageOutEvent() { + requestPreviousChapter(); + } + + @Override + public void onLastPageOutEvent() { + requestNextChapter(); + } + }); + viewPager.setOnChapterSingleTapListener(new VerticalViewPager.OnChapterSingleTapListener() { + @Override + public void onCenterTap() { + activity.onCenterSingleTap(); + } + + @Override + public void onLeftSideTap() { + viewPager.setCurrentItem(viewPager.getCurrentItem() - 1, transitions); + } + + @Override + public void onRightSideTap() { + viewPager.setCurrentItem(viewPager.getCurrentItem() + 1, transitions); + } + }); } @Override @@ -41,7 +75,7 @@ public class VerticalReader extends BaseReader { @Override public void setSelectedPage(int pageNumber) { - viewPager.setCurrentItem(getCurrentPageIndex(pageNumber)); + viewPager.setCurrentItem(getCurrentPageIndex(pageNumber), false); } @Override @@ -53,6 +87,11 @@ public class VerticalReader extends BaseReader { @Override public boolean onImageTouch(MotionEvent motionEvent) { - return true; + return viewPager.onImageTouch(motionEvent); + } + + @Override + public void destroy() { + transitionsSubscription.unsubscribe(); } } diff --git a/app/src/main/java/eu/kanade/mangafeed/ui/reader/viewer/vertical/VerticalViewPager.java b/app/src/main/java/eu/kanade/mangafeed/ui/reader/viewer/vertical/VerticalViewPager.java index a263a867e..3d5a7afab 100644 --- a/app/src/main/java/eu/kanade/mangafeed/ui/reader/viewer/vertical/VerticalViewPager.java +++ b/app/src/main/java/eu/kanade/mangafeed/ui/reader/viewer/vertical/VerticalViewPager.java @@ -3,17 +3,140 @@ package eu.kanade.mangafeed.ui.reader.viewer.vertical; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; +import android.view.MotionEvent; public class VerticalViewPager extends fr.castorflex.android.verticalviewpager.VerticalViewPager { private GestureDetector gestureDetector; + private OnChapterBoundariesOutListener mOnChapterBoundariesOutListener; + private OnChapterSingleTapListener mOnChapterSingleTapListener; + + private static final float LEFT_REGION = 0.33f; + private static final float RIGHT_REGION = 0.66f; + private static final float SWIPE_TOLERANCE = 0.25f; + private float startDragY; + public VerticalViewPager(Context context, AttributeSet attrs) { super(context, attrs); gestureDetector = new GestureDetector(getContext(), new ReaderViewGestureListener()); } + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + try { + gestureDetector.onTouchEvent(ev); + + if ((ev.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN) { + if (this.getCurrentItem() == 0 || this.getCurrentItem() == this.getAdapter().getCount() - 1) { + startDragY = ev.getY(); + } + } + + return super.onInterceptTouchEvent(ev); + } catch (IllegalArgumentException e) { + // Do Nothing. + } + + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent ev) { + try { + if (mOnChapterBoundariesOutListener != null) { + if (this.getCurrentItem() == 0) { + if ((ev.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) { + float displacement = ev.getY() - startDragY; + + if (ev.getY() > startDragY && displacement > getHeight() * SWIPE_TOLERANCE) { + mOnChapterBoundariesOutListener.onFirstPageOutEvent(); + return true; + } + + startDragY = 0; + } + } else if (this.getCurrentItem() == this.getAdapter().getCount() - 1) { + if ((ev.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP) { + float displacement = startDragY - ev.getY(); + + if (ev.getY() < startDragY && displacement > getHeight() * SWIPE_TOLERANCE) { + mOnChapterBoundariesOutListener.onLastPageOutEvent(); + return true; + } + + startDragY = 0; + } + } + } + + return super.onTouchEvent(ev); + } catch (IllegalArgumentException e) { + // Do Nothing. + } + + return false; + } + + public boolean onImageTouch(MotionEvent event) { + return gestureDetector.onTouchEvent(event); + } + + public interface OnChapterBoundariesOutListener { + void onFirstPageOutEvent(); + + void onLastPageOutEvent(); + } + + public interface OnChapterSingleTapListener { + void onCenterTap(); + void onLeftSideTap(); + void onRightSideTap(); + } + + public void setOnChapterBoundariesOutListener(OnChapterBoundariesOutListener onChapterBoundariesOutListener) { + mOnChapterBoundariesOutListener = onChapterBoundariesOutListener; + } + + public void setOnChapterSingleTapListener(OnChapterSingleTapListener onChapterSingleTapListener) { + mOnChapterSingleTapListener = onChapterSingleTapListener; + } + private class ReaderViewGestureListener extends GestureDetector.SimpleOnGestureListener { - // TODO + + @Override + public boolean onSingleTapConfirmed(MotionEvent e) { + final int position = getCurrentItem(); + final float positionX = e.getX(); + + if (positionX < getWidth() * LEFT_REGION) { + if (position != 0) { + if (mOnChapterSingleTapListener != null) { + mOnChapterSingleTapListener.onLeftSideTap(); + } + } else { + if (mOnChapterBoundariesOutListener != null) { + mOnChapterBoundariesOutListener.onFirstPageOutEvent(); + } + } + } else if (positionX > getWidth() * RIGHT_REGION) { + if (position != getAdapter().getCount() - 1) { + if (mOnChapterSingleTapListener != null) { + mOnChapterSingleTapListener.onRightSideTap(); + } + } else { + if (mOnChapterBoundariesOutListener != null) { + mOnChapterBoundariesOutListener.onLastPageOutEvent(); + } + } + } else { + if (mOnChapterSingleTapListener != null) { + mOnChapterSingleTapListener.onCenterTap(); + } + } + + return true; + } + } } diff --git a/app/src/main/res/drawable-hdpi/ic_brightness_high.png b/app/src/main/res/drawable-hdpi/ic_brightness_high.png new file mode 100644 index 000000000..d9276d779 Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_brightness_high.png differ diff --git a/app/src/main/res/drawable-ldpi/ic_brightness_high.png b/app/src/main/res/drawable-ldpi/ic_brightness_high.png new file mode 100644 index 000000000..c2e127e65 Binary files /dev/null and b/app/src/main/res/drawable-ldpi/ic_brightness_high.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_brightness_high.png b/app/src/main/res/drawable-mdpi/ic_brightness_high.png new file mode 100644 index 000000000..ad2327817 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_brightness_high.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_brightness_high.png b/app/src/main/res/drawable-xhdpi/ic_brightness_high.png new file mode 100644 index 000000000..77ca8377a Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_brightness_high.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_brightness_high.png b/app/src/main/res/drawable-xxhdpi/ic_brightness_high.png new file mode 100644 index 000000000..4da536ced Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_brightness_high.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_brightness_high.png b/app/src/main/res/drawable-xxxhdpi/ic_brightness_high.png new file mode 100644 index 000000000..6c893afc1 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_brightness_high.png differ diff --git a/app/src/main/res/layout/reader_brightness.xml b/app/src/main/res/layout/reader_brightness.xml new file mode 100644 index 000000000..b25426223 --- /dev/null +++ b/app/src/main/res/layout/reader_brightness.xml @@ -0,0 +1,23 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/reader_menu.xml b/app/src/main/res/layout/reader_menu.xml index e4c1351c3..25c311af8 100644 --- a/app/src/main/res/layout/reader_menu.xml +++ b/app/src/main/res/layout/reader_menu.xml @@ -72,14 +72,16 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" - android:id="@+id/lock_orientation" - android:src="@drawable/ic_screen_rotation" + android:id="@+id/reader_brightness" + android:src="@drawable/ic_brightness_high" android:layout_gravity="center_vertical" android:background="?android:selectableItemBackground" /> pref_enable_transitions_key pref_show_page_number_key pref_keep_screen_on_key + pref_custom_brightness_key + pref_custom_brightness_value_key pref_download_directory_key pref_download_threads_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 9d1c93f78..79b60a25c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -28,15 +28,16 @@ Hide status bar + Lock orientation + Enable transitions + Show page number + Use custom brightness Default viewer Default Left to right Right to left Vertical Webtoon (experimental) - Lock orientation - Enable transitions - Show page number Downloads directory diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 6297d281d..146bcf89e 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -103,6 +103,10 @@ @anim/enter_from_right @anim/exit_to_right + diff --git a/app/src/main/res/xml/pref_reader.xml b/app/src/main/res/xml/pref_reader.xml index aa0da21f5..60a8e07c4 100644 --- a/app/src/main/res/xml/pref_reader.xml +++ b/app/src/main/res/xml/pref_reader.xml @@ -17,6 +17,10 @@ android:key="@string/pref_show_page_number_key" android:defaultValue="true" /> + +