diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java index d0e7819230..8e1e0d6579 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadManager.java @@ -328,7 +328,6 @@ public class DownloadManager { // Return the page list from the chapter's directory if it exists, null otherwise public List getSavedPageList(Source source, Manga manga, Chapter chapter) { - List pages = null; File chapterDir = getAbsoluteChapterDirectory(source, manga, chapter); File pagesFile = new File(chapterDir, PAGE_LIST_FILE); @@ -337,14 +336,14 @@ public class DownloadManager { if (pagesFile.exists()) { reader = new JsonReader(new FileReader(pagesFile.getAbsolutePath())); Type collectionType = new TypeToken>() {}.getType(); - pages = gson.fromJson(reader, collectionType); + return gson.fromJson(reader, collectionType); } } catch (Exception e) { Timber.e(e.getCause(), e.getMessage()); } finally { if (reader != null) try { reader.close(); } catch (IOException e) { /* Do nothing */ } } - return pages; + return null; } // Shortcut for the method above diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.java b/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.java index 6a332ddcc2..c4c39a2ff0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.java @@ -47,7 +47,7 @@ public class DownloadQueue extends ArrayList { } public Observable getProgressObservable() { - return statusSubject + return statusSubject.onBackpressureBuffer() .startWith(getActiveDownloads()) .flatMap(download -> { if (download.getStatus() == Download.DOWNLOADING) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.java b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.java index af8001c573..ba8668658b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.java +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.java @@ -88,6 +88,10 @@ public class PreferencesHelper { return prefs.getInt(getKey(R.string.pref_default_viewer_key), 1); } + public Preference imageScaleType() { + return rxPrefs.getInteger(getKey(R.string.pref_image_scale_type_key), 1); + } + public Preference portraitColumns() { return rxPrefs.getInteger(getKey(R.string.pref_library_columns_portrait_key), 0); } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderMenu.java b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderMenu.java index 938cc2b9f8..39bb0e3697 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderMenu.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderMenu.java @@ -7,6 +7,7 @@ import android.view.Gravity; import android.view.Menu; import android.view.MenuItem; import android.view.View; +import android.view.ViewGroup; import android.view.WindowManager; import android.view.WindowManager.LayoutParams; import android.view.animation.Animation; @@ -44,7 +45,7 @@ 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; + @Bind(R.id.reader_scale_type_selector) ImageButton scaleTypeSelector; private MenuItem nextChapterBtn; private MenuItem prevChapterBtn; @@ -56,7 +57,6 @@ public class ReaderMenu { @State boolean showing; private PopupWindow settingsPopup; - private PopupWindow brightnessPopup; private boolean inverted; private DecimalFormat decimalFormat; @@ -73,7 +73,7 @@ public class ReaderMenu { decimalFormat = new DecimalFormat("#.###"); inverted = false; - initializeOptions(); + initializeMenu(); } public void add(Subscription subscription) { @@ -110,7 +110,6 @@ public class ReaderMenu { bottomMenu.startAnimation(bottomMenuAnimation); settingsPopup.dismiss(); - brightnessPopup.dismiss(); showing = false; } @@ -175,7 +174,7 @@ public class ReaderMenu { if (nextChapterBtn != null) nextChapterBtn.setVisible(nextChapter != null); } - private void initializeOptions() { + private void initializeMenu() { // Orientation changes add(preferences.lockOrientation().asObservable() .subscribe(locked -> { @@ -190,6 +189,18 @@ public class ReaderMenu { lockOrientation.setOnClickListener(v -> preferences.lockOrientation().set(!preferences.lockOrientation().get())); + // Scale type selector + scaleTypeSelector.setOnClickListener(v -> { + showImmersiveDialog(new MaterialDialog.Builder(activity) + .items(R.array.image_scale_type) + .itemsCallbackSingleChoice(preferences.imageScaleType().get() - 1, + (d, itemView, which, text) -> { + preferences.imageScaleType().set(which + 1); + return true; + }) + .build()); + }); + // Reader selector readerSelector.setOnClickListener(v -> { final Manga manga = activity.getPresenter().getManga(); @@ -215,17 +226,6 @@ public class ReaderMenu { 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(); - }); } private void showImmersiveDialog(Dialog dialog) { @@ -247,8 +247,11 @@ public class ReaderMenu { @Bind(R.id.hide_status_bar) CheckBox hideStatusBar; @Bind(R.id.keep_screen_on) CheckBox keepScreenOn; @Bind(R.id.reader_theme) CheckBox readerTheme; + @Bind(R.id.image_decoder_container) ViewGroup imageDecoderContainer; @Bind(R.id.image_decoder) TextView imageDecoder; @Bind(R.id.image_decoder_initial) TextView imageDecoderInitial; + @Bind(R.id.custom_brightness) CheckBox customBrightness; + @Bind(R.id.brightness_seekbar) SeekBar brightnessSeekbar; public SettingsPopupWindow(View view) { super(view, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); @@ -282,7 +285,7 @@ public class ReaderMenu { readerTheme.setOnCheckedChangeListener((view, isChecked) -> preferences.readerTheme().set(isChecked ? 1 : 0)); - imageDecoder.setOnClickListener(v -> { + imageDecoderContainer.setOnClickListener(v -> { showImmersiveDialog(new MaterialDialog.Builder(activity) .title(R.string.pref_image_decoder) .items(R.array.image_decoders) @@ -294,6 +297,21 @@ public class ReaderMenu { }) .build()); }); + + 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()); } private void setDecoderInitial(int decoder) { @@ -314,37 +332,6 @@ public class ReaderMenu { } - 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() { - 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()); - } - - } - class PageSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener { @Override diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.java b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.java index f3d5a4c266..c11570534e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReader.java @@ -22,6 +22,8 @@ public abstract class PagerReader extends BaseReader { protected boolean transitions; protected CompositeSubscription subscriptions; + protected int scaleType = 1; + protected void initializePager(Pager pager) { this.pager = pager; pager.setLayoutParams(new ViewGroup.LayoutParams(MATCH_PARENT, MATCH_PARENT)); @@ -66,6 +68,13 @@ public abstract class PagerReader extends BaseReader { .distinctUntilChanged() .subscribe(v -> adapter.notifyDataSetChanged())); + subscriptions.add(getReaderActivity().getPreferences().imageScaleType() + .asObservable() + .doOnNext(this::setImageScaleType) + .skip(1) + .distinctUntilChanged() + .subscribe(v -> adapter.notifyDataSetChanged())); + subscriptions.add(getReaderActivity().getPreferences().enableTransitions() .asObservable() .subscribe(value -> transitions = value)); @@ -110,6 +119,10 @@ public abstract class PagerReader extends BaseReader { return pager.onImageTouch(motionEvent); } + private void setImageScaleType(int scaleType) { + this.scaleType = scaleType; + } + public abstract void onFirstPageOut(); public abstract void onLastPageOut(); diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.java b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.java index d92ecd6539..4c3125225b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.java +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.java @@ -25,7 +25,6 @@ import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.data.source.model.Page; import eu.kanade.tachiyomi.ui.base.fragment.BaseFragment; import eu.kanade.tachiyomi.ui.reader.ReaderActivity; -import eu.kanade.tachiyomi.ui.reader.viewer.base.BaseReader; import rx.Observable; import rx.Subscription; import rx.android.schedulers.AndroidSchedulers; @@ -55,7 +54,7 @@ public class PagerReaderFragment extends BaseFragment { View view = inflater.inflate(R.layout.item_pager_reader, container, false); ButterKnife.bind(this, view); ReaderActivity activity = getReaderActivity(); - BaseReader parentFragment = (BaseReader) getParentFragment(); + PagerReader parentFragment = (PagerReader) getParentFragment(); if (activity.getReaderTheme() == ReaderActivity.BLACK_THEME) { progressText.setTextColor(ContextCompat.getColor(getContext(), R.color.light_grey)); @@ -65,7 +64,7 @@ public class PagerReaderFragment extends BaseFragment { imageView.setMaxDimensions(activity.getMaxBitmapSize(), activity.getMaxBitmapSize()); imageView.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED); imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE); - imageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE); + imageView.setMinimumScaleType(parentFragment.scaleType); imageView.setRegionDecoderClass(parentFragment.getRegionDecoderClass()); imageView.setOnTouchListener((v, motionEvent) -> parentFragment.onImageTouch(motionEvent)); imageView.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() { diff --git a/app/src/main/res/drawable-hdpi/ic_zoom_out_map_white_24dp.png b/app/src/main/res/drawable-hdpi/ic_zoom_out_map_white_24dp.png new file mode 100644 index 0000000000..141adc875e Binary files /dev/null and b/app/src/main/res/drawable-hdpi/ic_zoom_out_map_white_24dp.png differ diff --git a/app/src/main/res/drawable-mdpi/ic_zoom_out_map_white_24dp.png b/app/src/main/res/drawable-mdpi/ic_zoom_out_map_white_24dp.png new file mode 100644 index 0000000000..b707939e01 Binary files /dev/null and b/app/src/main/res/drawable-mdpi/ic_zoom_out_map_white_24dp.png differ diff --git a/app/src/main/res/drawable-xhdpi/ic_zoom_out_map_white_24dp.png b/app/src/main/res/drawable-xhdpi/ic_zoom_out_map_white_24dp.png new file mode 100644 index 0000000000..2182249ebc Binary files /dev/null and b/app/src/main/res/drawable-xhdpi/ic_zoom_out_map_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxhdpi/ic_zoom_out_map_white_24dp.png b/app/src/main/res/drawable-xxhdpi/ic_zoom_out_map_white_24dp.png new file mode 100644 index 0000000000..e85a816829 Binary files /dev/null and b/app/src/main/res/drawable-xxhdpi/ic_zoom_out_map_white_24dp.png differ diff --git a/app/src/main/res/drawable-xxxhdpi/ic_zoom_out_map_white_24dp.png b/app/src/main/res/drawable-xxxhdpi/ic_zoom_out_map_white_24dp.png new file mode 100644 index 0000000000..470a6f4897 Binary files /dev/null and b/app/src/main/res/drawable-xxxhdpi/ic_zoom_out_map_white_24dp.png differ diff --git a/app/src/main/res/layout/reader_brightness.xml b/app/src/main/res/layout/reader_brightness.xml deleted file mode 100644 index 7a19d8c3f4..0000000000 --- a/app/src/main/res/layout/reader_brightness.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - \ 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 f353b98684..0017425573 100644 --- a/app/src/main/res/layout/reader_menu.xml +++ b/app/src/main/res/layout/reader_menu.xml @@ -74,18 +74,19 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" - android:id="@+id/reader_brightness" - android:src="@drawable/ic_brightness_high" + android:id="@+id/lock_orientation" + android:src="@drawable/ic_screen_rotation" android:layout_gravity="center_vertical" android:background="?android:selectableItemBackground" /> + + android:layout_height="wrap_content" + android:id="@+id/image_decoder_container"> + + + + \ No newline at end of file diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml index ce29c52763..a2399ed968 100644 --- a/app/src/main/res/values/arrays.xml +++ b/app/src/main/res/values/arrays.xml @@ -48,6 +48,22 @@ 1 + + @string/scale_type_fit_screen + @string/scale_type_stretch + @string/scale_type_fit_width + @string/scale_type_fit_height + @string/scale_type_original_size + + + + 1 + 2 + 3 + 4 + 5 + + @string/update_never @string/update_1hour diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index e1013b9025..4eac520ce5 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -16,6 +16,7 @@ pref_ask_update_manga_sync_key pref_default_viewer_key + pref_image_scale_type_key pref_hide_status_bar_key pref_lock_orientation_key pref_enable_transitions_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index bb72d2f5bc..1a025ddab2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -97,6 +97,12 @@ Image decoder Rapid Skia + Scale type + Fit screen + Stretch + Fit width + Fit height + Original size Downloads directory diff --git a/app/src/main/res/xml/pref_reader.xml b/app/src/main/res/xml/pref_reader.xml index cd5789f77a..3a2f49aef8 100644 --- a/app/src/main/res/xml/pref_reader.xml +++ b/app/src/main/res/xml/pref_reader.xml @@ -25,6 +25,14 @@ android:defaultValue="1" android:summary="%s"/> + + VALID_SCALE_TYPES = Arrays.asList(SCALE_TYPE_CENTER_CROP, SCALE_TYPE_CENTER_INSIDE, SCALE_TYPE_CUSTOM); + + private static final List VALID_SCALE_TYPES = Arrays.asList(SCALE_TYPE_CENTER_CROP, SCALE_TYPE_CENTER_INSIDE, SCALE_TYPE_CUSTOM, SCALE_TYPE_FIT_WIDTH, SCALE_TYPE_FIT_HEIGHT, SCALE_TYPE_ORIGINAL_SIZE); // Bitmap (preview or full image) private Bitmap bitmap; @@ -2003,12 +2007,20 @@ public class SubsamplingScaleImageView extends View { private float minScale() { int vPadding = getPaddingBottom() + getPaddingTop(); int hPadding = getPaddingLeft() + getPaddingRight(); - if (minimumScaleType == SCALE_TYPE_CENTER_CROP) { - return Math.max((getWidth() - hPadding) / (float) sWidth(), (getHeight() - vPadding) / (float) sHeight()); - } else if (minimumScaleType == SCALE_TYPE_CUSTOM && minScale > 0) { - return minScale; - } else { - return Math.min((getWidth() - hPadding) / (float) sWidth(), (getHeight() - vPadding) / (float) sHeight()); + switch (minimumScaleType) { + case SCALE_TYPE_CENTER_INSIDE: + default: + return Math.min((getWidth() - hPadding) / (float) sWidth(), (getHeight() - vPadding) / (float) sHeight()); + case SCALE_TYPE_CENTER_CROP: + return Math.max((getWidth() - hPadding) / (float) sWidth(), (getHeight() - vPadding) / (float) sHeight()); + case SCALE_TYPE_FIT_WIDTH: + return (getWidth() - hPadding) / (float) sWidth(); + case SCALE_TYPE_FIT_HEIGHT: + return (getHeight() - vPadding) / (float) sHeight(); + case SCALE_TYPE_ORIGINAL_SIZE: + return 1; + case SCALE_TYPE_CUSTOM: + return minScale; } }