This commit is contained in:
Marek
2026-04-05 22:20:51 +02:00
parent a67e1393d7
commit 375169f496
9 changed files with 40 additions and 1 deletions

View File

@@ -15,6 +15,9 @@ interface VideoApi {
@POST("videos/{id}/download") @POST("videos/{id}/download")
suspend fun triggerDownload(@Path("id") id: Int): Map<String, String> suspend fun triggerDownload(@Path("id") id: Int): Map<String, String>
@retrofit2.http.DELETE("videos")
suspend fun deleteNotDownloaded(@Query("profile_id") profileId: Int): Map<String, Int>
@GET("profiles") @GET("profiles")
suspend fun getProfiles(): List<Profile> suspend fun getProfiles(): List<Profile>
} }

View File

@@ -13,6 +13,11 @@ class VideoRepository(private val api: VideoApi = ApiClient.api) {
response["status"] ?: "unknown" response["status"] ?: "unknown"
} }
suspend fun deleteNotDownloaded(profileId: Int): Result<Int> = runCatching {
val response = api.deleteNotDownloaded(profileId)
response["deleted"] ?: 0
}
suspend fun getProfiles(): Result<List<Profile>> = runCatching { api.getProfiles() } suspend fun getProfiles(): Result<List<Profile>> = runCatching { api.getProfiles() }
fun getStreamUrl(videoId: Int): String = "${ApiClient.BASE_URL}videos/$videoId/stream" fun getStreamUrl(videoId: Int): String = "${ApiClient.BASE_URL}videos/$videoId/stream"

View File

@@ -2,6 +2,7 @@ package com.youtubeapp.ui.navigation
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.DeleteSweep
import androidx.compose.material.icons.filled.Download import androidx.compose.material.icons.filled.Download
import androidx.compose.material.icons.filled.Person import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.VideoLibrary import androidx.compose.material.icons.filled.VideoLibrary
@@ -64,6 +65,9 @@ fun AppNavigation() {
TopAppBar( TopAppBar(
title = { Text("YouTube App") }, title = { Text("YouTube App") },
actions = { actions = {
IconButton(onClick = { viewModel.deleteNotDownloaded() }) {
Icon(Icons.Default.DeleteSweep, contentDescription = "Aufraeumen")
}
IconButton(onClick = { showProfileMenu = true }) { IconButton(onClick = { showProfileMenu = true }) {
Icon(Icons.Default.Person, contentDescription = "Profil") Icon(Icons.Default.Person, contentDescription = "Profil")
} }

View File

@@ -126,6 +126,14 @@ class VideoViewModel : ViewModel() {
} }
} }
fun deleteNotDownloaded() {
val profileId = _state.value.selectedProfileId ?: return
viewModelScope.launch {
repository.deleteNotDownloaded(profileId)
loadAllVideos()
}
}
fun deleteLocalVideo(videoId: Int) { fun deleteLocalVideo(videoId: Int) {
localStorage?.deleteLocalFile(videoId) localStorage?.deleteLocalFile(videoId)
_state.value = _state.value.copy(downloadStatus = "Lokal gelöscht") _state.value = _state.value.copy(downloadStatus = "Lokal gelöscht")

View File

@@ -39,6 +39,12 @@ def get_downloaded_videos(profile_id: Optional[int] = Query(None), db: Session =
return [VideoResponse.from_model(v) for v in videos] return [VideoResponse.from_model(v) for v in videos]
@router.delete("")
def delete_not_downloaded(profile_id: int = Query(...), db: Session = Depends(get_db)):
count = video_service.delete_not_downloaded(db, profile_id)
return {"deleted": count}
@router.post("/{video_id}/download") @router.post("/{video_id}/download")
def trigger_download(video_id: int, db: Session = Depends(get_db)): def trigger_download(video_id: int, db: Session = Depends(get_db)):
video = video_service.get_video(db, video_id) video = video_service.get_video(db, video_id)

View File

@@ -48,5 +48,17 @@ def update_file_path(db: Session, video_id: int, path: str):
db.commit() db.commit()
def delete_not_downloaded(db: Session, profile_id: int) -> int:
videos = db.query(Video).filter(
Video.file_path.is_(None),
Video.profiles.any(Profile.id == profile_id),
).all()
count = len(videos)
for video in videos:
db.delete(video)
db.commit()
return count
def get_all_profiles(db: Session) -> list[Profile]: def get_all_profiles(db: Session) -> list[Profile]:
return db.query(Profile).all() return db.query(Profile).all()

View File

@@ -11,4 +11,5 @@
- Klick auf Startet startet den Stream über den Server mit den Standard Video-Controls und einem Zurück-Button - Klick auf Startet startet den Stream über den Server mit den Standard Video-Controls und einem Zurück-Button
- Klick auf Download lädt das Video herunter und wird lokal auf dem Client gespeichert - Klick auf Download lädt das Video herunter und wird lokal auf dem Client gespeichert
- Klick auf Icon zeigt verfügbare Profile - Klick auf Icon zeigt verfügbare Profile
- Das ausgewählte Profil wird persistiert und bestimmt welche Videos angezeigt werden - Das ausgewählte Profil wird persistiert und bestimmt welche Videos angezeigt werden
- Klick auf Icon löscht alle nicht heruntergeladenen Videos vom aktuellen Profil