feat: Add tablet landscape orientation support (#490)

- Tablets now support landscape mode, phones remain portrait-only
- Add OrientationAwareActivity base class for orientation management
- Add DeviceUtils.isTablet() for runtime device detection
- Update MainActivity and GeohashPickerActivity to extend OrientationAwareActivity
- Uses multiple detection criteria (screen size, density, configuration)
Fixes #480
This commit is contained in:
Developer Chunk
2025-10-20 20:14:50 +02:00
committed by GitHub
parent f633509848
commit 9535ca8940
5 changed files with 71 additions and 8 deletions
-2
View File
@@ -64,14 +64,12 @@
android:name=".ui.GeohashPickerActivity"
android:exported="false"
android:theme="@style/Theme.BitchatAndroid"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.BitchatAndroid"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTop">
<intent-filter>
@@ -3,7 +3,6 @@ package com.bitchat.android
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.OnBackPressedCallback
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
@@ -15,7 +14,6 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.repeatOnLifecycle
@@ -39,12 +37,13 @@ import com.bitchat.android.onboarding.PermissionExplanationScreen
import com.bitchat.android.onboarding.PermissionManager
import com.bitchat.android.ui.ChatScreen
import com.bitchat.android.ui.ChatViewModel
import com.bitchat.android.ui.OrientationAwareActivity
import com.bitchat.android.ui.theme.BitchatTheme
import com.bitchat.android.nostr.PoWPreferenceManager
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
class MainActivity : OrientationAwareActivity() {
private lateinit var permissionManager: PermissionManager
private lateinit var onboardingCoordinator: OnboardingCoordinator
@@ -11,7 +11,6 @@ import android.webkit.WebChromeClient
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -45,7 +44,7 @@ import com.bitchat.android.geohash.LocationChannelManager
import com.bitchat.android.ui.theme.BASE_FONT_SIZE
@OptIn(ExperimentalMaterial3Api::class)
class GeohashPickerActivity : ComponentActivity() {
class GeohashPickerActivity : OrientationAwareActivity() {
companion object {
const val EXTRA_INITIAL_GEOHASH = "initial_geohash"
@@ -0,0 +1,28 @@
package com.bitchat.android.ui
import android.content.pm.ActivityInfo
import android.os.Bundle
import androidx.activity.ComponentActivity
import com.bitchat.android.utils.DeviceUtils
/**
* Base activity that automatically sets orientation based on device type.
* Tablets can rotate to landscape, phones are locked to portrait.
*/
abstract class OrientationAwareActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setOrientationBasedOnDeviceType()
}
private fun setOrientationBasedOnDeviceType() {
requestedOrientation = if (DeviceUtils.isTablet(this)) {
// Allow all orientations on tablets
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
} else {
// Lock to portrait on phones
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
}
}
@@ -0,0 +1,39 @@
package com.bitchat.android.utils
import android.content.Context
import android.content.res.Configuration
import android.util.DisplayMetrics
import android.view.WindowManager
import androidx.core.content.getSystemService
import kotlin.math.sqrt
object DeviceUtils {
/**
* Determines if the current device is a tablet based on screen size and density.
* Uses multiple criteria to accurately detect tablets vs phones.
*/
fun isTablet(context: Context): Boolean {
val windowManager = context.getSystemService<WindowManager>()
val displayMetrics = DisplayMetrics()
windowManager?.defaultDisplay?.getMetrics(displayMetrics)
// Calculate screen size in inches
val widthInches = displayMetrics.widthPixels / displayMetrics.xdpi
val heightInches = displayMetrics.heightPixels / displayMetrics.ydpi
val diagonalInches = sqrt((widthInches * widthInches) + (heightInches * heightInches))
// Check if device has tablet configuration
val configuration = context.resources.configuration
val isLargeScreen = (configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE
val isXLargeScreen = (configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE
// A device is considered a tablet if:
// 1. Screen diagonal is 7 inches or larger, OR
// 2. Configuration indicates large or xlarge screen, OR
// 3. Smallest width is 600dp or more (sw600dp)
val smallestWidthDp = context.resources.configuration.smallestScreenWidthDp
return diagonalInches >= 7.0 || isLargeScreen || isXLargeScreen || smallestWidthDp >= 600
}
}