Improves stability of composables
This commit is contained in:
@@ -51,6 +51,7 @@ import com.vitorpamplona.quartz.events.MetadataEvent
|
|||||||
import com.vitorpamplona.quartz.events.MuteListEvent
|
import com.vitorpamplona.quartz.events.MuteListEvent
|
||||||
import com.vitorpamplona.quartz.events.PrivateOutboxRelayListEvent
|
import com.vitorpamplona.quartz.events.PrivateOutboxRelayListEvent
|
||||||
import com.vitorpamplona.quartz.events.SearchRelayListEvent
|
import com.vitorpamplona.quartz.events.SearchRelayListEvent
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
@@ -555,8 +556,8 @@ object LocalPreferences {
|
|||||||
dontTranslateFrom = dontTranslateFrom,
|
dontTranslateFrom = dontTranslateFrom,
|
||||||
languagePreferences = languagePreferences,
|
languagePreferences = languagePreferences,
|
||||||
translateTo = translateTo,
|
translateTo = translateTo,
|
||||||
zapAmountChoices = MutableStateFlow(zapAmountChoices),
|
zapAmountChoices = MutableStateFlow(zapAmountChoices.toImmutableList()),
|
||||||
reactionChoices = MutableStateFlow(reactionChoices),
|
reactionChoices = MutableStateFlow(reactionChoices.toImmutableList()),
|
||||||
defaultZapType = MutableStateFlow(defaultZapType),
|
defaultZapType = MutableStateFlow(defaultZapType),
|
||||||
defaultFileServer = defaultFileServer,
|
defaultFileServer = defaultFileServer,
|
||||||
defaultHomeFollowList = MutableStateFlow(defaultHomeFollowList),
|
defaultHomeFollowList = MutableStateFlow(defaultHomeFollowList),
|
||||||
|
|||||||
@@ -45,6 +45,9 @@ import com.vitorpamplona.quartz.events.SearchRelayListEvent
|
|||||||
import com.vitorpamplona.quartz.signers.ExternalSignerLauncher
|
import com.vitorpamplona.quartz.signers.ExternalSignerLauncher
|
||||||
import com.vitorpamplona.quartz.signers.NostrSignerExternal
|
import com.vitorpamplona.quartz.signers.NostrSignerExternal
|
||||||
import com.vitorpamplona.quartz.signers.NostrSignerInternal
|
import com.vitorpamplona.quartz.signers.NostrSignerInternal
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.persistentListOf
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
@@ -61,7 +64,7 @@ val DefaultChannels =
|
|||||||
)
|
)
|
||||||
|
|
||||||
val DefaultReactions =
|
val DefaultReactions =
|
||||||
listOf(
|
persistentListOf(
|
||||||
"\uD83D\uDE80",
|
"\uD83D\uDE80",
|
||||||
"\uD83E\uDEC2",
|
"\uD83E\uDEC2",
|
||||||
"\uD83D\uDC40",
|
"\uD83D\uDC40",
|
||||||
@@ -92,7 +95,7 @@ val DefaultSearchRelayList =
|
|||||||
RelayUrlFormatter.normalize("wss://relay.noswhere.com"),
|
RelayUrlFormatter.normalize("wss://relay.noswhere.com"),
|
||||||
)
|
)
|
||||||
|
|
||||||
val DefaultZapAmounts = listOf(100L, 500L, 1000L)
|
val DefaultZapAmounts = persistentListOf(100L, 500L, 1000L)
|
||||||
|
|
||||||
fun getLanguagesSpokenByUser(): Set<String> {
|
fun getLanguagesSpokenByUser(): Set<String> {
|
||||||
val languageList = ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration())
|
val languageList = ConfigurationCompat.getLocales(Resources.getSystem().getConfiguration())
|
||||||
@@ -118,8 +121,8 @@ class AccountSettings(
|
|||||||
var dontTranslateFrom: Set<String> = getLanguagesSpokenByUser(),
|
var dontTranslateFrom: Set<String> = getLanguagesSpokenByUser(),
|
||||||
var languagePreferences: Map<String, String> = mapOf(),
|
var languagePreferences: Map<String, String> = mapOf(),
|
||||||
var translateTo: String = Locale.getDefault().language,
|
var translateTo: String = Locale.getDefault().language,
|
||||||
var zapAmountChoices: MutableStateFlow<List<Long>> = MutableStateFlow(DefaultZapAmounts),
|
var zapAmountChoices: MutableStateFlow<ImmutableList<Long>> = MutableStateFlow(DefaultZapAmounts),
|
||||||
var reactionChoices: MutableStateFlow<List<String>> = MutableStateFlow(DefaultReactions),
|
var reactionChoices: MutableStateFlow<ImmutableList<String>> = MutableStateFlow(DefaultReactions),
|
||||||
val defaultZapType: MutableStateFlow<LnZapEvent.ZapType> = MutableStateFlow(LnZapEvent.ZapType.PUBLIC),
|
val defaultZapType: MutableStateFlow<LnZapEvent.ZapType> = MutableStateFlow(LnZapEvent.ZapType.PUBLIC),
|
||||||
var defaultFileServer: Nip96MediaServers.ServerName = Nip96MediaServers.DEFAULT[0],
|
var defaultFileServer: Nip96MediaServers.ServerName = Nip96MediaServers.DEFAULT[0],
|
||||||
val defaultHomeFollowList: MutableStateFlow<String> = MutableStateFlow(KIND3_FOLLOWS),
|
val defaultHomeFollowList: MutableStateFlow<String> = MutableStateFlow(KIND3_FOLLOWS),
|
||||||
@@ -177,7 +180,7 @@ class AccountSettings(
|
|||||||
|
|
||||||
fun changeZapAmounts(newAmounts: List<Long>) {
|
fun changeZapAmounts(newAmounts: List<Long>) {
|
||||||
if (zapAmountChoices.value != newAmounts) {
|
if (zapAmountChoices.value != newAmounts) {
|
||||||
zapAmountChoices.tryEmit(newAmounts)
|
zapAmountChoices.tryEmit(newAmounts.toImmutableList())
|
||||||
saveAccountSettings()
|
saveAccountSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,7 +194,7 @@ class AccountSettings(
|
|||||||
|
|
||||||
fun changeReactionTypes(newTypes: List<String>) {
|
fun changeReactionTypes(newTypes: List<String>) {
|
||||||
if (reactionChoices.value != newTypes) {
|
if (reactionChoices.value != newTypes) {
|
||||||
reactionChoices.tryEmit(newTypes)
|
reactionChoices.tryEmit(newTypes.toImmutableList())
|
||||||
saveAccountSettings()
|
saveAccountSettings()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
package com.vitorpamplona.amethyst.model
|
package com.vitorpamplona.amethyst.model
|
||||||
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.compose.runtime.Stable
|
||||||
import com.fasterxml.jackson.annotation.JsonSubTypes
|
import com.fasterxml.jackson.annotation.JsonSubTypes
|
||||||
import com.fasterxml.jackson.annotation.JsonTypeInfo
|
import com.fasterxml.jackson.annotation.JsonTypeInfo
|
||||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||||
@@ -40,11 +41,13 @@ import kotlinx.collections.immutable.toImmutableMap
|
|||||||
JsonSubTypes.Type(value = Bundle::class, name = "Bundle"),
|
JsonSubTypes.Type(value = Bundle::class, name = "Bundle"),
|
||||||
JsonSubTypes.Type(value = VisionPrescription::class, name = "VisionPrescription"),
|
JsonSubTypes.Type(value = VisionPrescription::class, name = "VisionPrescription"),
|
||||||
)
|
)
|
||||||
|
@Stable
|
||||||
open class Resource(
|
open class Resource(
|
||||||
var resourceType: String? = null,
|
var resourceType: String? = null,
|
||||||
var id: String = "",
|
var id: String = "",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
class Practitioner(
|
class Practitioner(
|
||||||
resourceType: String? = null,
|
resourceType: String? = null,
|
||||||
id: String = "",
|
id: String = "",
|
||||||
@@ -53,6 +56,7 @@ class Practitioner(
|
|||||||
var gender: String? = null,
|
var gender: String? = null,
|
||||||
) : Resource(resourceType, id)
|
) : Resource(resourceType, id)
|
||||||
|
|
||||||
|
@Stable
|
||||||
class Patient(
|
class Patient(
|
||||||
resourceType: String? = null,
|
resourceType: String? = null,
|
||||||
id: String = "",
|
id: String = "",
|
||||||
@@ -61,6 +65,7 @@ class Patient(
|
|||||||
var gender: String? = null,
|
var gender: String? = null,
|
||||||
) : Resource(resourceType, id)
|
) : Resource(resourceType, id)
|
||||||
|
|
||||||
|
@Stable
|
||||||
class HumanName(
|
class HumanName(
|
||||||
var use: String? = null,
|
var use: String? = null,
|
||||||
var family: String? = null,
|
var family: String? = null,
|
||||||
@@ -69,6 +74,7 @@ class HumanName(
|
|||||||
fun assembleName(): String = given.joinToString(" ") + " " + family
|
fun assembleName(): String = given.joinToString(" ") + " " + family
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Stable
|
||||||
class Bundle(
|
class Bundle(
|
||||||
resourceType: String? = null,
|
resourceType: String? = null,
|
||||||
id: String = "",
|
id: String = "",
|
||||||
@@ -77,6 +83,7 @@ class Bundle(
|
|||||||
var entry: List<Resource> = arrayListOf(),
|
var entry: List<Resource> = arrayListOf(),
|
||||||
) : Resource(resourceType, id)
|
) : Resource(resourceType, id)
|
||||||
|
|
||||||
|
@Stable
|
||||||
class VisionPrescription(
|
class VisionPrescription(
|
||||||
resourceType: String? = null,
|
resourceType: String? = null,
|
||||||
id: String = "",
|
id: String = "",
|
||||||
@@ -89,6 +96,7 @@ class VisionPrescription(
|
|||||||
var lensSpecification: List<LensSpecification> = arrayListOf(),
|
var lensSpecification: List<LensSpecification> = arrayListOf(),
|
||||||
) : Resource(resourceType, id)
|
) : Resource(resourceType, id)
|
||||||
|
|
||||||
|
@Stable
|
||||||
class LensSpecification(
|
class LensSpecification(
|
||||||
var eye: String? = null,
|
var eye: String? = null,
|
||||||
var sphere: Double? = null,
|
var sphere: Double? = null,
|
||||||
@@ -105,6 +113,7 @@ class LensSpecification(
|
|||||||
var note: String? = null,
|
var note: String? = null,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Stable
|
||||||
class Prism(
|
class Prism(
|
||||||
var amount: Double? = null,
|
var amount: Double? = null,
|
||||||
var base: String? = null,
|
var base: String? = null,
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ import com.vitorpamplona.amethyst.ui.stringRes
|
|||||||
import com.vitorpamplona.ammolite.service.HttpClientManager
|
import com.vitorpamplona.ammolite.service.HttpClientManager
|
||||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||||
import com.vitorpamplona.quartz.events.Event
|
import com.vitorpamplona.quartz.events.Event
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.cbor.ByteString
|
import kotlinx.serialization.cbor.ByteString
|
||||||
@@ -61,11 +63,11 @@ class Proof(
|
|||||||
)
|
)
|
||||||
|
|
||||||
object CachedCashuProcessor {
|
object CachedCashuProcessor {
|
||||||
val cashuCache = LruCache<String, GenericLoadable<List<CashuToken>>>(20)
|
val cashuCache = LruCache<String, GenericLoadable<ImmutableList<CashuToken>>>(20)
|
||||||
|
|
||||||
fun cached(token: String): GenericLoadable<List<CashuToken>> = cashuCache[token] ?: GenericLoadable.Loading()
|
fun cached(token: String): GenericLoadable<ImmutableList<CashuToken>> = cashuCache[token] ?: GenericLoadable.Loading()
|
||||||
|
|
||||||
fun parse(token: String): GenericLoadable<List<CashuToken>> {
|
fun parse(token: String): GenericLoadable<ImmutableList<CashuToken>> {
|
||||||
if (cashuCache[token] !is GenericLoadable.Loaded) {
|
if (cashuCache[token] !is GenericLoadable.Loaded) {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
val newCachuData = CashuProcessor().parse(token)
|
val newCachuData = CashuProcessor().parse(token)
|
||||||
@@ -91,7 +93,7 @@ class CashuProcessor {
|
|||||||
val proofs: List<Proof>,
|
val proofs: List<Proof>,
|
||||||
)
|
)
|
||||||
|
|
||||||
fun parse(cashuToken: String): GenericLoadable<List<CashuToken>> {
|
fun parse(cashuToken: String): GenericLoadable<ImmutableList<CashuToken>> {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
if (cashuToken.startsWith("cashuA")) {
|
if (cashuToken.startsWith("cashuA")) {
|
||||||
@@ -105,7 +107,7 @@ class CashuProcessor {
|
|||||||
return GenericLoadable.Error("Could not parse this cashu token")
|
return GenericLoadable.Error("Could not parse this cashu token")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseCashuA(cashuToken: String): GenericLoadable<List<CashuToken>> {
|
fun parseCashuA(cashuToken: String): GenericLoadable<ImmutableList<CashuToken>> {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -129,10 +131,10 @@ class CashuProcessor {
|
|||||||
CashuToken(cashuToken, mint, totalAmount, proofs)
|
CashuToken(cashuToken, mint, totalAmount, proofs)
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericLoadable.Loaded(converted)
|
return GenericLoadable.Loaded(converted.toImmutableList())
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
if (e is CancellationException) throw e
|
if (e is CancellationException) throw e
|
||||||
return GenericLoadable.Error<List<CashuToken>>("Could not parse this cashu token")
|
return GenericLoadable.Error("Could not parse this cashu token")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +174,7 @@ class CashuProcessor {
|
|||||||
)
|
)
|
||||||
|
|
||||||
@OptIn(ExperimentalSerializationApi::class)
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
fun parseCashuB(cashuToken: String): GenericLoadable<List<CashuToken>> {
|
fun parseCashuB(cashuToken: String): GenericLoadable<ImmutableList<CashuToken>> {
|
||||||
checkNotInMainThread()
|
checkNotInMainThread()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -205,7 +207,7 @@ class CashuProcessor {
|
|||||||
CashuToken(cashuToken, mint, totalAmount, proofs)
|
CashuToken(cashuToken, mint, totalAmount, proofs)
|
||||||
}
|
}
|
||||||
|
|
||||||
return GenericLoadable.Loaded(converted)
|
return GenericLoadable.Loaded(converted.toImmutableList())
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
if (e is CancellationException) throw e
|
if (e is CancellationException) throw e
|
||||||
|
|||||||
+1
-3
@@ -40,7 +40,6 @@ import androidx.compose.ui.graphics.BlendMode
|
|||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.graphics.drawscope.DrawStyle
|
|
||||||
import androidx.compose.ui.graphics.drawscope.Fill
|
import androidx.compose.ui.graphics.drawscope.Fill
|
||||||
import androidx.compose.ui.graphics.graphicsLayer
|
import androidx.compose.ui.graphics.graphicsLayer
|
||||||
import androidx.compose.ui.unit.Dp
|
import androidx.compose.ui.unit.Dp
|
||||||
@@ -67,7 +66,6 @@ private const val DEFAULT_GRAPHICS_LAYER_ALPHA: Float = 0.99F
|
|||||||
@Composable
|
@Composable
|
||||||
fun AudioWaveformReadOnly(
|
fun AudioWaveformReadOnly(
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
style: DrawStyle = Fill,
|
|
||||||
waveformBrush: Brush = SolidColor(Color.White),
|
waveformBrush: Brush = SolidColor(Color.White),
|
||||||
progressBrush: Brush = SolidColor(Color.Blue),
|
progressBrush: Brush = SolidColor(Color.Blue),
|
||||||
waveformAlignment: WaveformAlignment = WaveformAlignment.Center,
|
waveformAlignment: WaveformAlignment = WaveformAlignment.Center,
|
||||||
@@ -131,7 +129,7 @@ fun AudioWaveformReadOnly(
|
|||||||
height = amplitude,
|
height = amplitude,
|
||||||
),
|
),
|
||||||
cornerRadius = CornerRadius(spikeRadiusState.toPx(), spikeRadiusState.toPx()),
|
cornerRadius = CornerRadius(spikeRadiusState.toPx(), spikeRadiusState.toPx()),
|
||||||
style = style,
|
style = Fill,
|
||||||
)
|
)
|
||||||
drawRect(
|
drawRect(
|
||||||
brush = progressBrush,
|
brush = progressBrush,
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size18Modifier
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.SmallishBorder
|
import com.vitorpamplona.amethyst.ui.theme.SmallishBorder
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer
|
||||||
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.coroutines.CancellationException
|
import kotlinx.coroutines.CancellationException
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
@@ -98,8 +99,8 @@ fun CashuPreview(
|
|||||||
|
|
||||||
CrossfadeIfEnabled(targetState = cashuData, label = "CashuPreview", accountViewModel = accountViewModel) {
|
CrossfadeIfEnabled(targetState = cashuData, label = "CashuPreview", accountViewModel = accountViewModel) {
|
||||||
when (it) {
|
when (it) {
|
||||||
is GenericLoadable.Loaded<List<CashuToken>> -> CashuPreview(it.loaded, accountViewModel)
|
is GenericLoadable.Loaded<ImmutableList<CashuToken>> -> CashuPreview(it.loaded, accountViewModel)
|
||||||
is GenericLoadable.Error<List<CashuToken>> ->
|
is GenericLoadable.Error<ImmutableList<CashuToken>> ->
|
||||||
Text(
|
Text(
|
||||||
text = "$cashutoken ",
|
text = "$cashutoken ",
|
||||||
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content),
|
style = LocalTextStyle.current.copy(textDirection = TextDirection.Content),
|
||||||
@@ -111,7 +112,7 @@ fun CashuPreview(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun CashuPreview(
|
fun CashuPreview(
|
||||||
tokens: List<CashuToken>,
|
tokens: ImmutableList<CashuToken>,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
) {
|
) {
|
||||||
tokens.forEach {
|
tokens.forEach {
|
||||||
|
|||||||
@@ -1329,7 +1329,7 @@ fun ReactionChoicePopup(
|
|||||||
onDismissRequest = { onDismiss() },
|
onDismissRequest = { onDismiss() },
|
||||||
) {
|
) {
|
||||||
ReactionChoicePopupContent(
|
ReactionChoicePopupContent(
|
||||||
reactions.toImmutableList(),
|
reactions,
|
||||||
toRemove = toRemove,
|
toRemove = toRemove,
|
||||||
onClick = { reactionType ->
|
onClick = { reactionType ->
|
||||||
accountViewModel.reactToOrDelete(
|
accountViewModel.reactToOrDelete(
|
||||||
@@ -1487,7 +1487,7 @@ fun ZapAmountChoicePopup(
|
|||||||
@Composable
|
@Composable
|
||||||
fun ZapAmountChoicePopup(
|
fun ZapAmountChoicePopup(
|
||||||
baseNote: Note,
|
baseNote: Note,
|
||||||
zapAmountChoices: List<Long>,
|
zapAmountChoices: ImmutableList<Long>,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
popupYOffset: Dp,
|
popupYOffset: Dp,
|
||||||
onDismiss: () -> Unit,
|
onDismiss: () -> Unit,
|
||||||
|
|||||||
+1
-1
@@ -461,7 +461,7 @@ fun ZapDVMButton(
|
|||||||
if (wantsToZap != null) {
|
if (wantsToZap != null) {
|
||||||
ZapAmountChoicePopup(
|
ZapAmountChoicePopup(
|
||||||
baseNote = baseNote,
|
baseNote = baseNote,
|
||||||
zapAmountChoices = listOf(amount / 1000),
|
zapAmountChoices = persistentListOf(amount / 1000),
|
||||||
popupYOffset = iconSize,
|
popupYOffset = iconSize,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ class TorrentEvent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Immutable
|
||||||
class TorrentFile(
|
class TorrentFile(
|
||||||
val fileName: String,
|
val fileName: String,
|
||||||
val bytes: Long?,
|
val bytes: Long?,
|
||||||
|
|||||||
Reference in New Issue
Block a user