diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt index 9093b1427b..bd5ce61ee3 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt @@ -1,6 +1,5 @@ package chat.simplex.app -import android.annotation.SuppressLint import android.app.* import android.content.Context import chat.simplex.common.platform.Log @@ -361,14 +360,12 @@ class SimplexApp: Application(), LifecycleEventObserver { override suspend fun androidUnfinishedBadgePurchases(): List = unfinishedBadgePurchases() - @SuppressLint("SourceLockedOrientationActivity") @Composable override fun androidLockPortraitOrientation() { val context = LocalContext.current DisposableEffect(Unit) { val activity = context as? Activity ?: return@DisposableEffect onDispose {} - // Lock orientation to portrait in order to have good experience with calls - activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED onDispose { // Unlock orientation activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED diff --git a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/UI.android.kt b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/UI.android.kt index 9dbcb6d263..aefa85124b 100644 --- a/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/UI.android.kt +++ b/apps/multiplatform/common/src/androidMain/kotlin/chat/simplex/common/platform/UI.android.kt @@ -27,14 +27,7 @@ actual fun LockToCurrentOrientationUntilDispose() { val context = LocalContext1.current DisposableEffect(Unit) { val activity = (context as Activity?) ?: return@DisposableEffect onDispose {} - val manager = context.getSystemService(Activity.WINDOW_SERVICE) as WindowManager - val rotation = if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.Q) manager.defaultDisplay.rotation else activity.display?.rotation - activity.requestedOrientation = when (rotation) { - Surface.ROTATION_90 -> ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE - Surface.ROTATION_180 -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT - Surface.ROTATION_270 -> ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE - else -> ActivityInfo.SCREEN_ORIENTATION_PORTRAIT - } + activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LOCKED // Unlock orientation onDispose { activity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt index 05c22155b8..013ad0eb25 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/migration/MigrateFromDevice.kt @@ -11,6 +11,10 @@ import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.layout.positionInWindow +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.platform.LocalWindowInfo import androidx.compose.foundation.background import androidx.compose.ui.graphics.Color import androidx.compose.ui.text.font.FontWeight @@ -29,6 +33,7 @@ import chat.simplex.common.views.database.* import chat.simplex.common.views.helpers.* import chat.simplex.common.views.newchat.LinkTextView import chat.simplex.common.views.newchat.SimpleXLinkQRCode +import chat.simplex.common.views.onboarding.OnboardingStage import chat.simplex.common.views.usersettings.* import chat.simplex.res.* import dev.icerock.moko.resources.compose.painterResource @@ -427,19 +432,44 @@ private fun ProgressView() { @Composable fun LargeProgressView(value: Float, title: String, description: String) { - Box(Modifier.padding(DEFAULT_PADDING).fillMaxSize(), contentAlignment = Alignment.Center) { + val landscape = !appPlatform.isDesktop && windowWidth() > windowHeight() + val scrollState = LocalAppBarHandler.current?.scrollState + val density = LocalDensity.current + val windowPx = LocalWindowInfo.current.containerSize.height + val oneHandUI = remember { derivedStateOf { appPrefs.onboardingStage.state.value == OnboardingStage.OnboardingComplete && appPrefs.oneHandUI.state.value } } + val bottomBarsPx = if (oneHandUI.value) { + WindowInsets.navigationBars.getBottom(density) + with(density) { (AppBarHeight * fontSizeSqrtMultiplier).roundToPx() } + } else { + WindowInsets.systemBars.getBottom(density) + } + var contentTopPx by remember { mutableStateOf(null) } + val size = when { + appPlatform.isDesktop -> DEFAULT_START_MODAL_WIDTH * fontSizeSqrtMultiplier + landscape -> contentTopPx?.let { top -> + (with(density) { (windowPx - top - bottomBarsPx).toDp() } - DEFAULT_PADDING * 2).coerceAtLeast(120.dp) + } ?: 120.dp + else -> windowWidth() - DEFAULT_PADDING * 2 + } + Box( + Modifier + .onGloballyPositioned { if (landscape) contentTopPx = it.positionInWindow().y + (scrollState?.value ?: 0) } + .padding(DEFAULT_PADDING) + .then(if (landscape) Modifier.fillMaxWidth() else Modifier.fillMaxSize()), + contentAlignment = Alignment.Center + ) { CircularProgressIndicator( progress = value, - (if (appPlatform.isDesktop) Modifier.size(DEFAULT_START_MODAL_WIDTH * fontSizeSqrtMultiplier) else Modifier.size(windowWidth() - DEFAULT_PADDING * - 2)) + Modifier.size(size) .rotate(-90f), color = MaterialTheme.colors.primary, strokeWidth = 25.dp ) + val textScale = if (landscape) (size / 300.dp).coerceIn(0.4f, 1f) else 1f + val descriptionStyle = MaterialTheme.typography.subtitle1.let { it.copy(fontSize = it.fontSize * textScale) } Column(horizontalAlignment = Alignment.CenterHorizontally) { - Text(description, color = Color.Transparent) - Text(title, style = MaterialTheme.typography.h1.copy(fontSize = 50.sp, fontWeight = FontWeight.Bold), color = MaterialTheme.colors.primary) - Text(description, style = MaterialTheme.typography.subtitle1) + Text(description, style = LocalTextStyle.current.let { it.copy(fontSize = it.fontSize * textScale) }, color = Color.Transparent) + Text(title, style = MaterialTheme.typography.h1.copy(fontSize = 50.sp * textScale, fontWeight = FontWeight.Bold), color = MaterialTheme.colors.primary) + Text(description, style = descriptionStyle) } } } diff --git a/apps/multiplatform/spec/architecture.md b/apps/multiplatform/spec/architecture.md index cdc43a794a..1ac6bbcc24 100644 --- a/apps/multiplatform/spec/architecture.md +++ b/apps/multiplatform/spec/architecture.md @@ -380,7 +380,7 @@ var platform: PlatformInterface = object : PlatformInterface {} | `androidApiLevel` | `null` | `Build.VERSION.SDK_INT` | | `androidIsPlayStoreBuild` | `false` | `BuildConfig.PLAY_STORE` | | `androidLoadPlayStoreCountry()` | no-op | Request the Play account country (google flavor only) | -| `androidLockPortraitOrientation()` | no-op | Lock to `SCREEN_ORIENTATION_PORTRAIT` | +| `androidLockPortraitOrientation()` | no-op | Lock to `SCREEN_ORIENTATION_LOCKED` (current orientation) | | `androidAskToAllowBackgroundCalls()` | `true` | Show battery restriction dialog | | `desktopShowAppUpdateNotice()` | no-op | Show update notice (Desktop only) |