From 09412719b7725387491be1cbe0143cbf77171d54 Mon Sep 17 00:00:00 2001 From: ztimms73 Date: Thu, 17 Jun 2021 00:46:27 +0300 Subject: [PATCH] Redesign (#24) --- .../koitharu/kotatsu/base/ui/BaseActivity.kt | 8 +- .../ui/list/decor/SectionItemDecoration.kt | 2 +- .../kotatsu/base/ui/widgets/ChipsView.kt | 13 +- .../ui/widgets/search/MaterialSearchView.kt | 231 ++++++ .../ui/widgets/search/SearchArrowDrawable.kt | 62 ++ .../base/ui/widgets/search/SearchBehavior.kt | 54 ++ .../widgets/search/internal/SearchEditText.kt | 40 + .../widgets/search/internal/SearchLayout.kt | 725 ++++++++++++++++++ .../search/internal/SearchViewSavedState.kt | 21 + .../ui/widgets/search/util/SearchUtils.kt | 37 + .../kotatsu/details/ui/DetailsFragment.kt | 61 +- .../kotatsu/list/ui/MangaListFragment.kt | 17 +- .../list/ui/model/ListModelConversionExt.kt | 3 +- .../koitharu/kotatsu/main/ui/MainActivity.kt | 23 +- .../kotatsu/reader/ui/ReaderActivity.kt | 2 +- .../ListPaginationListener.kt | 2 +- .../{wetoon => webtoon}/WebtoonAdapter.kt | 2 +- .../{wetoon => webtoon}/WebtoonFrameLayout.kt | 2 +- .../{wetoon => webtoon}/WebtoonHolder.kt | 2 +- .../{wetoon => webtoon}/WebtoonImageView.kt | 2 +- .../WebtoonReaderFragment.kt | 2 +- .../WebtoonRecyclerView.kt | 2 +- .../kotatsu/tracker/ui/FeedFragment.kt | 5 +- .../kotatsu/tracker/ui/adapter/FeedItemAD.kt | 2 +- .../ui/model/ListModelConversionExt.kt | 14 +- .../org/koitharu/kotatsu/utils/ext/CoilExt.kt | 1 + .../org/koitharu/kotatsu/utils/ext/UiExt.kt | 21 + app/src/main/res/color/divider.xml | 4 + .../color/navigation_item_background_tint.xml | 5 + app/src/main/res/color/selector_overlay.xml | 4 + app/src/main/res/drawable-hdpi/totoro.webp | Bin 0 -> 1654 bytes app/src/main/res/drawable-mdpi/totoro.webp | Bin 0 -> 1250 bytes .../res/drawable-w600dp/tab_indicator.xml | 11 + app/src/main/res/drawable-xhdpi/totoro.webp | Bin 0 -> 2524 bytes app/src/main/res/drawable-xxhdpi/totoro.webp | Bin 0 -> 3120 bytes app/src/main/res/drawable-xxxhdpi/totoro.webp | Bin 0 -> 5222 bytes app/src/main/res/drawable/badge.xml | 6 + app/src/main/res/drawable/divider.xml | 5 + app/src/main/res/drawable/gradient.xml | 10 + app/src/main/res/drawable/ic_arrow_back.xml | 11 + app/src/main/res/drawable/ic_book_page.xml | 21 +- app/src/main/res/drawable/ic_clear.xml | 10 + app/src/main/res/drawable/ic_eye.xml | 22 +- app/src/main/res/drawable/ic_eye_off.xml | 23 +- app/src/main/res/drawable/ic_lock.xml | 2 +- app/src/main/res/drawable/ic_menu.xml | 10 + app/src/main/res/drawable/ic_mic_none.xml | 10 + app/src/main/res/drawable/ic_person.xml | 10 + app/src/main/res/drawable/ic_settings.xml | 19 +- app/src/main/res/drawable/ic_share.xml | 14 +- app/src/main/res/drawable/ic_star.xml | 10 + .../main/res/drawable/ic_star_manga_info.xml | 11 + app/src/main/res/drawable/ic_web.xml | 10 + app/src/main/res/drawable/list_selector.xml | 42 + .../drawable/navigation_item_background.xml | 19 + app/src/main/res/drawable/tab_indicator.xml | 2 +- app/src/main/res/drawable/tabs_background.xml | 2 +- app/src/main/res/drawable/thumb.xml | 2 +- .../layout-w600dp-land/fragment_details.xml | 295 +++++++ .../layout-w600dp-port/fragment_details.xml | 303 ++++++++ .../res/layout-w600dp/activity_details.xml | 16 +- .../res/layout-w600dp/activity_settings.xml | 6 +- .../res/layout-w600dp/fragment_details.xml | 145 ---- app/src/main/res/layout/activity_browser.xml | 8 +- .../main/res/layout/activity_categories.xml | 22 +- app/src/main/res/layout/activity_details.xml | 17 +- app/src/main/res/layout/activity_main.xml | 10 +- app/src/main/res/layout/activity_reader.xml | 10 +- app/src/main/res/layout/activity_search.xml | 8 +- .../res/layout/activity_search_global.xml | 8 +- app/src/main/res/layout/activity_settings.xml | 10 +- .../res/layout/activity_settings_simple.xml | 8 +- app/src/main/res/layout/dialog_input.xml | 9 +- app/src/main/res/layout/dialog_list_mode.xml | 6 +- .../main/res/layout/dialog_reader_config.xml | 6 +- app/src/main/res/layout/fragment_chapters.xml | 6 +- app/src/main/res/layout/fragment_details.xml | 367 ++++++--- .../res/layout/fragment_reader_webtoon.xml | 2 +- .../main/res/layout/item_filter_header.xml | 16 + app/src/main/res/layout/item_header.xml | 6 +- app/src/main/res/layout/item_manga_grid.xml | 54 +- app/src/main/res/layout/item_manga_list.xml | 37 +- .../res/layout/item_manga_list_details.xml | 89 +-- app/src/main/res/layout/item_page_webtoon.xml | 14 +- .../main/res/layout/item_search_complete.xml | 6 +- app/src/main/res/layout/item_tracklog.xml | 118 +-- .../main/res/layout/layout_search_view.xml | 113 +++ app/src/main/res/layout/navigation_header.xml | 25 + app/src/main/res/values-be/strings.xml | 5 +- app/src/main/res/values-es/strings.xml | 2 +- app/src/main/res/values-night/colors.xml | 27 +- app/src/main/res/values-night/styles.xml | 8 - app/src/main/res/values-night/themes.xml | 11 +- .../main/res/values-notnight-v23/bools.xml | 4 + .../main/res/values-notnight-v23/colors.xml | 5 + .../main/res/values-notnight-v27/bools.xml | 4 + .../main/res/values-notnight-v27/colors.xml | 5 + app/src/main/res/values-ru/strings.xml | 6 +- app/src/main/res/values-v23/themes.xml | 8 + app/src/main/res/values-v29/themes.xml | 13 +- app/src/main/res/values-w600dp/dimens.xml | 2 +- app/src/main/res/values/attrs.xml | 53 ++ app/src/main/res/values/bools.xml | 2 + app/src/main/res/values/colors.xml | 37 + app/src/main/res/values/dimens.xml | 51 +- app/src/main/res/values/integers.xml | 6 + app/src/main/res/values/strings.xml | 3 +- app/src/main/res/values/styles.xml | 91 ++- app/src/main/res/values/themes.xml | 65 +- 109 files changed, 3114 insertions(+), 685 deletions(-) create mode 100644 app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/MaterialSearchView.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/SearchArrowDrawable.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/SearchBehavior.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchEditText.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchLayout.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchViewSavedState.kt create mode 100644 app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/util/SearchUtils.kt rename app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/{wetoon => webtoon}/ListPaginationListener.kt (95%) rename app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/{wetoon => webtoon}/WebtoonAdapter.kt (94%) rename app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/{wetoon => webtoon}/WebtoonFrameLayout.kt (91%) rename app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/{wetoon => webtoon}/WebtoonHolder.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/{wetoon => webtoon}/WebtoonImageView.kt (97%) rename app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/{wetoon => webtoon}/WebtoonReaderFragment.kt (98%) rename app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/{wetoon => webtoon}/WebtoonRecyclerView.kt (97%) create mode 100644 app/src/main/java/org/koitharu/kotatsu/utils/ext/UiExt.kt create mode 100644 app/src/main/res/color/divider.xml create mode 100644 app/src/main/res/color/navigation_item_background_tint.xml create mode 100644 app/src/main/res/color/selector_overlay.xml create mode 100644 app/src/main/res/drawable-hdpi/totoro.webp create mode 100644 app/src/main/res/drawable-mdpi/totoro.webp create mode 100644 app/src/main/res/drawable-w600dp/tab_indicator.xml create mode 100644 app/src/main/res/drawable-xhdpi/totoro.webp create mode 100644 app/src/main/res/drawable-xxhdpi/totoro.webp create mode 100644 app/src/main/res/drawable-xxxhdpi/totoro.webp create mode 100644 app/src/main/res/drawable/badge.xml create mode 100644 app/src/main/res/drawable/divider.xml create mode 100644 app/src/main/res/drawable/gradient.xml create mode 100644 app/src/main/res/drawable/ic_arrow_back.xml create mode 100644 app/src/main/res/drawable/ic_clear.xml create mode 100644 app/src/main/res/drawable/ic_menu.xml create mode 100644 app/src/main/res/drawable/ic_mic_none.xml create mode 100644 app/src/main/res/drawable/ic_person.xml create mode 100644 app/src/main/res/drawable/ic_star.xml create mode 100644 app/src/main/res/drawable/ic_star_manga_info.xml create mode 100644 app/src/main/res/drawable/ic_web.xml create mode 100644 app/src/main/res/drawable/list_selector.xml create mode 100644 app/src/main/res/drawable/navigation_item_background.xml create mode 100644 app/src/main/res/layout-w600dp-land/fragment_details.xml create mode 100644 app/src/main/res/layout-w600dp-port/fragment_details.xml delete mode 100644 app/src/main/res/layout-w600dp/fragment_details.xml create mode 100644 app/src/main/res/layout/item_filter_header.xml create mode 100644 app/src/main/res/layout/layout_search_view.xml create mode 100644 app/src/main/res/layout/navigation_header.xml delete mode 100644 app/src/main/res/values-night/styles.xml create mode 100644 app/src/main/res/values-notnight-v23/bools.xml create mode 100644 app/src/main/res/values-notnight-v23/colors.xml create mode 100644 app/src/main/res/values-notnight-v27/bools.xml create mode 100644 app/src/main/res/values-notnight-v27/colors.xml create mode 100644 app/src/main/res/values-v23/themes.xml create mode 100644 app/src/main/res/values/integers.xml diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt index d032ec3e9..e0b2cdef8 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/BaseActivity.kt @@ -37,7 +37,7 @@ abstract class BaseActivity : AppCompatActivity(), OnApplyWindo override fun onCreate(savedInstanceState: Bundle?) { if (get().isAmoledTheme) { - setTheme(R.style.AppTheme_Amoled) + setTheme(R.style.AppTheme_AMOLED) } super.onCreate(savedInstanceState) WindowCompat.setDecorFitsSystemWindows(window, false) @@ -59,12 +59,12 @@ abstract class BaseActivity : AppCompatActivity(), OnApplyWindo this.binding = binding super.setContentView(binding.root) (binding.root.findViewById(R.id.toolbar) as? Toolbar)?.let(this::setSupportActionBar) - val params = (binding.root.findViewById(R.id.toolbar) as? Toolbar)?.layoutParams as AppBarLayout.LayoutParams + val params = (binding.root.findViewById(R.id.toolbar) as? Toolbar)?.layoutParams as? AppBarLayout.LayoutParams ViewCompat.setOnApplyWindowInsetsListener(binding.root, this) if (get().isToolbarHideWhenScrolling) { - params.scrollFlags = SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS + params?.scrollFlags = SCROLL_FLAG_SCROLL or SCROLL_FLAG_ENTER_ALWAYS } else { - params.scrollFlags = SCROLL_FLAG_NO_SCROLL + params?.scrollFlags = SCROLL_FLAG_NO_SCROLL } } diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/SectionItemDecoration.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/SectionItemDecoration.kt index b5ecb78a2..d8181e5c7 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/SectionItemDecoration.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/list/decor/SectionItemDecoration.kt @@ -37,7 +37,7 @@ class SectionItemDecoration( override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) { super.onDrawOver(c, parent, state) - val textView = headerView ?: parent.inflate(R.layout.item_header).also { + val textView = headerView ?: parent.inflate(R.layout.item_filter_header).also { headerView = it } fixLayoutSize(textView, parent) diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ChipsView.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ChipsView.kt index 52ca53616..b11f96c9e 100644 --- a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ChipsView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/ChipsView.kt @@ -4,17 +4,18 @@ import android.content.Context import android.util.AttributeSet import android.view.View.OnClickListener import androidx.annotation.DrawableRes +import androidx.core.content.ContextCompat import androidx.core.view.children -import com.google.android.material.R import com.google.android.material.chip.Chip +import com.google.android.material.chip.ChipDrawable import com.google.android.material.chip.ChipGroup +import org.koitharu.kotatsu.R import org.koitharu.kotatsu.utils.ext.getThemeColor class ChipsView @JvmOverloads constructor( context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = R.attr.chipGroupStyle -) : ChipGroup(context, attrs, defStyleAttr) { + attrs: AttributeSet? = null +) : ChipGroup(context, attrs) { private var isLayoutSuppressedCompat = false private var isLayoutCalledOnSuppressed = false @@ -64,7 +65,9 @@ class ChipsView @JvmOverloads constructor( private fun addChip(): Chip { val chip = Chip(context) - chip.setTextColor(context.getThemeColor(android.R.attr.textColorPrimary)) + val drawable = ChipDrawable.createFromAttributes(context, null, 0, R.style.Widget_Kotatsu_Chip) + chip.setChipDrawable(drawable) + chip.setTextColor(ContextCompat.getColor(context, R.color.blue_primary)) chip.isCloseIconVisible = false chip.setEnsureMinTouchTargetSize(false) chip.setOnClickListener(chipOnClickListener) diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/MaterialSearchView.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/MaterialSearchView.kt new file mode 100644 index 000000000..fcb18c4de --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/MaterialSearchView.kt @@ -0,0 +1,231 @@ +/*https://github.com/lapism/search*/ + +package org.koitharu.kotatsu.base.ui.widgets.search + +import android.animation.LayoutTransition +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup +import android.widget.LinearLayout +import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.content.ContextCompat +import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.widgets.search.internal.SearchLayout + +class MaterialSearchView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + defStyleRes: Int = 0 +) : SearchLayout(context, attrs, defStyleAttr, defStyleRes), CoordinatorLayout.AttachedBehavior { + + // ********************************************************************************************* + private var mBehavior: CoordinatorLayout.Behavior<*> = SearchBehavior() + private var mTransition: LayoutTransition? = null + private var mStrokeWidth: Int = 0 + private var mRadius: Float = 0f + private var mElevation: Float = 0f + + // ********************************************************************************************* + init { + inflate(context, R.layout.layout_search_view, this) + init() + setTransition() + + val a = context.obtainStyledAttributes( + attrs, R.styleable.MaterialSearchView, defStyleAttr, defStyleRes + ) + + if (a.hasValue(R.styleable.MaterialSearchView_search_navigationIconSupport)) { + navigationIconSupport = a.getInt( + R.styleable.MaterialSearchView_search_navigationIconSupport, + NavigationIconSupport.NONE + ) + } + + if (a.hasValue(R.styleable.MaterialSearchView_search_navigationIcon)) { + setNavigationIconImageDrawable(a.getDrawable(R.styleable.MaterialSearchView_search_navigationIcon)) + } + + if (a.hasValue(R.styleable.MaterialSearchView_search_clearIcon)) { + setClearIconImageDrawable(a.getDrawable(R.styleable.MaterialSearchView_search_clearIcon)) + } else { + setClearIconImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.ic_clear + ) + ) + } + + if (a.hasValue(R.styleable.MaterialSearchView_search_micIcon)) { + setMicIconImageDrawable(a.getDrawable(R.styleable.MaterialSearchView_search_micIcon)) + } else { + setMicIconImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.ic_mic_none + ) + ) + } + + if (a.hasValue(R.styleable.MaterialSearchView_search_menuIcon)) { + setMicIconImageDrawable(a.getDrawable(R.styleable.MaterialSearchView_search_menuIcon)) + } else { + setMicIconImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.ic_more + ) + ) + } + + if (a.hasValue(R.styleable.MaterialSearchView_search_dividerColor)) { + setDividerColor(a.getInt(R.styleable.MaterialSearchView_search_dividerColor, 0)) + } + + val defaultShadowColor = ContextCompat.getColor(context, R.color.shadow) + setShadowColor( + a.getInt( + R.styleable.MaterialSearchView_search_shadowColor, + defaultShadowColor + ) + ) + + if (a.hasValue(R.styleable.MaterialSearchView_search_textHint)) { + setTextHint(a.getText(R.styleable.MaterialSearchView_search_textHint)) + } + + if (a.hasValue(R.styleable.MaterialSearchView_search_strokeColor)) { + setBackgroundStrokeColor(a.getInt(R.styleable.MaterialSearchView_search_strokeColor, 0)) + } + + if (a.hasValue(R.styleable.MaterialSearchView_search_strokeWidth)) { + setBackgroundStrokeWidth(a.getInt(R.styleable.MaterialSearchView_search_strokeWidth, 0)) + } + + val defaultTransitionDuration = + context.resources.getInteger(R.integer.search_animation_duration) + setTransitionDuration( + a.getInt( + R.styleable.MaterialSearchView_search_transitionDuration, + defaultTransitionDuration + ).toLong() + ) + + val defaultRadius = context.resources.getDimensionPixelSize(R.dimen.search_radius) + setBackgroundRadius( + a.getInt(R.styleable.MaterialSearchView_search_radius, defaultRadius).toFloat() + ) + + val defaultElevation = context.resources.getDimensionPixelSize(R.dimen.search_elevation) + elevation = + a.getInt(R.styleable.MaterialSearchView_android_elevation, defaultElevation).toFloat() + + val imeOptions = a.getInt(R.styleable.MaterialSearchView_android_imeOptions, -1) + if (imeOptions != -1) { + setTextImeOptions(imeOptions) + } + + val inputType = a.getInt(R.styleable.MaterialSearchView_android_inputType, -1) + if (inputType != -1) { + setTextInputType(inputType) + } + + a.recycle() + } + + // ********************************************************************************************* + override fun addFocus() { + mOnFocusChangeListener?.onFocusChange(true) + showKeyboard() + + mStrokeWidth = getBackgroundStrokeWidth() + mRadius = getBackgroundRadius() + mElevation = elevation + + setBackgroundStrokeWidth(context.resources.getDimensionPixelSize(R.dimen.search_stroke_width_focus)) + setBackgroundRadius(resources.getDimensionPixelSize(R.dimen.search_radius_focus).toFloat()) + elevation = + context.resources.getDimensionPixelSize(R.dimen.search_elevation_focus).toFloat() + + val left = context.resources.getDimensionPixelSize(R.dimen.search_dp_16) + val params = mSearchEditText?.layoutParams as LinearLayout.LayoutParams + params.setMargins(left, 0, 0, 0) + mSearchEditText?.layoutParams = params + + margins = Margins.FOCUS + setLayoutHeight(context.resources.getDimensionPixelSize(R.dimen.search_layout_height_focus)) + + mViewShadow?.visibility = View.VISIBLE + + mViewDivider?.visibility = View.VISIBLE + mViewAnim?.visibility = View.VISIBLE + mRecyclerView?.visibility = View.VISIBLE + + // layoutTransition = null + } + + override fun removeFocus() { + // layoutTransition = mTransition + + mOnFocusChangeListener?.onFocusChange(false) + hideKeyboard() + + val params = mSearchEditText?.layoutParams as LinearLayout.LayoutParams + params.setMargins(0, 0, 0, 0) + mSearchEditText?.layoutParams = params + + setBackgroundStrokeWidth(mStrokeWidth) + setBackgroundRadius(mRadius) + elevation = mElevation + + setLayoutHeight(context.resources.getDimensionPixelSize(R.dimen.search_layout_height)) + margins = Margins.NO_FOCUS + + mViewShadow?.visibility = View.GONE + + mRecyclerView?.visibility = View.GONE + mViewAnim?.visibility = View.GONE + mViewDivider?.visibility = View.GONE + } + + override fun getBehavior(): CoordinatorLayout.Behavior<*> { + return mBehavior + } + + fun setBehavior(behavior: CoordinatorLayout.Behavior<*>) { + mBehavior = behavior + } + + fun setTransitionDuration(duration: Long) { + mTransition?.setDuration(duration) + layoutTransition = mTransition + } + + private fun setTransition() { + mTransition = LayoutTransition() + mTransition?.enableTransitionType(LayoutTransition.CHANGING) + mTransition?.addTransitionListener(object : LayoutTransition.TransitionListener { + override fun startTransition( + transition: LayoutTransition?, + container: ViewGroup?, + view: View?, + transitionType: Int + ) { + + } + + override fun endTransition( + transition: LayoutTransition?, + container: ViewGroup?, + view: View?, + transitionType: Int + ) { + + } + }) + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/SearchArrowDrawable.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/SearchArrowDrawable.kt new file mode 100644 index 000000000..752c0071d --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/SearchArrowDrawable.kt @@ -0,0 +1,62 @@ +/*https://github.com/lapism/search*/ + +package org.koitharu.kotatsu.base.ui.widgets.search + +import android.animation.ObjectAnimator +import android.content.Context +import android.util.Property +import android.view.animation.AccelerateDecelerateInterpolator +import androidx.appcompat.graphics.drawable.DrawerArrowDrawable +import androidx.core.content.ContextCompat + +class SearchArrowDrawable constructor(context: Context) : DrawerArrowDrawable(context) { + + var position: Float + get() = progress + set(position) { + progress = position + } + + init { + color = ContextCompat.getColor(context, android.R.color.white) + } + + fun animate(state: Float, duration: Long) { + val anim: ObjectAnimator = if (state == ARROW) { + ObjectAnimator.ofFloat( + this, + PROGRESS, + MENU, + state + ) + } else { + ObjectAnimator.ofFloat( + this, + PROGRESS, + ARROW, + state + ) + } + anim.interpolator = AccelerateDecelerateInterpolator() + anim.duration = duration + anim.start() + } + + companion object { + + const val MENU = 0.0f + const val ARROW = 1.0f + + private val PROGRESS = + object : Property(Float::class.java, "progress") { + override fun set(obj: SearchArrowDrawable, value: Float?) { + obj.progress = value!! + } + + override fun get(obj: SearchArrowDrawable): Float { + return obj.progress + } + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/SearchBehavior.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/SearchBehavior.kt new file mode 100644 index 000000000..04e897837 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/SearchBehavior.kt @@ -0,0 +1,54 @@ +/*https://github.com/lapism/search*/ + +package org.koitharu.kotatsu.base.ui.widgets.search + +import android.view.View +import android.widget.LinearLayout +import androidx.coordinatorlayout.widget.CoordinatorLayout +import androidx.core.view.ViewCompat +import com.google.android.material.appbar.AppBarLayout +import com.google.android.material.bottomnavigation.BottomNavigationView +import org.koitharu.kotatsu.base.ui.widgets.search.internal.SearchLayout + +class SearchBehavior : CoordinatorLayout.Behavior() { + + override fun layoutDependsOn( + parent: CoordinatorLayout, + child: S, + dependency: View + ): Boolean { + return if (dependency is AppBarLayout) { + true + } else + if (dependency is LinearLayout || dependency is BottomNavigationView) { + dependency.z = child.z + 1 + true + } else { + super.layoutDependsOn(parent, child, dependency) + } + } + + override fun onDependentViewChanged( + parent: CoordinatorLayout, + child: S, + dependency: View + ): Boolean { + if (dependency is AppBarLayout) { + child.translationY = dependency.getY() + return true + } + return super.onDependentViewChanged(parent, child, dependency) + } + + override fun onStartNestedScroll( + coordinatorLayout: CoordinatorLayout, + child: S, + directTargetChild: View, + target: View, + axes: Int, + type: Int + ): Boolean { + return axes == ViewCompat.SCROLL_AXIS_VERTICAL + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchEditText.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchEditText.kt new file mode 100644 index 000000000..312e59e9f --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchEditText.kt @@ -0,0 +1,40 @@ +/*https://github.com/lapism/search*/ + +package org.koitharu.kotatsu.base.ui.widgets.search.internal + +import android.content.Context +import android.util.AttributeSet +import android.view.KeyEvent +import androidx.annotation.AttrRes +import androidx.appcompat.widget.AppCompatEditText + +class SearchEditText : AppCompatEditText { + + var clearFocusOnBackPressed: Boolean = false + + constructor(context: Context) : super(context) + + constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) + + constructor(context: Context, attrs: AttributeSet?, @AttrRes defStyleAttr: Int) : super( + context, + attrs, + defStyleAttr + ) + + override fun onKeyPreIme(keyCode: Int, event: KeyEvent): Boolean { + if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP && clearFocusOnBackPressed) { + if (hasFocus()) { + clearFocus() + return true + } + } + return super.onKeyPreIme(keyCode, event) + } + + override fun clearFocus() { + super.clearFocus() + text?.clear() + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchLayout.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchLayout.kt new file mode 100644 index 000000000..0c00f32de --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchLayout.kt @@ -0,0 +1,725 @@ +/*https://github.com/lapism/search*/ + +package org.koitharu.kotatsu.base.ui.widgets.search.internal + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.ColorFilter +import android.graphics.PorterDuff +import android.graphics.Rect +import android.graphics.Typeface +import android.graphics.drawable.Drawable +import android.os.Parcelable +import android.text.Editable +import android.text.TextUtils +import android.text.TextWatcher +import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup +import android.view.inputmethod.InputMethodManager +import android.widget.FrameLayout +import android.widget.ImageButton +import android.widget.LinearLayout +import androidx.annotation.* +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.DefaultItemAnimator +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.google.android.material.card.MaterialCardView +import org.koitharu.kotatsu.R + +abstract class SearchLayout @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + defStyleRes: Int = 0 +) : FrameLayout(context, attrs, defStyleAttr, defStyleRes), View.OnClickListener { + + // ********************************************************************************************* + // Better way than enum class :-) + @IntDef( + NavigationIconSupport.NONE, + NavigationIconSupport.MENU, + NavigationIconSupport.ARROW, + NavigationIconSupport.SEARCH + ) + @Retention(AnnotationRetention.SOURCE) + annotation class NavigationIconSupport { + companion object { + const val NONE = 0 + const val MENU = 1 + const val ARROW = 2 + const val SEARCH = 3 + } + } + + @IntDef( + Margins.NO_FOCUS, + Margins.FOCUS + ) + @Retention(AnnotationRetention.SOURCE) + internal annotation class Margins { + companion object { + const val NO_FOCUS = 4 + const val FOCUS = 5 + } + } + + // ********************************************************************************************* + private var mImageViewMic: ImageButton? = null + private var mImageViewMenu: ImageButton? = null + protected var mRecyclerView: RecyclerView? = null + private var mMaterialCardView: MaterialCardView? = null + var mSearchEditText: SearchEditText? = null + protected var mViewShadow: View? = null + protected var mViewDivider: View? = null + protected var mViewAnim: View? = null + protected var mOnFocusChangeListener: OnFocusChangeListener? = null + + private var mLinearLayout: LinearLayout? = null + private var mImageViewNavigation: ImageButton? = null + private var mImageViewClear: ImageButton? = null + private var mOnQueryTextListener: OnQueryTextListener? = null + private var mOnNavigationClickListener: OnNavigationClickListener? = null + private var mOnMicClickListener: OnMicClickListener? = null + private var mOnMenuClickListener: OnMenuClickListener? = null + private var mOnClearClickListener: OnClearClickListener? = null + + // ********************************************************************************************* + @NavigationIconSupport + @get:NavigationIconSupport + var navigationIconSupport: Int = 0 + set(@NavigationIconSupport navigationIconSupport) { + field = navigationIconSupport + + when (navigationIconSupport) { + NavigationIconSupport.NONE + -> { + setNavigationIconImageDrawable(null) + } + NavigationIconSupport.MENU -> { + setNavigationIconImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.ic_menu + ) + ) + } + NavigationIconSupport.ARROW -> { + setNavigationIconImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.ic_arrow_back + ) + ) + } + NavigationIconSupport.SEARCH -> { + setNavigationIconImageDrawable( + ContextCompat.getDrawable( + context, + R.drawable.ic_search + ) + ) + } + } + } + + @Margins + @get:Margins + protected var margins: Int = 0 + set(@Margins margins) { + field = margins + + val left: Int + val top: Int + val right: Int + val bottom: Int + val params = mMaterialCardView?.layoutParams as LayoutParams? + + when (margins) { + Margins.NO_FOCUS -> { + left = + context.resources.getDimensionPixelSize(R.dimen.search_margins_left_right) + top = + context.resources.getDimensionPixelSize(R.dimen.search_margins_top_bottom) + right = + context.resources.getDimensionPixelSize(R.dimen.search_margins_left_right) + bottom = + context.resources.getDimensionPixelSize(R.dimen.search_margins_top_bottom) + + params?.width = ViewGroup.LayoutParams.MATCH_PARENT + params?.height = ViewGroup.LayoutParams.WRAP_CONTENT + params?.setMargins(left, top, right, bottom) + mMaterialCardView?.layoutParams = params + } + Margins.FOCUS -> { + left = + context.resources.getDimensionPixelSize(R.dimen.search_margins_focus) + top = + context.resources.getDimensionPixelSize(R.dimen.search_margins_focus) + right = + context.resources.getDimensionPixelSize(R.dimen.search_margins_focus) + bottom = + context.resources.getDimensionPixelSize(R.dimen.search_margins_focus) + + params?.width = ViewGroup.LayoutParams.MATCH_PARENT + params?.height = ViewGroup.LayoutParams.MATCH_PARENT + params?.setMargins(left, top, right, bottom) + mMaterialCardView?.layoutParams = params + } + } + } + + // ********************************************************************************************* + protected abstract fun addFocus() + + protected abstract fun removeFocus() + + // ********************************************************************************************* + protected fun init() { + mLinearLayout = findViewById(R.id.search_linear_layout) + + mImageViewNavigation = findViewById(R.id.search_image_view_navigation) + mImageViewNavigation?.setOnClickListener(this) + + mImageViewMic = findViewById(R.id.search_image_view_mic) + mImageViewMic?.setOnClickListener(this) + + mImageViewMenu = findViewById(R.id.search_image_view_menu) + mImageViewMenu?.setOnClickListener(this) + + mImageViewClear = findViewById(R.id.search_image_view_clear) + mImageViewClear?.visibility = View.GONE + mImageViewClear?.setOnClickListener(this) + + mSearchEditText = findViewById(R.id.search_search_edit_text) + mSearchEditText?.addTextChangedListener(object : TextWatcher { + override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { + + } + + override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) { + this@SearchLayout.onTextChanged(s) + } + + override fun afterTextChanged(s: Editable?) { + + } + }) + mSearchEditText?.setOnEditorActionListener { _, _, _ -> + onSubmitQuery() + return@setOnEditorActionListener true // true + } + mSearchEditText?.setOnFocusChangeListener { _, hasFocus -> + if (hasFocus) { + addFocus() + } else { + removeFocus() + } + } + + mRecyclerView = findViewById(R.id.search_recycler_view) + mRecyclerView?.visibility = View.GONE + mRecyclerView?.layoutManager = LinearLayoutManager(context) + mRecyclerView?.isNestedScrollingEnabled = false + mRecyclerView?.itemAnimator = DefaultItemAnimator() + mRecyclerView?.overScrollMode = View.OVER_SCROLL_NEVER + mRecyclerView?.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + super.onScrollStateChanged(recyclerView, newState) + if (newState == RecyclerView.SCROLL_STATE_DRAGGING) { + hideKeyboard() + } + } + }) + + mViewShadow = findViewById(R.id.search_view_shadow) + mViewShadow?.visibility = View.GONE + + mViewDivider = findViewById(R.id.search_view_divider) + mViewDivider?.visibility = View.GONE + + mViewAnim = findViewById(R.id.search_view_anim) + mViewAnim?.visibility = View.GONE + + mMaterialCardView = findViewById(R.id.search_material_card_view) + margins = Margins.NO_FOCUS + + isClickable = true + isFocusable = true + isFocusableInTouchMode = true + } + + // ********************************************************************************************* + fun setNavigationIconVisibility(visibility: Int) { + mImageViewNavigation?.visibility = visibility + } + + fun setNavigationIconImageResource(@DrawableRes resId: Int) { + mImageViewNavigation?.setImageResource(resId) + } + + fun setNavigationIconImageDrawable(@Nullable drawable: Drawable?) { + mImageViewNavigation?.setImageDrawable(drawable) + } + + fun setNavigationIconColorFilter(color: Int) { + mImageViewNavigation?.setColorFilter(color) + } + + fun setNavigationIconColorFilter(color: Int, mode: PorterDuff.Mode) { + mImageViewNavigation?.setColorFilter(color, mode) + } + + fun setNavigationIconColorFilter(cf: ColorFilter?) { + mImageViewNavigation?.colorFilter = cf + } + + fun clearNavigationIconColorFilter() { + mImageViewNavigation?.clearColorFilter() + } + + fun setNavigationIconContentDescription(contentDescription: CharSequence) { + mImageViewNavigation?.contentDescription = contentDescription + } + + // ********************************************************************************************* + fun setMicIconImageResource(@DrawableRes resId: Int) { + mImageViewMic?.setImageResource(resId) + } + + fun setMicIconImageDrawable(@Nullable drawable: Drawable?) { + mImageViewMic?.setImageDrawable(drawable) + } + + fun setMicIconColorFilter(color: Int) { + mImageViewMic?.setColorFilter(color) + } + + fun setMicIconColorFilter(color: Int, mode: PorterDuff.Mode) { + mImageViewMic?.setColorFilter(color, mode) + } + + fun setMicIconColorFilter(cf: ColorFilter?) { + mImageViewMic?.colorFilter = cf + } + + fun clearMicIconColorFilter() { + mImageViewMic?.clearColorFilter() + } + + fun setMicIconContentDescription(contentDescription: CharSequence) { + mImageViewMic?.contentDescription = contentDescription + } + + // ********************************************************************************************* + fun setMenuIconImageResource(@DrawableRes resId: Int) { + mImageViewMenu?.setImageResource(resId) + } + + fun setMenuIconImageDrawable(@Nullable drawable: Drawable?) { + mImageViewMenu?.setImageDrawable(drawable) + } + + fun setMenuIconColorFilter(color: Int) { + mImageViewMenu?.setColorFilter(color) + } + + fun setMenuIconColorFilter(color: Int, mode: PorterDuff.Mode) { + mImageViewMenu?.setColorFilter(color, mode) + } + + fun setMenuIconColorFilter(cf: ColorFilter?) { + mImageViewMenu?.colorFilter = cf + } + + fun clearMenuIconColorFilter() { + mImageViewMenu?.clearColorFilter() + } + + fun setMenuIconContentDescription(contentDescription: CharSequence) { + mImageViewMenu?.contentDescription = contentDescription + } + + // ********************************************************************************************* + fun setClearIconImageResource(@DrawableRes resId: Int) { + mImageViewClear?.setImageResource(resId) + } + + fun setClearIconImageDrawable(@Nullable drawable: Drawable?) { + mImageViewClear?.setImageDrawable(drawable) + } + + fun setClearIconColorFilter(color: Int) { + mImageViewClear?.setColorFilter(color) + } + + fun setClearIconColorFilter(color: Int, mode: PorterDuff.Mode) { + mImageViewClear?.setColorFilter(color, mode) + } + + fun setClearIconColorFilter(cf: ColorFilter?) { + mImageViewClear?.colorFilter = cf + } + + fun clearClearIconColorFilter() { + mImageViewClear?.clearColorFilter() + } + + fun setClearIconContentDescription(contentDescription: CharSequence) { + mImageViewClear?.contentDescription = contentDescription + } + + // ********************************************************************************************* + fun setAdapterLayoutManager(@Nullable layout: RecyclerView.LayoutManager?) { + mRecyclerView?.layoutManager = layout + } + + // only when height == match_parent + fun setAdapterHasFixedSize(hasFixedSize: Boolean) { + mRecyclerView?.setHasFixedSize(hasFixedSize) + } + + fun addAdapterItemDecoration(@NonNull decor: RecyclerView.ItemDecoration) { + mRecyclerView?.addItemDecoration(decor) + } + + fun removeAdapterItemDecoration(@NonNull decor: RecyclerView.ItemDecoration) { + mRecyclerView?.removeItemDecoration(decor) + } + + fun setAdapter(@Nullable adapter: RecyclerView.Adapter<*>?) { + mRecyclerView?.adapter = adapter + } + + @Nullable + fun getAdapter(): RecyclerView.Adapter<*>? { + return mRecyclerView?.adapter + } + + // ********************************************************************************************* + /** + * Typeface.NORMAL + * Typeface.BOLD + * Typeface.ITALIC + * Typeface.BOLD_ITALIC + * + * Typeface.DEFAULT + * Typeface.DEFAULT_BOLD + * Typeface.SANS_SERIF + * Typeface.SERIF + * Typeface.MONOSPACE + * + * Typeface.create(Typeface.NORMAL, Typeface.DEFAULT) + */ + fun setTextTypeface(@Nullable tf: Typeface?) { + mSearchEditText?.typeface = tf + } + + fun getTextTypeface(): Typeface? { + return mSearchEditText?.typeface + } + + fun setTextInputType(type: Int) { + mSearchEditText?.inputType = type + } + + fun getTextInputType(): Int? { + return mSearchEditText?.inputType + } + + fun setTextImeOptions(imeOptions: Int) { + mSearchEditText?.imeOptions = imeOptions + } + + fun getTextImeOptions(): Int? { + return mSearchEditText?.imeOptions + } + + fun setTextQuery(query: CharSequence?, submit: Boolean) { + mSearchEditText?.setText(query) + if (query != null) { + mSearchEditText?.setSelection(mSearchEditText?.length()!!) + } + if (submit && !TextUtils.isEmpty(query)) { + onSubmitQuery() + } + } + + @Nullable + fun getTextQuery(): CharSequence? { + return mSearchEditText?.text + } + + fun setTextHint(hint: CharSequence?) { + mSearchEditText?.hint = hint + } + + fun getTextHint(): CharSequence? { + return mSearchEditText?.hint + } + + fun setTextColor(@ColorInt color: Int) { + mSearchEditText?.setTextColor(color) + } + + fun setTextSize(size: Float) { + mSearchEditText?.textSize = size + } + + fun setTextGravity(gravity: Int) { + mSearchEditText?.gravity = gravity + } + + fun setTextHint(@StringRes resid: Int) { + mSearchEditText?.setHint(resid) + } + + fun setTextHintColor(@ColorInt color: Int) { + mSearchEditText?.setHintTextColor(color) + } + + fun setClearFocusOnBackPressed(clearFocusOnBackPressed: Boolean) { + mSearchEditText?.clearFocusOnBackPressed = clearFocusOnBackPressed + } + + // ********************************************************************************************* + override fun setBackgroundColor(@ColorInt color: Int) { + mMaterialCardView?.setCardBackgroundColor(color) + } + + fun setBackgroundColor(@Nullable color: ColorStateList?) { + mMaterialCardView?.setCardBackgroundColor(color) + } + + override fun setElevation(elevation: Float) { + mMaterialCardView?.cardElevation = elevation + mMaterialCardView?.maxCardElevation = elevation + } + + override fun getElevation(): Float { + return mMaterialCardView?.elevation!! + } + + fun setBackgroundRadius(radius: Float) { + mMaterialCardView?.radius = radius + } + + fun getBackgroundRadius(): Float { + return mMaterialCardView?.radius!! + } + + fun setBackgroundRippleColor(@ColorRes rippleColorResourceId: Int) { + mMaterialCardView?.setRippleColorResource(rippleColorResourceId) + } + + fun setBackgroundRippleColorResource(@Nullable rippleColor: ColorStateList?) { + mMaterialCardView?.rippleColor = rippleColor + } + + fun setBackgroundStrokeColor(@ColorInt strokeColor: Int) { + mMaterialCardView?.strokeColor = strokeColor + } + + fun setBackgroundStrokeColor(strokeColor: ColorStateList) { + mMaterialCardView?.setStrokeColor(strokeColor) + } + + fun setBackgroundStrokeWidth(@Dimension strokeWidth: Int) { + mMaterialCardView?.strokeWidth = strokeWidth + } + + @Dimension + fun getBackgroundStrokeWidth(): Int { + return mMaterialCardView?.strokeWidth!! + } + + // ********************************************************************************************* + fun setDividerColor(@ColorInt color: Int) { + mViewDivider?.setBackgroundColor(color) + } + + fun setShadowColor(@ColorInt color: Int) { + mViewShadow?.setBackgroundColor(color) + } + + // ********************************************************************************************* + fun setOnFocusChangeListener(listener: OnFocusChangeListener) { + mOnFocusChangeListener = listener + } + + fun setOnQueryTextListener(listener: OnQueryTextListener) { + mOnQueryTextListener = listener + } + + fun setOnNavigationClickListener(listener: OnNavigationClickListener) { + mOnNavigationClickListener = listener + } + + fun setOnMicClickListener(listener: OnMicClickListener) { + mOnMicClickListener = listener + } + + fun setOnMenuClickListener(listener: OnMenuClickListener) { + mOnMenuClickListener = listener + } + + fun setOnClearClickListener(listener: OnClearClickListener) { + mOnClearClickListener = listener + } + + // ********************************************************************************************* + fun showKeyboard() { + if (!isInEditMode) { + val inputMethodManager = + context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + inputMethodManager.showSoftInput( + mSearchEditText, + InputMethodManager.RESULT_UNCHANGED_SHOWN + ) + } + } + + fun hideKeyboard() { + if (!isInEditMode) { + val inputMethodManager = + context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager + inputMethodManager.hideSoftInputFromWindow( + windowToken, + InputMethodManager.RESULT_UNCHANGED_SHOWN + ) + } + } + + // ********************************************************************************************* + protected fun setLayoutHeight(height: Int) { + val params = mLinearLayout?.layoutParams + params?.height = height + params?.width = ViewGroup.LayoutParams.MATCH_PARENT + mLinearLayout?.layoutParams = params + } + + // ********************************************************************************************* + private fun onTextChanged(newText: CharSequence) { + if (!TextUtils.isEmpty(newText)) { + mImageViewMic?.visibility = View.GONE + mImageViewClear?.visibility = View.VISIBLE + } else { + mImageViewClear?.visibility = View.GONE + if (mSearchEditText?.hasFocus()!!) { + mImageViewMic?.visibility = View.VISIBLE + } else { + mImageViewMic?.visibility = View.GONE + } + } + + if (mOnQueryTextListener != null) { + mOnQueryTextListener?.onQueryTextChange(newText) + } + } + + private fun onSubmitQuery() { + val query = mSearchEditText?.text + if (query != null && TextUtils.getTrimmedLength(query) > 0) { + if (mOnQueryTextListener == null || !mOnQueryTextListener!!.onQueryTextSubmit(query.toString())) { + mSearchEditText?.text = query + } + } + } + + // ********************************************************************************************* + override fun onSaveInstanceState(): Parcelable? { + val superState = super.onSaveInstanceState() + val ss = SearchViewSavedState(superState!!) + if (mSearchEditText?.text!!.isNotEmpty()) { + ss.query = mSearchEditText?.text + } + ss.hasFocus = mSearchEditText?.hasFocus()!! + return ss + } + + override fun onRestoreInstanceState(state: Parcelable?) { + if (state !is SearchViewSavedState) { + super.onRestoreInstanceState(state) + return + } + super.onRestoreInstanceState(state.superState) + if (state.hasFocus) { + mSearchEditText?.requestFocus() + } + if (state.query != null) { + setTextQuery(state.query, false) + } + requestLayout() + } + + override fun requestFocus(direction: Int, previouslyFocusedRect: Rect?): Boolean { + return if (!isFocusable) { + false + } else { + mSearchEditText?.requestFocus(direction, previouslyFocusedRect)!! + } + } + + override fun clearFocus() { + super.clearFocus() + mSearchEditText?.clearFocus() + } + + override fun onClick(view: View?) { + if (view === mImageViewNavigation) { + if (mOnNavigationClickListener != null) { + mOnNavigationClickListener?.onNavigationClick(mSearchEditText?.hasFocus()!!) + } + } else if (view === mImageViewMic) { + if (mOnMicClickListener != null) { + mOnMicClickListener?.onMicClick() + } + } else if (view === mImageViewMenu) { + if (mOnMenuClickListener != null) { + mOnMenuClickListener?.onMenuClick() + } + } else if (view === mImageViewClear) { + if (mSearchEditText?.text!!.isNotEmpty()) { + mSearchEditText?.text!!.clear() + } + if (mOnClearClickListener != null) { + mOnClearClickListener?.onClearClick() + } + } + } + + // ********************************************************************************************* + interface OnFocusChangeListener { + + fun onFocusChange(hasFocus: Boolean) + } + + interface OnQueryTextListener { + + fun onQueryTextChange(newText: CharSequence): Boolean + + fun onQueryTextSubmit(query: CharSequence): Boolean + } + + interface OnNavigationClickListener { + + fun onNavigationClick(hasFocus: Boolean) + } + + interface OnMicClickListener { + + fun onMicClick() + } + + interface OnMenuClickListener { + + fun onMenuClick() + } + + interface OnClearClickListener { + + fun onClearClick() + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchViewSavedState.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchViewSavedState.kt new file mode 100644 index 000000000..394a770c9 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/internal/SearchViewSavedState.kt @@ -0,0 +1,21 @@ +/*https://github.com/lapism/search*/ + +package org.koitharu.kotatsu.base.ui.widgets.search.internal + +import android.os.Parcel +import android.os.Parcelable +import android.text.TextUtils +import android.view.View + +internal class SearchViewSavedState(superState: Parcelable) : View.BaseSavedState(superState) { + + var query: CharSequence? = null + var hasFocus: Boolean = false + + override fun writeToParcel(out: Parcel, flags: Int) { + super.writeToParcel(out, flags) + TextUtils.writeToParcel(query, out, flags) + out.writeInt(if (hasFocus) 1 else 0) + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/util/SearchUtils.kt b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/util/SearchUtils.kt new file mode 100644 index 000000000..ed93e0848 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/base/ui/widgets/search/util/SearchUtils.kt @@ -0,0 +1,37 @@ +package org.koitharu.kotatsu.base.ui.widgets.search.util + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.speech.RecognizerIntent + +object SearchUtils { + + const val SPEECH_REQUEST_CODE = 300 + + @JvmStatic + fun setVoiceSearch(activity: Activity, text: String) { + val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH) + // intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.putExtra( + RecognizerIntent.EXTRA_LANGUAGE_MODEL, + RecognizerIntent.LANGUAGE_MODEL_FREE_FORM + ) + intent.putExtra(RecognizerIntent.EXTRA_PROMPT, text) + intent.putExtra(RecognizerIntent.EXTRA_MAX_RESULTS, 1) + + activity.startActivityForResult( + intent, + SPEECH_REQUEST_CODE + ) + } + + @JvmStatic + fun isVoiceSearchAvailable(context: Context): Boolean { + val pm = context.packageManager + val activities = + pm.queryIntentActivities(Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH), 0) + return activities.size != 0 + } + +} \ No newline at end of file diff --git a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt index 50a5d7302..e63c7d987 100644 --- a/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/details/ui/DetailsFragment.kt @@ -60,17 +60,41 @@ class DetailsFragment : BaseFragment(), View.OnClickList .lifecycle(viewLifecycleOwner) .enqueueWith(coil) textViewTitle.text = manga.title - textViewSubtitle.textAndVisible = manga.altTitle + textViewAuthor.textAndVisible = manga.author + textViewSource.text = manga.source.title textViewDescription.text = manga.description?.parseAsHtml()?.takeUnless(Spanned::isBlank) ?: getString(R.string.no_description) + if (manga.chapters?.isNotEmpty() == true) { + chaptersContainer.isVisible = true + textViewChapters.text = manga.chapters.let { + resources.getQuantityString( + R.plurals.chapters, + it.size, + manga.chapters.size + ) + } + } else { + chaptersContainer.isVisible = false + } if (manga.rating == Manga.NO_RATING) { ratingBar.isVisible = false + ratingContainer.isVisible = false } else { ratingBar.progress = (ratingBar.max * manga.rating).roundToInt() ratingBar.isVisible = true + textViewRating.text = String.format("%.1f", manga.rating * 5) + ratingContainer.isVisible = true } - imageViewFavourite.setOnClickListener(this@DetailsFragment) + val file = manga.url.toUri().toFileOrNull() + if (file != null) { + val size = file.length() + textViewSize.text = FileSizeUtils.formatBytes(requireContext(), size) + sizeContainer.isVisible = true + } else { + sizeContainer.isVisible = false + } + buttonFavorite.setOnClickListener(this@DetailsFragment) buttonRead.setOnClickListener(this@DetailsFragment) buttonRead.setOnLongClickListener(this@DetailsFragment) buttonRead.isEnabled = !manga.chapters.isNullOrEmpty() @@ -91,13 +115,13 @@ class DetailsFragment : BaseFragment(), View.OnClickList } private fun onFavouriteChanged(isFavourite: Boolean) { - binding.imageViewFavourite.setImageResource( + with(binding.buttonFavorite) { if (isFavourite) { - R.drawable.ic_heart + this?.setIconResource(R.drawable.ic_heart) } else { - R.drawable.ic_heart_outline + this?.setIconResource(R.drawable.ic_heart_outline) } - ) + } } private fun onLoadingStateChanged(isLoading: Boolean) { @@ -107,7 +131,7 @@ class DetailsFragment : BaseFragment(), View.OnClickList override fun onClick(v: View) { val manga = viewModel.manga.value when (v.id) { - R.id.imageView_favourite -> { + R.id.button_favorite -> { FavouriteCategoriesDialog.show(childFragmentManager, manga ?: return) } R.id.button_read -> { @@ -163,31 +187,10 @@ class DetailsFragment : BaseFragment(), View.OnClickList tagsJob?.cancel() tagsJob = viewLifecycleScope.launch { val tags = ArrayList(manga.tags.size + 2) - if (manga.author != null) { - tags += ChipsView.ChipModel( - title = manga.author, - icon = R.drawable.ic_chip_user - ) - } for (tag in manga.tags) { tags += ChipsView.ChipModel( title = tag.title, - icon = R.drawable.ic_chip_tag - ) - } - val file = manga.url.toUri().toFileOrNull() - if (file != null) { - val size = withContext(Dispatchers.IO) { - file.length() - } - tags += ChipsView.ChipModel( - title = FileSizeUtils.formatBytes(requireContext(), size), - icon = R.drawable.ic_chip_storage - ) - } else { - tags += ChipsView.ChipModel( - title = manga.source.title, - icon = R.drawable.ic_chip_web + icon = 0 ) } binding.chipsTags.setChips(tags) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt index da163f722..d75a627df 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt @@ -4,16 +4,15 @@ import android.os.Bundle import android.view.* import androidx.annotation.CallSuper import androidx.appcompat.widget.PopupMenu +import androidx.core.content.ContextCompat import androidx.core.graphics.Insets import androidx.core.view.GravityCompat import androidx.core.view.isGone import androidx.core.view.isVisible import androidx.core.view.updatePadding import androidx.drawerlayout.widget.DrawerLayout -import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import com.google.android.material.snackbar.Snackbar import kotlinx.coroutines.launch @@ -81,6 +80,10 @@ abstract class MangaListFragment : BaseFragment(), addOnScrollListener(paginationListener!!) } with(binding.swipeRefreshLayout) { + setColorSchemeColors( + ContextCompat.getColor(context, R.color.color_primary), + ContextCompat.getColor(context, R.color.color_primary_variant) + ) setOnRefreshListener(this@MangaListFragment) isEnabled = isSwipeRefreshEnabled } @@ -246,13 +249,9 @@ abstract class MangaListFragment : BaseFragment(), when (mode) { ListMode.LIST -> { layoutManager = LinearLayoutManager(context) - addItemDecoration( - DividerItemDecoration( - context, - RecyclerView.VERTICAL - ) - ) - updatePadding(left = 0, right = 0) + val spacing = resources.getDimensionPixelOffset(R.dimen.list_spacing) + addItemDecoration(SpacingItemDecoration(spacing)) + updatePadding(left = spacing, right = spacing) } ListMode.DETAILED_LIST -> { layoutManager = LinearLayoutManager(context) diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt index 9f3b2f561..b7a367591 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/model/ListModelConversionExt.kt @@ -6,7 +6,6 @@ import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.exceptions.resolve.ResolvableException import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.prefs.ListMode -import kotlin.math.roundToInt fun Manga.toListModel() = MangaListModel( id = id, @@ -20,7 +19,7 @@ fun Manga.toListDetailedModel() = MangaListDetailedModel( id = id, title = title, subtitle = altTitle, - rating = if (rating == Manga.NO_RATING) null else "${(rating * 10).roundToInt()}/10", + rating = if (rating == Manga.NO_RATING) null else String.format("%.1f", rating * 5), tags = tags.joinToString(", ") { it.title }, coverUrl = coverUrl, manga = this diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt index cd95e7e8a..58a5e82a5 100644 --- a/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/MainActivity.kt @@ -6,10 +6,7 @@ import android.content.res.Configuration import android.graphics.Color import android.os.Build import android.os.Bundle -import android.view.Menu -import android.view.MenuItem -import android.view.View -import android.view.ViewGroup +import android.view.* import androidx.appcompat.app.ActionBarDrawerToggle import androidx.appcompat.app.AlertDialog import androidx.core.graphics.Insets @@ -17,6 +14,7 @@ import androidx.core.view.* import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentTransaction import androidx.fragment.app.commit +import androidx.recyclerview.widget.RecyclerView import androidx.swiperefreshlayout.widget.CircularProgressDrawable import com.google.android.material.navigation.NavigationView import com.google.android.material.snackbar.Snackbar @@ -27,6 +25,7 @@ import org.koitharu.kotatsu.core.model.Manga import org.koitharu.kotatsu.core.model.MangaSource import org.koitharu.kotatsu.core.prefs.AppSection import org.koitharu.kotatsu.databinding.ActivityMainBinding +import org.koitharu.kotatsu.databinding.NavigationHeaderBinding import org.koitharu.kotatsu.details.ui.DetailsActivity import org.koitharu.kotatsu.favourites.ui.FavouritesContainerFragment import org.koitharu.kotatsu.history.ui.HistoryListFragment @@ -44,6 +43,7 @@ import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.tracker.ui.FeedFragment import org.koitharu.kotatsu.tracker.work.TrackWorker import org.koitharu.kotatsu.utils.ext.getDisplayMessage +import org.koitharu.kotatsu.utils.ext.navigationItemBackground import org.koitharu.kotatsu.utils.ext.resolveDp class MainActivity : BaseActivity(), @@ -55,12 +55,14 @@ class MainActivity : BaseActivity(), mode = LazyThreadSafetyMode.NONE ) + private lateinit var navHeaderBinding: NavigationHeaderBinding private lateinit var drawerToggle: ActionBarDrawerToggle private var searchUi: SearchUI? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(ActivityMainBinding.inflate(layoutInflater)) + navHeaderBinding = NavigationHeaderBinding.inflate(layoutInflater) drawerToggle = ActionBarDrawerToggle( this, binding.drawer, @@ -71,7 +73,18 @@ class MainActivity : BaseActivity(), binding.drawer.addDrawerListener(drawerToggle) supportActionBar?.setDisplayHomeAsUpEnabled(true) - binding.navigationView.setNavigationItemSelectedListener(this) + binding.navigationView.apply { + val menuView = findViewById(com.google.android.material.R.id.design_navigation_view) + navHeaderBinding.root.setOnApplyWindowInsetsListener { v, insets -> + v.updatePadding(top = insets.systemWindowInsetTop) + // NavigationView doesn't dispatch insets to the menu view, so pad the bottom here. + menuView.updatePadding(bottom = insets.systemWindowInsetBottom) + insets + } + addHeaderView(navHeaderBinding.root) + itemBackground = navigationItemBackground(context) + setNavigationItemSelectedListener(this@MainActivity) + } with(binding.fab) { imageTintList = ColorStateList.valueOf(Color.WHITE) diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt index 22d66a6c6..e34239b56 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/ReaderActivity.kt @@ -38,7 +38,7 @@ import org.koitharu.kotatsu.reader.ui.pager.BaseReader import org.koitharu.kotatsu.reader.ui.pager.ReaderUiState import org.koitharu.kotatsu.reader.ui.pager.reversed.ReversedReaderFragment import org.koitharu.kotatsu.reader.ui.pager.standard.PagerReaderFragment -import org.koitharu.kotatsu.reader.ui.pager.wetoon.WebtoonReaderFragment +import org.koitharu.kotatsu.reader.ui.pager.webtoon.WebtoonReaderFragment import org.koitharu.kotatsu.reader.ui.thumbnails.OnPageSelectListener import org.koitharu.kotatsu.reader.ui.thumbnails.PagesThumbnailsSheet import org.koitharu.kotatsu.utils.GridTouchHelper diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/ListPaginationListener.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/ListPaginationListener.kt similarity index 95% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/ListPaginationListener.kt rename to app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/ListPaginationListener.kt index bcd6ec292..a3879a762 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/ListPaginationListener.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/ListPaginationListener.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.reader.ui.pager.wetoon +package org.koitharu.kotatsu.reader.ui.pager.webtoon import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonAdapter.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonAdapter.kt similarity index 94% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonAdapter.kt rename to app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonAdapter.kt index 34e3b4713..a089d4d17 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonAdapter.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonAdapter.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.reader.ui.pager.wetoon +package org.koitharu.kotatsu.reader.ui.pager.webtoon import android.view.LayoutInflater import android.view.ViewGroup diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonFrameLayout.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonFrameLayout.kt similarity index 91% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonFrameLayout.kt rename to app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonFrameLayout.kt index cf0879e4c..2fe267156 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonFrameLayout.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonFrameLayout.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.reader.ui.pager.wetoon +package org.koitharu.kotatsu.reader.ui.pager.webtoon import android.content.Context import android.util.AttributeSet diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonHolder.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonHolder.kt rename to app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt index f7ac4b541..fcb81c602 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonHolder.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonHolder.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.reader.ui.pager.wetoon +package org.koitharu.kotatsu.reader.ui.pager.webtoon import android.net.Uri import android.view.View diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonImageView.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonImageView.kt rename to app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt index 88845b512..09cb044c0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonImageView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonImageView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.reader.ui.pager.wetoon +package org.koitharu.kotatsu.reader.ui.pager.webtoon import android.content.Context import android.graphics.PointF diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonReaderFragment.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt similarity index 98% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonReaderFragment.kt rename to app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt index e1b1ab879..1cb0b1079 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonReaderFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonReaderFragment.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.reader.ui.pager.wetoon +package org.koitharu.kotatsu.reader.ui.pager.webtoon import android.os.Bundle import android.view.LayoutInflater diff --git a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonRecyclerView.kt b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt similarity index 97% rename from app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonRecyclerView.kt rename to app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt index 16287fbeb..f4535d7be 100644 --- a/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/wetoon/WebtoonRecyclerView.kt +++ b/app/src/main/java/org/koitharu/kotatsu/reader/ui/pager/webtoon/WebtoonRecyclerView.kt @@ -1,4 +1,4 @@ -package org.koitharu.kotatsu.reader.ui.pager.wetoon +package org.koitharu.kotatsu.reader.ui.pager.webtoon import android.content.Context import android.util.AttributeSet diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedFragment.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedFragment.kt index 4abb468a9..99fd2bcd1 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/FeedFragment.kt @@ -47,9 +47,6 @@ class FeedFragment : BaseFragment(), PaginationScrollListen feedAdapter = FeedAdapter(get(), viewLifecycleOwner, this) with(binding.recyclerView) { adapter = feedAdapter - addItemDecoration( - SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing)) - ) setHasFixedSize(true) addOnScrollListener(PaginationScrollListener(4, this@FeedFragment)) } @@ -134,7 +131,7 @@ class FeedFragment : BaseFragment(), PaginationScrollListen return } val summaryText = getString( - R.string.chapers_checking_progress, + R.string.chapters_checking_progress, progress.value + 1, progress.total ) diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/adapter/FeedItemAD.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/adapter/FeedItemAD.kt index 75ffadd6d..2e3bdf446 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/adapter/FeedItemAD.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/adapter/FeedItemAD.kt @@ -37,7 +37,7 @@ fun feedItemAD( .lifecycle(lifecycleOwner) .enqueueWith(coil) binding.textViewTitle.text = item.title - binding.textViewSubtitle.text = item.subtitle + binding.badge.text = item.subtitle binding.textViewChapters.text = item.chapters } diff --git a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/model/ListModelConversionExt.kt b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/model/ListModelConversionExt.kt index 87c7efd2f..29ebb4790 100644 --- a/app/src/main/java/org/koitharu/kotatsu/tracker/ui/model/ListModelConversionExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/tracker/ui/model/ListModelConversionExt.kt @@ -1,10 +1,8 @@ package org.koitharu.kotatsu.tracker.ui.model import android.content.res.Resources -import android.text.format.DateUtils import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.model.TrackingLogItem -import org.koitharu.kotatsu.utils.ext.formatRelative fun TrackingLogItem.toFeedItem(resources: Resources): FeedItem { val chaptersString = if (chapters.size > MAX_CHAPTERS) { @@ -23,17 +21,7 @@ fun TrackingLogItem.toFeedItem(resources: Resources): FeedItem { id = id, imageUrl = manga.coverUrl, title = manga.title, - subtitle = buildString { - append(createdAt.formatRelative(DateUtils.DAY_IN_MILLIS)) - append(" ") - append( - resources.getQuantityString( - R.plurals.new_chapters, - chapters.size, - chapters.size - ) - ) - }, + subtitle = chapters.size.toString(), chapters = chaptersString, manga = manga ) diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt index 5b3081d8e..e31e3e20b 100644 --- a/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/CoilExt.kt @@ -12,6 +12,7 @@ import org.koitharu.kotatsu.core.network.CommonHeaders @Suppress("NOTHING_TO_INLINE") inline fun ImageView.newImageRequest(url: String) = ImageRequest.Builder(context) .data(url) + .crossfade(true) .target(this) @Suppress("NOTHING_TO_INLINE") diff --git a/app/src/main/java/org/koitharu/kotatsu/utils/ext/UiExt.kt b/app/src/main/java/org/koitharu/kotatsu/utils/ext/UiExt.kt new file mode 100644 index 000000000..f66e9f880 --- /dev/null +++ b/app/src/main/java/org/koitharu/kotatsu/utils/ext/UiExt.kt @@ -0,0 +1,21 @@ +package org.koitharu.kotatsu.utils.ext + +import android.content.Context +import android.graphics.drawable.Drawable +import androidx.appcompat.content.res.AppCompatResources +import androidx.core.graphics.drawable.DrawableCompat +import org.koitharu.kotatsu.R + +fun navigationItemBackground(context: Context): Drawable? { + // Need to inflate the drawable and CSL via AppCompatResources to work on Lollipop + // From Google I/O repo (https://github.com/google/iosched) + var background = AppCompatResources.getDrawable(context, R.drawable.navigation_item_background) + if (background != null) { + val tint = AppCompatResources.getColorStateList( + context, R.color.navigation_item_background_tint + ) + background = DrawableCompat.wrap(background.mutate()) + background.setTintList(tint) + } + return background +} \ No newline at end of file diff --git a/app/src/main/res/color/divider.xml b/app/src/main/res/color/divider.xml new file mode 100644 index 000000000..1915480d2 --- /dev/null +++ b/app/src/main/res/color/divider.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/color/navigation_item_background_tint.xml b/app/src/main/res/color/navigation_item_background_tint.xml new file mode 100644 index 000000000..06c5673d1 --- /dev/null +++ b/app/src/main/res/color/navigation_item_background_tint.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/color/selector_overlay.xml b/app/src/main/res/color/selector_overlay.xml new file mode 100644 index 000000000..c99447ac2 --- /dev/null +++ b/app/src/main/res/color/selector_overlay.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-hdpi/totoro.webp b/app/src/main/res/drawable-hdpi/totoro.webp new file mode 100644 index 0000000000000000000000000000000000000000..0430efcfc8fe16ad55cbeaaef597fb47776f2629 GIT binary patch literal 1654 zcmV-+28sDnNk&F)1^@t8MM6+kP&iCt1^@srN5ByfFXkYUWLN3^WDBUpBr*^X-~Ip| z;5L%vNQyfCufP8up8jmoaU@BOlD&6`KmNOg6TGx$+l^$qZDT+-6G-P=y7&FB&B$RGAb-a?}V z|2#BOM8x6>MF>J|K+;D7;Q$)J5aSR_4XqFqs;;DuBBYXyD}a(B96%WVK%E5?y}3ce zQ6Pa41BlTAE`SH2f&t z=fY|5AlEdd^x8J{+3Og`@k$G;GHxDxV{g^`J-hSYK3AmQ|JUWi;BhdY4}1J<$(w(^ z&&|~pcPA()TH9twlA>yC+qONk-W}U*yL+m#8e`iwTVva-svGN!_%kB+2J-tOqW=)w zwvi;+DIM2z@`R=2u=MoL2n|{`*zT;kuSI2?q|_SMc3?9A>TwQy^?zl0ER- z{i7}|FQG`R1QHG4vv*0f9GR?wOpeGTyM)iKWyS4VNwz9StT zW**Z{ql8yA_v1lk<~wnL15_$|0jp(%LtkfCF*8RSwO_}wq>*MzloteWx6?XR{|TV^ zgQibZu(GTx!oZ=Cc~J%Uq6BhOm6b3qDiqQD$;Rj4(+hd_d4o&wvD`@+H=2>+lm{-y z2AQes#V29z)&hAj06ToL^kQ2VV2tBoS>ES!oD0+T zV(H1Sx0=;Cyy;xGZ{0mfc~#T1gH_%%-M@AFXA^Us^;YO6GjpsYmA$<-$!j%Ws)LyO zq{CW|@4Ls*bt$xgw)7QxPQLuN*74DqM>;2jzQ1Q{aK`F#5LgYIY{N1!)B9&PUjA@- z_~l{mAI&t=1`osw-Nw11A=UM4HUFUMpc`Y%_r=PVs|;NIvzff|(DJ zBJs4ynIbSlCaDPN=(&s(dk-v{5SLIsjixhNE;{iE*MaxS`ajpvahWI$NM^X0ok9X1 zXjvfC$sJgFQb76ggpQOuai73z{V1~IMa7iY}{pqbnr42X+{B14^9FqxxMsKyQ`+pR)_SUZk znaH;`qV@?;|SLB=5;l=sP7i7c7O-T(Qf38?*V6W&rs=AOsvrn(Na zQO@H^jS#JXTOUkC)d&7VN9|-Hxn7xttXKR-N9t5d_0vqV1yMf(tzeKz{(z=t4oHfA1sCgg{J3sKWV z&%-Cj2kxhF^G36!Id%>R{1Sl1_5){~+rGQHup(0PP=IZuqOf}R_H(lac4*Wk1#=HH AApigX literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-mdpi/totoro.webp b/app/src/main/res/drawable-mdpi/totoro.webp new file mode 100644 index 0000000000000000000000000000000000000000..bfc0242b21c4b449ff341df27b22a3a95e19f897 GIT binary patch literal 1250 zcmV<81ReWQNk&H61ONb6MM6+kP&iD@1ONapFTe{BKjkWtBw5LR?-vEA#UwHia8AEV zgri2194V^j{QvkfTmZHlN0Q_y*?Wh6;=fxs!Aomsx3%rIjlpOUrcF??n2~j>gY?qrkj@ui@WN~%HHpN4 z8xgDh0TI9|P@n>+Lx4vh1_mAu0fbakAk?9P6mmmQi1-L8e@JL4AcZ2N$|*;Gfglxv zNCA#&;@TumLlHwnBF!IKcBf3Nz_|tfMyy0A3f3$Z3Idv8kdcc5JD^3QBVL*o8!?3i zfnYCe2h5@G55Vk8u*U~$ZFypi+KuE);Y)MP%$+12uG{sT`9e?2iUIVPOO^#%Df|C(L?x%#n770Uobo{Sh{5aAy7#8`{v;A;B~zz7z~C^qKcLnby7{V?ix?y9~C zhi1DOP++CGkbk908(U+vH@S*0k&5J!n%=^4zn?y$PcLo&oEN=eUd@8KP6xJZ` zI78Di_xV|o0q4Q~=*Q#Dtfo*8B`v$jcY)Gn4vny;U$zN@M9Z4Em+v>1>Aw(BAekSu zIka*#z4GCRc}VG_p+ka|WLG=3|7Yrhq}eTsv#7iuFdHfrHZIO4JxKZ4uOf6LQgdQY z3sWfbKCH?`%Xz9XM?%WC;mcXfvrwtYDouD6S#L=9=ghS#l`kqTAX^nt7@_Mkj$RvO zQys^)UVR*IEG``HkiBg5Q4_h6rGL*>Nv*w@WKtwExf6Qs*9(Sfca8-@uMgyOAp6Us zP+)9ltzf7AzP4s}2&1dtO$BeIiI!pLlAU^24FKMbSsii0j_ckot~%7n6f)md(Ocf^ zNLj7@F6{TqTyVdzUZkm1oV`CdcTjjf>vix8gvuB5yM?98K0jHv-3V*%o_`@USho(L zi!Qj=g*D8Y35O=uh#s!H7639eHN>}55*R<`l}EQzAOCVMUYaOn);l&HDB&9%Qgd5) zM$XfJpVvS5+{)UT0Bb;>*JJy?r;hL}H>ugjfQBp1G z3@9I0v8J5?*)J9gnJ*c7k<9>`pkiqo{sV1R#aa&k;tvye)yi3`Vnrpuhn(@pX>mxU zQL&KEz!!S&`6)}{LV1fS=nDYeC#8NMsZS0lO9%m>5B(tZp)Lw0`BFlk>&skow*o-r zq#D`*K)Od7Deln@P0=$U#STXAsiqY7wCb6T;iCZjMrzE~Bp*d|r&92w%3(St<#5Fv zUq!)vOp=uIiX%N2^al;3ckI&Ly^Y9 MzlT5ETLO(W04@ewtN;K2 literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-w600dp/tab_indicator.xml b/app/src/main/res/drawable-w600dp/tab_indicator.xml new file mode 100644 index 000000000..e2b1ad5c9 --- /dev/null +++ b/app/src/main/res/drawable-w600dp/tab_indicator.xml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable-xhdpi/totoro.webp b/app/src/main/res/drawable-xhdpi/totoro.webp new file mode 100644 index 0000000000000000000000000000000000000000..2b0dde6ca33b3eff8f375eac39984bc4fe8849a0 GIT binary patch literal 2524 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 mr$%;fQahnSuD`}%7eRSgIk^=QYQOA0^3iTsIo zaMfDmiXPjlz>MMvypQ9zS(tw`m9bv|EHi|0trU`Q0Q;0=fI@;8254YD5+b4M0DwRg zSQQvXfkUbS(!s9paK8@1OQY3001BW0H^=}009650f25%U>F5P!GwPpM$s^&!2t{qO^6I*sTLrF z1r~|KXuV;HC5)w{i#Axac@SUpQ86SuAOePIKmn?OLyqN0LO7bz2o?@bSO+TyLj%}{ zAlr!a0Yl6iK;4yuVHi%wnGUCmkN39A+}|pV1FdEb!V-6Vr3tEhCc>3?w4QU6~x zYxE~ew$(15IDYjaz3y${=29+v&YdA7Tzczv@EW%r z;Kl&59daAkX4;t#%k#<33_Q=6#vSJUChOOL98NR5t~Ym_e^^dH+;MM@tITjl<11tY znZrMHzv0JKuZY63|E1{yf&hqyHj{JF3hs0Z)Xx89;m3HOX++pm^ zBkXdfJipT=R+i<6u-vY4-{Z50=#7MWZzob-Q*4PPEo64CEh|DKWu%X=H zn<)HFRu?8*51<#=@2{EMse0JSbV5XLlEcUm(a{^<{+ub}H__3)>xO1Ip*P97*@-Ei zAk&%SB6M0Rqg-Syo96^*c1);;c=O`vyI(JG>#7Xj31-NM4ZZvH#apOvwdSd?P>GY{ zGJbVZ5`m?*sD|1nzAA!HC&NJ(LH2B6AV3F3XMz@em0+HjJRB0MVRyce6Gb*NTR%cX zh1KkW803S4=#@huRP?{-{A^A{TbRQwL`1WyiT)1=IuyO~&IpL2U4AXUdb~>^x1M!! z)++_(a`i{;A*~M*dsj-|BQFLdS-EQvoHYb5w z^tYW~Kgx+{xfic<#t3gwbQq$T*2ZSmcGTLU}}>$rg5h$)VTU($bqtvZD%p?N%_#1 zSJgl~IyJ1Cp1}-c>Q??c&HJVuC}&DneEmy-m*v0vbtS4_ZR007-jwq}P#3kG;6=!E zz7p~xEYZk#h1`#f8}!ZY6NgS#^8-9V-wYTRagRPV^tl*w$(%T-@1G1@(!b3_)1}x& zeOi&LX+Ixl($55Gu25@jN=!F$o5h){@fN-t<|SRWarv=_uQAszuP=~CTXb0@&3yYT zQ}XN^ByEu<|B&pI>jraZoa+DMm!n_I4WUn?-}xcv=NC2GRe-lr&V2Oi9fW%>KXWF)r0lIc|rE=8`hCXi8G^8YY-NgHC zFldx7g}&DyFY!~g#0qq&TxqX5=_`2kCY93 z0VW1XpjxUuDq$3gw}-gG*hhdkQbISy;_0xWE23i|t~4GHoy&lw#nt+U;9F7nXD(OV zuP(psU0sgpNXF+}tqnk0pS zN(+{npqG_890s*UVGojMF8eOdY~$b0HziOYz?Pu!VU->xXnLjKkBEd=PlGu&dioL~ zX9Ynzgx09E0MrtN&yvI+8F-@vdQX6@Knqk#fh;K(+#Qlp0=pt3^tGUTDP*QXB@sw_ zW{uA$7Y;V2WEW^k+=5*okrH(tCSbU>pr$Ehqb0d-Hm9IrvgHRU;XQ)d0f5%1Gas@5 ztx0o8YHX9idgX9oPH!}N`ci0Ck_A72OjhQ|Jjgb|UnE@8`z-dE>3}FJ${j|LJ59a! zEZ#p;K!IQzWZn@~PKF?d1Z^$LHkUC(JowP(4x~@sbPy4-Z0%%AS3xNxc2br71e}D{ zvK&s!HZc2m(LAaHX;p1&D^O(N7!@GxYR zDz5;-bp(TGodLmZ@&be!5AuP6ePO^TMJfvb`BwxlM-2u(D-S_vL|+zM$p`oqYMdot zw8~OeV0UW^CX4=X?cf%?X_tT1QWXWzSvB@UhNJasq6ZCzn0(J1PSNd0EZgKYwj8-9 z%4yCw$qdnG!s(a=M?j9Nu>;aV(3(@^K?5JiF*y;LnY|45y)VyiibjxWaw0NwdKGvG*!PqR1ENSC=gB5FA&85AvNX!=$hbT{YDE)2sl@bbjZJg zFZ3HGI0i{mV-lo=ptXLh1l=K@t1$vHTyQ|YdV&#G- z`ByCXvTmO->$!Z$YBlbKgzE?f>efcEFATX?jlUtZLC{Y(6g*7OztuPonj|R8(W}@O zECy9m!$^ftsRi5W)fKH52%2K3fscc>3I5V65Hto2V2YjrEf6Hl)@fEC_yAN(mBR&) z@M#O)73dTE#jJi9QgB$6_$&x@5yYqHgK7a3_a0?K%6ySGy1Soujz|B;;oC7jT z1(mPr@M<9NO;GV=mGDatJr}oN$sG02XV&--0>8tQJ_e&L0{k;qHUAt6w-UUbT8Xi+ zjB^647gH;Aj0ykDfQ?D0g$-adN`yN?DxuHBqX>Qj6+e;zqrnLQ_AgW??*#7CPh|+&KF7FJb zarp~;z3_C7JR)=Apc{X}O8T~$XmS^eYct)yal;xJH{ibACrVFN^Mg{P`v#1QaF@3; z{hxP9`RCCCE0%c)23~+CQ@vx!QRa>P3cUjRGp}4{dV~2OdZzJ{H?&6Yz=~hI;FkbB zb(nr%7|dG}9hSP2KHDdEFi0@(tub(EUPRXT3WmXWS$^J}_BEJCCocW5Yx$@`37=Fj zL=2viQ1EisT{SKxn8(NK*6iP_`JkaszC2|~R$&2UEH7h1Kggtl!mK4zUVie0LCt&h Kt64YBGz0*Se!AiS literal 0 HcmV?d00001 diff --git a/app/src/main/res/drawable-xxxhdpi/totoro.webp b/app/src/main/res/drawable-xxxhdpi/totoro.webp new file mode 100644 index 0000000000000000000000000000000000000000..4193ce397dbdc2b2cc3e3cc252c02694bbd02f7d GIT binary patch literal 5222 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 gQ!B&tRKK9`lnu#i=Wok@<4l8uCdHSV$ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/divider.xml b/app/src/main/res/drawable/divider.xml new file mode 100644 index 000000000..695880601 --- /dev/null +++ b/app/src/main/res/drawable/divider.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/gradient.xml b/app/src/main/res/drawable/gradient.xml new file mode 100644 index 000000000..f90e2ebb4 --- /dev/null +++ b/app/src/main/res/drawable/gradient.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_arrow_back.xml b/app/src/main/res/drawable/ic_arrow_back.xml new file mode 100644 index 000000000..2a31b2ef3 --- /dev/null +++ b/app/src/main/res/drawable/ic_arrow_back.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_book_page.xml b/app/src/main/res/drawable/ic_book_page.xml index e53b1da5c..375e7b424 100644 --- a/app/src/main/res/drawable/ic_book_page.xml +++ b/app/src/main/res/drawable/ic_book_page.xml @@ -1,11 +1,10 @@ - - - \ No newline at end of file + + + diff --git a/app/src/main/res/drawable/ic_clear.xml b/app/src/main/res/drawable/ic_clear.xml new file mode 100644 index 000000000..938bb9922 --- /dev/null +++ b/app/src/main/res/drawable/ic_clear.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_eye.xml b/app/src/main/res/drawable/ic_eye.xml index 52e210215..86a1ee448 100644 --- a/app/src/main/res/drawable/ic_eye.xml +++ b/app/src/main/res/drawable/ic_eye.xml @@ -1,12 +1,10 @@ - - - - \ No newline at end of file + + + diff --git a/app/src/main/res/drawable/ic_eye_off.xml b/app/src/main/res/drawable/ic_eye_off.xml index e558a36c4..33f8b6967 100644 --- a/app/src/main/res/drawable/ic_eye_off.xml +++ b/app/src/main/res/drawable/ic_eye_off.xml @@ -1,13 +1,10 @@ - - - - \ No newline at end of file + + + diff --git a/app/src/main/res/drawable/ic_lock.xml b/app/src/main/res/drawable/ic_lock.xml index 220e1b503..0781a7c4a 100644 --- a/app/src/main/res/drawable/ic_lock.xml +++ b/app/src/main/res/drawable/ic_lock.xml @@ -2,7 +2,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp" android:height="24dp" - android:tint="#FFFFFF" + android:tint="?attr/colorControlNormal" android:viewportWidth="24" android:viewportHeight="24"> + + diff --git a/app/src/main/res/drawable/ic_mic_none.xml b/app/src/main/res/drawable/ic_mic_none.xml new file mode 100644 index 000000000..2810bc9a2 --- /dev/null +++ b/app/src/main/res/drawable/ic_mic_none.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_person.xml b/app/src/main/res/drawable/ic_person.xml new file mode 100644 index 000000000..1b040f39f --- /dev/null +++ b/app/src/main/res/drawable/ic_person.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_settings.xml b/app/src/main/res/drawable/ic_settings.xml index 753697107..0d7a0a664 100644 --- a/app/src/main/res/drawable/ic_settings.xml +++ b/app/src/main/res/drawable/ic_settings.xml @@ -1,11 +1,10 @@ - - + + diff --git a/app/src/main/res/drawable/ic_share.xml b/app/src/main/res/drawable/ic_share.xml index 8ed8e7e87..6709b5625 100644 --- a/app/src/main/res/drawable/ic_share.xml +++ b/app/src/main/res/drawable/ic_share.xml @@ -1,5 +1,11 @@ - - + + diff --git a/app/src/main/res/drawable/ic_star.xml b/app/src/main/res/drawable/ic_star.xml new file mode 100644 index 000000000..0850e55fd --- /dev/null +++ b/app/src/main/res/drawable/ic_star.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/ic_star_manga_info.xml b/app/src/main/res/drawable/ic_star_manga_info.xml new file mode 100644 index 000000000..e4f9e867d --- /dev/null +++ b/app/src/main/res/drawable/ic_star_manga_info.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_web.xml b/app/src/main/res/drawable/ic_web.xml new file mode 100644 index 000000000..3f70646ba --- /dev/null +++ b/app/src/main/res/drawable/ic_web.xml @@ -0,0 +1,10 @@ + + + diff --git a/app/src/main/res/drawable/list_selector.xml b/app/src/main/res/drawable/list_selector.xml new file mode 100644 index 000000000..14508c152 --- /dev/null +++ b/app/src/main/res/drawable/list_selector.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/navigation_item_background.xml b/app/src/main/res/drawable/navigation_item_background.xml new file mode 100644 index 000000000..8c635e7a3 --- /dev/null +++ b/app/src/main/res/drawable/navigation_item_background.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/tab_indicator.xml b/app/src/main/res/drawable/tab_indicator.xml index 85211f67c..7f0ba0c38 100644 --- a/app/src/main/res/drawable/tab_indicator.xml +++ b/app/src/main/res/drawable/tab_indicator.xml @@ -4,6 +4,6 @@ android:shape="rectangle"> + android:topRightRadius="3dp"/> \ No newline at end of file diff --git a/app/src/main/res/drawable/tabs_background.xml b/app/src/main/res/drawable/tabs_background.xml index 6c1544f5f..d9df3de10 100644 --- a/app/src/main/res/drawable/tabs_background.xml +++ b/app/src/main/res/drawable/tabs_background.xml @@ -14,7 +14,7 @@ + android:color="@color/list_divider" /> \ No newline at end of file diff --git a/app/src/main/res/drawable/thumb.xml b/app/src/main/res/drawable/thumb.xml index 71e0a8113..8d1b235a1 100644 --- a/app/src/main/res/drawable/thumb.xml +++ b/app/src/main/res/drawable/thumb.xml @@ -9,6 +9,6 @@ android:paddingLeft="22dp" android:paddingRight="22dp" /> - + \ No newline at end of file diff --git a/app/src/main/res/layout-w600dp-land/fragment_details.xml b/app/src/main/res/layout-w600dp-land/fragment_details.xml new file mode 100644 index 000000000..c45f7b1c8 --- /dev/null +++ b/app/src/main/res/layout-w600dp-land/fragment_details.xml @@ -0,0 +1,295 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-w600dp-port/fragment_details.xml b/app/src/main/res/layout-w600dp-port/fragment_details.xml new file mode 100644 index 000000000..69630cb0a --- /dev/null +++ b/app/src/main/res/layout-w600dp-port/fragment_details.xml @@ -0,0 +1,303 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout-w600dp/activity_details.xml b/app/src/main/res/layout-w600dp/activity_details.xml index e5fc1b45a..af351d3aa 100644 --- a/app/src/main/res/layout-w600dp/activity_details.xml +++ b/app/src/main/res/layout-w600dp/activity_details.xml @@ -9,29 +9,27 @@ + app:elevation="0dp"> + app:layout_scrollFlags="scroll|enterAlways"> + app:tabGravity="center" + app:tabMode="fixed" /> diff --git a/app/src/main/res/layout-w600dp/activity_settings.xml b/app/src/main/res/layout-w600dp/activity_settings.xml index 8d031bc79..2a11422ce 100644 --- a/app/src/main/res/layout-w600dp/activity_settings.xml +++ b/app/src/main/res/layout-w600dp/activity_settings.xml @@ -13,15 +13,15 @@ app:layout_constraintTop_toTopOf="parent" android:layout_width="0dp" android:layout_height="wrap_content" - android:background="?colorPrimary" - android:theme="@style/AppToolbarTheme"> + app:elevation="0dp" + style="@style/Widget.Kotatsu.AppBar"> + style="@style/Widget.Kotatsu.Toolbar" /> diff --git a/app/src/main/res/layout-w600dp/fragment_details.xml b/app/src/main/res/layout-w600dp/fragment_details.xml deleted file mode 100644 index b224f5bc1..000000000 --- a/app/src/main/res/layout-w600dp/fragment_details.xml +++ /dev/null @@ -1,145 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_browser.xml b/app/src/main/res/layout/activity_browser.xml index 0c2add382..36b76f907 100644 --- a/app/src/main/res/layout/activity_browser.xml +++ b/app/src/main/res/layout/activity_browser.xml @@ -8,20 +8,20 @@ + app:layout_scrollFlags="scroll|enterAlways" /> diff --git a/app/src/main/res/layout/activity_categories.xml b/app/src/main/res/layout/activity_categories.xml index 57166010a..aa9a032e0 100644 --- a/app/src/main/res/layout/activity_categories.xml +++ b/app/src/main/res/layout/activity_categories.xml @@ -2,22 +2,22 @@ + android:layout_height="match_parent"> + app:elevation="0dp"> + android:layout_height="wrap_content" /> @@ -25,9 +25,9 @@ android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" + android:clipToPadding="false" android:orientation="vertical" android:scrollbars="vertical" - android:clipToPadding="false" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" /> @@ -36,13 +36,13 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" - android:gravity="center" - android:visibility="gone" - tools:visibility="visible" android:layout_margin="20dp" + android:gravity="center" + android:text="@string/text_categories_holder" android:textAppearance="?android:textAppearanceMedium" android:textColor="?android:textColorSecondary" - android:text="@string/text_categories_holder"/> + android:visibility="gone" + tools:visibility="visible" /> - + app:elevation="0dp"> + app:layout_scrollFlags="scroll|enterAlways" /> + app:tabGravity="fill" + app:tabMaxWidth="0dp" + app:tabMode="fixed" /> diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 62aee8a5f..e9506d317 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -6,8 +6,7 @@ android:id="@+id/drawer" android:layout_width="match_parent" android:layout_height="match_parent" - tools:context=".main.ui.MainActivity" - tools:openDrawer="start"> + tools:context=".main.ui.MainActivity"> + app:elevation="0dp"> @@ -54,7 +54,7 @@ + app:popupTheme="@style/ThemeOverlay.Kotatsu" /> @@ -50,7 +50,7 @@ android:layout_gravity="bottom" android:background="@color/dim" android:elevation="0dp" - android:theme="@style/AppToolbarTheme" + android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" app:elevation="0dp" tools:visibility="gone"> @@ -59,7 +59,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="top" - app:popupTheme="@style/AppPopupTheme" /> + app:popupTheme="@style/ThemeOverlay.Kotatsu" /> diff --git a/app/src/main/res/layout/activity_search.xml b/app/src/main/res/layout/activity_search.xml index a12c6daf6..7a7a4ab76 100644 --- a/app/src/main/res/layout/activity_search.xml +++ b/app/src/main/res/layout/activity_search.xml @@ -7,17 +7,17 @@ + app:elevation="0dp"> + app:layout_scrollFlags="scroll|enterAlways"> + app:elevation="0dp"> + app:layout_scrollFlags="scroll|enterAlways" /> diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml index 2fa97a72c..5c180d794 100644 --- a/app/src/main/res/layout/activity_settings.xml +++ b/app/src/main/res/layout/activity_settings.xml @@ -6,19 +6,19 @@ android:layout_height="match_parent" android:orientation="vertical"> - + app:elevation="0dp"> + app:layout_scrollFlags="scroll|enterAlways" /> diff --git a/app/src/main/res/layout/activity_settings_simple.xml b/app/src/main/res/layout/activity_settings_simple.xml index 4f6c56541..dd60a6ed2 100644 --- a/app/src/main/res/layout/activity_settings_simple.xml +++ b/app/src/main/res/layout/activity_settings_simple.xml @@ -7,17 +7,17 @@ + app:elevation="0dp"> + app:layout_scrollFlags="scroll|enterAlways" /> diff --git a/app/src/main/res/layout/dialog_input.xml b/app/src/main/res/layout/dialog_input.xml index 6c035d585..895bacb61 100644 --- a/app/src/main/res/layout/dialog_input.xml +++ b/app/src/main/res/layout/dialog_input.xml @@ -11,21 +11,16 @@ + android:layout_height="wrap_content"> diff --git a/app/src/main/res/layout/dialog_list_mode.xml b/app/src/main/res/layout/dialog_list_mode.xml index 01d5e426e..8fb04828e 100644 --- a/app/src/main/res/layout/dialog_list_mode.xml +++ b/app/src/main/res/layout/dialog_list_mode.xml @@ -18,7 +18,7 @@ + tools:listitem="@layout/item_branch" + tools:visibility="visible" /> + android:layout_height="match_parent" + android:scrollbars="vertical" + app:layout_behavior="@string/appbar_scrolling_view_behavior"> - - - - - - - - - - - - - - + android:layout_height="match_parent"> + + + + + + + + + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@id/guideline"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + app:layout_constraintTop_toBottomOf="@+id/buttons_layout" /> + + + tools:text="@tools:sample/lorem/random[25]" /> diff --git a/app/src/main/res/layout/fragment_reader_webtoon.xml b/app/src/main/res/layout/fragment_reader_webtoon.xml index ff906ec6e..bf60f0a5a 100644 --- a/app/src/main/res/layout/fragment_reader_webtoon.xml +++ b/app/src/main/res/layout/fragment_reader_webtoon.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/layout/item_header.xml b/app/src/main/res/layout/item_header.xml index 7031727d6..27b1c2c37 100644 --- a/app/src/main/res/layout/item_header.xml +++ b/app/src/main/res/layout/item_header.xml @@ -5,10 +5,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical|start" - android:paddingStart="?android:listPreferredItemPaddingStart" - android:paddingEnd="?android:listPreferredItemPaddingEnd" - android:minHeight="@dimen/header_height" + android:paddingStart="4dp" + android:paddingEnd="4dp" android:singleLine="true" + android:textAllCaps="true" android:textAppearance="@style/TextAppearance.MaterialComponents.Body2" android:textColor="?android:textColorSecondary" android:textStyle="bold" diff --git a/app/src/main/res/layout/item_manga_grid.xml b/app/src/main/res/layout/item_manga_grid.xml index 9727f3b88..6a168ea68 100644 --- a/app/src/main/res/layout/item_manga_grid.xml +++ b/app/src/main/res/layout/item_manga_grid.xml @@ -1,38 +1,50 @@ - + android:background="@drawable/list_selector"> - + - + android:layout_margin="4dp" + app:cardCornerRadius="4dp" + app:cardElevation="4dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> + + + + + android:lineSpacingExtra="-2dp" + android:maxLines="2" + android:padding="4dp" + android:textStyle="bold" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/card" + tools:text="Sample name" /> - + - - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_manga_list.xml b/app/src/main/res/layout/item_manga_list.xml index f6d964cdc..6a12cd8a3 100644 --- a/app/src/main/res/layout/item_manga_list.xml +++ b/app/src/main/res/layout/item_manga_list.xml @@ -1,24 +1,37 @@ - + android:layout_height="wrap_content" + android:layout_margin="4dp" + app:cardCornerRadius="4dp" + app:cardElevation="4dp"> + + + + + android:maxLines="1" + android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" + tools:text="@tools:sample/lorem/random" /> + android:textColor="?android:textColorSecondary" + tools:text="@tools:sample/lorem/random" /> diff --git a/app/src/main/res/layout/item_manga_list_details.xml b/app/src/main/res/layout/item_manga_list_details.xml index 7257473f2..11ebedae3 100644 --- a/app/src/main/res/layout/item_manga_list_details.xml +++ b/app/src/main/res/layout/item_manga_list_details.xml @@ -1,96 +1,91 @@ - + android:background="@drawable/list_selector" + android:orientation="horizontal"> - + android:layout_height="wrap_content" + android:layout_margin="4dp" + app:cardElevation="4dp"> + + + + + android:textAppearance="@style/TextAppearance.Kotatsu.ToolbarTitle" + android:textSize="18sp" + tools:text="@tools:sample/lorem/random" /> - - - - + android:layout_height="wrap_content" + android:layout_marginBottom="4dp" + android:ellipsize="none" + android:gravity="center_vertical" + android:requiresFadingEdge="horizontal" + android:singleLine="true" + android:textSize="16sp" + tools:text="@tools:sample/lorem/random" /> + android:orientation="horizontal"> + android:singleLine="true" + tools:text="@tools:sample/lorem/random" /> + android:paddingStart="6dp" + app:drawableEndCompat="@drawable/ic_star" + tools:text="9.6" /> @@ -98,4 +93,4 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_page_webtoon.xml b/app/src/main/res/layout/item_page_webtoon.xml index f032e1819..32afcd4f4 100644 --- a/app/src/main/res/layout/item_page_webtoon.xml +++ b/app/src/main/res/layout/item_page_webtoon.xml @@ -1,18 +1,18 @@ - - + app:zoomEnabled="false" /> + app:drawableTopCompat="@drawable/ic_error_large" + tools:text="@tools:sample/lorem[6]" /> - \ No newline at end of file + \ No newline at end of file diff --git a/app/src/main/res/layout/item_search_complete.xml b/app/src/main/res/layout/item_search_complete.xml index 6bb124b06..d0ecbdc80 100644 --- a/app/src/main/res/layout/item_search_complete.xml +++ b/app/src/main/res/layout/item_search_complete.xml @@ -12,6 +12,6 @@ android:paddingEnd="?listPreferredItemPaddingEnd" android:textAppearance="?textAppearanceListItemSmall" android:textColor="?android:textColorPrimary" - android:theme="@style/AppPopupTheme" - tools:text="@tools:sample/full_names" - app:drawableStartCompat="@drawable/ic_history" /> \ No newline at end of file + android:theme="@style/ThemeOverlay.Kotatsu" + app:drawableStartCompat="@drawable/ic_history" + tools:text="@tools:sample/full_names" /> \ No newline at end of file diff --git a/app/src/main/res/layout/item_tracklog.xml b/app/src/main/res/layout/item_tracklog.xml index d99dc5f14..38766f184 100644 --- a/app/src/main/res/layout/item_tracklog.xml +++ b/app/src/main/res/layout/item_tracklog.xml @@ -1,75 +1,83 @@ - + android:layout_height="wrap_content" + android:background="?attr/selectableItemBackground" + android:paddingEnd="16dp"> - + - + android:scaleType="centerCrop" + tools:src="@tools:sample/backgrounds/scenic" /> + + + + - - - - + android:textAppearance="@style/TextAppearance.MaterialComponents.Body1" + tools:text="@tools:sample/lorem" /> + android:layout_gravity="center" + android:background="@drawable/badge" + android:paddingHorizontal="6dp" + android:paddingVertical="2dp" + android:textColor="@android:color/white" + android:textSize="12sp" + android:textStyle="bold" + tools:text="54" /> - + - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_search_view.xml b/app/src/main/res/layout/layout_search_view.xml new file mode 100644 index 000000000..7686f1813 --- /dev/null +++ b/app/src/main/res/layout/layout_search_view.xml @@ -0,0 +1,113 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/navigation_header.xml b/app/src/main/res/layout/navigation_header.xml new file mode 100644 index 000000000..9c82c3288 --- /dev/null +++ b/app/src/main/res/layout/navigation_header.xml @@ -0,0 +1,25 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-be/strings.xml b/app/src/main/res/values-be/strings.xml index 926f62a66..c846e8b74 100644 --- a/app/src/main/res/values-be/strings.xml +++ b/app/src/main/res/values-be/strings.xml @@ -194,7 +194,7 @@ Прайсці Ачысціць кукi Усе кукi выдалены - Праверка новых частак: %1$d з %2$d + Праверка новых частак: %1$d з %2$d Ачысціць стужку Уся гісторыя абнаўленняў будзе ачышчана і яе нельга будзе вярнуць. Вы ўпэўненыя? Праверка новых частак @@ -208,4 +208,7 @@ Пацвярджаць Пароль павінен змяшчаць не менш за 4 сімвалаў Схаваць загаловак пры прагортцы + Пошук толькі па %s + Вы сапраўды хочаце выдаліць усе апошнія пошукавыя запыты? Гэта дзеянне не можа быць адменена. + Апісанне \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 8786b537d..819baa8e0 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -193,7 +193,7 @@ Resolver Borrar cookies Se han eliminado todas las cookies - Buscando nuevos capítulos: %1$d de %2$d + Buscando nuevos capítulos: %1$d de %2$d Limpiar feed Todo el historial de actualizaciones se borrará y esta acción no se puede deshacer. ¿Está seguro? Comprobación de nuevos capítulos diff --git a/app/src/main/res/values-night/colors.xml b/app/src/main/res/values-night/colors.xml index 7a2753729..957cea79b 100644 --- a/app/src/main/res/values-night/colors.xml +++ b/app/src/main/res/values-night/colors.xml @@ -1,10 +1,23 @@ - #1976D2 - #0D47A1 - #1A237E - #FF8A65 - #99000000 - #E57373 - #5E636A + #1976D2 + #1565C0 + #E57373 + @android:color/black + + #2EFFFFFF + #2a2b2e + + + #2EFFFFFF + #B3000000 + + + @android:color/transparent + + + #263238 + #1fffffff + + 0.27 \ No newline at end of file diff --git a/app/src/main/res/values-night/styles.xml b/app/src/main/res/values-night/styles.xml deleted file mode 100644 index 65256236f..000000000 --- a/app/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index d839f3aac..e4fc0c120 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -1,8 +1,13 @@ - + + + \ No newline at end of file diff --git a/app/src/main/res/values-notnight-v23/bools.xml b/app/src/main/res/values-notnight-v23/bools.xml new file mode 100644 index 000000000..3610539ef --- /dev/null +++ b/app/src/main/res/values-notnight-v23/bools.xml @@ -0,0 +1,4 @@ + + + true + \ No newline at end of file diff --git a/app/src/main/res/values-notnight-v23/colors.xml b/app/src/main/res/values-notnight-v23/colors.xml new file mode 100644 index 000000000..ef3e00027 --- /dev/null +++ b/app/src/main/res/values-notnight-v23/colors.xml @@ -0,0 +1,5 @@ + + + + @color/system_ui_scrim_light + \ No newline at end of file diff --git a/app/src/main/res/values-notnight-v27/bools.xml b/app/src/main/res/values-notnight-v27/bools.xml new file mode 100644 index 000000000..2ee1ed1bf --- /dev/null +++ b/app/src/main/res/values-notnight-v27/bools.xml @@ -0,0 +1,4 @@ + + + true + \ No newline at end of file diff --git a/app/src/main/res/values-notnight-v27/colors.xml b/app/src/main/res/values-notnight-v27/colors.xml new file mode 100644 index 000000000..8e4e067bf --- /dev/null +++ b/app/src/main/res/values-notnight-v27/colors.xml @@ -0,0 +1,5 @@ + + + + @color/system_ui_scrim_light + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index b20c30211..f3887596f 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -24,7 +24,7 @@ Читать Добавить закладку Добавьте интересующую Вас мангу в избренное, чтобы не потерять её - Добавить в избранное + В избранное Создать категорию Добавить Введите название @@ -192,7 +192,7 @@ Пройти Очистить куки Все куки удалены - Проверка новых глав: %1$d из %2$d + Проверка новых глав: %1$d из %2$d Очистить ленту Вся история обновлений будет очищена и её нельзя будет вернуть. Вы уверены? Проверка новых глав @@ -207,4 +207,6 @@ Пароль должен содержать не менее 4 символов Прятать заголовок при прокрутке Поиск только по %s + Описание + Вы действительно хотите удалить все последние поисковые запросы? Это действие не может быть отменено. \ No newline at end of file diff --git a/app/src/main/res/values-v23/themes.xml b/app/src/main/res/values-v23/themes.xml new file mode 100644 index 000000000..0955e00db --- /dev/null +++ b/app/src/main/res/values-v23/themes.xml @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-v29/themes.xml b/app/src/main/res/values-v29/themes.xml index b8b075c5d..4ae0ef5db 100644 --- a/app/src/main/res/values-v29/themes.xml +++ b/app/src/main/res/values-v29/themes.xml @@ -1,15 +1,10 @@ - + \ No newline at end of file diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml index 442ae059a..044349fc7 100644 --- a/app/src/main/res/values-w600dp/dimens.xml +++ b/app/src/main/res/values-w600dp/dimens.xml @@ -1,6 +1,6 @@ - 4dp + 6dp 2dp 140dp \ No newline at end of file diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 4c8767415..8d2f3f480 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -1,6 +1,59 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/bools.xml b/app/src/main/res/values/bools.xml index 07aafe1c4..735d84e13 100644 --- a/app/src/main/res/values/bools.xml +++ b/app/src/main/res/values/bools.xml @@ -1,4 +1,6 @@ false + false + false \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 5d1c1d8ba..77bb1b4d4 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -1,5 +1,40 @@ + + #1976D2 + #1565C0 + #EF5350 + @android:color/white + + #39000000 + #F8F9FA + + + #B3FFFFFF + #40000000 + + + @color/system_ui_scrim_black + + @color/system_ui_scrim_black + + + #e8f0fe + @color/event_card_header_background_light + #1f000000> + + + #999 + #e6e6e6 + #33000000 + + #f8f9fa + #252729 + + 0.18 + + + #1976D2 #1565C0 #283593 @@ -10,4 +45,6 @@ #D32F2F #33000000 #C3CFDD + #99000000 + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index ee61388a6..ebeb00c0d 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,8 +1,31 @@ - 2.5dp + + + 16dp + 8dp + 32dp + + + 8dp + 24dp + 36dp + + + @dimen/match_parent + 32dp + 36dp + 24dp + + 0dp + 100dp + 0dp + 8dp> + + 6dp + 6dp 2dp - 84dp + 78dp 120dp 46dp 120dp @@ -10,4 +33,28 @@ 16dp 48dp 16dp + + + + 16dp + 16sp + 48dp + 56dp + 1dp + 1dp + 0dp + 48dp + 56dp + 8dp + 0dp + 3dp + 0dp + 16dp + 8dp + 0dp + + + -1 + -2 + \ No newline at end of file diff --git a/app/src/main/res/values/integers.xml b/app/src/main/res/values/integers.xml new file mode 100644 index 000000000..5532e13df --- /dev/null +++ b/app/src/main/res/values/integers.xml @@ -0,0 +1,6 @@ + + + + @android:integer/config_shortAnimTime + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 64fb9d0bc..f18633f5d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -194,7 +194,7 @@ Solve Clear cookies All cookies was removed - Checking for new chapters: %1$d of %2$d + Checking for new chapters: %1$d of %2$d Clear feed All updates history will be cleared and this action cannot be undone. Are you sure? New chapters checking @@ -210,4 +210,5 @@ Hide toolbar when scrolling Search only on %s Do you really want to remove all recent search queries? This action cannot be undone. + Description \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 161614112..9e1bc7b0c 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -1,6 +1,52 @@ - + - + + + + + + + + + + - - - - - - + + + + + - + + + + + + -