Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add volume progress #1199

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions core/resources/src/main/res/values-ja/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,5 @@

<string name="back">バック</string>
<string name="error_generic">不明なエラーが発生しました…</string>
<string name="series_detail_volumes_owned_title">所有ボリューム</string>
</resources>
1 change: 1 addition & 0 deletions core/resources/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@

<string name="series_detail_dash">-</string>
<string name="series_detail_progress_title">Progress</string>
<string name="series_detail_volumes_owned_title">Volumes owned</string>
<string name="series_detail_progress_out_of">/ %s</string>
<string name="series_detail_status_title">Users series status</string>
<string name="series_detail_rating">Rating</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class IncrementSeriesUseCase @Inject constructor(private val repo: SeriesReposit
repo.updateSeries(
userSeriesId = domain.userId,
progress = domain.progress + 1,
volumesOwned = domain.volumesOwned,
status = domain.userSeriesStatus,
rating = newRating
).mapEither(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class UpdateItemUseCase @Inject constructor(private val seriesRepo: SeriesReposi
seriesRepo.updateSeries(
userSeriesId = updateItemModel.userSeriesId,
progress = updateItemModel.progress,
volumesOwned = updateItemModel.volumesOwned,
status = updateItemModel.newStatus,
rating = updateItemModel.rating
).mapEither(
Expand All @@ -28,6 +29,7 @@ class UpdateItemUseCase @Inject constructor(private val seriesRepo: SeriesReposi
data class UpdateItemModel(
val userSeriesId: Int,
val progress: Int,
val volumesOwned: Int?,
val newStatus: UserSeriesStatus,
val rating: Int
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

package com.chesire.nekome.app.series.item.ui

import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
Expand Down Expand Up @@ -79,6 +80,7 @@ fun ItemScreen(
state = state,
onSeriesStatusChanged = { viewModel.execute(ViewAction.SeriesStatusChanged(it)) },
onProgressChanged = { viewModel.execute(ViewAction.ProgressChanged(it)) },
onVolumesOwnedChanged = { viewModel.execute(ViewAction.VolumesOwnedChanged(it)) },
onRatingChanged = { viewModel.execute(ViewAction.RatingChanged(it)) },
onConfirmPressed = { viewModel.execute(ViewAction.ConfirmPressed) },
onDeletePressed = { viewModel.execute(ViewAction.DeletePressed) },
Expand All @@ -94,6 +96,7 @@ private fun Render(
state: State<UIState>,
onSeriesStatusChanged: (UserSeriesStatus) -> Unit,
onProgressChanged: (String) -> Unit,
onVolumesOwnedChanged: (String) -> Unit,
onRatingChanged: (Float) -> Unit,
onConfirmPressed: () -> Unit,
onDeletePressed: () -> Unit,
Expand Down Expand Up @@ -161,6 +164,15 @@ private fun Render(
length = state.value.length,
onProgressChanged = onProgressChanged
)

if(state.value.volumesOwned != null) {
VolumeProgress(
volumesOwned = state.value.volumesOwned ?: "0",
volumeCount = state.value.volumeCount ?: "-",
onVolumesOwnedChanged = onVolumesOwnedChanged
)
}

Rating(
rating = state.value.rating,
onRatingChanged = onRatingChanged
Expand Down Expand Up @@ -326,6 +338,35 @@ private fun Progress(
)
}

//TODO use a genic method for Volume and progress?
@Composable
private fun VolumeProgress(
volumesOwned: String,
volumeCount: String,
onVolumesOwnedChanged: (String) -> Unit
) {
Text(
text = stringResource(id =StringResource.series_detail_volumes_owned_title),
modifier = Modifier.padding(top = 16.dp, bottom = 8.dp),
style = MaterialTheme.typography.bodyLarge
)
OutlinedTextField(
value = volumesOwned,
onValueChange = onVolumesOwnedChanged,
modifier = Modifier.fillMaxWidth(),
trailingIcon = {
Text(
text = stringResource(
id = StringResource.series_detail_progress_out_of,
volumeCount
)
)
},
singleLine = true,
keyboardOptions = KeyboardOptions.Default.copy(keyboardType = KeyboardType.Number)
)
}

@Composable
private fun Rating(
rating: Float,
Expand Down Expand Up @@ -421,7 +462,7 @@ private fun RenderSnackbar(

@Composable
@Preview
private fun Preview() {
private fun PreviewAnime() {
val initialState = UIState(
id = 0,
title = "Title",
Expand All @@ -437,6 +478,58 @@ private fun Preview() {
seriesStatus = UserSeriesStatus.Planned,
progress = "0",
length = "12",
volumesOwned = null,
volumeCount = null,
rating = 0f,
isSendingData = false,
finishScreen = false,
deleteDialog = Delete(
show = false,
title = "Title"
),
errorSnackbar = null
)
NekomeTheme(isDarkTheme = true) {
Render(
state = produceState(
initialValue = initialState,
producer = { value = initialState }
),
onSeriesStatusChanged = { /**/ },
onProgressChanged = { /**/ },
onVolumesOwnedChanged = { /**/ },
onRatingChanged = { /**/ },
onConfirmPressed = { /**/ },
onDeletePressed = { /**/ },
onDeleteResult = { /**/ },
onSnackbarShown = { /**/ },
finishScreen = { /**/ },
onFinishedScreen = { /**/ }
)
}
}


@Composable
@Preview
private fun PreviewManga() {
val initialState = UIState(
id = 0,
title = "Title",
subtitle = "Manga - Manga - Finished",
imageUrl = "",
possibleSeriesStatus = listOf(
UserSeriesStatus.Current,
UserSeriesStatus.Completed,
UserSeriesStatus.Dropped,
UserSeriesStatus.OnHold,
UserSeriesStatus.Planned
),
seriesStatus = UserSeriesStatus.Planned,
progress = "0",
length = "141",
volumesOwned = "0",
volumeCount = "34",
rating = 0f,
isSendingData = false,
finishScreen = false,
Expand All @@ -454,6 +547,7 @@ private fun Preview() {
),
onSeriesStatusChanged = { /**/ },
onProgressChanged = { /**/ },
onVolumesOwnedChanged = { /**/ },
onRatingChanged = { /**/ },
onConfirmPressed = { /**/ },
onDeletePressed = { /**/ },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import kotlinx.coroutines.launch
// Note this value is pulled from the nav_graph.xml
private const val SERIES_ID = "seriesId"
private const val MAX_PROGRESS_NUMBERS = 4
private const val MAX_VOLUMES_OWNED_NUMBERS = 4

@HiltViewModel
class ItemViewModel @Inject constructor(
Expand Down Expand Up @@ -59,6 +60,8 @@ class ItemViewModel @Inject constructor(
seriesStatus = series.userSeriesStatus,
progress = series.progress.toString(),
length = series.totalLength.takeUnless { it == 0 }?.toString() ?: "-",
volumesOwned = series.volumesOwned?.toString(),
volumeCount = series.volumeCount?.takeUnless { it == 0 }?.toString() ?: "-",
rating = series.rating.toFloat()
)
}
Expand All @@ -72,6 +75,7 @@ class ItemViewModel @Inject constructor(
ViewAction.FinishScreenObserved -> handleFinishScreenObserved()
is ViewAction.OnDeleteResult -> handleDeleteResult(action.result)
is ViewAction.ProgressChanged -> handleProgressChanged(action.newProgress)
is ViewAction.VolumesOwnedChanged -> handleVolumesOwnedChanged(action.newVolumesOwned)
is ViewAction.RatingChanged -> handleRatingChanged(action.newRating)
is ViewAction.SeriesStatusChanged -> handleSeriesStatusChanged(action.newSeriesStatus)
}
Expand All @@ -84,6 +88,7 @@ class ItemViewModel @Inject constructor(
UpdateItemModel(
userSeriesId = state.id,
progress = state.progress.toIntOrNull() ?: 0,
volumesOwned = state.volumesOwned?.toInt(),
newStatus = state.seriesStatus,
rating = state.rating.roundToInt()
)
Expand Down Expand Up @@ -155,6 +160,12 @@ class ItemViewModel @Inject constructor(
}
}

private fun handleVolumesOwnedChanged(newVolumesOwned: String) {
if (newVolumesOwned.count() <= MAX_VOLUMES_OWNED_NUMBERS) {
state = state.copy(volumesOwned = newVolumesOwned)
}
}

private fun handleRatingChanged(newRating: Float) {
state = state.copy(rating = newRating)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ data class UIState(
val seriesStatus: UserSeriesStatus,
val progress: String,
val length: String,
val volumesOwned: String?,
val volumeCount: String?,
val rating: Float,
val isSendingData: Boolean,
val finishScreen: Boolean,
Expand All @@ -34,6 +36,8 @@ data class UIState(
seriesStatus = UserSeriesStatus.Unknown,
progress = "0",
length = "-",
volumesOwned = null,
volumeCount = null,
rating = 0f,
finishScreen = false,
isSendingData = false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.chesire.nekome.core.flags.UserSeriesStatus
sealed interface ViewAction {
data class OnDeleteResult(val result: Boolean) : ViewAction
data class ProgressChanged(val newProgress: String) : ViewAction
data class VolumesOwnedChanged(val newVolumesOwned: String) : ViewAction
data class RatingChanged(val newRating: Float) : ViewAction
data class SeriesStatusChanged(val newSeriesStatus: UserSeriesStatus) : ViewAction
object ConfirmPressed : ViewAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ class UpdateSeriesUseCase @Inject constructor(
.updateSeries(
currentSeries.userId,
currentSeries.progress + 1,
currentSeries.volumesOwned,
currentSeries.userSeriesStatus,
currentSeries.rating
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,20 @@ internal val MIGRATION_4_5 = object : Migration(4, 5) {
database.execSQL("ALTER TABLE SeriesEntity ADD COLUMN otherTitles TEXT NOT NULL DEFAULT ''")
}
}

/**
* Provides a migration from version 5 to version 6 of the database.
*
* Changes:
* * volumesOwend and volumeCount were added to the SeriesEntity table
*/
internal val MIGRATION_5_6 = object : Migration(5, 6) {
override fun migrate(database: SupportSQLiteDatabase) {
database.beginTransaction()
database.execSQL("ALTER TABLE SeriesEntity ADD COLUMN volumesOwned INTEGER DEFAULT NULL")
database.execSQL("ALTER TABLE SeriesEntity ADD COLUMN volumeCount INTEGER DEFAULT NULL")
database.execSQL("Update SeriesEntity SET volumesOwned = 0, volumeCount = 0 WHERE type = Manga")
database.execSQL("Update SeriesEntity SET volumeCount = 0, volumeCount = 0 WHERE type = Manga")
database.endTransaction()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import com.chesire.nekome.database.entity.UserEntity
*/
@Database(
entities = [SeriesEntity::class, UserEntity::class],
version = 5
version = 6
)
@TypeConverters(
ImageModelConverter::class,
Expand Down Expand Up @@ -51,7 +51,7 @@ abstract class RoomDB : RoomDatabase() {
fun build(context: Context, databaseName: String = "nekome_database.db"): RoomDB {
return Room
.databaseBuilder(context, RoomDB::class.java, databaseName)
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5)
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_4_5, MIGRATION_5_6)
.fallbackToDestructiveMigration()
.build()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ data class SeriesEntity(
val userSeriesStatus: UserSeriesStatus,
val progress: Int,
val totalLength: Int,
val volumesOwned: Int?,
val volumeCount: Int?,
val rating: Int,
val posterImage: ImageModel,
val startDate: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ data class SeriesDomain(
val userSeriesStatus: UserSeriesStatus,
val progress: Int,
val totalLength: Int,
val volumesOwned: Int?,
val volumeCount: Int?,
val rating: Int,
val posterImage: ImageModel,
val startDate: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class SeriesMapper @Inject constructor() {
input.userSeriesStatus,
input.progress,
input.totalLength,
input.volumesOwned,
input.volumeCount,
input.rating,
input.posterImage,
input.startDate,
Expand All @@ -46,6 +48,8 @@ class SeriesMapper @Inject constructor() {
input.userSeriesStatus,
input.progress,
input.totalLength,
input.volumesOwned,
input.volumeCount,
input.rating,
input.posterImage,
input.startDate,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.chesire.nekome.datasource.series

import com.chesire.nekome.core.flags.SeriesType
import com.chesire.nekome.core.flags.UserSeriesStatus
import com.chesire.nekome.core.models.ErrorDomain
import com.chesire.nekome.database.dao.SeriesDao
Expand Down Expand Up @@ -49,7 +50,8 @@ class SeriesRepository(
seriesId = seriesId,
startingStatus = startingStatus
).onSuccess {
val entity = map.toSeriesEntity(it)
// The api always returns any anime with volumesOwned = 0
val entity = map.toSeriesEntity(it.copy(volumesOwned = null))
seriesDao.insert(entity)
}.onFailure {
Timber.e("Error adding anime [$seriesId], ${it.message}")
Expand Down Expand Up @@ -138,12 +140,14 @@ class SeriesRepository(
suspend fun updateSeries(
userSeriesId: Int,
progress: Int,
volumesOwned: Int?,
status: UserSeriesStatus,
rating: Int
): Result<SeriesDomain, ErrorDomain> {
return seriesApi.update(
userSeriesId = userSeriesId,
progress = progress,
volumesOwned = volumesOwned,
newStatus = status,
rating = rating
).onSuccess {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ interface SeriesApi {
suspend fun update(
userSeriesId: Int,
progress: Int,
volumesOwned: Int?,
newStatus: UserSeriesStatus,
rating: Int
): Result<SeriesDomain, ErrorDomain>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,14 @@ class KitsuLibrary @Inject constructor(
override suspend fun update(
userSeriesId: Int,
progress: Int,
volumesOwned: Int?,
newStatus: UserSeriesStatus,
rating: Int
): Result<SeriesDomain, ErrorDomain> {
val updateJson = entityFactory.createUpdateDto(
userSeriesId,
progress,
volumesOwned,
userSeriesStatusAdapter.userSeriesStatusToString(newStatus),
rating
)
Expand Down
Loading