Merge branch 'master' of https://github.com/nv95/Kotatsu
This commit is contained in:
@@ -61,7 +61,6 @@ dependencies {
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0-alpha03'
|
||||
implementation 'androidx.recyclerview:recyclerview:1.2.0-alpha01'
|
||||
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0-alpha01'
|
||||
implementation 'androidx.preference:preference:1.1.0'
|
||||
implementation 'com.google.android.material:material:1.2.0-alpha04'
|
||||
|
||||
@@ -80,7 +79,7 @@ dependencies {
|
||||
implementation 'org.jsoup:jsoup:1.12.1'
|
||||
|
||||
implementation 'org.koin:koin-android:2.0.1'
|
||||
implementation 'io.coil-kt:coil:0.9.2'
|
||||
implementation 'io.coil-kt:coil:0.9.4'
|
||||
implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0'
|
||||
|
||||
testImplementation 'junit:junit:4.13'
|
||||
|
||||
@@ -54,5 +54,5 @@ class KotatsuApp : Application() {
|
||||
applicationContext,
|
||||
MangaDatabase::class.java,
|
||||
"kotatsu-db"
|
||||
).fallbackToDestructiveMigration() //TODO remove
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
|
||||
import androidx.room.Dao
|
||||
import androidx.room.Insert
|
||||
import androidx.room.OnConflictStrategy
|
||||
import androidx.room.Query
|
||||
import org.koitharu.kotatsu.core.db.entity.FavouriteCategoryEntity
|
||||
|
||||
@Dao
|
||||
abstract class FavouriteCategoriesDao {
|
||||
|
||||
@Query("SELECT category_id,title,created_at FROM favourite_categories ORDER BY :orderBy")
|
||||
abstract suspend fun findAll(orderBy: String): List<FavouriteCategoryEntity>
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.ABORT)
|
||||
abstract suspend fun insert(category: FavouriteCategoryEntity): Long
|
||||
|
||||
@Query("DELETE FROM favourite_categories WHERE category_id = :id")
|
||||
abstract suspend fun delete(id: Long)
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package org.koitharu.kotatsu.core.db
|
||||
|
||||
import androidx.room.*
|
||||
import org.koitharu.kotatsu.core.db.entity.FavouriteEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.FavouriteManga
|
||||
|
||||
@Dao
|
||||
abstract class FavouritesDao {
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM favourites ORDER BY :orderBy LIMIT :limit OFFSET :offset")
|
||||
abstract suspend fun findAll(offset: Int, limit: Int, orderBy: String): List<FavouriteManga>
|
||||
|
||||
@Transaction
|
||||
@Query("SELECT * FROM favourites WHERE manga_id = :id")
|
||||
abstract suspend fun find(id: Long): FavouriteManga?
|
||||
|
||||
@Insert(onConflict = OnConflictStrategy.IGNORE)
|
||||
abstract suspend fun add(favourite: FavouriteEntity)
|
||||
|
||||
@Delete
|
||||
abstract suspend fun delete(favourite: FavouriteEntity)
|
||||
}
|
||||
@@ -2,12 +2,14 @@ package org.koitharu.kotatsu.core.db
|
||||
|
||||
import androidx.room.Database
|
||||
import androidx.room.RoomDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.HistoryEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.MangaTagsEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.*
|
||||
|
||||
@Database(entities = [MangaEntity::class, TagEntity::class, HistoryEntity::class, MangaTagsEntity::class], version = 1)
|
||||
@Database(
|
||||
entities = [
|
||||
MangaEntity::class, TagEntity::class, HistoryEntity::class, MangaTagsEntity::class,
|
||||
FavouriteCategoryEntity::class, FavouriteEntity::class
|
||||
], version = 1
|
||||
)
|
||||
abstract class MangaDatabase : RoomDatabase() {
|
||||
|
||||
abstract fun historyDao(): HistoryDao
|
||||
@@ -15,4 +17,8 @@ abstract class MangaDatabase : RoomDatabase() {
|
||||
abstract fun tagsDao(): TagsDao
|
||||
|
||||
abstract fun mangaDao(): MangaDao
|
||||
|
||||
abstract fun favouritesDao(): FavouritesDao
|
||||
|
||||
abstract fun favouriteCategoriesDao(): FavouriteCategoriesDao
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package org.koitharu.kotatsu.core.db.entity
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
import androidx.room.PrimaryKey
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import java.util.*
|
||||
|
||||
@Entity(tableName = "favourite_categories")
|
||||
data class FavouriteCategoryEntity(
|
||||
@PrimaryKey(autoGenerate = true)
|
||||
@ColumnInfo(name = "category_id") val categoryId: Int,
|
||||
@ColumnInfo(name = "created_at") val createdAt: Long,
|
||||
@ColumnInfo(name = "title") val title: String
|
||||
) {
|
||||
|
||||
fun toFavouriteCategory(id: Long? = null) = FavouriteCategory(
|
||||
id = id ?: categoryId.toLong(),
|
||||
title = title,
|
||||
createdAt = Date(createdAt)
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.koitharu.kotatsu.core.db.entity
|
||||
|
||||
import androidx.room.ColumnInfo
|
||||
import androidx.room.Entity
|
||||
|
||||
@Entity(tableName = "favourites", primaryKeys = ["manga_id", "category_id"])
|
||||
data class FavouriteEntity(
|
||||
@ColumnInfo(name = "manga_id") val mangaId: Long,
|
||||
@ColumnInfo(name = "category_id") val categoryId: Long,
|
||||
@ColumnInfo(name = "created_at") val createdAt: Long
|
||||
)
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.koitharu.kotatsu.core.db.entity
|
||||
|
||||
import androidx.room.Embedded
|
||||
import androidx.room.Junction
|
||||
import androidx.room.Relation
|
||||
|
||||
data class FavouriteManga(
|
||||
@Embedded val favourite: FavouriteEntity,
|
||||
@Relation(
|
||||
parentColumn = "manga_id",
|
||||
entityColumn = "manga_id"
|
||||
)
|
||||
val manga: MangaEntity,
|
||||
@Relation(
|
||||
parentColumn = "category_id",
|
||||
entityColumn = "category_id"
|
||||
)
|
||||
val categories: List<FavouriteCategoryEntity>,
|
||||
@Relation(
|
||||
parentColumn = "manga_id",
|
||||
entityColumn = "tag_id",
|
||||
associateBy = Junction(MangaTagsEntity::class)
|
||||
)
|
||||
val tags: List<TagEntity>
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.core.model
|
||||
|
||||
import android.os.Parcelable
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import java.util.*
|
||||
|
||||
@Parcelize
|
||||
data class FavouriteCategory(
|
||||
val id: Long,
|
||||
val title: String,
|
||||
val createdAt: Date
|
||||
) : Parcelable
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.koitharu.kotatsu.domain.favourites
|
||||
|
||||
import org.koin.core.KoinComponent
|
||||
import org.koin.core.inject
|
||||
import org.koitharu.kotatsu.core.db.MangaDatabase
|
||||
import org.koitharu.kotatsu.core.db.entity.FavouriteCategoryEntity
|
||||
import org.koitharu.kotatsu.core.db.entity.TagEntity
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.core.model.Manga
|
||||
|
||||
class FavouritesRepository : KoinComponent {
|
||||
|
||||
private val db: MangaDatabase by inject()
|
||||
|
||||
suspend fun getAllManga(offset: Int): List<Manga> {
|
||||
val entities = db.favouritesDao().findAll(offset, 20, "created_at")
|
||||
return entities.map { it.manga.toManga(it.tags.map(TagEntity::toMangaTag).toSet()) }
|
||||
}
|
||||
|
||||
suspend fun getAllCategories(): List<FavouriteCategory> {
|
||||
val entities = db.favouriteCategoriesDao().findAll("created_at")
|
||||
return entities.map { it.toFavouriteCategory() }
|
||||
}
|
||||
|
||||
suspend fun getCategories(mangaId: Long): List<FavouriteCategory> {
|
||||
val entities = db.favouritesDao().find(mangaId)?.categories
|
||||
return entities?.map { it.toFavouriteCategory() }.orEmpty()
|
||||
}
|
||||
|
||||
suspend fun addCategory(title: String): FavouriteCategory {
|
||||
val entity = FavouriteCategoryEntity(
|
||||
title = title,
|
||||
createdAt = System.currentTimeMillis(),
|
||||
categoryId = 0
|
||||
)
|
||||
val id = db.favouriteCategoriesDao().insert(entity)
|
||||
return entity.toFavouriteCategory(id)
|
||||
}
|
||||
|
||||
suspend fun removeCategory(id: Long) {
|
||||
db.favouriteCategoriesDao().delete(id)
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@ package org.koitharu.kotatsu.ui.details
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import kotlinx.android.synthetic.main.activity_details.*
|
||||
import moxy.ktx.moxyPresenter
|
||||
@@ -39,11 +41,24 @@ class MangaDetailsActivity : BaseActivity(), MangaDetailsView {
|
||||
Snackbar.make(pager, e.getDisplayMessage(resources), Snackbar.LENGTH_LONG).show()
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
|
||||
menuInflater.inflate(R.menu.opt_details, menu)
|
||||
return super.onCreateOptionsMenu(menu)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem) = when (item.itemId) {
|
||||
R.id.action_favourite -> {
|
||||
true
|
||||
}
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
private const val EXTRA_MANGA = "manga"
|
||||
|
||||
fun newIntent(context: Context, manga: Manga) = Intent(context, MangaDetailsActivity::class.java)
|
||||
.putExtra(EXTRA_MANGA, manga)
|
||||
fun newIntent(context: Context, manga: Manga) =
|
||||
Intent(context, MangaDetailsActivity::class.java)
|
||||
.putExtra(EXTRA_MANGA, manga)
|
||||
}
|
||||
}
|
||||
@@ -10,6 +10,7 @@ import kotlinx.android.synthetic.main.activity_main.*
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.MangaSource
|
||||
import org.koitharu.kotatsu.ui.common.BaseActivity
|
||||
import org.koitharu.kotatsu.ui.main.list.favourites.FavouritesListFragment
|
||||
import org.koitharu.kotatsu.ui.main.list.history.HistoryListFragment
|
||||
import org.koitharu.kotatsu.ui.main.list.remote.RemoteListFragment
|
||||
|
||||
@@ -56,7 +57,7 @@ class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedList
|
||||
setPrimaryFragment(RemoteListFragment.newInstance(source))
|
||||
} else when (item.itemId) {
|
||||
R.id.nav_history -> setPrimaryFragment(HistoryListFragment.newInstance())
|
||||
R.id.nav_favourites -> Unit
|
||||
R.id.nav_favourites -> setPrimaryFragment(FavouritesListFragment.newInstance())
|
||||
R.id.nav_local_storage -> Unit
|
||||
else -> return false
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package org.koitharu.kotatsu.ui.main.list.favourites
|
||||
|
||||
import android.util.SparseBooleanArray
|
||||
import android.view.ViewGroup
|
||||
import android.widget.Checkable
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseRecyclerAdapter
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
|
||||
|
||||
class CategoriesAdapter(private val listener: OnCategoryCheckListener) :
|
||||
BaseRecyclerAdapter<FavouriteCategory, Boolean>() {
|
||||
|
||||
private val checkedIds = SparseBooleanArray()
|
||||
|
||||
override fun getExtra(item: FavouriteCategory, position: Int) =
|
||||
checkedIds.get(item.id.toInt(), false)
|
||||
|
||||
override fun onCreateViewHolder(parent: ViewGroup) = CategoryHolder(parent)
|
||||
|
||||
override fun onGetItemId(item: FavouriteCategory) = item.id
|
||||
|
||||
override fun onViewHolderCreated(holder: BaseViewHolder<FavouriteCategory, Boolean>) {
|
||||
super.onViewHolderCreated(holder)
|
||||
holder.itemView.setOnClickListener {
|
||||
if (it !is Checkable) return@setOnClickListener
|
||||
it.toggle()
|
||||
if (it.isChecked) {
|
||||
listener.onCategoryChecked(holder.requireData())
|
||||
} else {
|
||||
listener.onCategoryUnchecked(holder.requireData())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.koitharu.kotatsu.ui.main.list.favourites
|
||||
|
||||
import android.view.ViewGroup
|
||||
import kotlinx.android.synthetic.main.item_caegory_checkable.*
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
import org.koitharu.kotatsu.ui.common.list.BaseViewHolder
|
||||
|
||||
class CategoryHolder(parent: ViewGroup) :
|
||||
BaseViewHolder<FavouriteCategory, Boolean>(parent, R.layout.item_caegory_checkable) {
|
||||
|
||||
override fun onBind(data: FavouriteCategory, extra: Boolean) {
|
||||
checkedTextView.text = data.title
|
||||
checkedTextView.isChecked = extra
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package org.koitharu.kotatsu.ui.main.list.favourites
|
||||
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.ui.common.AlertDialogFragment
|
||||
|
||||
class FavouriteCategoriesDialog() : AlertDialogFragment(R.layout.dialog_favorite_categories) {
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.koitharu.kotatsu.ui.main.list.favourites
|
||||
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import kotlinx.android.synthetic.main.fragment_list.*
|
||||
import moxy.ktx.moxyPresenter
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.ui.main.list.MangaListFragment
|
||||
import org.koitharu.kotatsu.ui.main.list.MangaListView
|
||||
|
||||
class FavouritesListFragment : MangaListFragment<Unit>(), MangaListView<Unit>{
|
||||
|
||||
private val presenter by moxyPresenter(factory = ::FavouritesListPresenter)
|
||||
|
||||
override fun onRequestMoreItems(offset: Int) {
|
||||
presenter.loadList(offset)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
// inflater.inflate(R.menu.opt_history, menu)
|
||||
super.onCreateOptionsMenu(menu, inflater)
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem) = when(item.itemId) {
|
||||
|
||||
else -> super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
override fun getTitle(): CharSequence? {
|
||||
return getString(R.string.favourites)
|
||||
}
|
||||
|
||||
override fun setUpEmptyListHolder() {
|
||||
textView_holder.setText(R.string.you_have_not_favourites_yet)
|
||||
textView_holder.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0)
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun newInstance() = FavouritesListFragment()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package org.koitharu.kotatsu.ui.main.list.favourites
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import moxy.InjectViewState
|
||||
import org.koitharu.kotatsu.BuildConfig
|
||||
import org.koitharu.kotatsu.domain.favourites.FavouritesRepository
|
||||
import org.koitharu.kotatsu.ui.common.BasePresenter
|
||||
import org.koitharu.kotatsu.ui.main.list.MangaListView
|
||||
|
||||
@InjectViewState
|
||||
class FavouritesListPresenter : BasePresenter<MangaListView<Unit>>() {
|
||||
|
||||
private lateinit var repository: FavouritesRepository
|
||||
|
||||
override fun onFirstViewAttach() {
|
||||
repository = FavouritesRepository()
|
||||
super.onFirstViewAttach()
|
||||
}
|
||||
|
||||
fun loadList(offset: Int) {
|
||||
launch {
|
||||
viewState.onLoadingChanged(true)
|
||||
try {
|
||||
val list = withContext(Dispatchers.IO) {
|
||||
repository.getAllManga(offset = offset)
|
||||
}
|
||||
if (offset == 0) {
|
||||
viewState.onListChanged(list)
|
||||
} else {
|
||||
viewState.onListAppended(list)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
if (BuildConfig.DEBUG) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
viewState.onError(e)
|
||||
} finally {
|
||||
viewState.onLoadingChanged(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.ui.main.list.favourites
|
||||
|
||||
import org.koitharu.kotatsu.core.model.FavouriteCategory
|
||||
|
||||
interface OnCategoryCheckListener {
|
||||
|
||||
fun onCategoryChecked(category: FavouriteCategory)
|
||||
|
||||
fun onCategoryUnchecked(category: FavouriteCategory)
|
||||
}
|
||||
@@ -8,13 +8,13 @@
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="@style/ThemeOverlay.MaterialComponents.Dark.ActionBar"
|
||||
app:layout_scrollFlags="scroll|enterAlways"
|
||||
app:popupTheme="@style/ThemeOverlay.MaterialComponents.Light" />
|
||||
|
||||
|
||||
31
app/src/main/res/layout/dialog_favorite_categories.xml
Normal file
31
app/src/main/res/layout/dialog_favorite_categories.xml
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView_categories"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
android:scrollbars="vertical"
|
||||
tools:listitem="@layout/item_caegory_checkable" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textView_add"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?listPreferredItemHeightSmall"
|
||||
android:background="?selectableItemBackground"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="?listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?listPreferredItemPaddingEnd"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
android:text="" />
|
||||
|
||||
</LinearLayout>
|
||||
16
app/src/main/res/layout/item_caegory_checkable.xml
Normal file
16
app/src/main/res/layout/item_caegory_checkable.xml
Normal file
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<CheckedTextView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/checkedTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?listPreferredItemHeightSmall"
|
||||
android:background="?selectableItemBackground"
|
||||
android:checkMark="?android:attr/listChoiceIndicatorMultiple"
|
||||
android:gravity="start|center_vertical"
|
||||
android:paddingStart="?listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?listPreferredItemPaddingEnd"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||
android:textColor="?android:textColorPrimary"
|
||||
tools:checked="true"
|
||||
tools:text="@tools:sample/lorem[4]" />
|
||||
11
app/src/main/res/menu/opt_details.xml
Normal file
11
app/src/main/res/menu/opt_details.xml
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_favourite"
|
||||
android:icon="@drawable/ic_favourites"
|
||||
android:title="@string/favourites"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
</menu>
|
||||
@@ -25,4 +25,5 @@
|
||||
<string name="read">Read</string>
|
||||
<string name="continue_">Continue</string>
|
||||
<string name="add_bookmark">Add bookmark</string>
|
||||
<string name="you_have_not_favourites_yet">You have not favourites yet</string>
|
||||
</resources>
|
||||
Reference in New Issue
Block a user