Skip to content
Merged
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
53 changes: 51 additions & 2 deletions api/src/commonMain/kotlin/com/free/tvtracker/Endpoints.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,17 @@ import com.free.tvtracker.user.request.UpdatePreferencesApiRequestBody
import com.free.tvtracker.user.response.DataExportApiResponse
import com.free.tvtracker.user.response.SessionApiResponse
import com.free.tvtracker.user.response.UserApiResponse
import com.free.tvtracker.watchlists.requests.AddWatchlistApiRequestBody
import com.free.tvtracker.watchlists.requests.AddWatchlistContentApiRequestBody
import com.free.tvtracker.watchlists.requests.DeleteWatchlistApiRequestBody
import com.free.tvtracker.watchlists.requests.DeleteWatchlistContentApiRequestBody
import com.free.tvtracker.watchlists.requests.GetWatchlistContentApiRequestBody
import com.free.tvtracker.watchlists.requests.RenameWatchlistApiRequestBody
import com.free.tvtracker.watchlists.response.WatchlistsApiResponse
import kotlin.reflect.KClass

object Endpoints {
object Path {
const val GET_USER = ""
const val POST_USER_CREDENTIALS = "user/complete-credentials"
const val UPDATE_PREFERENCES = "user/update-push-notifications"
const val CREATE_ANON_USER = "/user/create-anon"
Expand All @@ -59,9 +65,15 @@ object Endpoints {
const val GET_RECOMMENDED_CONTENT_SHOWS = "discover/recommended/shows"
const val GET_RECOMMENDED_CONTENT_MOVIES = "discover/recommended/movies"
const val GET_EXPORT_SHOWS = "export/shows"
const val GET_WATCHLISTS = "watchlists/"
const val ADD_WATCHLISTS = "watchlists/"
const val REMOVE_WATCHLIST = "watchlists/delete"
const val EDIT_WATCHLIST = "watchlists/edit"
const val GET_WATCHLIST_CONTENT = "watchlists/content"
const val ADD_TRACKED_CONTENT_TO_WATCHLIST = "watchlists/content/add"
const val REMOVE_TRACKED_CONTENT_TO_WATCHLIST = "watchlists/content/delete"
}

val getUser = EndpointNoBody(Path.GET_USER, UserApiResponse::class, Endpoint.Verb.GET)
val createAnonUser = EndpointNoBody(Path.CREATE_ANON_USER, SessionApiResponse::class, Endpoint.Verb.POST)
val postUserCredentials =
Endpoint(Path.POST_USER_CREDENTIALS, SessionApiResponse::class, SignupApiRequestBody::class, Endpoint.Verb.POST)
Expand Down Expand Up @@ -171,6 +183,43 @@ object Endpoints {
Endpoint.Verb.POST
)
val getDataExport = EndpointNoBody(Path.GET_EXPORT_SHOWS, DataExportApiResponse::class, Endpoint.Verb.GET)
val getWatchlists = EndpointNoBody(Path.GET_WATCHLISTS, WatchlistsApiResponse::class, Endpoint.Verb.GET)
val getWatchlistContent = Endpoint(
Path.GET_WATCHLIST_CONTENT,
TrackedShowsApiResponse::class,
GetWatchlistContentApiRequestBody::class,
Endpoint.Verb.POST
)
val postWatchlistRename = Endpoint(
Path.EDIT_WATCHLIST,
WatchlistsApiResponse::class,
RenameWatchlistApiRequestBody::class,
Endpoint.Verb.POST
)
val postWatchlistDelete = Endpoint(
Path.REMOVE_WATCHLIST,
WatchlistsApiResponse::class,
DeleteWatchlistApiRequestBody::class,
Endpoint.Verb.POST
)
val postWatchlistCreate = Endpoint(
Path.ADD_WATCHLISTS,
WatchlistsApiResponse::class,
AddWatchlistApiRequestBody::class,
Endpoint.Verb.POST
)
val addContentToWatchlist = Endpoint(
Path.ADD_TRACKED_CONTENT_TO_WATCHLIST,
TrackedShowApiResponse::class,
AddWatchlistContentApiRequestBody::class,
Endpoint.Verb.POST
)
val removeContentToWatchlist = Endpoint(
Path.REMOVE_TRACKED_CONTENT_TO_WATCHLIST,
TrackedShowApiResponse::class,
DeleteWatchlistContentApiRequestBody::class,
Endpoint.Verb.POST
)
}

open class Endpoint<ReturnType : ApiResponse<out Any>, BodyType : Any>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,5 +23,6 @@ data class RecommendedContentApiModel(
@SerialName("first_air_date") val firstAirDate: String? = null,
@SerialName("vote_average") val voteAverage: Double? = null,
@SerialName("vote_count") val voteCount: Int? = null,
@SerialName("is_tvshow") val isTvShow: Boolean? = null,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ data class TrackedContentApiModel(
@SerialName("watchlisted") val watchlisted: Boolean,
@SerialName("content_type") val mediaType: ContentType,
@SerialName("tv_show") val tvShow: TvShow?,
@SerialName("movie") val movie: Movie?
@SerialName("movie") val movie: Movie?,
@SerialName("lists") var watchlists: List<Watchlist>
) {
enum class ContentType(val key:String) {
enum class ContentType(val key: String) {
TvShow("tvshow"),
Person("person"),
Movie("movie");
Expand Down Expand Up @@ -78,4 +79,10 @@ data class TrackedContentApiModel(
@SerialName("air_date") val airDate: String?,
)
}

@Serializable
data class Watchlist(
@SerialName("id") val id: Int,
@SerialName("name") val name: String
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.free.tvtracker.watchlists.requests

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class AddWatchlistApiRequestBody(
@SerialName("name") val name: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.free.tvtracker.watchlists.requests

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class AddWatchlistContentApiRequestBody(
@SerialName("tracked_content_id") val trackedContentId: Int,
@SerialName("watchlist_id") val watchlistId: Int,
@SerialName("is_tv_show") val isTvShow: Boolean
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.free.tvtracker.watchlists.requests

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class DeleteWatchlistApiRequestBody(
@SerialName("watchlist_id") val watchlistId: Int
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.free.tvtracker.watchlists.requests

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class DeleteWatchlistContentApiRequestBody(
@SerialName("tracked_content_id") val trackedContentId: Int,
@SerialName("watchlist_id") val watchlistId: Int,
@SerialName("is_tv_show") val isTvShow: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.free.tvtracker.watchlists.requests

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class GetWatchlistContentApiRequestBody(
@SerialName("watchlist_id") val watchlistId: Int,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.free.tvtracker.watchlists.requests

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class RenameWatchlistApiRequestBody(
@SerialName("watchlist_id") val watchlistId: Int,
@SerialName("name") val name: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.free.tvtracker.watchlists.response

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class WatchlistApiModel(
@SerialName("id") val id: Int,
@SerialName("name") val name: String,
@SerialName("tv_show_count") val showsCount: Int,
@SerialName("movie_count") val moviesCount: Int
) {
companion object {
const val WATCHLIST_LIST_ID = Int.MAX_VALUE
const val FINISHED_LIST_ID = Int.MAX_VALUE -1
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.free.tvtracker.watchlists.response

import com.free.tvtracker.base.ApiError
import com.free.tvtracker.base.ApiResponse
import kotlinx.serialization.Serializable

@Serializable
data class WatchlistsApiResponse(
override val data: List<WatchlistApiModel>? = null,
override val application_error: ApiError? = null
) : ApiResponse<List<WatchlistApiModel>>() {
companion object {
fun ok(data: List<WatchlistApiModel>): WatchlistsApiResponse {
return WatchlistsApiResponse(data = data)
}

fun error(application_error: ApiError): WatchlistsApiResponse {
return WatchlistsApiResponse(application_error = application_error)
}
}
}
2 changes: 2 additions & 0 deletions composeApp/src/androidMain/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
android:name=".activities.main.MainActivity" android:label="MainActivity"/>
<activity android:name=".activities.welcome.WelcomeActivity" android:label="WelcomeActivity"/>
<activity android:name=".activities.showdetails.ShowDetailsActivity" android:label="ShowDetailsActivity"/>
<activity android:name=".activities.watchlists.WatchlistDetailsActivity"
android:label="WatchlistDetailsActivity"/>
<activity android:name=".activities.add.AddTrackedActivity" android:label="AddTrackedActivity"/>
<activity android:name=".activities.person.PersonDetailsActivity" android:label="PersonDetailsActivity"/>
<activity android:name=".activities.discover.RecommendationsActivity" android:label="RecommendationsActivity"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@ import com.free.tvtracker.di.appModules
import com.free.tvtracker.expect.AndroidAppPriceProvider
import com.free.tvtracker.expect.AndroidFileExporter
import com.free.tvtracker.expect.initSentry
import com.free.tvtracker.ui.details.DetailsViewModel
import com.free.tvtracker.ui.details.ContentDetailsViewModel
import com.free.tvtracker.ui.discover.DiscoverViewModel
import com.free.tvtracker.ui.finished.FinishedShowsViewModel
import com.free.tvtracker.ui.person.PersonViewModel
import com.free.tvtracker.ui.search.AddTrackedViewModel
import com.free.tvtracker.ui.settings.FileExporter
Expand All @@ -21,7 +20,8 @@ import com.free.tvtracker.ui.settings.login.LoginViewModel
import com.free.tvtracker.ui.settings.signup.SignupViewModel
import com.free.tvtracker.ui.splash.SplashViewModel
import com.free.tvtracker.ui.watching.WatchingViewModel
import com.free.tvtracker.ui.watchlist.WatchlistedShowsViewModel
import com.free.tvtracker.ui.watchlists.details.WatchlistDetailsViewModel
import com.free.tvtracker.ui.watchlists.list.WatchlistsViewModel
import com.free.tvtracker.ui.welcome.WelcomeViewModel
import com.posthog.android.PostHogAndroid
import com.posthog.android.PostHogAndroidConfig
Expand All @@ -32,6 +32,7 @@ import kotlinx.coroutines.launch
import org.koin.android.ext.android.get
import org.koin.androidx.viewmodel.dsl.viewModel
import org.koin.core.context.startKoin
import org.koin.core.scope.Scope
import org.koin.dsl.module


Expand Down Expand Up @@ -84,24 +85,24 @@ class AndroidApplication : Application() {
module {
single<AppPriceProvider> { AndroidAppPriceProvider(context) }
single<FileExporter> { AndroidFileExporter() }
viewModel { SplashViewModel(get(), get()) }
viewModel { WelcomeViewModel(get(), get(), get(), get()) }
viewModel { AddTrackedViewModel(get(), get(), get(), get(), get(), get()) }
viewModel { WatchingViewModel(get(), get(), get(), get(), get(), get(), get()) }
viewModel { FinishedShowsViewModel(get(), get(), get(), get(), get(), get(), get()) }
viewModel { WatchlistedShowsViewModel(get(), get(), get(), get(), get(), get(), get()) }
viewModel { DetailsViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) }
viewModel { PersonViewModel(get(), get()) }
viewModel { LoginViewModel(get(), get()) }
viewModel { SignupViewModel(get()) }
viewModel { SplashViewModel(g(), g()) }
viewModel { WelcomeViewModel(g(), g(), g(), g()) }
viewModel { AddTrackedViewModel(g(), g(), g(), g(), g(), g()) }
viewModel { WatchingViewModel(g(), g(), g(), g(), g(), g(), g()) }
viewModel { WatchlistsViewModel(g(), g(), g(), g(), g(), g(), g(), g()) }
viewModel { WatchlistDetailsViewModel(g(), g(), g(), g(), g(), g(), g()) }
viewModel { ContentDetailsViewModel(g(), g(), g(), g(), g(), g(), g(), g(), g(), g(), g(), g()) }
viewModel { PersonViewModel(g(), g()) }
viewModel { LoginViewModel(g(), g()) }
viewModel { SignupViewModel(g()) }
single {
// shared on TvTrackerTheme for all activities
SettingsViewModel(get(), get(), get(), get(), get())
SettingsViewModel(g(), g(), g(), g(), g())
}
single {
// why `single` and not `viewmodel`? to share it
// between the discover and recommendations activities
DiscoverViewModel(get(), get(), get(), get(), get())
DiscoverViewModel(g(), g(), g(), g(), g())
}
}
)
Expand All @@ -114,3 +115,5 @@ class AndroidApplication : Application() {
}
}
}

inline fun <reified T : Any> Scope.g() = get<T>()
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
Expand Down Expand Up @@ -86,7 +87,11 @@ class AddTrackedActivity : BaseActivity() {
colors = TopAppBarDefaults.topAppBarColors(),
navigationIcon = {
IconButton(onClick = { this.finish() }) {
Icon(Icons.AutoMirrored.Rounded.ArrowBack, "")
Icon(
Icons.AutoMirrored.Rounded.ArrowBack,
"",
tint = MaterialTheme.colorScheme.primary
)
}
},
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
Expand Down Expand Up @@ -56,7 +57,11 @@ class RecommendationsActivity : BaseActivity() {
colors = TopAppBarDefaults.mediumTopAppBarColors(),
navigationIcon = {
IconButton(onClick = { this.finish() }) {
Icon(Icons.AutoMirrored.Rounded.ArrowBack, "")
Icon(
Icons.AutoMirrored.Rounded.ArrowBack,
"",
tint = MaterialTheme.colorScheme.primary
)
}
}
)
Expand Down
Loading