mirror of
https://github.com/apognu/otter
synced 2025-02-15 02:10:35 +01:00
Implement home screen item cache and actions system. First action when clicking on artist.
This commit is contained in:
parent
21a545d70a
commit
73ab61e64b
@ -6,21 +6,39 @@ import android.view.View
|
|||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.github.apognu.otter.R
|
import com.github.apognu.otter.R
|
||||||
|
import com.github.apognu.otter.fragments.HomeFragment
|
||||||
|
import com.github.apognu.otter.utils.Artist
|
||||||
import com.github.apognu.otter.utils.mustNormalizeUrl
|
import com.github.apognu.otter.utils.mustNormalizeUrl
|
||||||
import com.squareup.picasso.Picasso
|
import com.squareup.picasso.Picasso
|
||||||
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
|
import jp.wasabeef.picasso.transformations.RoundedCornersTransformation
|
||||||
import kotlinx.android.synthetic.main.row_home_media.view.*
|
import kotlinx.android.synthetic.main.row_home_media.view.*
|
||||||
|
|
||||||
class HomeMediaAdapter(val context: Context?, val viewRes: Int = R.layout.row_home_media) : RecyclerView.Adapter<HomeMediaAdapter.ViewHolder>() {
|
class HomeMediaAdapter(
|
||||||
data class HomeMediaItem(val label: String, val cover: String?)
|
private val context: Context?,
|
||||||
|
private val kind: ItemType,
|
||||||
|
private val viewRes: Int = R.layout.row_home_media,
|
||||||
|
private val listener: HomeFragment.OnHomeClickListener? = null
|
||||||
|
) : RecyclerView.Adapter<HomeMediaAdapter.ViewHolder>() {
|
||||||
|
|
||||||
|
enum class ItemType {
|
||||||
|
Tag, Artist, Album, Track
|
||||||
|
}
|
||||||
|
|
||||||
|
data class HomeMediaItem(
|
||||||
|
val label: String,
|
||||||
|
val cover: String?,
|
||||||
|
val artist: Artist? = null
|
||||||
|
)
|
||||||
|
|
||||||
var data: List<HomeMediaItem> = listOf()
|
var data: List<HomeMediaItem> = listOf()
|
||||||
|
|
||||||
override fun getItemCount() = data.size
|
override fun getItemCount() = data.size
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
|
||||||
return LayoutInflater.from(context).inflate(viewRes, parent, false).run {
|
val view = LayoutInflater.from(context).inflate(viewRes, parent, false)
|
||||||
ViewHolder(this)
|
|
||||||
|
return ViewHolder(view).also {
|
||||||
|
view.setOnClickListener(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,8 +58,14 @@ class HomeMediaAdapter(val context: Context?, val viewRes: Int = R.layout.row_ho
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
|
inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view), View.OnClickListener {
|
||||||
val label = view.label
|
val label = view.label
|
||||||
val cover = view.cover
|
val cover = view.cover
|
||||||
|
|
||||||
|
override fun onClick(view: View?) {
|
||||||
|
when {
|
||||||
|
kind == ItemType.Artist -> listener?.onClick(artist = data[layoutPosition].artist)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,39 +8,75 @@ import androidx.fragment.app.Fragment
|
|||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import com.github.apognu.otter.R
|
import com.github.apognu.otter.R
|
||||||
import com.github.apognu.otter.adapters.home.HomeMediaAdapter
|
import com.github.apognu.otter.adapters.home.HomeMediaAdapter
|
||||||
|
import com.github.apognu.otter.adapters.home.HomeMediaAdapter.ItemType
|
||||||
import com.github.apognu.otter.repositories.Repository
|
import com.github.apognu.otter.repositories.Repository
|
||||||
|
import com.github.apognu.otter.repositories.home.RandomArtistsRepository
|
||||||
import com.github.apognu.otter.repositories.home.RecentlyAddedRepository
|
import com.github.apognu.otter.repositories.home.RecentlyAddedRepository
|
||||||
import com.github.apognu.otter.repositories.home.RecentlyListenedRepository
|
import com.github.apognu.otter.repositories.home.RecentlyListenedRepository
|
||||||
import com.github.apognu.otter.repositories.home.TagsRepository
|
import com.github.apognu.otter.repositories.home.TagsRepository
|
||||||
import com.github.apognu.otter.utils.untilNetwork
|
import com.github.apognu.otter.utils.*
|
||||||
import com.google.android.flexbox.FlexboxLayoutManager
|
import com.google.android.flexbox.FlexboxLayoutManager
|
||||||
|
import com.google.android.flexbox.JustifyContent
|
||||||
|
import com.google.gson.Gson
|
||||||
import kotlinx.android.synthetic.main.fragment_home.*
|
import kotlinx.android.synthetic.main.fragment_home.*
|
||||||
import kotlinx.coroutines.Dispatchers.IO
|
import kotlinx.coroutines.Dispatchers.IO
|
||||||
import kotlinx.coroutines.Dispatchers.Main
|
import kotlinx.coroutines.Dispatchers.Main
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
|
import kotlinx.coroutines.Job
|
||||||
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
class HomeFragment : Fragment() {
|
class HomeFragment : Fragment() {
|
||||||
|
interface OnHomeClickListener {
|
||||||
|
fun onClick(artist: Artist? = null, album: Album? = null, track: Track? = null)
|
||||||
|
}
|
||||||
|
|
||||||
|
val CACHE_DURATION = 15 * 60 * 1000
|
||||||
|
|
||||||
|
private var bus: Job? = null
|
||||||
|
|
||||||
private lateinit var tagsRepository: TagsRepository
|
private lateinit var tagsRepository: TagsRepository
|
||||||
|
private lateinit var randomArtistsRepository: RandomArtistsRepository
|
||||||
private lateinit var recentlyAddedRepository: RecentlyAddedRepository
|
private lateinit var recentlyAddedRepository: RecentlyAddedRepository
|
||||||
private lateinit var recentlyListenedRepository: RecentlyListenedRepository
|
private lateinit var recentlyListenedRepository: RecentlyListenedRepository
|
||||||
|
|
||||||
private lateinit var tagsAdapter: HomeMediaAdapter
|
private lateinit var tagsAdapter: HomeMediaAdapter
|
||||||
|
private lateinit var randomAdapter: HomeMediaAdapter
|
||||||
private lateinit var recentlyAddedAdapter: HomeMediaAdapter
|
private lateinit var recentlyAddedAdapter: HomeMediaAdapter
|
||||||
private lateinit var recentlyListenedAdapter: HomeMediaAdapter
|
private lateinit var recentlyListenedAdapter: HomeMediaAdapter
|
||||||
private lateinit var randomAdapter: HomeMediaAdapter
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
tagsRepository = TagsRepository(context)
|
tagsRepository = TagsRepository(context)
|
||||||
|
randomArtistsRepository = RandomArtistsRepository(context)
|
||||||
recentlyAddedRepository = RecentlyAddedRepository(context)
|
recentlyAddedRepository = RecentlyAddedRepository(context)
|
||||||
recentlyListenedRepository = RecentlyListenedRepository(context)
|
recentlyListenedRepository = RecentlyListenedRepository(context)
|
||||||
|
|
||||||
tagsAdapter = HomeMediaAdapter(context, R.layout.row_tag)
|
tagsAdapter = HomeMediaAdapter(context, ItemType.Tag, R.layout.row_tag)
|
||||||
recentlyAddedAdapter = HomeMediaAdapter(context)
|
randomAdapter = HomeMediaAdapter(context, ItemType.Artist, listener = ArtistClickListener())
|
||||||
recentlyListenedAdapter = HomeMediaAdapter(context)
|
recentlyAddedAdapter = HomeMediaAdapter(context, ItemType.Track)
|
||||||
randomAdapter = HomeMediaAdapter(context)
|
recentlyListenedAdapter = HomeMediaAdapter(context, ItemType.Track)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onResume() {
|
||||||
|
super.onResume()
|
||||||
|
|
||||||
|
bus = GlobalScope.launch(IO) {
|
||||||
|
EventBus.get().collect { event ->
|
||||||
|
if (event is Event.ListingsChanged) {
|
||||||
|
refresh(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onPause() {
|
||||||
|
super.onPause()
|
||||||
|
|
||||||
|
bus?.cancel()
|
||||||
|
bus = null
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
||||||
@ -51,9 +87,11 @@ class HomeFragment : Fragment() {
|
|||||||
super.onViewCreated(view, savedInstanceState)
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
|
||||||
tags.apply {
|
tags.apply {
|
||||||
|
isNestedScrollingEnabled = false
|
||||||
|
|
||||||
adapter = tagsAdapter
|
adapter = tagsAdapter
|
||||||
layoutManager = FlexboxLayoutManager(context).apply {
|
layoutManager = FlexboxLayoutManager(context).apply {
|
||||||
isNestedScrollingEnabled = false
|
justifyContent = JustifyContent.SPACE_BETWEEN
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,34 +113,89 @@ class HomeFragment : Fragment() {
|
|||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun refresh() {
|
private fun originFor(repository: Repository<*, *>, force: Boolean = false): Repository.Origin {
|
||||||
tagsRepository.fetch(Repository.Origin.Network.origin).untilNetwork(IO) {data, _, _ ->
|
if (force) return Repository.Origin.Network
|
||||||
|
|
||||||
|
repository.cacheId?.let { cacheId ->
|
||||||
|
repository.cache(listOf())?.let {
|
||||||
|
Cache.get(context, "$cacheId-at")?.readLine()?.toLong()?.let { date ->
|
||||||
|
return if ((Date().time - date) < CACHE_DURATION) Repository.Origin.Cache
|
||||||
|
else Repository.Origin.Network
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Repository.Origin.Network
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T: Any> cache(repository: Repository<T, *>, data: List<T>) {
|
||||||
|
repository.cacheId?.let { cacheId ->
|
||||||
|
repository.cache(data)?.let { cache ->
|
||||||
|
Cache.set(
|
||||||
|
context,
|
||||||
|
cacheId,
|
||||||
|
Gson().toJson(cache).toByteArray()
|
||||||
|
)
|
||||||
|
|
||||||
|
Cache.set(context, "$cacheId-at", Date().time.toString().toByteArray())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun refresh(force: Boolean = false) {
|
||||||
|
tagsRepository.fetch(originFor(tagsRepository, force).origin).untilNetwork(IO) { data, isCache, _ ->
|
||||||
GlobalScope.launch(Main) {
|
GlobalScope.launch(Main) {
|
||||||
tagsAdapter.data = data.map { HomeMediaAdapter.HomeMediaItem(it.name, null) }
|
tagsAdapter.data = data.map { HomeMediaAdapter.HomeMediaItem(it.name, null) }
|
||||||
tagsAdapter.notifyDataSetChanged()
|
tagsAdapter.notifyDataSetChanged()
|
||||||
|
|
||||||
tags_loader.visibility = View.GONE
|
tags_loader?.visibility = View.GONE
|
||||||
tags.visibility = View.VISIBLE
|
tags?.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
if (!isCache) cache(tagsRepository, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recentlyListenedRepository.fetch(Repository.Origin.Network.origin).untilNetwork(IO) { data, _, _ ->
|
randomArtistsRepository.fetch(originFor(randomArtistsRepository, force).origin).untilNetwork(IO) { data, isCache, _ ->
|
||||||
|
GlobalScope.launch(Main) {
|
||||||
|
randomAdapter.data = data.map { HomeMediaAdapter.HomeMediaItem(it.name, it.albums?.getOrNull(0)?.cover?.original, artist = it) }
|
||||||
|
randomAdapter.notifyDataSetChanged()
|
||||||
|
|
||||||
|
random_loader?.visibility = View.GONE
|
||||||
|
random?.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
if (!isCache) cache(randomArtistsRepository, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recentlyListenedRepository.fetch(originFor(recentlyListenedRepository, force).origin).untilNetwork(IO) { data, isCache, _ ->
|
||||||
GlobalScope.launch(Main) {
|
GlobalScope.launch(Main) {
|
||||||
recentlyListenedAdapter.data = data.map { HomeMediaAdapter.HomeMediaItem(it.track.title, it.track.album.cover.original) }
|
recentlyListenedAdapter.data = data.map { HomeMediaAdapter.HomeMediaItem(it.track.title, it.track.album.cover.original) }
|
||||||
recentlyListenedAdapter.notifyDataSetChanged()
|
recentlyListenedAdapter.notifyDataSetChanged()
|
||||||
|
|
||||||
recently_listened_loader.visibility = View.GONE
|
recently_listened_loader?.visibility = View.GONE
|
||||||
recently_listened.visibility = View.VISIBLE
|
recently_listened?.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
if (!isCache) cache(recentlyListenedRepository, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
recentlyAddedRepository.fetch(Repository.Origin.Network.origin).untilNetwork(IO) { data, _, _ ->
|
recentlyAddedRepository.fetch(originFor(recentlyAddedRepository, force).origin).untilNetwork(IO) { data, isCache, _ ->
|
||||||
GlobalScope.launch(Main) {
|
GlobalScope.launch(Main) {
|
||||||
recentlyAddedAdapter.data = data.map { HomeMediaAdapter.HomeMediaItem(it.title, it.album.cover.original) }
|
recentlyAddedAdapter.data = data.map { HomeMediaAdapter.HomeMediaItem(it.title, it.album.cover.original) }
|
||||||
recentlyAddedAdapter.notifyDataSetChanged()
|
recentlyAddedAdapter.notifyDataSetChanged()
|
||||||
|
|
||||||
recently_added_loader.visibility = View.GONE
|
recently_added_loader?.visibility = View.GONE
|
||||||
recently_added.visibility = View.VISIBLE
|
recently_added?.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
if (!isCache) cache(recentlyAddedRepository, data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inner class ArtistClickListener : OnHomeClickListener {
|
||||||
|
override fun onClick(artist: Artist?, album: Album?, track: Track?) {
|
||||||
|
artist?.let {
|
||||||
|
ArtistsFragment.openAlbums(context, artist)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
package com.github.apognu.otter.repositories.home
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import com.github.apognu.otter.repositories.HttpUpstream
|
||||||
|
import com.github.apognu.otter.repositories.Repository
|
||||||
|
import com.github.apognu.otter.utils.Artist
|
||||||
|
import com.github.apognu.otter.utils.ArtistsCache
|
||||||
|
import com.github.apognu.otter.utils.ArtistsResponse
|
||||||
|
import com.github.apognu.otter.utils.FunkwhaleResponse
|
||||||
|
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
|
||||||
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import java.io.BufferedReader
|
||||||
|
|
||||||
|
class RandomArtistsRepository(override val context: Context?) : Repository<Artist, ArtistsCache>() {
|
||||||
|
override val cacheId = "home-random-artists"
|
||||||
|
|
||||||
|
override val upstream =
|
||||||
|
HttpUpstream<Artist, FunkwhaleResponse<Artist>>(
|
||||||
|
HttpUpstream.Behavior.Single,
|
||||||
|
"/api/v1/artists/?playable=true&ordering=random",
|
||||||
|
object : TypeToken<ArtistsResponse>() {}.type,
|
||||||
|
10
|
||||||
|
)
|
||||||
|
|
||||||
|
override fun cache(data: List<Artist>) = ArtistsCache(data)
|
||||||
|
override fun uncache(reader: BufferedReader) = gsonDeserializerOf(ArtistsCache::class.java).deserialize(reader)
|
||||||
|
}
|
@ -3,8 +3,13 @@ package com.github.apognu.otter.repositories.home
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.apognu.otter.repositories.HttpUpstream
|
import com.github.apognu.otter.repositories.HttpUpstream
|
||||||
import com.github.apognu.otter.repositories.Repository
|
import com.github.apognu.otter.repositories.Repository
|
||||||
import com.github.apognu.otter.utils.*
|
import com.github.apognu.otter.utils.FunkwhaleResponse
|
||||||
|
import com.github.apognu.otter.utils.Track
|
||||||
|
import com.github.apognu.otter.utils.TracksCache
|
||||||
|
import com.github.apognu.otter.utils.TracksResponse
|
||||||
|
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import java.io.BufferedReader
|
||||||
|
|
||||||
class RecentlyAddedRepository(override val context: Context?) : Repository<Track, TracksCache>() {
|
class RecentlyAddedRepository(override val context: Context?) : Repository<Track, TracksCache>() {
|
||||||
override val cacheId = "home-recently-added"
|
override val cacheId = "home-recently-added"
|
||||||
@ -16,4 +21,7 @@ class RecentlyAddedRepository(override val context: Context?) : Repository<Track
|
|||||||
object : TypeToken<TracksResponse>() {}.type,
|
object : TypeToken<TracksResponse>() {}.type,
|
||||||
10
|
10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override fun cache(data: List<Track>) = TracksCache(data)
|
||||||
|
override fun uncache(reader: BufferedReader) = gsonDeserializerOf(TracksCache::class.java).deserialize(reader)
|
||||||
}
|
}
|
@ -3,8 +3,13 @@ package com.github.apognu.otter.repositories.home
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.apognu.otter.repositories.HttpUpstream
|
import com.github.apognu.otter.repositories.HttpUpstream
|
||||||
import com.github.apognu.otter.repositories.Repository
|
import com.github.apognu.otter.repositories.Repository
|
||||||
import com.github.apognu.otter.utils.*
|
import com.github.apognu.otter.utils.FunkwhaleResponse
|
||||||
|
import com.github.apognu.otter.utils.PlaylistTrack
|
||||||
|
import com.github.apognu.otter.utils.PlaylistTracksCache
|
||||||
|
import com.github.apognu.otter.utils.PlaylistTracksResponse
|
||||||
|
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import java.io.BufferedReader
|
||||||
|
|
||||||
class RecentlyListenedRepository(override val context: Context?) : Repository<PlaylistTrack, PlaylistTracksCache>() {
|
class RecentlyListenedRepository(override val context: Context?) : Repository<PlaylistTrack, PlaylistTracksCache>() {
|
||||||
override val cacheId = "home-recently-listened"
|
override val cacheId = "home-recently-listened"
|
||||||
@ -16,4 +21,7 @@ class RecentlyListenedRepository(override val context: Context?) : Repository<Pl
|
|||||||
object : TypeToken<PlaylistTracksResponse>() {}.type,
|
object : TypeToken<PlaylistTracksResponse>() {}.type,
|
||||||
10
|
10
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override fun cache(data: List<PlaylistTrack>) = PlaylistTracksCache(data)
|
||||||
|
override fun uncache(reader: BufferedReader) = gsonDeserializerOf(PlaylistTracksCache::class.java).deserialize(reader)
|
||||||
}
|
}
|
@ -3,11 +3,16 @@ package com.github.apognu.otter.repositories.home
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import com.github.apognu.otter.repositories.HttpUpstream
|
import com.github.apognu.otter.repositories.HttpUpstream
|
||||||
import com.github.apognu.otter.repositories.Repository
|
import com.github.apognu.otter.repositories.Repository
|
||||||
import com.github.apognu.otter.utils.*
|
import com.github.apognu.otter.utils.FunkwhaleResponse
|
||||||
|
import com.github.apognu.otter.utils.Tag
|
||||||
|
import com.github.apognu.otter.utils.TagsCache
|
||||||
|
import com.github.apognu.otter.utils.TagsResponse
|
||||||
|
import com.github.kittinunf.fuel.gson.gsonDeserializerOf
|
||||||
import com.google.gson.reflect.TypeToken
|
import com.google.gson.reflect.TypeToken
|
||||||
|
import java.io.BufferedReader
|
||||||
|
|
||||||
class TagsRepository(override val context: Context?) : Repository<Tag, TagsCache>() {
|
class TagsRepository(override val context: Context?) : Repository<Tag, TagsCache>() {
|
||||||
override val cacheId = "tags"
|
override val cacheId = "home-tags"
|
||||||
|
|
||||||
override val upstream =
|
override val upstream =
|
||||||
HttpUpstream<Tag, FunkwhaleResponse<Tag>>(
|
HttpUpstream<Tag, FunkwhaleResponse<Tag>>(
|
||||||
@ -15,4 +20,9 @@ class TagsRepository(override val context: Context?) : Repository<Tag, TagsCache
|
|||||||
"/api/v1/tags/",
|
"/api/v1/tags/",
|
||||||
object : TypeToken<TagsResponse>() {}.type
|
object : TypeToken<TagsResponse>() {}.type
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override fun onDataFetched(data: List<Tag>) = data.shuffled().take(10)
|
||||||
|
|
||||||
|
override fun cache(data: List<Tag>) = TagsCache(data)
|
||||||
|
override fun uncache(reader: BufferedReader) = gsonDeserializerOf(TagsCache::class.java).deserialize(reader)
|
||||||
}
|
}
|
@ -76,6 +76,7 @@ object Cache {
|
|||||||
|
|
||||||
fun set(context: Context?, key: String, value: ByteArray) = context?.let {
|
fun set(context: Context?, key: String, value: ByteArray) = context?.let {
|
||||||
with(File(it.cacheDir, key(key))) {
|
with(File(it.cacheDir, key(key))) {
|
||||||
|
"$key (${key(key)} : $value"
|
||||||
writeBytes(value)
|
writeBytes(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
android:layout_marginBottom="16dp"
|
android:layout_marginBottom="16dp"
|
||||||
android:text="Tags" />
|
android:text="Some tags" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/tags_loader"
|
android:id="@+id/tags_loader"
|
||||||
|
@ -3,13 +3,16 @@
|
|||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginHorizontal="8dp"
|
android:layout_marginHorizontal="8dp"
|
||||||
android:orientation="vertical">
|
android:background="@drawable/ripple"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:padding="8dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/cover"
|
android:id="@+id/cover"
|
||||||
android:layout_width="150dp"
|
android:layout_width="150dp"
|
||||||
android:layout_height="150dp"
|
android:layout_height="150dp"
|
||||||
android:layout_marginBottom="8dp"
|
android:layout_marginBottom="8dp"
|
||||||
|
android:contentDescription="@string/alt_album_cover"
|
||||||
android:src="@drawable/cover" />
|
android:src="@drawable/cover" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
@ -7,13 +7,13 @@
|
|||||||
android:background="@drawable/rounded"
|
android:background="@drawable/rounded"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:paddingHorizontal="12dp"
|
android:paddingHorizontal="12dp"
|
||||||
android:paddingVertical="8dp">
|
android:paddingVertical="6dp">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/label"
|
android:id="@+id/label"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textColor="@android:color/white"
|
android:textColor="@android:color/white"
|
||||||
android:textSize="18sp" />
|
android:textSize="16sp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
Loading…
x
Reference in New Issue
Block a user