|
|
|
@ -6,13 +6,14 @@ import android.net.Uri
|
|
|
|
|
import android.widget.Toast
|
|
|
|
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
|
|
|
|
import androidx.compose.foundation.combinedClickable
|
|
|
|
|
import androidx.compose.foundation.layout.Arrangement
|
|
|
|
|
import androidx.compose.foundation.layout.Column
|
|
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
|
|
import androidx.compose.foundation.layout.RowScope
|
|
|
|
|
import androidx.compose.foundation.layout.Spacer
|
|
|
|
|
import androidx.compose.foundation.layout.fillMaxHeight
|
|
|
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
|
|
|
import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
|
|
import androidx.compose.foundation.layout.size
|
|
|
|
|
import androidx.compose.foundation.lazy.LazyColumn
|
|
|
|
|
import androidx.compose.foundation.lazy.LazyListState
|
|
|
|
|
import androidx.compose.foundation.lazy.items
|
|
|
|
@ -20,8 +21,11 @@ import androidx.compose.foundation.lazy.rememberLazyListState
|
|
|
|
|
import androidx.compose.foundation.text.KeyboardActions
|
|
|
|
|
import androidx.compose.material.icons.Icons
|
|
|
|
|
import androidx.compose.material.icons.filled.Search
|
|
|
|
|
import androidx.compose.material.icons.outlined.CalendarToday
|
|
|
|
|
import androidx.compose.material.icons.outlined.DataUsage
|
|
|
|
|
import androidx.compose.material.icons.outlined.FileUpload
|
|
|
|
|
import androidx.compose.material3.ButtonDefaults
|
|
|
|
|
import androidx.compose.material3.Divider
|
|
|
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
|
|
|
import androidx.compose.material3.Icon
|
|
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
|
|
import androidx.compose.material3.Text
|
|
|
|
@ -33,12 +37,14 @@ 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.ExperimentalComposeUiApi
|
|
|
|
|
import androidx.compose.ui.Modifier
|
|
|
|
|
import androidx.compose.ui.focus.FocusRequester
|
|
|
|
|
import androidx.compose.ui.focus.focusRequester
|
|
|
|
|
import androidx.compose.ui.focus.onFocusChanged
|
|
|
|
|
import androidx.compose.ui.graphics.Color
|
|
|
|
|
import androidx.compose.ui.graphics.vector.ImageVector
|
|
|
|
|
import androidx.compose.ui.input.key.NativeKeyEvent
|
|
|
|
|
import androidx.compose.ui.input.key.onKeyEvent
|
|
|
|
|
import androidx.compose.ui.platform.LocalClipboardManager
|
|
|
|
@ -46,7 +52,6 @@ import androidx.compose.ui.platform.LocalContext
|
|
|
|
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|
|
|
|
import androidx.compose.ui.res.stringResource
|
|
|
|
|
import androidx.compose.ui.text.AnnotatedString
|
|
|
|
|
import androidx.compose.ui.text.style.TextAlign
|
|
|
|
|
import androidx.compose.ui.text.style.TextOverflow
|
|
|
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
|
|
|
import androidx.compose.ui.unit.dp
|
|
|
|
@ -62,25 +67,10 @@ import kotlinx.coroutines.delay
|
|
|
|
|
import java.util.Date
|
|
|
|
|
import java.util.Locale
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
fun RowScope.TableCell(
|
|
|
|
|
text: String,
|
|
|
|
|
weight: Float,
|
|
|
|
|
textAlign: TextAlign = TextAlign.Start,
|
|
|
|
|
color: Color = MaterialTheme.colorScheme.onBackground,
|
|
|
|
|
) {
|
|
|
|
|
Text(
|
|
|
|
|
text = text,
|
|
|
|
|
Modifier.weight(weight),
|
|
|
|
|
style = MaterialTheme.typography.bodySmall,
|
|
|
|
|
color = color,
|
|
|
|
|
textAlign = textAlign,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
fun TorrentListView(torrents: List<Torrent>, listState: LazyListState) {
|
|
|
|
|
Column(modifier = Modifier.padding(DEFAULT_PADDING)) {
|
|
|
|
|
Column {
|
|
|
|
|
Spacer(Modifier.size(DEFAULT_PADDING))
|
|
|
|
|
LazyColumn(state = listState, modifier = Modifier.fillMaxHeight()) {
|
|
|
|
|
items(torrents) { torrent ->
|
|
|
|
|
TorrentView(torrent)
|
|
|
|
@ -128,62 +118,69 @@ fun TorrentView(torrent: Torrent) {
|
|
|
|
|
),
|
|
|
|
|
) {
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier.padding(0.dp, 0.dp, 0.dp, DEFAULT_PADDING),
|
|
|
|
|
modifier = Modifier.padding(
|
|
|
|
|
DEFAULT_PADDING,
|
|
|
|
|
0.dp,
|
|
|
|
|
DEFAULT_PADDING,
|
|
|
|
|
DEFAULT_PADDING,
|
|
|
|
|
),
|
|
|
|
|
) {
|
|
|
|
|
Text(
|
|
|
|
|
torrent.name,
|
|
|
|
|
maxLines = 4,
|
|
|
|
|
overflow = TextOverflow.Ellipsis,
|
|
|
|
|
style = MaterialTheme.typography.titleSmall,
|
|
|
|
|
style = MaterialTheme.typography.titleMedium,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// The table
|
|
|
|
|
val column1Weight = .5f
|
|
|
|
|
val column2Weight = .5f
|
|
|
|
|
Column(
|
|
|
|
|
Modifier
|
|
|
|
|
.fillMaxSize()
|
|
|
|
|
.padding(horizontal = DEFAULT_PADDING),
|
|
|
|
|
Row(
|
|
|
|
|
modifier = Modifier
|
|
|
|
|
.fillMaxWidth()
|
|
|
|
|
.padding(horizontal = DEFAULT_PADDING.times(1.5f)),
|
|
|
|
|
horizontalArrangement = Arrangement.SpaceBetween,
|
|
|
|
|
) {
|
|
|
|
|
Row(Modifier.fillMaxWidth()) {
|
|
|
|
|
val seeders = torrent.seeders
|
|
|
|
|
TableCell(text = stringResource(R.string.seeds), weight = column1Weight)
|
|
|
|
|
TableCell(
|
|
|
|
|
text = seeders.toString(),
|
|
|
|
|
weight = column2Weight,
|
|
|
|
|
textAlign = TextAlign.End,
|
|
|
|
|
color = seederColor(seeders),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
// Row(Modifier.fillMaxWidth()) {
|
|
|
|
|
// TableCell(text = "Leeches", weight = column1Weight)
|
|
|
|
|
// TableCell(text = torrent.leechers.toString(), weight = column2Weight)
|
|
|
|
|
// }
|
|
|
|
|
Row(Modifier.fillMaxWidth()) {
|
|
|
|
|
TableCell(text = stringResource(R.string.size), weight = column1Weight)
|
|
|
|
|
TableCell(
|
|
|
|
|
text = formatSize(torrent.size_bytes),
|
|
|
|
|
weight = column2Weight,
|
|
|
|
|
textAlign = TextAlign.End,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
Row(Modifier.fillMaxWidth()) {
|
|
|
|
|
TableCell(text = stringResource(R.string.created), weight = column1Weight)
|
|
|
|
|
TableCell(
|
|
|
|
|
text = created,
|
|
|
|
|
weight = column2Weight,
|
|
|
|
|
textAlign = TextAlign.End,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
// Row(Modifier.fillMaxWidth()) {
|
|
|
|
|
// TableCell(text = "Scraped", weight = column1Weight)
|
|
|
|
|
// TableCell(text = scraped, weight = column2Weight)
|
|
|
|
|
// }
|
|
|
|
|
IconAndText(
|
|
|
|
|
text = torrent.seeders.toString(),
|
|
|
|
|
icon = Icons.Outlined.FileUpload,
|
|
|
|
|
iconText = stringResource(R.string.seeds),
|
|
|
|
|
color = seederColor(torrent.seeders),
|
|
|
|
|
)
|
|
|
|
|
IconAndText(
|
|
|
|
|
text = formatSize(torrent.size_bytes),
|
|
|
|
|
icon = Icons.Outlined.DataUsage,
|
|
|
|
|
iconText = stringResource(R.string.size),
|
|
|
|
|
)
|
|
|
|
|
IconAndText(
|
|
|
|
|
text = created,
|
|
|
|
|
icon = Icons.Outlined.CalendarToday,
|
|
|
|
|
iconText = stringResource(R.string.created),
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
private fun IconAndText(
|
|
|
|
|
text: String,
|
|
|
|
|
icon: ImageVector,
|
|
|
|
|
iconText: String,
|
|
|
|
|
color: Color = Color.Unspecified,
|
|
|
|
|
) {
|
|
|
|
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
|
|
|
|
Icon(
|
|
|
|
|
icon,
|
|
|
|
|
iconText,
|
|
|
|
|
modifier = Modifier.size(24.dp),
|
|
|
|
|
)
|
|
|
|
|
Spacer(modifier = Modifier.size(ButtonDefaults.IconSpacing))
|
|
|
|
|
Text(
|
|
|
|
|
text = text,
|
|
|
|
|
style = MaterialTheme.typography.bodySmall,
|
|
|
|
|
color = color,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Composable
|
|
|
|
|
fun seederColor(seeders: Int): Color {
|
|
|
|
|
return if (seeders in 1..5) {
|
|
|
|
@ -195,7 +192,7 @@ fun seederColor(seeders: Int): Color {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@OptIn(ExperimentalMaterial3Api::class, ExperimentalComposeUiApi::class)
|
|
|
|
|
@OptIn(ExperimentalComposeUiApi::class)
|
|
|
|
|
@Composable
|
|
|
|
|
fun SearchField(
|
|
|
|
|
text: String,
|
|
|
|
@ -215,8 +212,10 @@ fun SearchField(
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TextField(
|
|
|
|
|
colors = TextFieldDefaults.textFieldColors(
|
|
|
|
|
containerColor = Color.Transparent,
|
|
|
|
|
colors = TextFieldDefaults.colors(
|
|
|
|
|
focusedContainerColor = Color.Transparent,
|
|
|
|
|
unfocusedContainerColor = Color.Transparent,
|
|
|
|
|
errorContainerColor = Color.Transparent,
|
|
|
|
|
),
|
|
|
|
|
value = text,
|
|
|
|
|
modifier = Modifier
|
|
|
|
|