mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-24 05:38:01 +03:00
Add pin icon to sources list (closes #2862)
This commit is contained in:
parent
2dc47352f8
commit
a52fbb012a
8 changed files with 84 additions and 29 deletions
|
@ -22,26 +22,15 @@ class SourceAdapter(val controller: SourceController) :
|
||||||
/**
|
/**
|
||||||
* Listener for browse item clicks.
|
* Listener for browse item clicks.
|
||||||
*/
|
*/
|
||||||
val browseClickListener: OnBrowseClickListener = controller
|
val clickListener: OnSourceClickListener = controller
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener for latest item clicks.
|
|
||||||
*/
|
|
||||||
val latestClickListener: OnLatestClickListener = controller
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener which should be called when user clicks browse.
|
* Listener which should be called when user clicks browse.
|
||||||
* Note: Should only be handled by [SourceController]
|
* Note: Should only be handled by [SourceController]
|
||||||
*/
|
*/
|
||||||
interface OnBrowseClickListener {
|
interface OnSourceClickListener {
|
||||||
fun onBrowseClick(position: Int)
|
fun onBrowseClick(position: Int)
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener which should be called when user clicks latest.
|
|
||||||
* Note: Should only be handled by [SourceController]
|
|
||||||
*/
|
|
||||||
interface OnLatestClickListener {
|
|
||||||
fun onLatestClick(position: Int)
|
fun onLatestClick(position: Int)
|
||||||
|
fun onPinClick(position: Int)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,15 +41,14 @@ import uy.kohesive.injekt.api.get
|
||||||
/**
|
/**
|
||||||
* This controller shows and manages the different catalogues enabled by the user.
|
* This controller shows and manages the different catalogues enabled by the user.
|
||||||
* This controller should only handle UI actions, IO actions should be done by [SourcePresenter]
|
* This controller should only handle UI actions, IO actions should be done by [SourcePresenter]
|
||||||
* [SourceAdapter.OnBrowseClickListener] call function data on browse item click.
|
* [SourceAdapter.OnSourceClickListener] call function data on browse item click.
|
||||||
* [SourceAdapter.OnLatestClickListener] call function data on latest item click
|
* [SourceAdapter.OnLatestClickListener] call function data on latest item click
|
||||||
*/
|
*/
|
||||||
class SourceController :
|
class SourceController :
|
||||||
NucleusController<SourceMainControllerBinding, SourcePresenter>(),
|
NucleusController<SourceMainControllerBinding, SourcePresenter>(),
|
||||||
FlexibleAdapter.OnItemClickListener,
|
FlexibleAdapter.OnItemClickListener,
|
||||||
FlexibleAdapter.OnItemLongClickListener,
|
FlexibleAdapter.OnItemLongClickListener,
|
||||||
SourceAdapter.OnBrowseClickListener,
|
SourceAdapter.OnSourceClickListener {
|
||||||
SourceAdapter.OnLatestClickListener {
|
|
||||||
|
|
||||||
private val preferences: PreferencesHelper = Injekt.get()
|
private val preferences: PreferencesHelper = Injekt.get()
|
||||||
|
|
||||||
|
@ -134,7 +133,7 @@ class SourceController :
|
||||||
val items = mutableListOf(
|
val items = mutableListOf(
|
||||||
Pair(
|
Pair(
|
||||||
activity.getString(if (isPinned) R.string.action_unpin else R.string.action_pin),
|
activity.getString(if (isPinned) R.string.action_unpin else R.string.action_pin),
|
||||||
{ pinSource(item.source, isPinned) }
|
{ toggleSourcePin(item.source) }
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if (item.source !is LocalSource) {
|
if (item.source !is LocalSource) {
|
||||||
|
@ -159,12 +158,12 @@ class SourceController :
|
||||||
presenter.updateSources()
|
presenter.updateSources()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun pinSource(source: Source, isPinned: Boolean) {
|
private fun toggleSourcePin(source: Source) {
|
||||||
val current = preferences.pinnedSources().get()
|
val isPinned = source.id.toString() in preferences.pinnedSources().get()
|
||||||
if (isPinned) {
|
if (isPinned) {
|
||||||
preferences.pinnedSources().set(current - source.id.toString())
|
preferences.pinnedSources() -= source.id.toString()
|
||||||
} else {
|
} else {
|
||||||
preferences.pinnedSources().set(current + source.id.toString())
|
preferences.pinnedSources() += source.id.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
presenter.updateSources()
|
presenter.updateSources()
|
||||||
|
@ -185,6 +184,14 @@ class SourceController :
|
||||||
openSource(item.source, LatestUpdatesController(item.source))
|
openSource(item.source, LatestUpdatesController(item.source))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when pin icon is clicked in [SourceAdapter]
|
||||||
|
*/
|
||||||
|
override fun onPinClick(position: Int) {
|
||||||
|
val item = adapter?.getItem(position) as? SourceItem ?: return
|
||||||
|
toggleSourcePin(item.source)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a catalogue with the given controller.
|
* Opens a catalogue with the given controller.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.ui.base.holder.SlicedHolder
|
||||||
import io.github.mthli.slice.Slice
|
import io.github.mthli.slice.Slice
|
||||||
import kotlinx.android.synthetic.main.source_main_controller_card_item.card
|
import kotlinx.android.synthetic.main.source_main_controller_card_item.card
|
||||||
import kotlinx.android.synthetic.main.source_main_controller_card_item.image
|
import kotlinx.android.synthetic.main.source_main_controller_card_item.image
|
||||||
|
import kotlinx.android.synthetic.main.source_main_controller_card_item.pin
|
||||||
import kotlinx.android.synthetic.main.source_main_controller_card_item.source_browse
|
import kotlinx.android.synthetic.main.source_main_controller_card_item.source_browse
|
||||||
import kotlinx.android.synthetic.main.source_main_controller_card_item.source_latest
|
import kotlinx.android.synthetic.main.source_main_controller_card_item.source_latest
|
||||||
import kotlinx.android.synthetic.main.source_main_controller_card_item.title
|
import kotlinx.android.synthetic.main.source_main_controller_card_item.title
|
||||||
|
@ -27,11 +28,15 @@ class SourceHolder(view: View, override val adapter: SourceAdapter) :
|
||||||
|
|
||||||
init {
|
init {
|
||||||
source_browse.setOnClickListener {
|
source_browse.setOnClickListener {
|
||||||
adapter.browseClickListener.onBrowseClick(bindingAdapterPosition)
|
adapter.clickListener.onBrowseClick(bindingAdapterPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
source_latest.setOnClickListener {
|
source_latest.setOnClickListener {
|
||||||
adapter.latestClickListener.onLatestClick(bindingAdapterPosition)
|
adapter.clickListener.onLatestClick(bindingAdapterPosition)
|
||||||
|
}
|
||||||
|
|
||||||
|
pin.setOnClickListener {
|
||||||
|
adapter.clickListener.onPinClick(bindingAdapterPosition)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,5 +58,14 @@ class SourceHolder(view: View, override val adapter: SourceAdapter) :
|
||||||
|
|
||||||
source_browse.setText(R.string.browse)
|
source_browse.setText(R.string.browse)
|
||||||
source_latest.isVisible = source.supportsLatest
|
source_latest.isVisible = source.supportsLatest
|
||||||
|
|
||||||
|
pin.isVisible = true
|
||||||
|
pin.setImageResource(
|
||||||
|
if (item.isPinned) {
|
||||||
|
R.drawable.ic_push_pin_filled_24dp
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_push_pin_24dp
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,11 @@ import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
* @param source Instance of [CatalogueSource] containing source information.
|
* @param source Instance of [CatalogueSource] containing source information.
|
||||||
* @param header The header for this item.
|
* @param header The header for this item.
|
||||||
*/
|
*/
|
||||||
data class SourceItem(val source: CatalogueSource, val header: LangItem? = null) :
|
data class SourceItem(
|
||||||
|
val source: CatalogueSource,
|
||||||
|
val header: LangItem? = null,
|
||||||
|
val isPinned: Boolean = false
|
||||||
|
) :
|
||||||
AbstractSectionableItem<SourceHolder, LangItem>(header) {
|
AbstractSectionableItem<SourceHolder, LangItem>(header) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -72,11 +72,12 @@ class SourcePresenter(
|
||||||
var sourceItems = byLang.flatMap {
|
var sourceItems = byLang.flatMap {
|
||||||
val langItem = LangItem(it.key)
|
val langItem = LangItem(it.key)
|
||||||
it.value.map { source ->
|
it.value.map { source ->
|
||||||
if (source.id.toString() in pinnedSourceIds) {
|
val isPinned = source.id.toString() in pinnedSourceIds
|
||||||
pinnedSources.add(SourceItem(source, LangItem(PINNED_KEY)))
|
if (isPinned) {
|
||||||
|
pinnedSources.add(SourceItem(source, LangItem(PINNED_KEY), isPinned))
|
||||||
}
|
}
|
||||||
|
|
||||||
SourceItem(source, langItem)
|
SourceItem(source, langItem, isPinned)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
app/src/main/res/drawable/ic_push_pin_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_push_pin_24dp.xml
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:pathData="M14,4v5c0,1.12 0.37,2.16 1,3H9c0.65,-0.86 1,-1.9 1,-3V4H14M17,2H7C6.45,2 6,2.45 6,3c0,0.55 0.45,1 1,1c0,0 0,0 0,0l1,0v5c0,1.66 -1.34,3 -3,3v2h5.97v7l1,1l1,-1v-7H19v-2c0,0 0,0 0,0c-1.66,0 -3,-1.34 -3,-3V4l1,0c0,0 0,0 0,0c0.55,0 1,-0.45 1,-1C18,2.45 17.55,2 17,2L17,2z" />
|
||||||
|
</vector>
|
10
app/src/main/res/drawable/ic_push_pin_filled_24dp.xml
Normal file
10
app/src/main/res/drawable/ic_push_pin_filled_24dp.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#FF000000"
|
||||||
|
android:fillType="evenOdd"
|
||||||
|
android:pathData="M16,9V4l1,0c0.55,0 1,-0.45 1,-1v0c0,-0.55 -0.45,-1 -1,-1H7C6.45,2 6,2.45 6,3v0c0,0.55 0.45,1 1,1l1,0v5c0,1.66 -1.34,3 -3,3h0v2h5.97v7l1,1l1,-1v-7H19v-2h0C17.34,12 16,10.66 16,9z" />
|
||||||
|
</vector>
|
|
@ -20,6 +20,7 @@
|
||||||
app:layout_constraintDimensionRatio="1:1"
|
app:layout_constraintDimensionRatio="1:1"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
tools:src="@mipmap/ic_launcher_round" />
|
tools:src="@mipmap/ic_launcher_round" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -43,7 +44,10 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:maxHeight="48dp"
|
android:maxHeight="48dp"
|
||||||
|
android:minWidth="0dp"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
android:text="@string/latest"
|
android:text="@string/latest"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/source_browse"
|
app:layout_constraintEnd_toStartOf="@+id/source_browse"
|
||||||
|
@ -55,12 +59,29 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:maxHeight="48dp"
|
android:maxHeight="48dp"
|
||||||
|
android:minWidth="0dp"
|
||||||
android:minHeight="48dp"
|
android:minHeight="48dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
android:text="@string/browse"
|
android:text="@string/browse"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toStartOf="@+id/pin"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/pin"
|
||||||
|
android:layout_width="44dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:alpha="0.75"
|
||||||
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
|
android:contentDescription="@string/action_pin"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:srcCompat="@drawable/ic_push_pin_24dp"
|
||||||
|
app:tint="?attr/colorOnSurface" />
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
Loading…
Reference in a new issue