From 05c0516a57b5b332df47a25341c8da20c47a0ef7 Mon Sep 17 00:00:00 2001 From: inorichi Date: Mon, 27 Jun 2016 16:46:31 +0200 Subject: [PATCH] New reader menu (#368) --- app/build.gradle | 3 + .../data/preference/PreferenceKeys.kt | 2 +- .../data/preference/PreferencesHelper.kt | 2 +- .../tachiyomi/data/source/model/Page.kt | 6 +- .../tachiyomi/ui/reader/ReaderActivity.kt | 275 ++++++------------ .../tachiyomi/ui/reader/ReaderPopupMenu.kt | 108 ------- .../ui/reader/ReaderSettingsDialog.kt | 129 ++++++++ .../viewer/pager/PagerReaderFragment.kt | 3 +- .../ui/reader/viewer/webtoon/WebtoonHolder.kt | 5 +- .../widget/SimpleItemSelectedListener.kt | 16 + app/src/main/res/drawable/empty_divider.xml | 10 + .../res/drawable/ic_settings_white_24dp.xml | 9 + app/src/main/res/layout/activity_reader.xml | 110 +++++-- .../res/layout/dialog_reader_settings.xml | 197 +++++++++++++ app/src/main/res/layout/reader_menu.xml | 119 -------- app/src/main/res/layout/reader_popup.xml | 85 ------ app/src/main/res/menu/reader.xml | 17 +- app/src/main/res/values-v21/themes.xml | 10 + app/src/main/res/values/keys.xml | 2 +- app/src/main/res/values/strings.xml | 3 +- app/src/main/res/values/themes.xml | 8 +- app/src/main/res/xml/pref_reader.xml | 4 +- 22 files changed, 585 insertions(+), 538 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPopupMenu.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsDialog.kt create mode 100644 app/src/main/java/eu/kanade/tachiyomi/widget/SimpleItemSelectedListener.kt create mode 100644 app/src/main/res/drawable/empty_divider.xml create mode 100644 app/src/main/res/drawable/ic_settings_white_24dp.xml create mode 100644 app/src/main/res/layout/dialog_reader_settings.xml delete mode 100644 app/src/main/res/layout/reader_menu.xml delete mode 100644 app/src/main/res/layout/reader_popup.xml diff --git a/app/build.gradle b/app/build.gradle index 74839ead9..300992383 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -155,12 +155,14 @@ dependencies { compile 'ch.acra:acra:4.8.5' // UI + compile 'com.dmitrymalkovich.android:material-design-dimens:1.2' compile 'com.github.dmytrodanylyk.android-process-button:library:1.0.4' compile 'eu.davidea:flexible-adapter:4.2.0' compile 'com.nononsenseapps:filepicker:2.5.2' compile 'com.github.amulyakhare:TextDrawable:558677e' compile 'com.afollestad.material-dialogs:core:0.8.5.9' compile 'net.xpece.android:support-preference:0.8.1' + compile 'me.zhanghai.android.systemuihelper:library:1.0.0' // Tests testCompile 'junit:junit:4.12' @@ -183,4 +185,5 @@ buildscript { repositories { mavenCentral() + maven { url "https://dl.bintray.com/kotlin/kotlin-eap" } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 45c8e5ddd..b4493e682 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -18,7 +18,7 @@ class PreferenceKeys(context: Context) { val showPageNumber = context.getString(R.string.pref_show_page_number_key) - val hideStatusBar = context.getString(R.string.pref_hide_status_bar_key) + val fullscreen = context.getString(R.string.pref_fullscreen_key) val keepScreenOn = context.getString(R.string.pref_keep_screen_on_key) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 8a159c3a7..e1af01e98 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -42,7 +42,7 @@ class PreferencesHelper(context: Context) { fun showPageNumber() = rxPrefs.getBoolean(keys.showPageNumber, true) - fun hideStatusBar() = rxPrefs.getBoolean(keys.hideStatusBar, true) + fun fullscreen() = rxPrefs.getBoolean(keys.fullscreen, true) fun keepScreenOn() = rxPrefs.getBoolean(keys.keepScreenOn, true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/source/model/Page.kt b/app/src/main/java/eu/kanade/tachiyomi/data/source/model/Page.kt index 89f19566b..bfdf22fd3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/source/model/Page.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/source/model/Page.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.data.source.model import eu.kanade.tachiyomi.data.network.ProgressListener import eu.kanade.tachiyomi.ui.reader.ReaderChapter -import rx.subjects.PublishSubject +import rx.subjects.Subject class Page( val pageNumber: Int, @@ -21,13 +21,13 @@ class Page( @Transient @Volatile var progress: Int = 0 - @Transient private var statusSubject: PublishSubject? = null + @Transient private var statusSubject: Subject? = null override fun update(bytesRead: Long, contentLength: Long, done: Boolean) { progress = (100 * bytesRead / contentLength).toInt() } - fun setStatusSubject(subject: PublishSubject?) { + fun setStatusSubject(subject: Subject?) { this.statusSubject = subject } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index b61202593..f4544e52a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -1,16 +1,16 @@ package eu.kanade.tachiyomi.ui.reader -import android.app.Dialog import android.content.Context import android.content.Intent import android.content.pm.ActivityInfo import android.content.res.Configuration import android.graphics.Color import android.os.Build +import android.os.Build.VERSION_CODES.KITKAT import android.os.Bundle import android.support.v4.content.ContextCompat import android.view.* -import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE +import android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS import android.view.animation.Animation import android.view.animation.AnimationUtils import android.widget.SeekBar @@ -33,11 +33,13 @@ import eu.kanade.tachiyomi.util.toast import eu.kanade.tachiyomi.widget.SimpleAnimationListener import eu.kanade.tachiyomi.widget.SimpleSeekBarListener import kotlinx.android.synthetic.main.activity_reader.* -import kotlinx.android.synthetic.main.reader_menu.* +import me.zhanghai.android.systemuihelper.SystemUiHelper +import me.zhanghai.android.systemuihelper.SystemUiHelper.* import nucleus.factory.RequiresPresenter import rx.Subscription import rx.subscriptions.CompositeSubscription import timber.log.Timber +import uy.kohesive.injekt.injectLazy import java.text.DecimalFormat @RequiresPresenter(ReaderPresenter::class) @@ -62,8 +64,6 @@ class ReaderActivity : BaseRxActivity() { private var viewer: BaseReader? = null - private var uiFlags: Int = 0 - lateinit var subscriptions: CompositeSubscription private set @@ -77,16 +77,13 @@ class ReaderActivity : BaseRxActivity() { private val decimalFormat = DecimalFormat("#.###") - private var popupMenu: ReaderPopupMenu? = null - - private var nextChapterBtn: MenuItem? = null - - private var prevChapterBtn: MenuItem? = null - private val volumeKeysEnabled by lazy { preferences.readWithVolumeKeys().getOrDefault() } - val preferences: PreferencesHelper - get() = presenter.prefs + val preferences by injectLazy() + + private var systemUi: SystemUiHelper? = null + + private var menuVisible = false override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) @@ -100,47 +97,56 @@ class ReaderActivity : BaseRxActivity() { setupToolbar(toolbar) subscriptions = CompositeSubscription() - initializeMenu() initializeSettings() + initializeBottomMenu() if (savedState != null) { - setMenuVisibility(savedState.getBoolean(MENU_VISIBLE), animate = false) + menuVisible = savedState.getBoolean(MENU_VISIBLE) } - maxBitmapSize = GLUtil.getMaxTextureSize() - } + setMenuVisibility(menuVisible) - override fun onResume() { - super.onResume() - setSystemUiVisibility() + maxBitmapSize = GLUtil.getMaxTextureSize() + + left_chapter.setOnClickListener { + if (viewer != null) { + if (viewer is RightToLeftReader) + requestNextChapter() + else + requestPreviousChapter() + } + } + right_chapter.setOnClickListener { + if (viewer != null) { + if (viewer is RightToLeftReader) + requestPreviousChapter() + else + requestNextChapter() + } + } } override fun onDestroy() { subscriptions.unsubscribe() - popupMenu?.dismiss() viewer = null super.onDestroy() } override fun onCreateOptionsMenu(menu: Menu): Boolean { menuInflater.inflate(R.menu.reader, menu) - nextChapterBtn = menu.findItem(R.id.action_next_chapter) - prevChapterBtn = menu.findItem(R.id.action_previous_chapter) - setAdjacentChaptersVisibility() return true } override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { - R.id.action_previous_chapter -> requestPreviousChapter() - R.id.action_next_chapter -> requestNextChapter() + R.id.action_settings -> ReaderSettingsDialog().show(supportFragmentManager, "settings") else -> return super.onOptionsItemSelected(item) } return true } override fun onSaveInstanceState(outState: Bundle) { - outState.putBoolean(MENU_VISIBLE, reader_menu.visibility == View.VISIBLE) + outState.putBoolean(MENU_VISIBLE, menuVisible) super.onSaveInstanceState(outState) } @@ -148,7 +154,7 @@ class ReaderActivity : BaseRxActivity() { val chapterToUpdate = presenter.getMangaSyncChapterToUpdate() if (chapterToUpdate > 0) { - if (presenter.prefs.askUpdateMangaSync()) { + if (preferences.askUpdateMangaSync()) { MaterialDialog.Builder(this) .content(getString(R.string.confirm_update_manga_sync, chapterToUpdate)) .positiveText(android.R.string.yes) @@ -165,13 +171,6 @@ class ReaderActivity : BaseRxActivity() { } } - override fun onWindowFocusChanged(hasFocus: Boolean) { - super.onWindowFocusChanged(hasFocus) - if (hasFocus) { - setSystemUiVisibility() - } - } - override fun dispatchKeyEvent(event: KeyEvent): Boolean { if (!isFinishing) { when (event.keyCode) { @@ -270,16 +269,19 @@ class ReaderActivity : BaseRxActivity() { viewer?.onPageListAppendReady(chapter) } - @Suppress("UNUSED_PARAMETER") fun onAdjacentChapters(previous: Chapter?, next: Chapter?) { - setAdjacentChaptersVisibility() - } + val isInverted = viewer is RightToLeftReader - private fun setAdjacentChaptersVisibility() { - prevChapterBtn?.isVisible = presenter.hasPreviousChapter() - nextChapterBtn?.isVisible = presenter.hasNextChapter() - } + // Chapters are inverted for the right to left reader + val hasRightChapter = (if (isInverted) previous else next) != null + val hasLeftChapter = (if (isInverted) next else previous) != null + right_chapter.isEnabled = hasRightChapter + right_chapter.alpha = if (hasRightChapter) 1f else 0.4f + + left_chapter.isEnabled = hasLeftChapter + left_chapter.alpha = if (hasLeftChapter) 1f else 0.4f + } private fun getOrCreateViewer(manga: Manga): BaseReader { val mangaViewer = if (manga.viewer == 0) preferences.defaultViewer() else manga.viewer @@ -323,7 +325,7 @@ class ReaderActivity : BaseRxActivity() { } fun toggleMenu() { - setMenuVisibility(reader_menu.visibility == View.GONE) + setMenuVisibility(!menuVisible) } fun requestNextChapter() { @@ -338,34 +340,7 @@ class ReaderActivity : BaseRxActivity() { } } - private fun setMenuVisibility(visible: Boolean, animate: Boolean = true) { - if (visible) { - reader_menu.visibility = View.VISIBLE - - if (animate) { - val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top) - toolbar.startAnimation(toolbarAnimation) - - val bottomMenuAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_bottom) - reader_menu_bottom.startAnimation(bottomMenuAnimation) - } - } else { - val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_top) - toolbarAnimation.setAnimationListener(object : SimpleAnimationListener() { - override fun onAnimationEnd(animation: Animation) { - reader_menu.visibility = View.GONE - } - }) - toolbar.startAnimation(toolbarAnimation) - - val bottomMenuAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_bottom) - reader_menu_bottom.startAnimation(bottomMenuAnimation) - - popupMenu?.dismiss() - } - } - - private fun initializeMenu() { + private fun initializeBottomMenu() { // Intercept all events in this layout reader_menu_bottom.setOnTouchListener { v, event -> true } @@ -376,94 +351,17 @@ class ReaderActivity : BaseRxActivity() { } } }) - - lock_orientation.setOnClickListener { v -> - showImmersiveDialog(MaterialDialog.Builder(this) - .title(R.string.pref_rotation_type) - .items(R.array.rotation_type) - .itemsCallbackSingleChoice(preferences.rotation().getOrDefault() - 1, - { d, itemView, which, text -> - preferences.rotation().set(which + 1) - true - }) - .build()) - } - - reader_zoom_selector.setOnClickListener { v -> - showImmersiveDialog(MaterialDialog.Builder(this) - .title(R.string.pref_zoom_start) - .items(R.array.zoom_start) - .itemsCallbackSingleChoice(preferences.zoomStart().getOrDefault() - 1, - { d, itemView, which, text -> - preferences.zoomStart().set(which + 1) - true - }) - .build()) - } - - reader_scale_type_selector.setOnClickListener { v -> - showImmersiveDialog(MaterialDialog.Builder(this) - .title(R.string.pref_image_scale_type) - .items(R.array.image_scale_type) - .itemsCallbackSingleChoice(preferences.imageScaleType().getOrDefault() - 1, - { d, itemView, which, text -> - preferences.imageScaleType().set(which + 1) - true - }) - .build()) - } - - reader_selector.setOnClickListener { v -> - showImmersiveDialog(MaterialDialog.Builder(this) - .title(R.string.pref_viewer_type) - .items(R.array.viewers_selector) - .itemsCallbackSingleChoice(presenter.manga.viewer, - { d, itemView, which, text -> - presenter.updateMangaViewer(which) - recreate() - true - }) - .build()) - } - - val popupView = layoutInflater.inflate(R.layout.reader_popup, null) - popupMenu = ReaderPopupMenu(this, popupView) - - reader_extra_settings.setOnClickListener { - popupMenu?.let { - if (!it.isShowing) - it.showAtLocation(reader_extra_settings, - Gravity.BOTTOM or Gravity.RIGHT, 0, reader_menu_bottom.height) - else - it.dismiss() - } - - } - } private fun initializeSettings() { + subscriptions += preferences.rotation().asObservable() + .subscribe { setRotation(it) } + subscriptions += preferences.showPageNumber().asObservable() .subscribe { setPageNumberVisibility(it) } - subscriptions += preferences.rotation().asObservable() - .subscribe { - setRotation(it) - - val isPortrait = resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT - - val resourceId = if (it == 1) - R.drawable.ic_screen_rotation_white_24dp - else if (isPortrait) - R.drawable.ic_screen_lock_portrait_white_24dp - else - R.drawable.ic_screen_lock_landscape_white_24dp - - lock_orientation.setImageResource(resourceId) - } - - subscriptions += preferences.hideStatusBar().asObservable() - .subscribe { setStatusBarVisibility(it) } + subscriptions += preferences.fullscreen().asObservable() + .subscribe { setFullscreen(it) } subscriptions += preferences.keepScreenOn().asObservable() .subscribe { setKeepScreenOn(it) } @@ -496,6 +394,16 @@ class ReaderActivity : BaseRxActivity() { page_number.visibility = if (visible) View.VISIBLE else View.INVISIBLE } + private fun setFullscreen(enabled: Boolean) { + systemUi = if (enabled) { + val level = if (Build.VERSION.SDK_INT >= KITKAT) LEVEL_IMMERSIVE else LEVEL_HIDE_STATUS_BAR + val flags = FLAG_IMMERSIVE_STICKY or FLAG_LAYOUT_IN_SCREEN_OLDER_DEVICES + SystemUiHelper(this, level, flags) + } else { + null + } + } + private fun setKeepScreenOn(enabled: Boolean) { if (enabled) { window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) @@ -523,29 +431,6 @@ class ReaderActivity : BaseRxActivity() { window.attributes = window.attributes.apply { screenBrightness = value } } - private fun setStatusBarVisibility(hidden: Boolean) { - createUiHideFlags(hidden) - setSystemUiVisibility() - } - - private fun createUiHideFlags(statusBarHidden: Boolean) { - uiFlags = 0 - uiFlags = uiFlags or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION - if (statusBarHidden) { - uiFlags = uiFlags or View.SYSTEM_UI_FLAG_LAYOUT_STABLE or - View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or - View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or - View.SYSTEM_UI_FLAG_FULLSCREEN - } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - uiFlags = uiFlags or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY - } - } - - fun setSystemUiVisibility() { - window.decorView.systemUiVisibility = uiFlags - } - private fun applyTheme(theme: Int) { readerTheme = theme val rootView = window.decorView.rootView @@ -560,12 +445,38 @@ class ReaderActivity : BaseRxActivity() { } } - private fun showImmersiveDialog(dialog: Dialog) { - // Hack to not leave immersive mode - dialog.window.setFlags(FLAG_NOT_FOCUSABLE, FLAG_NOT_FOCUSABLE) - dialog.show() - dialog.window.decorView.systemUiVisibility = window.decorView.systemUiVisibility - dialog.window.clearFlags(FLAG_NOT_FOCUSABLE) + private fun setMenuVisibility(visible: Boolean) { + menuVisible = visible + if (visible) { + systemUi?.show() + reader_menu.visibility = View.VISIBLE + + val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top) + toolbarAnimation.setAnimationListener(object : SimpleAnimationListener() { + override fun onAnimationStart(animation: Animation) { + // Fix status bar being translucent the first time it's opened. + if (Build.VERSION.SDK_INT >= 21) { + window.addFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + } + } + }) + toolbar.startAnimation(toolbarAnimation) + + val bottomMenuAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_bottom) + reader_menu_bottom.startAnimation(bottomMenuAnimation) + } else { + systemUi?.hide() + val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_top) + toolbarAnimation.setAnimationListener(object : SimpleAnimationListener() { + override fun onAnimationEnd(animation: Animation) { + reader_menu.visibility = View.GONE + } + }) + toolbar.startAnimation(toolbarAnimation) + + val bottomMenuAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_bottom) + reader_menu_bottom.startAnimation(bottomMenuAnimation) + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPopupMenu.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPopupMenu.kt deleted file mode 100644 index 2829f29d4..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPopupMenu.kt +++ /dev/null @@ -1,108 +0,0 @@ -package eu.kanade.tachiyomi.ui.reader - -import android.app.Dialog -import android.view.View -import android.view.ViewGroup.LayoutParams.WRAP_CONTENT -import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE -import android.widget.PopupWindow -import android.widget.SeekBar -import com.afollestad.materialdialogs.MaterialDialog -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.widget.SimpleSeekBarListener -import kotlinx.android.synthetic.main.reader_popup.view.* -import java.lang.ref.WeakReference - -class ReaderPopupMenu(activity: ReaderActivity, val view: View) : PopupWindow(view, WRAP_CONTENT, WRAP_CONTENT) { - - val activity = WeakReference(activity) - - init { - animationStyle = R.style.reader_settings_popup_animation - setValues(activity.preferences) - } - - private fun setValues(preferences: PreferencesHelper) = with(view) { - enable_transitions.isChecked = preferences.enableTransitions().getOrDefault() - show_page_number.isChecked = preferences.showPageNumber().getOrDefault() - hide_status_bar.isChecked = preferences.hideStatusBar().getOrDefault() - keep_screen_on.isChecked = preferences.keepScreenOn().getOrDefault() - reader_theme.isChecked = preferences.readerTheme().getOrDefault() == 1 - - setDecoderInitial(preferences.imageDecoder().getOrDefault()) - - // Add a listener to change the corresponding setting - enable_transitions.setOnCheckedChangeListener { v, isChecked -> - preferences.enableTransitions().set(isChecked) - } - - show_page_number.setOnCheckedChangeListener { v, isChecked -> - preferences.showPageNumber().set(isChecked) - } - - hide_status_bar.setOnCheckedChangeListener { v, isChecked -> - preferences.hideStatusBar().set(isChecked) - } - - keep_screen_on.setOnCheckedChangeListener { v, isChecked -> - preferences.keepScreenOn().set(isChecked) - } - - reader_theme.setOnCheckedChangeListener { v, isChecked -> - preferences.readerTheme().set(if (isChecked) 1 else 0) - } - - image_decoder_container.setOnClickListener { v -> - showImmersiveDialog(MaterialDialog.Builder(view.context) - .title(R.string.pref_image_decoder) - .items(R.array.image_decoders) - .itemsCallbackSingleChoice(preferences.imageDecoder().getOrDefault(), { dialog, itemView, which, text -> - preferences.imageDecoder().set(which) - setDecoderInitial(which) - true - }) - .build()) - } - - activity.get().subscriptions.add(preferences.customBrightness().asObservable() - .subscribe { isEnabled -> - custom_brightness.isChecked = isEnabled - brightness_seekbar.isEnabled = isEnabled - }) - - custom_brightness.setOnCheckedChangeListener { v, isChecked -> - preferences.customBrightness().set(isChecked) - } - - brightness_seekbar.max = 100 - brightness_seekbar.progress = Math.round( - preferences.customBrightnessValue().getOrDefault() * brightness_seekbar.max) - brightness_seekbar.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { - override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { - if (fromUser) { - preferences.customBrightnessValue().set(progress.toFloat() / seekBar.max) - } - } - }) - } - - private fun setDecoderInitial(decoder: Int) { - val initial: String - when (decoder) { - 0 -> initial = "R" - 1 -> initial = "S" - else -> initial = "" - } - view.image_decoder_initial.text = initial - } - - private fun showImmersiveDialog(dialog: Dialog) { - // Hack to not leave immersive mode - dialog.window.setFlags(FLAG_NOT_FOCUSABLE, FLAG_NOT_FOCUSABLE) - dialog.show() - dialog.window.decorView.systemUiVisibility = activity.get().window.decorView.systemUiVisibility - dialog.window.clearFlags(FLAG_NOT_FOCUSABLE) - } - -} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsDialog.kt new file mode 100644 index 000000000..ec668ac82 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderSettingsDialog.kt @@ -0,0 +1,129 @@ +package eu.kanade.tachiyomi.ui.reader + +import android.app.Dialog +import android.os.Bundle +import android.support.v4.app.DialogFragment +import android.view.View +import android.widget.SeekBar +import com.afollestad.materialdialogs.MaterialDialog +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.data.preference.getOrDefault +import eu.kanade.tachiyomi.util.plusAssign +import eu.kanade.tachiyomi.widget.SimpleItemSelectedListener +import eu.kanade.tachiyomi.widget.SimpleSeekBarListener +import kotlinx.android.synthetic.main.dialog_reader_settings.view.* +import rx.Observable +import rx.android.schedulers.AndroidSchedulers +import rx.subscriptions.CompositeSubscription +import uy.kohesive.injekt.injectLazy +import java.util.concurrent.TimeUnit.MILLISECONDS + +class ReaderSettingsDialog : DialogFragment() { + + private val preferences by injectLazy() + + private lateinit var subscriptions: CompositeSubscription + + override fun onCreateDialog(savedState: Bundle?): Dialog { + val dialog = MaterialDialog.Builder(activity) + .title(R.string.label_settings) + .customView(R.layout.dialog_reader_settings, true) + .positiveText(android.R.string.ok) + .build() + + subscriptions = CompositeSubscription() + onViewCreated(dialog.view, savedState) + + return dialog + } + + override fun onViewCreated(view: View, savedState: Bundle?) = with(view) { + viewer.setSelection((activity as ReaderActivity).presenter.manga.viewer, false) + viewer.onItemSelectedListener = SimpleItemSelectedListener { position -> + subscriptions += Observable.timer(250, MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + (activity as ReaderActivity).presenter.updateMangaViewer(position) + activity.recreate() + } + } + + rotation_mode.setSelection(preferences.rotation().getOrDefault() - 1, false) + rotation_mode.onItemSelectedListener = SimpleItemSelectedListener { position -> + subscriptions += Observable.timer(250, MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe { + preferences.rotation().set(position + 1) + } + } + + scale_type.setSelection(preferences.imageScaleType().getOrDefault() - 1, false) + scale_type.onItemSelectedListener = SimpleItemSelectedListener { position -> + preferences.imageScaleType().set(position + 1) + } + + zoom_start.setSelection(preferences.zoomStart().getOrDefault() - 1, false) + zoom_start.onItemSelectedListener = SimpleItemSelectedListener { position -> + preferences.zoomStart().set(position + 1) + } + + image_decoder.setSelection(preferences.imageDecoder().getOrDefault(), false) + image_decoder.onItemSelectedListener = SimpleItemSelectedListener { position -> + preferences.imageDecoder().set(position) + } + + background_color.setSelection(preferences.readerTheme().getOrDefault(), false) + background_color.onItemSelectedListener = SimpleItemSelectedListener { position -> + preferences.readerTheme().set(position) + } + + enable_transitions.isChecked = preferences.enableTransitions().getOrDefault() + enable_transitions.setOnCheckedChangeListener { v, isChecked -> + preferences.enableTransitions().set(isChecked) + } + + show_page_number.isChecked = preferences.showPageNumber().getOrDefault() + show_page_number.setOnCheckedChangeListener { v, isChecked -> + preferences.showPageNumber().set(isChecked) + } + + fullscreen.isChecked = preferences.fullscreen().getOrDefault() + fullscreen.setOnCheckedChangeListener { v, isChecked -> + preferences.fullscreen().set(isChecked) + } + + keep_screen_on.isChecked = preferences.keepScreenOn().getOrDefault() + keep_screen_on.setOnCheckedChangeListener { v, isChecked -> + preferences.keepScreenOn().set(isChecked) + } + + subscriptions += preferences.customBrightness().asObservable() + .subscribe { isEnabled -> + custom_brightness.isChecked = isEnabled + brightness_seekbar.isEnabled = isEnabled + } + + custom_brightness.setOnCheckedChangeListener { v, isChecked -> + preferences.customBrightness().set(isChecked) + } + + brightness_seekbar.max = 100 + brightness_seekbar.progress = Math.round( + preferences.customBrightnessValue().getOrDefault() * brightness_seekbar.max) + brightness_seekbar.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { + override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { + if (fromUser) { + preferences.customBrightnessValue().set(progress.toFloat() / seekBar.max) + } + } + }) + + } + + override fun onDestroyView() { + subscriptions.unsubscribe() + super.onDestroyView() + } + +} \ No newline at end of file diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.kt index aea00b28c..b6c04c67e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerReaderFragment.kt @@ -23,6 +23,7 @@ import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers import rx.subjects.PublishSubject +import rx.subjects.SerializedSubject import java.io.File import java.util.concurrent.TimeUnit import java.util.concurrent.atomic.AtomicInteger @@ -150,7 +151,7 @@ class PagerReaderFragment : BaseFragment() { */ private fun observeStatus() { page?.let { page -> - val statusSubject = PublishSubject.create() + val statusSubject = SerializedSubject(PublishSubject.create()) page.setStatusSubject(statusSubject) statusSubscription?.unsubscribe() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonHolder.kt index 3df86f398..ff077882e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonHolder.kt @@ -14,6 +14,7 @@ import kotlinx.android.synthetic.main.item_webtoon_reader.view.* import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.subjects.PublishSubject +import rx.subjects.SerializedSubject import java.io.File /** @@ -56,7 +57,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter) setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() { override fun onImageLoaded() { // When the image is loaded, reset the minimum height to avoid gaps - view.frame_container.minimumHeight = 0 + view.frame_container.minimumHeight = 30 } override fun onImageLoadError(e: Exception) { @@ -106,7 +107,7 @@ class WebtoonHolder(private val view: View, private val adapter: WebtoonAdapter) */ private fun observeStatus() { page?.let { page -> - val statusSubject = PublishSubject.create() + val statusSubject = SerializedSubject(PublishSubject.create()) page.setStatusSubject(statusSubject) statusSubscription?.unsubscribe() diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/SimpleItemSelectedListener.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/SimpleItemSelectedListener.kt new file mode 100644 index 000000000..00a18c92b --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/SimpleItemSelectedListener.kt @@ -0,0 +1,16 @@ +package eu.kanade.tachiyomi.widget + +import android.view.View +import android.widget.AdapterView +import android.widget.AdapterView.OnItemSelectedListener + +class SimpleItemSelectedListener(private val callback: (Int) -> Unit): OnItemSelectedListener { + + override fun onNothingSelected(parent: AdapterView<*>?) { + + } + + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + callback(position) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/empty_divider.xml b/app/src/main/res/drawable/empty_divider.xml new file mode 100644 index 000000000..2d9192e3c --- /dev/null +++ b/app/src/main/res/drawable/empty_divider.xml @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_settings_white_24dp.xml b/app/src/main/res/drawable/ic_settings_white_24dp.xml new file mode 100644 index 000000000..ce997a727 --- /dev/null +++ b/app/src/main/res/drawable/ic_settings_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/activity_reader.xml b/app/src/main/res/layout/activity_reader.xml index e71d6f5ae..54db3108f 100644 --- a/app/src/main/res/layout/activity_reader.xml +++ b/app/src/main/res/layout/activity_reader.xml @@ -1,30 +1,102 @@ + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:gravity="center"> + + + + + + + + - + - + - + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_reader_settings.xml b/app/src/main/res/layout/dialog_reader_settings.xml new file mode 100644 index 000000000..10c6e8cdd --- /dev/null +++ b/app/src/main/res/layout/dialog_reader_settings.xml @@ -0,0 +1,197 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 deleted file mode 100644 index e5c11ebc3..000000000 --- a/app/src/main/res/layout/reader_menu.xml +++ /dev/null @@ -1,119 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/reader_popup.xml b/app/src/main/res/layout/reader_popup.xml deleted file mode 100644 index aab501eb6..000000000 --- a/app/src/main/res/layout/reader_popup.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/reader.xml b/app/src/main/res/menu/reader.xml index 4dbb59813..72121c053 100644 --- a/app/src/main/res/menu/reader.xml +++ b/app/src/main/res/menu/reader.xml @@ -3,17 +3,10 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> - - + android:id="@+id/action_settings" + android:title="@string/label_settings" + android:icon="@drawable/ic_settings_white_24dp" + app:showAsAction="always" + /> \ No newline at end of file diff --git a/app/src/main/res/values-v21/themes.xml b/app/src/main/res/values-v21/themes.xml index 61f0c68af..dc0ae7073 100644 --- a/app/src/main/res/values-v21/themes.xml +++ b/app/src/main/res/values-v21/themes.xml @@ -19,4 +19,14 @@ @android:color/transparent @color/colorPrimaryDark + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/keys.xml b/app/src/main/res/values/keys.xml index 3543a757e..4565d56a0 100644 --- a/app/src/main/res/values/keys.xml +++ b/app/src/main/res/values/keys.xml @@ -21,7 +21,7 @@ pref_default_viewer_key pref_image_scale_type_key pref_zoom_start_key - pref_hide_status_bar_key + fullscreen pref_rotation_type_key pref_enable_transitions_key pref_show_page_number_key diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 83aa3376b..019e9684e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -96,7 +96,7 @@ Dark theme - Hide status bar + Fullscreen Lock orientation Enable transitions Show page number @@ -264,6 +264,7 @@ Previous chapter not found Image could not be loaded.\nTry changing the image decoder or with one of the options below Update last chapter read in enabled services to %1$d? + Viewer for this series Backup diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 5e40a8c03..a38ec375f 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -83,10 +83,16 @@ - + + + diff --git a/app/src/main/res/xml/pref_reader.xml b/app/src/main/res/xml/pref_reader.xml index 8f27859e6..995688876 100644 --- a/app/src/main/res/xml/pref_reader.xml +++ b/app/src/main/res/xml/pref_reader.xml @@ -55,8 +55,8 @@ android:summary="%s" />