feat(deeplink): add DeeplinkNavigator, DeeplinkBottomSheet and integrate into History and Player

This commit is contained in:
nk
2026-06-01 13:15:31 +03:00
parent aa287f7588
commit ada422053f
4 changed files with 79 additions and 5 deletions

View File

@@ -0,0 +1,16 @@
package com.radiola.deeplink
import android.content.Context
import android.content.Intent
import android.net.Uri
import com.radiola.domain.model.DeeplinkService
import com.radiola.domain.model.Track
object DeeplinkNavigator {
fun openSearch(context: Context, track: Track, service: DeeplinkService) {
val url = service.buildSearchUrl(track.artist, track.song)
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
context.startActivity(Intent.createChooser(intent, "Открыть в..."))
}
}

View File

@@ -0,0 +1,50 @@
package com.radiola.ui.components
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.radiola.deeplink.DeeplinkNavigator
import com.radiola.domain.model.DeeplinkService
import com.radiola.domain.model.Track
import com.radiola.ui.player.PlayerViewModel
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun DeeplinkBottomSheet(
track: Track,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
viewModel: PlayerViewModel = hiltViewModel()
) {
val context = androidx.compose.ui.platform.LocalContext.current
val enabledServices by viewModel.enabledServices.collectAsState()
ModalBottomSheet(
onDismissRequest = onDismiss,
modifier = modifier
) {
Text(
text = "Найти трек",
style = MaterialTheme.typography.headlineSmall,
modifier = Modifier.padding(horizontal = 24.dp, vertical = 16.dp)
)
LazyColumn {
items(enabledServices) { service ->
ListItem(
headlineContent = { Text(service.displayName) },
modifier = Modifier.clickable {
DeeplinkNavigator.openSearch(context, track, service)
onDismiss()
}
)
}
}
}
}

View File

@@ -8,6 +8,8 @@ import androidx.compose.runtime.*
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import com.radiola.domain.model.Track
import com.radiola.ui.components.DeeplinkBottomSheet
import com.radiola.ui.components.EmptyState import com.radiola.ui.components.EmptyState
import com.radiola.ui.components.SearchBar import com.radiola.ui.components.SearchBar
import com.radiola.ui.components.TrackListItem import com.radiola.ui.components.TrackListItem
@@ -20,6 +22,7 @@ fun HistoryScreen(
) { ) {
val history by viewModel.history.collectAsState() val history by viewModel.history.collectAsState()
val searchQuery by viewModel.searchQuery.collectAsState() val searchQuery by viewModel.searchQuery.collectAsState()
var selectedTrack by remember { mutableStateOf<Track?>(null) }
Scaffold( Scaffold(
topBar = { topBar = {
@@ -52,7 +55,7 @@ fun HistoryScreen(
items(history) { track -> items(history) { track ->
TrackListItem( TrackListItem(
track = track, track = track,
onClick = { /* TODO: open deeplink bottom sheet */ } onClick = { selectedTrack = track }
) )
Divider(color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.05f)) Divider(color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.05f))
} }
@@ -60,4 +63,11 @@ fun HistoryScreen(
} }
} }
} }
if (selectedTrack != null) {
DeeplinkBottomSheet(
track = selectedTrack!!,
onDismiss = { selectedTrack = null }
)
}
} }

View File

@@ -1,7 +1,5 @@
package com.radiola.ui.player package com.radiola.ui.player
import android.content.Intent
import android.net.Uri
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
@@ -26,6 +24,7 @@ import com.composables.icons.lucide.Pause
import com.composables.icons.lucide.Play import com.composables.icons.lucide.Play
import com.radiola.domain.model.DeeplinkService import com.radiola.domain.model.DeeplinkService
import com.radiola.domain.model.Station import com.radiola.domain.model.Station
import com.radiola.deeplink.DeeplinkNavigator
import com.radiola.domain.model.Track import com.radiola.domain.model.Track
@Composable @Composable
@@ -97,8 +96,7 @@ fun PlayerBottomSheet(
service = service, service = service,
onClick = { onClick = {
track?.let { t -> track?.let { t ->
val url = viewModel.getDeeplinkUrl(t, service) DeeplinkNavigator.openSearch(context, t, service)
context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(url)))
} }
} }
) )