mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-24 23:45:19 +00:00
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:
@@ -64,14 +64,12 @@
|
|||||||
android:name=".ui.GeohashPickerActivity"
|
android:name=".ui.GeohashPickerActivity"
|
||||||
android:exported="false"
|
android:exported="false"
|
||||||
android:theme="@style/Theme.BitchatAndroid"
|
android:theme="@style/Theme.BitchatAndroid"
|
||||||
android:screenOrientation="portrait"
|
|
||||||
android:windowSoftInputMode="adjustResize" />
|
android:windowSoftInputMode="adjustResize" />
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
android:exported="true"
|
android:exported="true"
|
||||||
android:label="@string/app_name"
|
android:label="@string/app_name"
|
||||||
android:theme="@style/Theme.BitchatAndroid"
|
android:theme="@style/Theme.BitchatAndroid"
|
||||||
android:screenOrientation="portrait"
|
|
||||||
android:windowSoftInputMode="adjustResize"
|
android:windowSoftInputMode="adjustResize"
|
||||||
android:launchMode="singleTop">
|
android:launchMode="singleTop">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.bitchat.android
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.OnBackPressedCallback
|
import androidx.activity.OnBackPressedCallback
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.activity.enableEdgeToEdge
|
import androidx.activity.enableEdgeToEdge
|
||||||
@@ -15,7 +14,6 @@ import androidx.compose.material3.Scaffold
|
|||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.platform.LocalContext
|
import androidx.compose.ui.platform.LocalContext
|
||||||
import androidx.compose.ui.unit.dp
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.lifecycle.ViewModelProvider
|
import androidx.lifecycle.ViewModelProvider
|
||||||
import androidx.lifecycle.repeatOnLifecycle
|
import androidx.lifecycle.repeatOnLifecycle
|
||||||
@@ -39,13 +37,14 @@ import com.bitchat.android.onboarding.PermissionExplanationScreen
|
|||||||
import com.bitchat.android.onboarding.PermissionManager
|
import com.bitchat.android.onboarding.PermissionManager
|
||||||
import com.bitchat.android.ui.ChatScreen
|
import com.bitchat.android.ui.ChatScreen
|
||||||
import com.bitchat.android.ui.ChatViewModel
|
import com.bitchat.android.ui.ChatViewModel
|
||||||
|
import com.bitchat.android.ui.OrientationAwareActivity
|
||||||
import com.bitchat.android.ui.theme.BitchatTheme
|
import com.bitchat.android.ui.theme.BitchatTheme
|
||||||
import com.bitchat.android.nostr.PoWPreferenceManager
|
import com.bitchat.android.nostr.PoWPreferenceManager
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class MainActivity : ComponentActivity() {
|
class MainActivity : OrientationAwareActivity() {
|
||||||
|
|
||||||
private lateinit var permissionManager: PermissionManager
|
private lateinit var permissionManager: PermissionManager
|
||||||
private lateinit var onboardingCoordinator: OnboardingCoordinator
|
private lateinit var onboardingCoordinator: OnboardingCoordinator
|
||||||
private lateinit var bluetoothStatusManager: BluetoothStatusManager
|
private lateinit var bluetoothStatusManager: BluetoothStatusManager
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import android.webkit.WebChromeClient
|
|||||||
import android.webkit.WebSettings
|
import android.webkit.WebSettings
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import androidx.activity.ComponentActivity
|
|
||||||
import androidx.activity.compose.setContent
|
import androidx.activity.compose.setContent
|
||||||
import androidx.compose.foundation.layout.*
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
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
|
import com.bitchat.android.ui.theme.BASE_FONT_SIZE
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
class GeohashPickerActivity : ComponentActivity() {
|
class GeohashPickerActivity : OrientationAwareActivity() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val EXTRA_INITIAL_GEOHASH = "initial_geohash"
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user