Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.plugin.compose)
alias(libs.plugins.kotlin.plugin.parcelize)
alias(libs.plugins.androidx.navigation)
alias(libs.plugins.tremotesf.common.settings)
}

Expand Down Expand Up @@ -91,12 +90,12 @@ dependencies {
implementation(libs.androidx.activity)
implementation(libs.androidx.annotation)
implementation(libs.androidx.core)
implementation(libs.androidx.fragment)
implementation(libs.androidx.lifecycle.runtime)
implementation(libs.androidx.lifecycle.viewmodel)
implementation(libs.androidx.lifecycle.viewmodel.savedstate)
implementation(libs.androidx.lifecycle.service)
implementation(libs.androidx.navigation.fragment)
implementation(libs.androidx.navigation3.runtime)
implementation(libs.androidx.navigation3.ui)
implementation(libs.androidx.webkit)
implementation(libs.androidx.window)
implementation(libs.androidx.work.runtime)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,12 @@ package org.equeim.tremotesf.service
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Icon
import androidx.annotation.StringRes
import androidx.core.content.getSystemService
import androidx.navigation.NavDeepLinkBuilder
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import org.equeim.tremotesf.R
Expand All @@ -20,8 +21,10 @@ import org.equeim.tremotesf.rpc.RpcRequestState
import org.equeim.tremotesf.rpc.Server
import org.equeim.tremotesf.rpc.getErrorString
import org.equeim.tremotesf.rpc.requests.SessionStatsResponseArguments
import org.equeim.tremotesf.ui.NavigationActivity
import org.equeim.tremotesf.ui.Settings
import org.equeim.tremotesf.ui.torrentpropertiesfragment.TorrentPropertiesFragmentArgs
import org.equeim.tremotesf.ui.toInternalDeepLink
import org.equeim.tremotesf.ui.torrentproperties.TorrentPropertiesDestination
import org.equeim.tremotesf.ui.utils.FileSizeFormatter
import org.equeim.tremotesf.ui.utils.localeChangedEvents
import timber.log.Timber
Expand Down Expand Up @@ -114,11 +117,14 @@ class NotificationsController(private val context: Context, coroutineScope: Coro
.setContentTitle(context.getText(notificationTitle))
.setContentText(torrentName)
.setContentIntent(
NavDeepLinkBuilder(context)
.setGraph(R.navigation.nav_main)
.setDestination(R.id.torrent_properties_fragment)
.setArguments(TorrentPropertiesFragmentArgs(hashString).toBundle())
.createPendingIntent()
PendingIntent.getActivity(
context,
0,
Intent(context, NavigationActivity::class.java)
.setData(TorrentPropertiesDestination(hashString).toInternalDeepLink())
.setAction(Intent.ACTION_VIEW),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
)
.setAutoCancel(true)
.build()
Expand All @@ -133,10 +139,12 @@ class NotificationsController(private val context: Context, coroutineScope: Coro
Notification.Builder(context, PERSISTENT_NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.notification_icon)
.setContentIntent(
NavDeepLinkBuilder(context)
.setGraph(R.navigation.nav_main)
.setDestination(R.id.torrents_list_fragment)
.createPendingIntent()
PendingIntent.getActivity(
context,
0,
Intent(context, NavigationActivity::class.java),
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
)
.setOngoing(true)
.setShowWhen(false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,23 +55,24 @@ import androidx.compose.ui.text.withStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.viewinterop.AndroidView
import androidx.navigation.NavController
import androidx.webkit.WebSettingsCompat
import androidx.webkit.WebViewFeature
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import org.equeim.tremotesf.BuildConfig
import org.equeim.tremotesf.R
import org.equeim.tremotesf.ui.components.TremotesfTopAppBar
import org.equeim.tremotesf.ui.components.TremotesfTopAppBarDefaults
import org.equeim.tremotesf.ui.utils.safeNavigate
import timber.log.Timber

class AboutFragment : ComposeFragment() {
@Parcelize
data object AboutDestination : Destination {
@Composable
override fun Content(navController: NavController) {
AboutScreen(
navigateUp = navController::navigateUp,
showLicense = { navController.safeNavigate(AboutFragmentDirections.toLicenseFragment()) })
navigateUp = navController::popBackStack,
showLicense = { navController.navigateTo(LicenseDestination) }
)
}
}

Expand Down Expand Up @@ -284,14 +285,14 @@ private fun TranslatorsTab(innerPadding: PaddingValues) {
}
}

class LicenceFragment : ComposeFragment() {
@Parcelize
data object LicenseDestination : Destination {
@Composable
override fun Content(navController: NavController) {
LicenseScreen(navController::navigateUp)
LicenseScreen(navController::popBackStack)
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun LicenseScreen(navigateUp: () -> Unit) {
Scaffold(
Expand Down

This file was deleted.

37 changes: 0 additions & 37 deletions app/src/main/kotlin/org/equeim/tremotesf/ui/ComposeFragment.kt

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// SPDX-FileCopyrightText: 2017-2026 Alexey Rochev <equeim@gmail.com>
//
// SPDX-License-Identifier: GPL-3.0-or-later

package org.equeim.tremotesf.ui

import android.app.Application
import androidx.activity.compose.LocalActivity
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.remember
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.ViewModelStoreOwner
import androidx.lifecycle.viewmodel.MutableCreationExtras
import androidx.lifecycle.viewmodel.ViewModelStoreProvider
import androidx.lifecycle.viewmodel.compose.LocalViewModelStoreOwner
import androidx.lifecycle.viewmodel.compose.rememberViewModelStoreOwner
import androidx.navigation3.runtime.NavEntryDecorator
import androidx.savedstate.compose.LocalSavedStateRegistryOwner

@Composable
fun <T : Any> rememberExtendedViewModelStoreNavEntryDecorator(
viewModelStoreOwner: ViewModelStoreOwner =
checkNotNull(LocalViewModelStoreOwner.current) {
"No ViewModelStoreOwner was provided via LocalViewModelStoreOwner"
}
): ExtendedViewModelStoreNavEntryDecorator<T> {
val application = checkNotNull(LocalActivity.current).application
return remember(viewModelStoreOwner) {
ExtendedViewModelStoreNavEntryDecorator(
viewModelStoreOwner = viewModelStoreOwner,
application = application
)
}
}

class ExtendedViewModelStoreNavEntryDecorator<T : Any>(private val viewModelStoreProvider: ViewModelStoreProvider) :
NavEntryDecorator<T>(
onPop = viewModelStoreProvider::clearKey,
decorate = { entry ->
val childViewModelStoreOwner = rememberViewModelStoreOwner(
provider = viewModelStoreProvider,
savedStateRegistryOwner = LocalSavedStateRegistryOwner.current,
key = entry.contentKey,
)
CompositionLocalProvider(LocalViewModelStoreOwner provides childViewModelStoreOwner) {
entry.Content()
}
},
) {

constructor(
viewModelStoreOwner: ViewModelStoreOwner,
application: Application,
) : this(
viewModelStoreProvider = ViewModelStoreProvider(
parentStore = viewModelStoreOwner.viewModelStore,
parentKey = ExtendedViewModelStoreNavEntryDecorator::class.qualifiedName,
defaultCreationExtras = MutableCreationExtras().also {
it[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] = application
})
)

@Composable
fun viewModelStoreOwnerForKey(contentKey: Any): ViewModelStoreOwner {
return rememberViewModelStoreOwner(
provider = viewModelStoreProvider,
savedStateRegistryOwner = LocalSavedStateRegistryOwner.current,
key = contentKey
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.snapshots.SnapshotStateList
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.window.DialogProperties
import androidx.lifecycle.ViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import androidx.navigation.NavController
import androidx.navigation3.runtime.metadata
import androidx.navigation3.scene.DialogSceneStrategy
import androidx.navigation3.scene.DialogSceneStrategy.Companion.DialogKey
import kotlinx.coroutines.flow.StateFlow
import org.equeim.tremotesf.R
import org.equeim.tremotesf.rpc.GlobalRpcClient
Expand All @@ -33,19 +36,26 @@ import org.equeim.tremotesf.ui.components.TremotesfScreenContentWithPlaceholder
import org.equeim.tremotesf.ui.components.rememberTremotesfInitialFocusRequester
import org.equeim.tremotesf.ui.utils.SnapshotStateListSaver
import org.equeim.tremotesf.ui.utils.rememberAlphanumericComparator
import kotlinx.parcelize.Parcelize

class LabelsEditDialogFragment : ComposeDialogFragment() {
@Parcelize
data class LabelsEditDialogDestination(
val torrentHashStrings: List<String>,
val enabledLabels: List<String>
) : Destination {
@Composable
override fun Content(navController: NavController) {
val args = LabelsEditDialogFragmentArgs.fromBundle(requireArguments())
val model = viewModel<LabelsEditDialogViewModel> { LabelsEditDialogViewModel(args.torrentHashStrings.asList()) }
val model = viewModel { LabelsEditDialogViewModel(torrentHashStrings) }
LabelsEditDialogContent(
initialEnabledLabels = args::enabledLabels,
initialEnabledLabels = { enabledLabels.toTypedArray() },
allLabels = model.allLabels.collectAsStateWithLifecycle(),
updateLabels = model::updateLabels,
onDismissRequest = ::dismiss,
onDismissRequest = navController::popBackStack
)
}

override val metadata: Map<String, Any>
get() = metadata { put(DialogKey, DialogProperties()) }
}

@Composable
Expand Down
Loading