mirror of
https://github.com/jellyfin/jellyfin-android.git
synced 2026-10-26 16:45:26 +00:00
Pre-fill last hostname and add history to suggestions in connect screen (#1134)
This commit is contained in:
1 parent
4de69d8845
commit
c1d0561704
6 files changed
+83
-23
No files matched your search
@@ -62,6 +62,12 @@ class ApiClientController(
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun loadPreviouslyUsedServers(): List<ServerEntity> = withContext(Dispatchers.IO) {
|
||||
serverDao.getAllServers().filterNot { server ->
|
||||
server.id == appPreferences.currentServerId
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureApiClientServer(server: ServerEntity?) {
|
||||
apiClient.baseUrl = server?.hostname
|
||||
}
|
||||
|
||||
@@ -17,6 +17,9 @@ interface ServerDao {
|
||||
@Query("SELECT * FROM $TABLE_NAME WHERE id = :id")
|
||||
fun getServer(id: Long): ServerEntity?
|
||||
|
||||
@Query("SELECT * FROM $TABLE_NAME ORDER BY last_used_timestamp DESC")
|
||||
fun getAllServers(): List<ServerEntity>
|
||||
|
||||
@Query("SELECT * FROM $TABLE_NAME WHERE hostname = :hostname")
|
||||
fun getServerByHostname(hostname: String): ServerEntity?
|
||||
}
|
||||
@@ -13,10 +13,10 @@ import org.jellyfin.mobile.ui.screens.connect.ConnectScreen
|
||||
import org.jellyfin.mobile.ui.utils.AppTheme
|
||||
import org.jellyfin.mobile.utils.Constants
|
||||
import org.jellyfin.mobile.utils.applyWindowInsetsAsMargins
|
||||
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
|
||||
import org.koin.androidx.viewmodel.ext.android.activityViewModel
|
||||
|
||||
class ConnectFragment : Fragment() {
|
||||
private val mainViewModel: MainViewModel by sharedViewModel()
|
||||
private val mainViewModel: MainViewModel by activityViewModel()
|
||||
private var _viewBinding: FragmentComposeBinding? = null
|
||||
private val viewBinding get() = _viewBinding!!
|
||||
private val composeView: ComposeView get() = viewBinding.composeView
|
||||
|
||||
@@ -53,31 +53,61 @@ import androidx.compose.ui.text.input.KeyboardType
|
||||
import androidx.compose.ui.unit.dp
|
||||
import kotlinx.coroutines.launch
|
||||
import org.jellyfin.mobile.R
|
||||
import org.jellyfin.mobile.app.ApiClientController
|
||||
import org.jellyfin.mobile.setup.ConnectionHelper
|
||||
import org.jellyfin.mobile.ui.state.CheckUrlState
|
||||
import org.jellyfin.mobile.ui.state.ServerSelectionType
|
||||
import org.jellyfin.mobile.ui.state.ServerSelectionMode
|
||||
import org.jellyfin.mobile.ui.utils.CenterRow
|
||||
import org.jellyfin.sdk.model.api.ServerDiscoveryInfo
|
||||
import org.koin.androidx.compose.get
|
||||
import org.koin.compose.koinInject
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Suppress("LongMethod")
|
||||
@Composable
|
||||
fun ServerSelection(
|
||||
showExternalConnectionError: Boolean,
|
||||
connectionHelper: ConnectionHelper = get(),
|
||||
apiClientController: ApiClientController = koinInject(),
|
||||
connectionHelper: ConnectionHelper = koinInject(),
|
||||
onConnected: suspend (String) -> Unit,
|
||||
) {
|
||||
val coroutineScope = rememberCoroutineScope()
|
||||
val keyboardController = LocalSoftwareKeyboardController.current
|
||||
var serverSelectionType by remember { mutableStateOf(ServerSelectionType.ADDRESS) }
|
||||
var serverSelectionMode by remember { mutableStateOf(ServerSelectionMode.ADDRESS) }
|
||||
var hostname by remember { mutableStateOf("") }
|
||||
val serverSuggestions = remember { mutableStateListOf<ServerSuggestion>() }
|
||||
var checkUrlState by remember<MutableState<CheckUrlState>> { mutableStateOf(CheckUrlState.Unchecked) }
|
||||
var externalError by remember { mutableStateOf(showExternalConnectionError) }
|
||||
|
||||
val discoveredServers = remember { mutableStateListOf<ServerDiscoveryInfo>() }
|
||||
// Prefill currently selected server if available
|
||||
LaunchedEffect(Unit) {
|
||||
val server = apiClientController.loadSavedServer()
|
||||
if (server != null) {
|
||||
hostname = server.hostname
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
// Suggest saved servers
|
||||
apiClientController.loadPreviouslyUsedServers().mapTo(serverSuggestions) { server ->
|
||||
ServerSuggestion(
|
||||
type = ServerSuggestion.Type.SAVED,
|
||||
name = server.hostname,
|
||||
address = server.hostname,
|
||||
timestamp = server.lastUsedTimestamp,
|
||||
)
|
||||
}
|
||||
|
||||
// Prepend discovered servers to suggestions
|
||||
connectionHelper.discoverServersAsFlow().collect { serverInfo ->
|
||||
discoveredServers.add(serverInfo)
|
||||
serverSuggestions.removeIf { existing -> existing.address == serverInfo.address }
|
||||
serverSuggestions.add(
|
||||
index = 0,
|
||||
ServerSuggestion(
|
||||
type = ServerSuggestion.Type.DISCOVERED,
|
||||
name = serverInfo.name,
|
||||
address = serverInfo.address,
|
||||
timestamp = System.currentTimeMillis(),
|
||||
),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,9 +129,12 @@ fun ServerSelection(
|
||||
modifier = Modifier.padding(bottom = 8.dp),
|
||||
style = MaterialTheme.typography.h5,
|
||||
)
|
||||
Crossfade(serverSelectionType) { selectionType ->
|
||||
Crossfade(
|
||||
targetState = serverSelectionMode,
|
||||
label = "Server selection mode",
|
||||
) { selectionType ->
|
||||
when (selectionType) {
|
||||
ServerSelectionType.ADDRESS -> AddressSelection(
|
||||
ServerSelectionMode.ADDRESS -> AddressSelection(
|
||||
text = hostname,
|
||||
errorText = when {
|
||||
externalError -> stringResource(R.string.connection_error_cannot_connect)
|
||||
@@ -116,20 +149,20 @@ fun ServerSelection(
|
||||
onDiscoveryClick = {
|
||||
externalError = false
|
||||
keyboardController?.hide()
|
||||
serverSelectionType = ServerSelectionType.AUTO_DISCOVERY
|
||||
serverSelectionMode = ServerSelectionMode.AUTO_DISCOVERY
|
||||
},
|
||||
onSubmit = {
|
||||
onSubmit()
|
||||
},
|
||||
)
|
||||
ServerSelectionType.AUTO_DISCOVERY -> ServerDiscoveryList(
|
||||
discoveredServers = discoveredServers,
|
||||
ServerSelectionMode.AUTO_DISCOVERY -> ServerDiscoveryList(
|
||||
serverSuggestions = serverSuggestions,
|
||||
onGoBack = {
|
||||
serverSelectionType = ServerSelectionType.ADDRESS
|
||||
serverSelectionMode = ServerSelectionMode.ADDRESS
|
||||
},
|
||||
onSelectServer = { url ->
|
||||
hostname = url
|
||||
serverSelectionType = ServerSelectionType.ADDRESS
|
||||
serverSelectionMode = ServerSelectionMode.ADDRESS
|
||||
onSubmit()
|
||||
},
|
||||
)
|
||||
@@ -257,7 +290,7 @@ private fun StyledTextButton(
|
||||
@Stable
|
||||
@Composable
|
||||
private fun ServerDiscoveryList(
|
||||
discoveredServers: SnapshotStateList<ServerDiscoveryInfo>,
|
||||
serverSuggestions: SnapshotStateList<ServerSuggestion>,
|
||||
onGoBack: () -> Unit,
|
||||
onSelectServer: (String) -> Unit,
|
||||
) {
|
||||
@@ -290,9 +323,9 @@ private fun ServerDiscoveryList(
|
||||
shape = MaterialTheme.shapes.medium,
|
||||
),
|
||||
) {
|
||||
items(discoveredServers) { server ->
|
||||
items(serverSuggestions) { server ->
|
||||
ServerDiscoveryItem(
|
||||
serverInfo = server,
|
||||
serverSuggestion = server,
|
||||
onClickServer = {
|
||||
onSelectServer(server.address)
|
||||
},
|
||||
@@ -306,7 +339,7 @@ private fun ServerDiscoveryList(
|
||||
@Stable
|
||||
@Composable
|
||||
private fun ServerDiscoveryItem(
|
||||
serverInfo: ServerDiscoveryInfo,
|
||||
serverSuggestion: ServerSuggestion,
|
||||
onClickServer: () -> Unit,
|
||||
) {
|
||||
ListItem(
|
||||
@@ -314,10 +347,10 @@ private fun ServerDiscoveryItem(
|
||||
.clip(MaterialTheme.shapes.medium)
|
||||
.clickable(onClick = onClickServer),
|
||||
text = {
|
||||
Text(text = serverInfo.name)
|
||||
Text(text = serverSuggestion.name)
|
||||
},
|
||||
secondaryText = {
|
||||
Text(text = serverInfo.address)
|
||||
Text(text = serverSuggestion.address)
|
||||
},
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.jellyfin.mobile.ui.screens.connect
|
||||
|
||||
data class ServerSuggestion(
|
||||
val type: Type,
|
||||
val name: String,
|
||||
val address: String,
|
||||
/**
|
||||
* A timestamp for this suggestion, used for sorting.
|
||||
* For discovered servers, this should be the discovery time,
|
||||
* for saved servers, this should be the last used time.
|
||||
*/
|
||||
val timestamp: Long,
|
||||
) {
|
||||
enum class Type {
|
||||
DISCOVERED,
|
||||
SAVED,
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
package org.jellyfin.mobile.ui.state
|
||||
|
||||
enum class ServerSelectionType {
|
||||
enum class ServerSelectionMode {
|
||||
ADDRESS,
|
||||
AUTO_DISCOVERY,
|
||||
}
|
||||
Reference in new issue
Block a user