update
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
plugins {
|
||||
id("com.android.application")
|
||||
id("org.jetbrains.kotlin.android")
|
||||
id("org.jetbrains.kotlin.plugin.compose")
|
||||
alias(libs.plugins.android.application)
|
||||
alias(libs.plugins.kotlin.android)
|
||||
alias(libs.plugins.kotlin.compose)
|
||||
}
|
||||
|
||||
android {
|
||||
@@ -24,50 +24,54 @@ android {
|
||||
keyPassword = "youtubeapp"
|
||||
enableV1Signing = true
|
||||
enableV2Signing = true
|
||||
enableV3Signing = true
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
getByName("release") {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
debug {
|
||||
buildConfigField("String", "BASE_URL", "\"http://192.168.178.34:8000/\"")
|
||||
}
|
||||
release {
|
||||
signingConfig = signingConfigs.getByName("release")
|
||||
buildConfigField("String", "BASE_URL", "\"https://youtube.marha.de/\"")
|
||||
isMinifyEnabled = false
|
||||
proguardFiles(
|
||||
getDefaultProguardFile("proguard-android-optimize.txt"),
|
||||
"proguard-rules.pro"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
compose = true
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
compose = true
|
||||
buildConfig = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(platform("androidx.compose:compose-bom:2024.12.01"))
|
||||
implementation("androidx.compose.ui:ui")
|
||||
implementation("androidx.compose.material3:material3")
|
||||
implementation("androidx.compose.material:material-icons-extended")
|
||||
implementation("androidx.activity:activity-compose:1.9.3")
|
||||
implementation("androidx.navigation:navigation-compose:2.8.5")
|
||||
|
||||
// Networking
|
||||
implementation("com.squareup.retrofit2:retrofit:2.11.0")
|
||||
implementation("com.squareup.retrofit2:converter-gson:2.11.0")
|
||||
implementation("com.squareup.okhttp3:okhttp:4.12.0")
|
||||
|
||||
// Image Loading
|
||||
implementation("io.coil-kt:coil-compose:2.7.0")
|
||||
|
||||
// Video Player
|
||||
implementation("androidx.media3:media3-exoplayer:1.5.1")
|
||||
implementation("androidx.media3:media3-ui:1.5.1")
|
||||
|
||||
// ViewModel
|
||||
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:2.8.7")
|
||||
implementation("androidx.lifecycle:lifecycle-runtime-compose:2.8.7")
|
||||
implementation(platform(libs.androidx.compose.bom))
|
||||
implementation(libs.androidx.ui)
|
||||
implementation(libs.androidx.material3)
|
||||
implementation(libs.androidx.compose.material.icons.extended)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
implementation(libs.androidx.navigation.compose)
|
||||
implementation(libs.androidx.lifecycle.viewmodel.compose)
|
||||
implementation(libs.androidx.lifecycle.runtime.compose)
|
||||
implementation(libs.retrofit)
|
||||
implementation(libs.retrofit.converter.gson)
|
||||
implementation(libs.okhttp)
|
||||
implementation(libs.okhttp.logging.interceptor)
|
||||
implementation(libs.coil.compose)
|
||||
implementation(libs.media3.exoplayer)
|
||||
implementation(libs.media3.ui)
|
||||
}
|
||||
|
||||
1
app/frontend/proguard-rules.pro
vendored
Normal file
1
app/frontend/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1 @@
|
||||
# Add project-specific ProGuard rules here.
|
||||
@@ -10,6 +10,7 @@
|
||||
android:banner="@drawable/tv_banner"
|
||||
android:allowBackup="true"
|
||||
android:label="YouTube App"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
android:usesCleartextTraffic="true"
|
||||
android:theme="@android:style/Theme.Material.Light.NoActionBar">
|
||||
|
||||
|
||||
@@ -1,18 +1,27 @@
|
||||
package com.youtubeapp.data
|
||||
|
||||
import android.os.Build
|
||||
import com.youtubeapp.BuildConfig
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.gson.GsonConverterFactory
|
||||
|
||||
object ApiClient {
|
||||
val BASE_URL: String = if (Build.FINGERPRINT.contains("generic") || Build.FINGERPRINT.contains("sdk"))
|
||||
"http://10.0.2.2:8000/"
|
||||
else
|
||||
"http://192.168.178.34:8000/"
|
||||
val BASE_URL: String =
|
||||
if (BuildConfig.DEBUG && (Build.FINGERPRINT.contains("generic") || Build.FINGERPRINT.contains("sdk")))
|
||||
"http://10.0.2.2:8000/"
|
||||
else
|
||||
BuildConfig.BASE_URL
|
||||
|
||||
private val okHttp: OkHttpClient = OkHttpClient.Builder()
|
||||
.addInterceptor(HttpLoggingInterceptor().apply { level = HttpLoggingInterceptor.Level.BASIC })
|
||||
.build()
|
||||
|
||||
val api: VideoApi by lazy {
|
||||
Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.client(okHttp)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build()
|
||||
.create(VideoApi::class.java)
|
||||
|
||||
@@ -9,7 +9,7 @@ interface VideoApi {
|
||||
suspend fun getAllVideos(@Path("profileId") profileId: Int): List<Video>
|
||||
|
||||
@POST("videos/{id}/download")
|
||||
suspend fun triggerDownload(@Path("id") id: Int): Map<String, String>
|
||||
suspend fun triggerDownload(@Path("id") id: Int, @retrofit2.http.Query("maxHeight") maxHeight: Int): Map<String, String>
|
||||
|
||||
@POST("profiles/{profileId}/videos/cleanup")
|
||||
suspend fun cleanupVideos(
|
||||
|
||||
@@ -5,8 +5,8 @@ class VideoRepository(private val api: VideoApi = ApiClient.api) {
|
||||
suspend fun getAllVideos(profileId: Int): Result<List<Video>> =
|
||||
runCatching { api.getAllVideos(profileId) }
|
||||
|
||||
suspend fun triggerDownload(videoId: Int): Result<String> = runCatching {
|
||||
val response = api.triggerDownload(videoId)
|
||||
suspend fun triggerDownload(videoId: Int, maxHeight: Int = 1080): Result<String> = runCatching {
|
||||
val response = api.triggerDownload(videoId, maxHeight)
|
||||
response["status"] ?: "unknown"
|
||||
}
|
||||
|
||||
@@ -23,5 +23,6 @@ class VideoRepository(private val api: VideoApi = ApiClient.api) {
|
||||
|
||||
suspend fun getProfiles(): Result<List<Profile>> = runCatching { api.getProfiles() }
|
||||
|
||||
fun getStreamUrl(videoId: Int): String = "${ApiClient.BASE_URL}videos/$videoId/stream"
|
||||
fun getStreamUrl(videoId: Int, maxHeight: Int = 1080): String =
|
||||
"${ApiClient.BASE_URL}videos/$videoId/stream?maxHeight=$maxHeight"
|
||||
}
|
||||
|
||||
@@ -56,7 +56,9 @@ class VideoViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
private fun connectWebSocket() {
|
||||
val wsUrl = ApiClient.BASE_URL.replace("http://", "ws://") + "ws"
|
||||
val wsUrl = ApiClient.BASE_URL
|
||||
.replace("https://", "wss://")
|
||||
.replace("http://", "ws://") + "ws"
|
||||
val request = Request.Builder().url(wsUrl).build()
|
||||
val client = OkHttpClient()
|
||||
webSocket = client.newWebSocket(request, object : WebSocketListener() {
|
||||
@@ -122,10 +124,11 @@ class VideoViewModel : ViewModel() {
|
||||
}
|
||||
|
||||
fun triggerDownload(videoId: Int) {
|
||||
val maxHeight = if (android.os.Build.VERSION.SDK_INT < 29) 720 else 1080
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
_state.value = _state.value.copy(isDownloading = true, downloadStatus = null)
|
||||
try {
|
||||
val result = repository.triggerDownload(videoId)
|
||||
val result = repository.triggerDownload(videoId, maxHeight)
|
||||
if (result.isFailure) {
|
||||
_state.value = _state.value.copy(
|
||||
isDownloading = false,
|
||||
@@ -200,7 +203,8 @@ class VideoViewModel : ViewModel() {
|
||||
return if (localFile != null) {
|
||||
android.net.Uri.fromFile(localFile).toString()
|
||||
} else {
|
||||
repository.getStreamUrl(videoId)
|
||||
val maxHeight = if (android.os.Build.VERSION.SDK_INT < 29) 720 else 1080
|
||||
repository.getStreamUrl(videoId, maxHeight)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true" />
|
||||
</network-security-config>
|
||||
Reference in New Issue
Block a user