This commit is contained in:
Marek Lenczewski
2026-04-06 21:40:43 +02:00
parent f48f0aac08
commit 8e1d482ef2
7 changed files with 63 additions and 19 deletions

View File

@@ -16,6 +16,23 @@ android {
versionName = "1.0"
}
signingConfigs {
create("release") {
storeFile = file("../release-key.jks")
storePassword = "youtubeapp"
keyAlias = "youtubeapp"
keyPassword = "youtubeapp"
enableV1Signing = true
enableV2Signing = true
}
}
buildTypes {
getByName("release") {
signingConfig = signingConfigs.getByName("release")
}
}
buildFeatures {
compose = true
}

View File

@@ -15,7 +15,8 @@
<activity
android:name=".MainActivity"
android:exported="true">
android:exported="true"
android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />

View File

@@ -8,7 +8,7 @@ object ApiClient {
val BASE_URL: String = if (Build.FINGERPRINT.contains("generic") || Build.FINGERPRINT.contains("sdk"))
"http://10.0.2.2:8000/"
else
"http://marha.local:8000/"
"http://192.168.178.34:8000/"
val api: VideoApi by lazy {
Retrofit.Builder()

View File

@@ -1,12 +1,15 @@
package com.youtubeapp.data
import android.content.Context
import com.google.gson.Gson
import java.io.File
import java.io.FileOutputStream
import java.net.URL
class LocalStorageService(private val context: Context) {
private val gson = Gson()
private fun videosDir(): File {
val dir = File(context.filesDir, "videos")
if (!dir.exists()) dir.mkdirs()
@@ -15,6 +18,8 @@ class LocalStorageService(private val context: Context) {
private fun videoFile(videoId: Int): File = File(videosDir(), "$videoId.mp4")
private fun metadataFile(videoId: Int): File = File(videosDir(), "$videoId.json")
fun isLocallyAvailable(videoId: Int): Boolean = videoFile(videoId).exists()
fun getLocalFile(videoId: Int): File? {
@@ -22,7 +27,10 @@ class LocalStorageService(private val context: Context) {
return if (file.exists()) file else null
}
fun deleteLocalFile(videoId: Int): Boolean = videoFile(videoId).delete()
fun deleteLocalFile(videoId: Int): Boolean {
metadataFile(videoId).delete()
return videoFile(videoId).delete()
}
fun getLocalVideoIds(): List<Int> {
return videosDir().listFiles()
@@ -31,6 +39,24 @@ class LocalStorageService(private val context: Context) {
?: emptyList()
}
fun saveMetadata(video: Video) {
metadataFile(video.id).writeText(gson.toJson(video))
}
fun getLocalVideos(): List<Video> {
return videosDir().listFiles()
?.filter { it.extension == "json" }
?.mapNotNull { file ->
try {
val video = gson.fromJson(file.readText(), Video::class.java)
if (videoFile(video.id).exists()) video else null
} catch (_: Exception) {
null
}
}
?: emptyList()
}
fun downloadAndSave(videoId: Int): File {
val url = "${ApiClient.BASE_URL}videos/$videoId/file"
val file = videoFile(videoId)

View File

@@ -109,24 +109,15 @@ class VideoViewModel : ViewModel() {
.onSuccess { videos ->
_state.value = _state.value.copy(allVideos = videos, isLoading = false)
}
.onFailure { e ->
_state.value = _state.value.copy(error = e.message, isLoading = false)
.onFailure {
_state.value = _state.value.copy(error = "Server nicht erreichbar", isLoading = false)
}
}
}
fun loadDownloadedVideos() {
viewModelScope.launch {
_state.value = _state.value.copy(isLoading = true, error = null)
repository.getAllVideos(profileId = _state.value.selectedProfileId)
.onSuccess { videos ->
val local = videos.filter { localStorage?.isLocallyAvailable(it.id) == true }
_state.value = _state.value.copy(downloadedVideos = local, isLoading = false)
}
.onFailure { e ->
_state.value = _state.value.copy(error = e.message, isLoading = false)
}
}
val videos = localStorage?.getLocalVideos() ?: emptyList()
_state.value = _state.value.copy(downloadedVideos = videos)
}
fun triggerDownload(videoId: Int) {
@@ -144,16 +135,24 @@ class VideoViewModel : ViewModel() {
val status = result.getOrNull()
if (status == "download_started") {
while (true) {
var attempts = 0
while (attempts < 150) {
delay(2000)
val videosResult = repository.getAllVideos()
val video = videosResult.getOrNull()?.find { it.id == videoId }
if (video?.is_downloaded == true) break
attempts++
}
if (attempts >= 150) throw Exception("Download fehlgeschlagen")
}
localStorage?.downloadAndSave(videoId)
val video = _state.value.allVideos.find { it.id == videoId }
if (video != null) {
localStorage?.saveMetadata(video)
}
repository.deleteServerFile(videoId)
loadDownloadedVideos()
_state.value = _state.value.copy(
isDownloading = false,
downloadStatus = "Lokal gespeichert"
@@ -187,6 +186,7 @@ class VideoViewModel : ViewModel() {
fun getVideoById(videoId: Int): Video? {
return _state.value.allVideos.find { it.id == videoId }
?: _state.value.downloadedVideos.find { it.id == videoId }
}
fun isLocallyAvailable(videoId: Int): Boolean {

BIN
app/release-key.jks Normal file

Binary file not shown.