fix: deep link (and hide back button if not possible)
This commit is contained in:
parent
e168ab2396
commit
ba7c197957
@ -6,7 +6,7 @@ import org.koin.core.qualifier.named
|
|||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val coreApiModule = module {
|
val coreApiModule = module {
|
||||||
single<ServiceProvider> {
|
single<ServiceProvider>(named("default")) {
|
||||||
DefaultServiceProvider()
|
DefaultServiceProvider()
|
||||||
}
|
}
|
||||||
single<ServiceProvider>(named("custom")) {
|
single<ServiceProvider>(named("custom")) {
|
||||||
|
@ -57,7 +57,17 @@ internal class DefaultServiceProvider : ServiceProvider {
|
|||||||
|
|
||||||
private val factory = provideHttpClientEngineFactory()
|
private val factory = provideHttpClientEngineFactory()
|
||||||
|
|
||||||
private val client = HttpClient(factory) {
|
init {
|
||||||
|
reinitialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun changeInstance(value: String) {
|
||||||
|
currentInstance = value
|
||||||
|
reinitialize()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reinitialize() {
|
||||||
|
val client = HttpClient(factory) {
|
||||||
defaultRequest {
|
defaultRequest {
|
||||||
url {
|
url {
|
||||||
host = currentInstance
|
host = currentInstance
|
||||||
@ -76,17 +86,6 @@ internal class DefaultServiceProvider : ServiceProvider {
|
|||||||
json(Json { isLenient = true; ignoreUnknownKeys = true })
|
json(Json { isLenient = true; ignoreUnknownKeys = true })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
|
||||||
reinitialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun changeInstance(value: String) {
|
|
||||||
currentInstance = value
|
|
||||||
reinitialize()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reinitialize() {
|
|
||||||
val ktorfit = Ktorfit.Builder()
|
val ktorfit = Ktorfit.Builder()
|
||||||
.baseUrl(baseUrl)
|
.baseUrl(baseUrl)
|
||||||
.httpClient(client)
|
.httpClient(client)
|
||||||
|
@ -213,14 +213,16 @@ class CommunityDetailScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
|
if (navigator?.canPop == true) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick {
|
modifier = Modifier.onClick {
|
||||||
navigator?.pop()
|
navigator.pop()
|
||||||
},
|
},
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}, floatingActionButton = {
|
}, floatingActionButton = {
|
||||||
|
@ -9,7 +9,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.CommunityModel
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.PostModel
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.data.UserModel
|
||||||
|
|
||||||
fun getCommmunityFromUrl(url: String): CommunityModel? {
|
fun getCommunityFromUrl(url: String?): CommunityModel? {
|
||||||
val (normalizedUrl, instance) = normalizeUrl(url)
|
val (normalizedUrl, instance) = normalizeUrl(url)
|
||||||
val res = extractCommunity(normalizedUrl)
|
val res = extractCommunity(normalizedUrl)
|
||||||
return if (res != null && res.host.isEmpty()) {
|
return if (res != null && res.host.isEmpty()) {
|
||||||
@ -19,7 +19,7 @@ fun getCommmunityFromUrl(url: String): CommunityModel? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getUserFromUrl(url: String): UserModel? {
|
fun getUserFromUrl(url: String?): UserModel? {
|
||||||
val (normalizedUrl, instance) = normalizeUrl(url)
|
val (normalizedUrl, instance) = normalizeUrl(url)
|
||||||
val res = extractUser(normalizedUrl)
|
val res = extractUser(normalizedUrl)
|
||||||
return if (res != null && res.host.isEmpty()) {
|
return if (res != null && res.host.isEmpty()) {
|
||||||
@ -29,10 +29,10 @@ fun getUserFromUrl(url: String): UserModel? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getPostFromUrl(url: String): Pair<PostModel, String>? {
|
fun getPostFromUrl(url: String?): Pair<PostModel, String>? {
|
||||||
val (normalizedUrl, instance) = normalizeUrl(url)
|
val (normalizedUrl, instance) = normalizeUrl(url)
|
||||||
val post = extractPost(normalizedUrl)
|
val post = extractPost(normalizedUrl)
|
||||||
return if (post != null && instance != null) {
|
return if (post != null && instance.isNotEmpty()) {
|
||||||
post to instance
|
post to instance
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
@ -45,7 +45,7 @@ fun handleUrl(
|
|||||||
uriHandler: UriHandler,
|
uriHandler: UriHandler,
|
||||||
navigator: Navigator? = null,
|
navigator: Navigator? = null,
|
||||||
) {
|
) {
|
||||||
val community = getCommmunityFromUrl(url)
|
val community = getCommunityFromUrl(url)
|
||||||
val user = getUserFromUrl(url)
|
val user = getUserFromUrl(url)
|
||||||
|
|
||||||
when {
|
when {
|
||||||
@ -79,8 +79,8 @@ fun handleUrl(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun normalizeUrl(url: String): Pair<String, String> {
|
private fun normalizeUrl(url: String?): Pair<String, String> {
|
||||||
val matches = Regex("https?://(?<instance>.*?)(?<pathAndQuery>/.*)").findAll(url)
|
val matches = Regex("https?://(?<instance>.*?)(?<pathAndQuery>/.*)").findAll(url.orEmpty())
|
||||||
var instance = ""
|
var instance = ""
|
||||||
val res = buildString {
|
val res = buildString {
|
||||||
if (matches.count() > 0) {
|
if (matches.count() > 0) {
|
||||||
|
@ -7,12 +7,13 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.SupervisorJob
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.getAndUpdate
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
||||||
|
|
||||||
override val onDoubleTabSelection = MutableSharedFlow<Tab>()
|
override val onDoubleTabSelection = MutableSharedFlow<Tab>()
|
||||||
override val deeplinkUrl = MutableStateFlow<String?>(null)
|
override val deepLinkUrl = MutableStateFlow<String?>(null)
|
||||||
|
|
||||||
private var connection: NestedScrollConnection? = null
|
private var connection: NestedScrollConnection? = null
|
||||||
private var navigator: Navigator? = null
|
private var navigator: Navigator? = null
|
||||||
@ -43,8 +44,10 @@ internal class DefaultNavigationCoordinator : NavigationCoordinator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun submitDeeplink(url: String?) {
|
override fun consumeDeeplink(): String? = deepLinkUrl.getAndUpdate { null }
|
||||||
deeplinkUrl.value = url
|
|
||||||
|
override fun submitDeeplink(url: String) {
|
||||||
|
deepLinkUrl.value = url
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setCanGoBackCallback(value: (() -> Boolean)?) {
|
override fun setCanGoBackCallback(value: (() -> Boolean)?) {
|
||||||
|
@ -3,18 +3,20 @@ package com.github.diegoberaldin.raccoonforlemmy.core.commonui.navigation
|
|||||||
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
import androidx.compose.ui.input.nestedscroll.NestedScrollConnection
|
||||||
import cafe.adriel.voyager.navigator.Navigator
|
import cafe.adriel.voyager.navigator.Navigator
|
||||||
import cafe.adriel.voyager.navigator.tab.Tab
|
import cafe.adriel.voyager.navigator.tab.Tab
|
||||||
import kotlinx.coroutines.flow.SharedFlow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
interface NavigationCoordinator {
|
interface NavigationCoordinator {
|
||||||
|
|
||||||
val deeplinkUrl: StateFlow<String?>
|
val onDoubleTabSelection: Flow<Tab>
|
||||||
val onDoubleTabSelection: SharedFlow<Tab>
|
|
||||||
val inboxUnread: StateFlow<Int>
|
val inboxUnread: StateFlow<Int>
|
||||||
|
val deepLinkUrl: StateFlow<String?>
|
||||||
|
|
||||||
fun setCurrentSection(tab: Tab)
|
fun setCurrentSection(tab: Tab)
|
||||||
|
|
||||||
fun submitDeeplink(url: String?)
|
fun consumeDeeplink(): String?
|
||||||
|
|
||||||
|
fun submitDeeplink(url: String)
|
||||||
|
|
||||||
fun setRootNavigator(value: Navigator?)
|
fun setRootNavigator(value: Navigator?)
|
||||||
|
|
||||||
|
@ -127,7 +127,8 @@ class PostDetailScreen(
|
|||||||
model.bindToLifecycle(key)
|
model.bindToLifecycle(key)
|
||||||
val uiState by model.uiState.collectAsState()
|
val uiState by model.uiState.collectAsState()
|
||||||
val isOnOtherInstance = otherInstance.isNotEmpty()
|
val isOnOtherInstance = otherInstance.isNotEmpty()
|
||||||
val navigator = remember { getNavigationCoordinator().getRootNavigator() }
|
val navigationCoordinator = remember { getNavigationCoordinator() }
|
||||||
|
val navigator = remember { navigationCoordinator.getRootNavigator() }
|
||||||
val bottomSheetNavigator = LocalBottomSheetNavigator.current
|
val bottomSheetNavigator = LocalBottomSheetNavigator.current
|
||||||
val topAppBarState = rememberTopAppBarState()
|
val topAppBarState = rememberTopAppBarState()
|
||||||
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(topAppBarState)
|
val scrollBehavior = TopAppBarDefaults.enterAlwaysScrollBehavior(topAppBarState)
|
||||||
@ -207,14 +208,16 @@ class PostDetailScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
|
if (navigator?.canPop == true) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick {
|
modifier = Modifier.onClick {
|
||||||
navigator?.pop()
|
navigator.pop()
|
||||||
},
|
},
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -107,7 +107,6 @@ class PostDetailViewModel(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (highlightCommentId != null) {
|
if (highlightCommentId != null) {
|
||||||
val auth = identityRepository.authToken.value
|
|
||||||
val comment = commentRepository.getBy(
|
val comment = commentRepository.getBy(
|
||||||
id = highlightCommentId,
|
id = highlightCommentId,
|
||||||
auth = auth,
|
auth = auth,
|
||||||
|
@ -192,14 +192,16 @@ class UserDetailScreen(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
navigationIcon = {
|
navigationIcon = {
|
||||||
|
if (navigator?.canPop == true) {
|
||||||
Image(
|
Image(
|
||||||
modifier = Modifier.onClick {
|
modifier = Modifier.onClick {
|
||||||
navigator?.pop()
|
navigator.pop()
|
||||||
},
|
},
|
||||||
imageVector = Icons.Default.ArrowBack,
|
imageVector = Icons.Default.ArrowBack,
|
||||||
contentDescription = null,
|
contentDescription = null,
|
||||||
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
colorFilter = ColorFilter.tint(MaterialTheme.colorScheme.onBackground),
|
||||||
)
|
)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
@ -12,12 +12,13 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.identity.usecase.DefaultS
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.usecase.LoginUseCase
|
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.usecase.LoginUseCase
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.usecase.LogoutUseCase
|
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.usecase.LogoutUseCase
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.usecase.SwitchAccountUseCase
|
import com.github.diegoberaldin.raccoonforlemmy.domain.identity.usecase.SwitchAccountUseCase
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val coreIdentityModule = module {
|
val coreIdentityModule = module {
|
||||||
single<ApiConfigurationRepository> {
|
single<ApiConfigurationRepository> {
|
||||||
DefaultApiConfigurationRepository(
|
DefaultApiConfigurationRepository(
|
||||||
serviceProvider = get(),
|
serviceProvider = get(named("default")),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
single<IdentityRepository> {
|
single<IdentityRepository> {
|
||||||
@ -27,7 +28,7 @@ val coreIdentityModule = module {
|
|||||||
}
|
}
|
||||||
single<AuthRepository> {
|
single<AuthRepository> {
|
||||||
DefaultAuthRepository(
|
DefaultAuthRepository(
|
||||||
services = get(),
|
services = get(named("default")),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
single<LoginUseCase> {
|
single<LoginUseCase> {
|
||||||
@ -52,7 +53,7 @@ val coreIdentityModule = module {
|
|||||||
identityRepository = get(),
|
identityRepository = get(),
|
||||||
accountRepository = get(),
|
accountRepository = get(),
|
||||||
settingsRepository = get(),
|
settingsRepository = get(),
|
||||||
serviceProvider = get(),
|
serviceProvider = get(named("default")),
|
||||||
notificationCenter = get(),
|
notificationCenter = get(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,10 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository
|
package com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository
|
||||||
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
|
||||||
interface ApiConfigurationRepository {
|
interface ApiConfigurationRepository {
|
||||||
|
|
||||||
val instance: Flow<String>
|
val instance: StateFlow<String>
|
||||||
|
|
||||||
fun getInstance(): String
|
|
||||||
|
|
||||||
fun changeInstance(value: String)
|
fun changeInstance(value: String)
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,32 @@
|
|||||||
package com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository
|
package com.github.diegoberaldin.raccoonforlemmy.domain.identity.repository
|
||||||
|
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.api.provider.ServiceProvider
|
import com.github.diegoberaldin.raccoonforlemmy.core.api.provider.ServiceProvider
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
import kotlinx.coroutines.flow.channelFlow
|
import kotlinx.coroutines.flow.channelFlow
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
|
import kotlinx.coroutines.flow.stateIn
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
|
|
||||||
internal class DefaultApiConfigurationRepository(
|
internal class DefaultApiConfigurationRepository(
|
||||||
private val serviceProvider: ServiceProvider,
|
private val serviceProvider: ServiceProvider,
|
||||||
) : ApiConfigurationRepository {
|
) : ApiConfigurationRepository {
|
||||||
|
|
||||||
override val instance: Flow<String> = channelFlow {
|
private val scope = CoroutineScope(SupervisorJob())
|
||||||
|
|
||||||
|
override val instance = channelFlow {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
val value = getInstance()
|
val value = serviceProvider.currentInstance
|
||||||
trySend(value)
|
trySend(value)
|
||||||
delay(1000)
|
delay(1000)
|
||||||
}
|
}
|
||||||
}.distinctUntilChanged()
|
}.distinctUntilChanged().stateIn(
|
||||||
|
scope = scope,
|
||||||
override fun getInstance() = serviceProvider.currentInstance
|
started = SharingStarted.Lazily,
|
||||||
|
initialValue = "",
|
||||||
|
)
|
||||||
|
|
||||||
override fun changeInstance(value: String) {
|
override fun changeInstance(value: String) {
|
||||||
serviceProvider.changeInstance(value)
|
serviceProvider.changeInstance(value)
|
||||||
|
@ -23,7 +23,7 @@ internal class DefaultLoginUseCase(
|
|||||||
password: String,
|
password: String,
|
||||||
totp2faToken: String?,
|
totp2faToken: String?,
|
||||||
): Result<Unit> {
|
): Result<Unit> {
|
||||||
val oldInstance = apiConfigurationRepository.getInstance()
|
val oldInstance = apiConfigurationRepository.instance.value
|
||||||
apiConfigurationRepository.changeInstance(instance)
|
apiConfigurationRepository.changeInstance(instance)
|
||||||
|
|
||||||
val response = authRepository.login(
|
val response = authRepository.login(
|
||||||
|
@ -8,7 +8,7 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.utils.to
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.utils.toModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.utils.toModel
|
||||||
|
|
||||||
class PrivateMessageRepository(
|
class PrivateMessageRepository(
|
||||||
private val serviceProvider: ServiceProvider,
|
private val services: ServiceProvider,
|
||||||
) {
|
) {
|
||||||
suspend fun getAll(
|
suspend fun getAll(
|
||||||
auth: String? = null,
|
auth: String? = null,
|
||||||
@ -16,7 +16,7 @@ class PrivateMessageRepository(
|
|||||||
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
||||||
unreadOnly: Boolean = true,
|
unreadOnly: Boolean = true,
|
||||||
): List<PrivateMessageModel>? = runCatching {
|
): List<PrivateMessageModel>? = runCatching {
|
||||||
val response = serviceProvider.privateMessages.getPrivateMessages(
|
val response = services.privateMessages.getPrivateMessages(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
auth = auth,
|
auth = auth,
|
||||||
limit = limit,
|
limit = limit,
|
||||||
@ -37,7 +37,7 @@ class PrivateMessageRepository(
|
|||||||
auth = auth.orEmpty(),
|
auth = auth.orEmpty(),
|
||||||
recipientId = recipiendId,
|
recipientId = recipiendId,
|
||||||
)
|
)
|
||||||
serviceProvider.privateMessages.createPrivateMessage(
|
services.privateMessages.createPrivateMessage(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
form = data,
|
form = data,
|
||||||
)
|
)
|
||||||
@ -53,7 +53,7 @@ class PrivateMessageRepository(
|
|||||||
auth = auth.orEmpty(),
|
auth = auth.orEmpty(),
|
||||||
read = read,
|
read = read,
|
||||||
)
|
)
|
||||||
serviceProvider.privateMessages.markPrivateMessageAsRead(
|
services.privateMessages.markPrivateMessageAsRead(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
form = data,
|
form = data,
|
||||||
)
|
)
|
||||||
|
@ -9,10 +9,10 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.utils.to
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.utils.toModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.utils.toModel
|
||||||
|
|
||||||
class SiteRepository(
|
class SiteRepository(
|
||||||
private val serviceProvider: ServiceProvider,
|
private val services: ServiceProvider,
|
||||||
) {
|
) {
|
||||||
suspend fun getCurrentUser(auth: String): UserModel? = runCatching {
|
suspend fun getCurrentUser(auth: String): UserModel? = runCatching {
|
||||||
val response = serviceProvider.site.get(
|
val response = services.site.get(
|
||||||
auth = auth,
|
auth = auth,
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
)
|
)
|
||||||
@ -28,14 +28,14 @@ class SiteRepository(
|
|||||||
instanceId = id,
|
instanceId = id,
|
||||||
block = blocked,
|
block = blocked,
|
||||||
)
|
)
|
||||||
serviceProvider.site.block(
|
services.site.block(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
form = data,
|
form = data,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun getMetadata(url: String): MetadataModel? = runCatching {
|
suspend fun getMetadata(url: String): MetadataModel? = runCatching {
|
||||||
val response = serviceProvider.site.getSiteMetadata(
|
val response = services.site.getSiteMetadata(
|
||||||
url = url,
|
url = url,
|
||||||
)
|
)
|
||||||
response.body()?.metadata?.toModel()
|
response.body()?.metadata?.toModel()
|
||||||
|
@ -16,8 +16,8 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.utils.to
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.utils.toModel
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.utils.toModel
|
||||||
|
|
||||||
class UserRepository(
|
class UserRepository(
|
||||||
private val serviceProvider: ServiceProvider,
|
private val services: ServiceProvider,
|
||||||
private val customServiceProvider: ServiceProvider,
|
private val customServices: ServiceProvider,
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun get(
|
suspend fun get(
|
||||||
@ -25,7 +25,7 @@ class UserRepository(
|
|||||||
auth: String? = null,
|
auth: String? = null,
|
||||||
username: String? = null,
|
username: String? = null,
|
||||||
): UserModel? = runCatching {
|
): UserModel? = runCatching {
|
||||||
val response = serviceProvider.user.getDetails(
|
val response = services.user.getDetails(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
auth = auth,
|
auth = auth,
|
||||||
personId = id,
|
personId = id,
|
||||||
@ -48,8 +48,8 @@ class UserRepository(
|
|||||||
username: String? = null,
|
username: String? = null,
|
||||||
auth: String? = null,
|
auth: String? = null,
|
||||||
): UserModel? = runCatching {
|
): UserModel? = runCatching {
|
||||||
customServiceProvider.changeInstance(instance)
|
customServices.changeInstance(instance)
|
||||||
val response = customServiceProvider.user.getDetails(
|
val response = customServices.user.getDetails(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
auth = auth,
|
auth = auth,
|
||||||
username = username,
|
username = username,
|
||||||
@ -73,7 +73,7 @@ class UserRepository(
|
|||||||
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
||||||
sort: SortType = SortType.Active,
|
sort: SortType = SortType.Active,
|
||||||
): List<PostModel>? = runCatching {
|
): List<PostModel>? = runCatching {
|
||||||
val response = serviceProvider.user.getDetails(
|
val response = services.user.getDetails(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
auth = auth,
|
auth = auth,
|
||||||
personId = id,
|
personId = id,
|
||||||
@ -92,7 +92,7 @@ class UserRepository(
|
|||||||
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
||||||
sort: SortType = SortType.Active,
|
sort: SortType = SortType.Active,
|
||||||
): List<PostModel>? = runCatching {
|
): List<PostModel>? = runCatching {
|
||||||
val response = serviceProvider.user.getDetails(
|
val response = services.user.getDetails(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
auth = auth,
|
auth = auth,
|
||||||
personId = id,
|
personId = id,
|
||||||
@ -112,7 +112,7 @@ class UserRepository(
|
|||||||
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
||||||
sort: SortType = SortType.Active,
|
sort: SortType = SortType.Active,
|
||||||
): List<CommentModel>? = runCatching {
|
): List<CommentModel>? = runCatching {
|
||||||
val response = serviceProvider.user.getDetails(
|
val response = services.user.getDetails(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
auth = auth,
|
auth = auth,
|
||||||
personId = id,
|
personId = id,
|
||||||
@ -131,7 +131,7 @@ class UserRepository(
|
|||||||
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
limit: Int = PostRepository.DEFAULT_PAGE_SIZE,
|
||||||
sort: SortType = SortType.Active,
|
sort: SortType = SortType.Active,
|
||||||
): List<CommentModel>? = runCatching {
|
): List<CommentModel>? = runCatching {
|
||||||
val response = serviceProvider.user.getDetails(
|
val response = services.user.getDetails(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
auth = auth,
|
auth = auth,
|
||||||
personId = id,
|
personId = id,
|
||||||
@ -151,7 +151,7 @@ class UserRepository(
|
|||||||
sort: SortType = SortType.New,
|
sort: SortType = SortType.New,
|
||||||
unreadOnly: Boolean = true,
|
unreadOnly: Boolean = true,
|
||||||
): List<PersonMentionModel>? = runCatching {
|
): List<PersonMentionModel>? = runCatching {
|
||||||
val response = serviceProvider.user.getMentions(
|
val response = services.user.getMentions(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
auth = auth,
|
auth = auth,
|
||||||
limit = limit,
|
limit = limit,
|
||||||
@ -170,7 +170,7 @@ class UserRepository(
|
|||||||
sort: SortType = SortType.New,
|
sort: SortType = SortType.New,
|
||||||
unreadOnly: Boolean = true,
|
unreadOnly: Boolean = true,
|
||||||
): List<PersonMentionModel>? = runCatching {
|
): List<PersonMentionModel>? = runCatching {
|
||||||
val response = serviceProvider.user.getReplies(
|
val response = services.user.getReplies(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
auth = auth,
|
auth = auth,
|
||||||
limit = limit,
|
limit = limit,
|
||||||
@ -186,7 +186,7 @@ class UserRepository(
|
|||||||
auth: String? = null,
|
auth: String? = null,
|
||||||
) {
|
) {
|
||||||
val data = MarkAllAsReadForm(auth.orEmpty())
|
val data = MarkAllAsReadForm(auth.orEmpty())
|
||||||
serviceProvider.user.markAllAsRead(
|
services.user.markAllAsRead(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
form = data,
|
form = data,
|
||||||
)
|
)
|
||||||
@ -198,7 +198,7 @@ class UserRepository(
|
|||||||
read = read,
|
read = read,
|
||||||
auth = auth.orEmpty(),
|
auth = auth.orEmpty(),
|
||||||
)
|
)
|
||||||
serviceProvider.user.markPersonMentionAsRead(
|
services.user.markPersonMentionAsRead(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
form = data,
|
form = data,
|
||||||
)
|
)
|
||||||
@ -210,7 +210,7 @@ class UserRepository(
|
|||||||
read = read,
|
read = read,
|
||||||
auth = auth.orEmpty(),
|
auth = auth.orEmpty(),
|
||||||
)
|
)
|
||||||
serviceProvider.user.markCommentReplyAsRead(
|
services.user.markCommentReplyAsRead(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
form = data,
|
form = data,
|
||||||
)
|
)
|
||||||
@ -222,7 +222,7 @@ class UserRepository(
|
|||||||
block = blocked,
|
block = blocked,
|
||||||
auth = auth.orEmpty(),
|
auth = auth.orEmpty(),
|
||||||
)
|
)
|
||||||
serviceProvider.user.block(
|
services.user.block(
|
||||||
authHeader = auth.toAuthHeader(),
|
authHeader = auth.toAuthHeader(),
|
||||||
form = data,
|
form = data,
|
||||||
)
|
)
|
||||||
|
@ -6,25 +6,42 @@ import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PostRepo
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PrivateMessageRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.PrivateMessageRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.SiteRepository
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
|
import com.github.diegoberaldin.raccoonforlemmy.domain.lemmy.repository.UserRepository
|
||||||
import org.koin.core.module.dsl.singleOf
|
|
||||||
import org.koin.core.qualifier.named
|
import org.koin.core.qualifier.named
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
|
|
||||||
val repositoryModule = module {
|
val repositoryModule = module {
|
||||||
single {
|
single {
|
||||||
PostRepository(
|
PostRepository(
|
||||||
services = get(),
|
services = get(named("default")),
|
||||||
customServices = get(named("custom")),
|
customServices = get(named("custom")),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
single {
|
single {
|
||||||
CommunityRepository(
|
CommunityRepository(
|
||||||
services = get(),
|
services = get(named("default")),
|
||||||
customServices = get(named("custom")),
|
customServices = get(named("custom")),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
singleOf(::UserRepository)
|
single {
|
||||||
singleOf(::SiteRepository)
|
UserRepository(
|
||||||
singleOf(::CommentRepository)
|
services = get(named("default")),
|
||||||
singleOf(::PrivateMessageRepository)
|
customServices = get(named("custom")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
single {
|
||||||
|
SiteRepository(
|
||||||
|
services = get(named("default")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
single {
|
||||||
|
CommentRepository(
|
||||||
|
services = get(named("default")),
|
||||||
|
customServices = get(named("custom")),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
single {
|
||||||
|
PrivateMessageRepository(
|
||||||
|
services = get(named("default")),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ class ExploreViewModel(
|
|||||||
mvi.onStarted()
|
mvi.onStarted()
|
||||||
mvi.updateState {
|
mvi.updateState {
|
||||||
it.copy(
|
it.copy(
|
||||||
instance = apiConfigRepository.getInstance(),
|
instance = apiConfigRepository.instance.value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
mvi.scope?.launch(Dispatchers.Main) {
|
mvi.scope?.launch(Dispatchers.Main) {
|
||||||
|
@ -31,9 +31,7 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
import androidx.compose.ui.unit.Density
|
import androidx.compose.ui.unit.Density
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
|
||||||
import cafe.adriel.voyager.navigator.CurrentScreen
|
import cafe.adriel.voyager.navigator.CurrentScreen
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
|
||||||
import cafe.adriel.voyager.navigator.Navigator
|
import cafe.adriel.voyager.navigator.Navigator
|
||||||
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
|
import cafe.adriel.voyager.navigator.bottomSheet.BottomSheetNavigator
|
||||||
import cafe.adriel.voyager.navigator.tab.TabNavigator
|
import cafe.adriel.voyager.navigator.tab.TabNavigator
|
||||||
@ -47,7 +45,7 @@ import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.AppTheme
|
|||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.CornerSize
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
import com.github.diegoberaldin.raccoonforlemmy.core.appearance.theme.Spacing
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.communitydetail.CommunityDetailScreen
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.getCommmunityFromUrl
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.getCommunityFromUrl
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.getPostFromUrl
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.getPostFromUrl
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.getUserFromUrl
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.components.getUserFromUrl
|
||||||
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getDrawerCoordinator
|
import com.github.diegoberaldin.raccoonforlemmy.core.commonui.di.getDrawerCoordinator
|
||||||
@ -77,12 +75,20 @@ fun App() {
|
|||||||
val settingsRepository = remember { getSettingsRepository() }
|
val settingsRepository = remember { getSettingsRepository() }
|
||||||
val settings by settingsRepository.currentSettings.collectAsState()
|
val settings by settingsRepository.currentSettings.collectAsState()
|
||||||
var hasBeenInitialized by remember { mutableStateOf(false) }
|
var hasBeenInitialized by remember { mutableStateOf(false) }
|
||||||
LaunchedEffect(settingsRepository) {
|
val apiConfigurationRepository = remember { getApiConfigurationRepository() }
|
||||||
|
|
||||||
|
LaunchedEffect(accountRepository) {
|
||||||
val accountId = accountRepository.getActive()?.id
|
val accountId = accountRepository.getActive()?.id
|
||||||
val currentSettings = settingsRepository.getSettings(accountId)
|
val currentSettings = settingsRepository.getSettings(accountId)
|
||||||
settingsRepository.changeCurrentSettings(currentSettings)
|
settingsRepository.changeCurrentSettings(currentSettings)
|
||||||
|
val lastActiveAccount = accountRepository.getActive()
|
||||||
|
val lastInstance = lastActiveAccount?.instance
|
||||||
|
if (lastInstance != null) {
|
||||||
|
apiConfigurationRepository.changeInstance(lastInstance)
|
||||||
|
}
|
||||||
hasBeenInitialized = true
|
hasBeenInitialized = true
|
||||||
}
|
}
|
||||||
|
|
||||||
val defaultTheme = if (isSystemInDarkTheme()) {
|
val defaultTheme = if (isSystemInDarkTheme()) {
|
||||||
UiTheme.Dark.toInt()
|
UiTheme.Dark.toInt()
|
||||||
} else {
|
} else {
|
||||||
@ -100,15 +106,6 @@ fun App() {
|
|||||||
StringDesc.localeType = StringDesc.LocaleType.Custom(lang)
|
StringDesc.localeType = StringDesc.LocaleType.Custom(lang)
|
||||||
}.launchIn(scope)
|
}.launchIn(scope)
|
||||||
|
|
||||||
val apiConfigurationRepository = remember { getApiConfigurationRepository() }
|
|
||||||
LaunchedEffect(Unit) {
|
|
||||||
val lastActiveAccount = accountRepository.getActive()
|
|
||||||
val lastInstance = lastActiveAccount?.instance
|
|
||||||
if (lastInstance != null) {
|
|
||||||
apiConfigurationRepository.changeInstance(lastInstance)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val themeRepository = remember { getThemeRepository() }
|
val themeRepository = remember { getThemeRepository() }
|
||||||
LaunchedEffect(settings) {
|
LaunchedEffect(settings) {
|
||||||
with(themeRepository) {
|
with(themeRepository) {
|
||||||
@ -136,49 +133,41 @@ fun App() {
|
|||||||
val lang by languageRepository.currentLanguage.collectAsState()
|
val lang by languageRepository.currentLanguage.collectAsState()
|
||||||
LaunchedEffect(lang) {}
|
LaunchedEffect(lang) {}
|
||||||
|
|
||||||
CompositionLocalProvider(
|
val url = navigationCoordinator.consumeDeeplink()
|
||||||
LocalDensity provides Density(
|
LaunchedEffect(navigationCoordinator, url) {
|
||||||
density = LocalDensity.current.density,
|
val community = getCommunityFromUrl(url)
|
||||||
fontScale = uiFontScale,
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
BottomSheetNavigator(
|
|
||||||
sheetShape = RoundedCornerShape(topStart = CornerSize.xl, topEnd = CornerSize.xl),
|
|
||||||
sheetBackgroundColor = MaterialTheme.colorScheme.background,
|
|
||||||
) {
|
|
||||||
val screens: List<Screen> = remember(navigationCoordinator.deeplinkUrl) {
|
|
||||||
val url = navigationCoordinator.deeplinkUrl.value.orEmpty()
|
|
||||||
val community = getCommmunityFromUrl(url)
|
|
||||||
val user = getUserFromUrl(url)
|
val user = getUserFromUrl(url)
|
||||||
val postAndInstance = getPostFromUrl(url)
|
val postAndInstance = getPostFromUrl(url)
|
||||||
buildList {
|
val newScreen = when {
|
||||||
if (community != null) {
|
community != null -> {
|
||||||
add(
|
|
||||||
CommunityDetailScreen(
|
CommunityDetailScreen(
|
||||||
community = community,
|
community = community,
|
||||||
otherInstance = community.host,
|
otherInstance = community.host,
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
} else if (user != null) {
|
|
||||||
add(
|
user != null -> {
|
||||||
UserDetailScreen(
|
UserDetailScreen(
|
||||||
user = user,
|
user = user,
|
||||||
otherInstance = user.host,
|
otherInstance = user.host,
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
} else if (postAndInstance != null) {
|
|
||||||
|
postAndInstance != null -> {
|
||||||
val (post, otherInstance) = postAndInstance
|
val (post, otherInstance) = postAndInstance
|
||||||
add(
|
|
||||||
PostDetailScreen(
|
PostDetailScreen(
|
||||||
post = post,
|
post = post,
|
||||||
otherInstance = otherInstance,
|
otherInstance = otherInstance,
|
||||||
)
|
)
|
||||||
)
|
}
|
||||||
} else {
|
|
||||||
add(MainScreen())
|
else -> null
|
||||||
}
|
}
|
||||||
|
if (newScreen != null) {
|
||||||
|
navigationCoordinator.getRootNavigator()?.push(newScreen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
val drawerState = rememberDrawerState(initialValue = DrawerValue.Closed)
|
||||||
val drawerCoordinator = remember { getDrawerCoordinator() }
|
val drawerCoordinator = remember { getDrawerCoordinator() }
|
||||||
LaunchedEffect(drawerCoordinator) {
|
LaunchedEffect(drawerCoordinator) {
|
||||||
@ -210,6 +199,20 @@ fun App() {
|
|||||||
}.launchIn(this)
|
}.launchIn(this)
|
||||||
}
|
}
|
||||||
val drawerGestureEnabled by drawerCoordinator.gesturesEnabled.collectAsState()
|
val drawerGestureEnabled by drawerCoordinator.gesturesEnabled.collectAsState()
|
||||||
|
|
||||||
|
CompositionLocalProvider(
|
||||||
|
LocalDensity provides Density(
|
||||||
|
density = LocalDensity.current.density,
|
||||||
|
fontScale = uiFontScale,
|
||||||
|
),
|
||||||
|
) {
|
||||||
|
BottomSheetNavigator(
|
||||||
|
sheetShape = RoundedCornerShape(
|
||||||
|
topStart = CornerSize.xl,
|
||||||
|
topEnd = CornerSize.xl
|
||||||
|
),
|
||||||
|
sheetBackgroundColor = MaterialTheme.colorScheme.background,
|
||||||
|
) {
|
||||||
ModalNavigationDrawer(
|
ModalNavigationDrawer(
|
||||||
drawerState = drawerState,
|
drawerState = drawerState,
|
||||||
gesturesEnabled = drawerGestureEnabled,
|
gesturesEnabled = drawerGestureEnabled,
|
||||||
@ -217,21 +220,19 @@ fun App() {
|
|||||||
ModalDrawerSheet {
|
ModalDrawerSheet {
|
||||||
TabNavigator(ModalDrawerContent)
|
TabNavigator(ModalDrawerContent)
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
) {
|
) {
|
||||||
Navigator(
|
Navigator(
|
||||||
screens = screens,
|
screen = MainScreen,
|
||||||
onBackPressed = {
|
onBackPressed = {
|
||||||
val callback = navigationCoordinator.getCanGoBackCallback()
|
val callback = navigationCoordinator.getCanGoBackCallback()
|
||||||
callback?.let { it() } ?: true
|
callback?.let { it() } ?: true
|
||||||
}
|
}
|
||||||
) {
|
) { navigator ->
|
||||||
val navigator = LocalNavigator.current
|
|
||||||
navigationCoordinator.setRootNavigator(navigator)
|
navigationCoordinator.setRootNavigator(navigator)
|
||||||
if (hasBeenInitialized) {
|
if (hasBeenInitialized) {
|
||||||
CurrentScreen()
|
CurrentScreen()
|
||||||
} else {
|
} else {
|
||||||
// loading screen
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
contentAlignment = Alignment.Center,
|
contentAlignment = Alignment.Center,
|
||||||
|
@ -43,7 +43,7 @@ import kotlinx.coroutines.flow.launchIn
|
|||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
internal class MainScreen : Screen {
|
internal object MainScreen : Screen {
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user