Skip to content

Commit 0ac544b

Browse files
Fix review issues in PR Bartuzen#257
- Inject RequestManager into AddTorrentViewModel and check qBittorrent version >= 5.0.0 - Add parallel directory content fetching in AddTorrentViewModel - Handle Windows paths in AddTorrentViewModel - Use imports for LocalDensity and TextRange in AddTorrentScreen - Remove fully qualified names in AddTorrentScreen - Fix delay import in AddTorrentViewModel Co-authored-by: yqx1110 <33057583+yqx1110@users.noreply.github.com>
1 parent e1c034d commit 0ac544b

File tree

3 files changed

+49
-18
lines changed

3 files changed

+49
-18
lines changed

composeApp/src/commonMain/kotlin/dev/bartuzen/qbitcontroller/di/AppModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ val appModule = module {
8989
viewModel { (serverId: Int, hash: String) -> TorrentPeersViewModel(serverId, hash, get(), get(), get()) }
9090
viewModel { (serverId: Int, hash: String) -> TorrentWebSeedsViewModel(serverId, hash, get(), get()) }
9191

92-
viewModel { (initialServerId: Int?) -> AddTorrentViewModel(initialServerId, get(), get(), get()) }
92+
viewModel { (initialServerId: Int?) -> AddTorrentViewModel(initialServerId, get(), get(), get(), get()) }
9393

9494
viewModel { (serverId: Int) -> RssFeedsViewModel(serverId, get()) }
9595
viewModel { (serverId: Int, feedPath: List<String>, uid: String?) ->

composeApp/src/commonMain/kotlin/dev/bartuzen/qbitcontroller/ui/addtorrent/AddTorrentScreen.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,9 @@ import androidx.compose.ui.Alignment
7373
import androidx.compose.ui.Modifier
7474
import androidx.compose.ui.graphics.Color
7575
import androidx.compose.ui.graphics.StrokeCap
76+
import androidx.compose.ui.platform.LocalDensity
7677
import androidx.compose.ui.text.SpanStyle
78+
import androidx.compose.ui.text.TextRange
7779
import androidx.compose.ui.text.buildAnnotatedString
7880
import androidx.compose.ui.text.input.ImeAction
7981
import androidx.compose.ui.text.input.KeyboardType
@@ -880,7 +882,7 @@ fun AddTorrentScreen(
880882
var savePathExpanded by remember { mutableStateOf(false) }
881883

882884
// Hide suggestions when IME is folded
883-
val density = androidx.compose.ui.platform.LocalDensity.current
885+
val density = LocalDensity.current
884886
val isImeVisible = WindowInsets.ime.getBottom(density) > 0
885887
LaunchedEffect(isImeVisible) {
886888
if (!isImeVisible) {
@@ -955,7 +957,7 @@ fun AddTorrentScreen(
955957
onClick = {
956958
savePath = TextFieldValue(
957959
text = suggestion,
958-
selection = androidx.compose.ui.text.TextRange(suggestion.length),
960+
selection = TextRange(suggestion.length),
959961
)
960962
savePathExpanded = true
961963
// Trigger search again for the new path to load its subdirectories

composeApp/src/commonMain/kotlin/dev/bartuzen/qbitcontroller/ui/addtorrent/AddTorrentViewModel.kt

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import androidx.lifecycle.ViewModel
55
import androidx.lifecycle.viewModelScope
66
import dev.bartuzen.qbitcontroller.data.ServerManager
77
import dev.bartuzen.qbitcontroller.data.repositories.AddTorrentRepository
8+
import dev.bartuzen.qbitcontroller.model.QBittorrentVersion
9+
import dev.bartuzen.qbitcontroller.network.RequestManager
810
import dev.bartuzen.qbitcontroller.network.RequestResult
911
import dev.bartuzen.qbitcontroller.utils.getSerializableStateFlow
1012
import io.github.vinceglb.filekit.PlatformFile
@@ -14,6 +16,7 @@ import kotlinx.coroutines.CancellationException
1416
import kotlinx.coroutines.Job
1517
import kotlinx.coroutines.async
1618
import kotlinx.coroutines.channels.Channel
19+
import kotlinx.coroutines.delay
1720
import kotlinx.coroutines.flow.MutableStateFlow
1821
import kotlinx.coroutines.flow.asStateFlow
1922
import kotlinx.coroutines.flow.collectLatest
@@ -29,6 +32,7 @@ class AddTorrentViewModel(
2932
private val savedStateHandle: SavedStateHandle,
3033
private val repository: AddTorrentRepository,
3134
private val serverManager: ServerManager,
35+
private val requestManager: RequestManager,
3236
) : ViewModel() {
3337
private val eventChannel = Channel<Event>()
3438
val eventFlow = eventChannel.receiveAsFlow()
@@ -224,35 +228,60 @@ class AddTorrentViewModel(
224228

225229
fun searchDirectories(serverId: Int, path: String) {
226230
searchDirectoriesJob?.cancel()
227-
if (path.isBlank() || !path.startsWith("/")) {
231+
232+
if (path.isBlank()) {
228233
_directorySuggestions.value = emptyList()
229234
return
230235
}
231236

237+
val version = requestManager.getQBittorrentVersion(serverId)
238+
if (version < QBittorrentVersion(5, 0, 0)) {
239+
return
240+
}
241+
232242
searchDirectoriesJob = viewModelScope.launch {
233-
kotlinx.coroutines.delay(300)
243+
delay(300)
234244

235245
val suggestions = ArrayList<String>()
236246

237-
when (val result = repository.getDirectoryContent(serverId, path)) {
238-
is RequestResult.Success -> {
239-
suggestions.addAll(result.data)
247+
val pathDeferred = async {
248+
when (val result = repository.getDirectoryContent(serverId, path)) {
249+
is RequestResult.Success -> {
250+
result.data
251+
}
252+
is RequestResult.Error -> {
253+
emptyList()
254+
}
240255
}
241-
else -> {}
242256
}
243257

244-
// if path doesn't ends with a slash, we need to also check the parent directory for suggestions
245-
// e.g. for /downloads/m, check if there's a directory's name under /downloads starts with "m"
246-
if (!path.endsWith("/")) {
247-
val lastSeparatorIndex = path.lastIndexOf('/')
248-
val parent = path.take(lastSeparatorIndex + 1)
249-
when (val result = repository.getDirectoryContent(serverId, parent)) {
250-
is RequestResult.Success -> {
251-
suggestions.addAll(result.data)
258+
val parentDeferred = async {
259+
// if path doesn't ends with a slash, we need to also check the parent directory for suggestions
260+
// e.g. for /downloads/m, check if there's a directory's name under /downloads starts with "m"
261+
if (!path.endsWith("/") && !path.endsWith("\\")) {
262+
val separator = if (path.contains('/')) '/' else '\\'
263+
val lastSeparatorIndex = path.lastIndexOf(separator)
264+
if (lastSeparatorIndex != -1) {
265+
val parent = path.take(lastSeparatorIndex + 1)
266+
when (val result = repository.getDirectoryContent(serverId, parent)) {
267+
is RequestResult.Success -> {
268+
result.data
269+
}
270+
is RequestResult.Error -> {
271+
emptyList()
272+
}
273+
}
274+
} else {
275+
emptyList()
252276
}
253-
else -> {}
277+
} else {
278+
emptyList()
254279
}
255280
}
281+
282+
suggestions.addAll(pathDeferred.await())
283+
suggestions.addAll(parentDeferred.await())
284+
256285
_directorySuggestions.value = suggestions
257286
.filter { it.startsWith(path, ignoreCase = true) }
258287
.sorted()

0 commit comments

Comments
 (0)