Skip to content

Commit

Permalink
#16 Add support for removing movie from trakt history
Browse files Browse the repository at this point in the history
  • Loading branch information
moallemi committed Jun 16, 2024
1 parent 3e7fedb commit a5e903d
Show file tree
Hide file tree
Showing 14 changed files with 86 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ interface TraktSyncRemoteSource {
suspend fun getHistoryById(id: Int): Result<Boolean, GeneralError>

suspend fun addToHistory(id: Int): Result<Unit, GeneralError>

suspend fun removeFromHistory(id: Int): Result<Unit, GeneralError>
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ package io.filmtime.data.api.trakt
import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.network.adapter.NetworkResponse
import io.filmtime.data.network.trakt.AddHistoryRequest
import io.filmtime.data.network.trakt.HistoryIDS
import io.filmtime.data.network.trakt.MovieHistory
import io.filmtime.data.network.trakt.SyncHistoryRequest
import io.filmtime.data.network.trakt.TraktSyncService
import io.filmtime.data.storage.trakt.TraktAuthLocalSource
import kotlinx.coroutines.flow.firstOrNull
Expand Down Expand Up @@ -56,7 +56,7 @@ class TraktSyncRemoteSourceImpl
traktAuthLocalSource.tokens.firstOrNull() ?: return Result.Failure(GeneralError.ApiError("Unauthorized", 401))
val result = traktSyncService.addMovieToHistory(
accessToken = "Bearer " + tokens.accessToken,
body = AddHistoryRequest(
body = SyncHistoryRequest(
movies = listOf(
MovieHistory(
ids = HistoryIDS(
Expand All @@ -67,10 +67,33 @@ class TraktSyncRemoteSourceImpl
),
)
return when (result) {
is NetworkResponse.Success -> Result.Success(Unit)
is NetworkResponse.ApiError -> Result.Failure(GeneralError.ApiError(result.body.error, result.code))
is NetworkResponse.NetworkError -> Result.Failure(GeneralError.NetworkError)
is NetworkResponse.UnknownError -> Result.Failure(GeneralError.UnknownError(result.error))
}
}

override suspend fun removeFromHistory(id: Int): Result<Unit, GeneralError> {
val tokens =
traktAuthLocalSource.tokens.firstOrNull() ?: return Result.Failure(GeneralError.ApiError("Unauthorized", 401))
val result = traktSyncService.removeMovieFromHistory(
accessToken = "Bearer " + tokens.accessToken,
body = SyncHistoryRequest(
movies = listOf(
MovieHistory(
ids = HistoryIDS(
trakt = id,
),
),
),
),
)
return when (result) {
is NetworkResponse.Success -> Result.Success(Unit)
is NetworkResponse.ApiError -> Result.Failure(GeneralError.ApiError(result.body.error, result.code))
is NetworkResponse.NetworkError -> Result.Failure(GeneralError.NetworkError)
is NetworkResponse.UnknownError -> Result.Failure(GeneralError.UnknownError(result.error))
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class AddHistoryRequest(
data class SyncHistoryRequest(
val movies: List<MovieHistory>? = null,
val shows: List<Show>? = null,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@ package io.filmtime.data.network.trakt
import kotlinx.serialization.Serializable

@Serializable
data class AddToHistoryResponse(
val added: Added,
data class SyncHistoryResponse(
val added: SyncHistoryDto? = null,
val deleted: SyncHistoryDto? = null,
)

@Serializable
data class Added(
data class SyncHistoryDto(
val movies: Long,
val episodes: Long,
)
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ interface TraktSyncService {
@POST("sync/history")
suspend fun addMovieToHistory(
@Header("Authorization") accessToken: String,
@Body body: AddHistoryRequest,
): NetworkResponse<AddToHistoryResponse, TraktErrorResponse>
@Body body: SyncHistoryRequest,
): NetworkResponse<SyncHistoryResponse, TraktErrorResponse>

@POST("sync/history/remove")
suspend fun removeMovieFromHistory(
@Header("Authorization") accessToken: String,
@Body body: SyncHistoryRequest,
): NetworkResponse<SyncHistoryResponse, TraktErrorResponse>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ interface TraktHistoryRepository {
suspend fun isWatched(tmdbId: Int): Result<TraktHistory, GeneralError>

suspend fun addToHistory(traktId: Int): Result<Unit, GeneralError>

suspend fun removeFromHistory(traktId: Int): Result<Unit, GeneralError>
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ class TraktHistoryRepositoryImpl @Inject constructor(
}
}

override suspend fun addToHistory(traktId: Int): Result<Unit, GeneralError> {
return traktSyncRemoteSource.addToHistory(traktId)
}
override suspend fun addToHistory(traktId: Int): Result<Unit, GeneralError> =
traktSyncRemoteSource.addToHistory(traktId)

override suspend fun removeFromHistory(traktId: Int): Result<Unit, GeneralError> =
traktSyncRemoteSource.removeFromHistory(traktId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ import io.filmtime.data.model.Result

interface RemoveFromHistoryUseCase {

suspend operator fun invoke(id: String): Result<Boolean, GeneralError>
suspend operator fun invoke(id: Int): Result<Unit, GeneralError>
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import io.filmtime.domain.trakt.history.impl.AddToHistoryUseCaseImpl
import io.filmtime.domain.trakt.history.impl.IsMovieWatchedUseCaseImpl
import io.filmtime.domain.trakt.history.impl.RemoveFromHistoryUseCaseImpl

@InstallIn(SingletonComponent::class)
@Module
Expand All @@ -14,4 +17,7 @@ internal abstract class TraktHistoryModule {

@Binds
internal abstract fun bindAddToHistoryUseCase(impl: AddToHistoryUseCaseImpl): AddToHistoryUseCase

@Binds
internal abstract fun bindRemoveFromHistoryUseCase(impl: RemoveFromHistoryUseCaseImpl): RemoveFromHistoryUseCase
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package io.filmtime.domain.trakt.history
package io.filmtime.domain.trakt.history.impl

import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.trakt.TraktHistoryRepository
import io.filmtime.domain.trakt.history.AddToHistoryUseCase
import javax.inject.Inject

internal class AddToHistoryUseCaseImpl @Inject constructor(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package io.filmtime.domain.trakt.history
package io.filmtime.domain.trakt.history.impl

import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.model.TraktHistory
import io.filmtime.data.trakt.TraktHistoryRepository
import io.filmtime.domain.trakt.history.IsMovieWatchedUseCase
import javax.inject.Inject

internal class IsMovieWatchedUseCaseImpl @Inject constructor(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.filmtime.domain.trakt.history.impl

import io.filmtime.data.model.GeneralError
import io.filmtime.data.model.Result
import io.filmtime.data.trakt.TraktHistoryRepository
import io.filmtime.domain.trakt.history.RemoveFromHistoryUseCase
import javax.inject.Inject

internal class RemoveFromHistoryUseCaseImpl @Inject constructor(
private val traktHistoryRepository: TraktHistoryRepository,
) : RemoveFromHistoryUseCase {

override suspend fun invoke(id: Int): Result<Unit, GeneralError> =
traktHistoryRepository.removeFromHistory(id)
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fun TraktAddRemoveHistoryButton(
modifier = modifier,
onClick = {
if (state.isWatched) {
viewModel.removeItemFromHistory(tmdbId)
viewModel.removeItemFromHistory()
} else {
viewModel.addItemToHistory()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import io.filmtime.data.model.Result.Success
import io.filmtime.data.model.VideoType
import io.filmtime.domain.trakt.history.AddToHistoryUseCase
import io.filmtime.domain.trakt.history.IsMovieWatchedUseCase
import io.filmtime.domain.trakt.history.RemoveFromHistoryUseCase
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
Expand All @@ -16,8 +17,9 @@ import javax.inject.Inject

@HiltViewModel
internal class TraktHistoryViewModel @Inject constructor(
private val addToHistory: AddToHistoryUseCase,
private val isMovieWatchedUseCase: IsMovieWatchedUseCase,
private val addToHistory: AddToHistoryUseCase,
private val removeFromHistory: RemoveFromHistoryUseCase,
) : ViewModel() {

private val _state = MutableStateFlow(TraktAddRemoveUiState())
Expand Down Expand Up @@ -46,6 +48,14 @@ internal class TraktHistoryViewModel @Inject constructor(
}
}

fun removeItemFromHistory(traktId: Int) = viewModelScope.launch {
fun removeItemFromHistory() = viewModelScope.launch {
val traktId = state.value.traktId ?: return@launch

_state.update { state -> state.copy(isLoading = true) }

when (removeFromHistory(traktId)) {
is Success -> _state.update { state -> state.copy(isWatched = false, isLoading = false) }
is Failure -> _state.update { state -> state.copy(isLoading = false) }
}
}
}

0 comments on commit a5e903d

Please sign in to comment.