From 7f3c7ea69c54a44adcae95772f39141e343283fc Mon Sep 17 00:00:00 2001 From: KotlinGeekDev Date: Sat, 29 Jun 2024 01:13:16 +0100 Subject: [PATCH] Remove unnecessary files. --- .../mediaServers/MediaServerEditField.kt | 94 ------ .../mediaServers/MediaServersLIstView.kt | 288 ------------------ .../mediaServers/MediaServersViewModel.kt | 121 -------- 3 files changed, 503 deletions(-) delete mode 100644 app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServerEditField.kt delete mode 100644 app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServersLIstView.kt delete mode 100644 app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServersViewModel.kt diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServerEditField.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServerEditField.kt deleted file mode 100644 index d504f824ad..0000000000 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServerEditField.kt +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright (c) 2024 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.vitorpamplona.amethyst.ui.actions.mediaServers.mediaServers - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedTextField -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.ui.stringRes -import com.vitorpamplona.amethyst.ui.theme.ButtonBorder -import com.vitorpamplona.amethyst.ui.theme.Size10dp -import com.vitorpamplona.amethyst.ui.theme.placeholderText - -@Composable -fun MediaServerEditField( - modifier: Modifier = Modifier, - onAddServer: (String) -> Unit, -) { - var url by remember { mutableStateOf("") } - - Row( - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = - Arrangement.spacedBy( - Size10dp, - ), - ) { - OutlinedTextField( - label = { Text(text = stringRes(R.string.add_a_relay)) }, - modifier = Modifier.weight(1f), - value = url, - onValueChange = { url = it }, - placeholder = { - Text( - text = "server.com", - color = MaterialTheme.colorScheme.placeholderText, - maxLines = 1, - ) - }, - singleLine = true, - ) - - Button( - onClick = { - if (url.isNotBlank() && url != "/") { - onAddServer(url) - url = "" - } - }, - shape = ButtonBorder, - colors = - ButtonDefaults.buttonColors( - containerColor = - if (url.isNotBlank()) { - MaterialTheme.colorScheme.primary - } else { - MaterialTheme.colorScheme.placeholderText - }, - ), - ) { - Text(text = stringRes(id = R.string.add), color = Color.White) - } - } -} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServersLIstView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServersLIstView.kt deleted file mode 100644 index 689ad5ce96..0000000000 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServersLIstView.kt +++ /dev/null @@ -1,288 +0,0 @@ -/** - * Copyright (c) 2024 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.vitorpamplona.amethyst.ui.actions.mediaServers.mediaServers - -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListScope -import androidx.compose.foundation.lazy.itemsIndexed -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.rounded.Add -import androidx.compose.material.icons.rounded.Delete -import androidx.compose.material3.ExperimentalMaterial3Api -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.OutlinedButton -import androidx.compose.material3.Scaffold -import androidx.compose.material3.Text -import androidx.compose.material3.TopAppBar -import androidx.compose.material3.TopAppBarDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.LaunchedEffect -import androidx.compose.runtime.getValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog -import androidx.compose.ui.window.DialogProperties -import androidx.lifecycle.compose.collectAsStateWithLifecycle -import androidx.lifecycle.viewmodel.compose.viewModel -import com.vitorpamplona.amethyst.R -import com.vitorpamplona.amethyst.service.Nip96MediaServers -import com.vitorpamplona.amethyst.ui.actions.CloseButton -import com.vitorpamplona.amethyst.ui.actions.SaveButton -import com.vitorpamplona.amethyst.ui.actions.relays.SettingsCategoryWithButton -import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel -import com.vitorpamplona.amethyst.ui.stringRes -import com.vitorpamplona.amethyst.ui.theme.DoubleVertPadding -import com.vitorpamplona.amethyst.ui.theme.FeedPadding -import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer -import com.vitorpamplona.amethyst.ui.theme.grayText - -// TODO: Implement UI for Media servers view. -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun MediaServersListView( - onClose: () -> Unit, - accountViewModel: AccountViewModel, - nav: (String) -> Unit, -) { - val mediaServersViewModel: MediaServersViewModel = viewModel() - val mediaServersState by mediaServersViewModel.fileServers.collectAsStateWithLifecycle() - - LaunchedEffect(key1 = Unit) { - mediaServersViewModel.load(accountViewModel.account) - } - - Dialog( - onDismissRequest = onClose, - properties = DialogProperties(usePlatformDefaultWidth = false), - ) { - Scaffold( - topBar = { - TopAppBar( - title = { - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceAround, - verticalAlignment = Alignment.CenterVertically, - ) { - Text( - text = stringRes(id = R.string.media_servers), - style = MaterialTheme.typography.titleLarge, - ) - } - }, - navigationIcon = { - CloseButton( - onPress = { - mediaServersViewModel.refresh() - onClose() - }, - ) - }, - actions = { - SaveButton( - onPost = { - mediaServersViewModel.saveFileServers() - onClose() - }, - isActive = true, - ) - }, - colors = - TopAppBarDefaults.topAppBarColors( - containerColor = MaterialTheme.colorScheme.surface, - ), - ) - }, - ) { padding -> - Column( - modifier = - Modifier - .fillMaxSize() - .padding( - start = 16.dp, - top = padding.calculateTopPadding(), - end = 16.dp, - bottom = padding.calculateBottomPadding(), - ), - verticalArrangement = Arrangement.spacedBy(5.dp, alignment = Alignment.Top), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Text( - stringRes(id = R.string.set_preferred_media_servers), - textAlign = TextAlign.Center, - style = MaterialTheme.typography.bodyLarge, - color = MaterialTheme.colorScheme.grayText, - ) - - LazyColumn( - verticalArrangement = Arrangement.SpaceAround, - horizontalAlignment = Alignment.CenterHorizontally, - contentPadding = FeedPadding, - ) { - renderMediaServerList( - mediaServersState = mediaServersState, - onAddServer = { server -> - mediaServersViewModel.addServer(server) - }, - onDeleteServer = { - mediaServersViewModel.removeServer(serverUrl = it) - }, - ) - - Nip96MediaServers.DEFAULT.let { - item { - SettingsCategoryWithButton( - title = stringRes(id = R.string.built_in_media_servers_title), - description = stringRes(id = R.string.built_in_servers_description), - action = { - OutlinedButton( - onClick = { - mediaServersViewModel.addServerList(it.map { s -> s.baseUrl }) - }, - ) { - Text(text = stringRes(id = R.string.use_default_servers)) - } - }, - ) - } - itemsIndexed( - it, - key = { index: Int, server: Nip96MediaServers.ServerName -> - server.baseUrl - }, - ) { index, server -> - MediaServerEntry( - serverEntry = server, - isAmethystDefault = true, - onAddOrDelete = { serverUrl -> - mediaServersViewModel.addServer(serverUrl) - }, - ) - } - } - } - } - } - } -} - -fun LazyListScope.renderMediaServerList( - mediaServersState: List, - onAddServer: (String) -> Unit, - onDeleteServer: (String) -> Unit, -) { - if (mediaServersState.isEmpty()) { - item { - Text( - text = stringRes(id = R.string.no_media_server_message), - modifier = DoubleVertPadding, - ) - } - } else { - itemsIndexed( - mediaServersState, - key = { index: Int, server: Nip96MediaServers.ServerName -> - server.baseUrl - }, - ) { index, entry -> - MediaServerEntry( - serverEntry = entry, - onAddOrDelete = { - onDeleteServer(it) - }, - ) - } - } - - item { - Spacer(modifier = StdVertSpacer) - MediaServerEditField { - onAddServer(it) - } - } -} - -@Composable -fun MediaServerEntry( - modifier: Modifier = Modifier, - serverEntry: Nip96MediaServers.ServerName, - isAmethystDefault: Boolean = false, - onAddOrDelete: (serverUrl: String) -> Unit, -) { - Row( - modifier = - modifier - .fillMaxWidth() - .padding(vertical = 10.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceAround, - ) { - Column( - modifier = - Modifier - .weight(1f), - ) { - serverEntry.let { - Text( - text = it.name.replaceFirstChar(Char::titlecase), - style = MaterialTheme.typography.bodyLarge, - ) - Spacer(modifier = StdVertSpacer) - Text( - text = it.baseUrl, - style = MaterialTheme.typography.bodyMedium, - color = MaterialTheme.colorScheme.grayText, - ) - } - } - - Row( - horizontalArrangement = Arrangement.End, - ) { - IconButton( - onClick = { - onAddOrDelete(serverEntry.baseUrl) - }, - ) { - Icon( - imageVector = if (isAmethystDefault) Icons.Rounded.Add else Icons.Rounded.Delete, - contentDescription = - if (isAmethystDefault) { - stringRes(id = R.string.add_media_server) - } else { - stringRes(id = R.string.delete_media_server) - }, - ) - } - } - } -} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServersViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServersViewModel.kt deleted file mode 100644 index 4de113b0bc..0000000000 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/actions/mediaServers/mediaServers/MediaServersViewModel.kt +++ /dev/null @@ -1,121 +0,0 @@ -/** - * Copyright (c) 2024 Vitor Pamplona - * - * Permission is hereby granted, free of charge, to any person obtaining a copy of - * this software and associated documentation files (the "Software"), to deal in - * the Software without restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the - * Software, and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS - * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR - * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ -package com.vitorpamplona.amethyst.ui.actions.mediaServers.mediaServers - -import androidx.lifecycle.ViewModel -import androidx.lifecycle.viewModelScope -import com.vitorpamplona.amethyst.model.Account -import com.vitorpamplona.amethyst.service.Nip96MediaServers -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.MutableStateFlow -import kotlinx.coroutines.flow.asStateFlow -import kotlinx.coroutines.flow.update -import kotlinx.coroutines.launch -import org.czeal.rfc3986.URIReference - -class MediaServersViewModel : ViewModel() { - lateinit var account: Account - - private val _fileServers = MutableStateFlow>(emptyList()) - val fileServers = _fileServers.asStateFlow() - private var isModified = false - - fun load(account: Account) { - this.account = account - refresh() - } - - fun refresh() { - isModified = false - _fileServers.update { - val obtainedFileServers = obtainFileServers() ?: emptyList() - obtainedFileServers.map { serverUrl -> - Nip96MediaServers - .ServerName( - URIReference.parse(serverUrl).host.value, - serverUrl, - ) - } - } - } - - fun addServerList(serverList: List) { - serverList.forEach { serverUrl -> - addServer(serverUrl) - } - } - - fun addServer(serverUrl: String) { - val normalizedUrl = - try { - URIReference.parse(serverUrl.trim()).normalize().toString() - } catch (e: Exception) { - serverUrl - } - val serverNameReference = - try { - URIReference.parse(normalizedUrl).host.value - } catch (e: Exception) { - normalizedUrl - } - val serverRef = Nip96MediaServers.ServerName(serverNameReference, normalizedUrl) - if (_fileServers.value.contains(serverRef)) { - return - } else { - _fileServers.update { - it.plus(serverRef) - } - } - isModified = true - } - - fun removeServer( - name: String = "", - serverUrl: String, - ) { - viewModelScope.launch { - val serverName = if (name.isNotBlank()) name else URIReference.parse(serverUrl).host.value - _fileServers.update { - it.minus( - Nip96MediaServers.ServerName(serverName, serverUrl), - ) - } - isModified = true - } - } - - fun removeAllServers() { - _fileServers.update { emptyList() } - isModified = true - } - - fun saveFileServers() { - if (isModified) { - viewModelScope.launch(Dispatchers.IO) { - val serverList = _fileServers.value.map { it.baseUrl } - account.sendFileServersList(serverList) - refresh() - } - } - } - - private fun obtainFileServers(): List? = account.getFileServersList()?.servers() -}