diff --git a/app/.idea/.gitignore b/app/.idea/.gitignore
new file mode 100644
index 0000000..26d3352
--- /dev/null
+++ b/app/.idea/.gitignore
@@ -0,0 +1,3 @@
+# Default ignored files
+/shelf/
+/workspace.xml
diff --git a/app/.idea/AndroidProjectSystem.xml b/app/.idea/AndroidProjectSystem.xml
new file mode 100644
index 0000000..4a53bee
--- /dev/null
+++ b/app/.idea/AndroidProjectSystem.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.idea/caches/deviceStreaming.xml b/app/.idea/caches/deviceStreaming.xml
new file mode 100644
index 0000000..8cc741b
--- /dev/null
+++ b/app/.idea/caches/deviceStreaming.xml
@@ -0,0 +1,2410 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.idea/gradle.xml b/app/.idea/gradle.xml
new file mode 100644
index 0000000..b838237
--- /dev/null
+++ b/app/.idea/gradle.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.idea/migrations.xml b/app/.idea/migrations.xml
new file mode 100644
index 0000000..f8051a6
--- /dev/null
+++ b/app/.idea/migrations.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.idea/misc.xml b/app/.idea/misc.xml
new file mode 100644
index 0000000..3aec57f
--- /dev/null
+++ b/app/.idea/misc.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.idea/runConfigurations.xml b/app/.idea/runConfigurations.xml
new file mode 100644
index 0000000..16660f1
--- /dev/null
+++ b/app/.idea/runConfigurations.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.idea/vcs.xml b/app/.idea/vcs.xml
new file mode 100644
index 0000000..6c0b863
--- /dev/null
+++ b/app/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 9bda6b3..3a6e55c 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -54,5 +54,6 @@ dependencies {
debugImplementation(libs.androidx.compose.ui.test.manifest)
debugImplementation(libs.androidx.compose.ui.tooling)
+ implementation("androidx.activity:activity-ktx:1.13.0")
implementation("androidx.navigation:navigation-compose:2.10.2")
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4ca46b6..1624f43 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,7 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
-
+
@@ -19,7 +19,6 @@
android:theme="@style/Theme.SmartWatchAndroid">
diff --git a/app/src/main/java/com/example/smart_watch_android/BLE/BleManager.kt b/app/src/main/java/com/example/smart_watch_android/BLE/BleManager.kt
index 7529169..8387f48 100644
--- a/app/src/main/java/com/example/smart_watch_android/BLE/BleManager.kt
+++ b/app/src/main/java/com/example/smart_watch_android/BLE/BleManager.kt
@@ -9,16 +9,22 @@ import android.bluetooth.BluetoothGattCharacteristic
import android.bluetooth.BluetoothManager
import android.bluetooth.BluetoothProfile
import android.content.Context
+import android.content.Intent
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
+import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.annotation.RequiresPermission
-import androidx.compose.runtime.mutableStateOf
+import androidx.compose.ui.platform.LocalContext
import androidx.core.app.ActivityCompat
+import com.example.smart_watch_android.MainViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.time.LocalDate
import java.time.LocalTime
@@ -26,18 +32,15 @@ import java.time.format.DateTimeFormatter
import java.util.UUID
import kotlin.time.Duration.Companion.milliseconds
-class BleManager(private val context: Context) {
-
- //var deviceAddress = "10:BD:A3:8F:01:0E"
+object BLEManager{
var devices = mutableListOf()
- var isConnected = mutableStateOf(false)
-
+ private val _isConnected = MutableStateFlow(false)
+ val isConnected: StateFlow = _isConnected.asStateFlow()
val currentDate: LocalDate? = LocalDate.now()
private val deviceUUIDs = DeviceUUIDs
private var bluetoothGatt: BluetoothGatt? = null
- private var bluetoothManager: BluetoothManager? = null
- private var bluetoothAdapter: BluetoothAdapter? = null
- var deviceAddress: String = ""
+ private lateinit var bluetoothManager: BluetoothManager
+ private lateinit var bluetoothAdapter: BluetoothAdapter
val gattCallback = object : BluetoothGattCallback() {
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
override fun onConnectionStateChange(gatt: BluetoothGatt, status: Int, newState: Int) {
@@ -46,7 +49,7 @@ class BleManager(private val context: Context) {
Log.d("ESP32_BLE", "Connected! Start discoverServices()...")
gatt.discoverServices()
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
- isConnected.value = false
+ updateConnectionStatus(false)
gatt.close()
bluetoothGatt = null
@@ -54,14 +57,14 @@ class BleManager(private val context: Context) {
}
} else {
Log.d("ESP32_BLE", "error in onConnectionStateChange! Status-Code: $status")
- isConnected.value = false
+ updateConnectionStatus(false)
}
}
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
if (status == BluetoothGatt.GATT_SUCCESS) {
Log.d("ESP32_BLE", "connected successfully.")
- isConnected.value = true
+ updateConnectionStatus(true)
}
}
}
@@ -69,28 +72,31 @@ class BleManager(private val context: Context) {
val deviceName: String,
val deviceMac: String
)
-
@RequiresApi(Build.VERSION_CODES.S)
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- fun init() {
- checkAndRequestBluetoothPermissions()
+ fun init(context: Context, activity: Activity) {
+ checkAndRequestBluetoothPermissions(
+ activity = activity
+ )
bluetoothManager = context.getSystemService(Context.BLUETOOTH_SERVICE) as BluetoothManager
- bluetoothAdapter = bluetoothManager?.adapter
+ bluetoothAdapter = bluetoothManager.adapter
devices = getDeviceList() as MutableList
}
-
+ fun updateConnectionStatus(status: Boolean) {
+ _isConnected.value = status
+ }
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
fun getDeviceList(): List{
- bluetoothAdapter?.bondedDevices?.forEach { device ->
+ devices.clear()
+ bluetoothAdapter.bondedDevices?.forEach { device ->
devices.add(Devices(deviceName = device.name, deviceMac = device.address))
}
Log.d("devices","$devices")
return devices
}
-
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
@RequiresApi(Build.VERSION_CODES.S)
- fun checkAndRequestBluetoothPermissions() {
+ fun checkAndRequestBluetoothPermissions(activity: Activity) {
val permissions = arrayOf(
Manifest.permission.BLUETOOTH_CONNECT,
Manifest.permission.BLUETOOTH_SCAN,
@@ -98,27 +104,20 @@ class BleManager(private val context: Context) {
)
val missingPermissions = permissions.filter {
- ActivityCompat.checkSelfPermission(context, it) != PackageManager.PERMISSION_GRANTED
+ ActivityCompat.checkSelfPermission(activity, it) != PackageManager.PERMISSION_GRANTED
}
if (missingPermissions.isNotEmpty()) {
- val activity = context as? Activity
- if (activity != null) {
- ActivityCompat.requestPermissions(activity, missingPermissions.toTypedArray(), 101)
- } else {
- Log.d("ESP32_BLE", "Cannot request permissions: Context is not an Activity!")
- }
+ // Berechtigungen anfordern
+ ActivityCompat.requestPermissions(activity, missingPermissions.toTypedArray(), 101)
+ } else {
+ Log.d("ESP32_BLE", "Alle Bluetooth-Berechtigungen sind bereits erteilt!")
}
}
-
- fun connectToEsp32() {
+ fun connectToEsp32(context: Context, deviceAddress: String) {
Log.d("ESP32_BLE", "connectToEsp32 started with address: $deviceAddress")
- if (bluetoothAdapter == null) {
- Log.d("ESP32_BLE", "error: Bluetooth is not supported!")
- return
- }
try {
- val device = bluetoothAdapter!!.getRemoteDevice(deviceAddress)
+ val device = bluetoothAdapter.getRemoteDevice(deviceAddress)
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
bluetoothGatt = device.connectGatt(context, false, gattCallback)
@@ -131,7 +130,7 @@ class BleManager(private val context: Context) {
}
}
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- fun disconnectEsp32() {
+ fun disconnectEsp32(context: Context) {
if (ActivityCompat.checkSelfPermission(context, Manifest.permission.BLUETOOTH_CONNECT) == PackageManager.PERMISSION_GRANTED) {
bluetoothGatt?.disconnect()
Log.d("ESP32_BLE","disconnectEsp32")
@@ -140,8 +139,7 @@ class BleManager(private val context: Context) {
Log.d("BLE_DEBUG", "Permission BLUETOOTH_CONNECT error!")
}
}
-
- fun writeToEsp32(dataString: String, SERVICE_UUID: UUID?, CHARACTERISTIC_UUID: UUID?) {
+ fun writeToEsp32(context: Context, dataString: String, SERVICE_UUID: UUID?, CHARACTERISTIC_UUID: UUID?) {
val gatt = bluetoothGatt
if (gatt == null) {
Log.d("ESP32_BLE", "error: no GATT-Objekt existing (not connected).")
@@ -170,7 +168,7 @@ class BleManager(private val context: Context) {
Log.d("ESP32_BLE", "started writing: $success")
}
}
- fun syncTime() {
+ fun syncTime(context: Context) {
val currentTime = LocalTime.now()
val formatterTime = DateTimeFormatter.ofPattern("HH mm ss")
val formattedTime = currentTime.format(formatterTime)
@@ -181,11 +179,19 @@ class BleManager(private val context: Context) {
Log.d("Time/Date","$formattedDate $formattedTime")
CoroutineScope(Dispatchers.IO).launch {
- writeToEsp32(formattedTime, deviceUUIDs.SERVICE_UUID, deviceUUIDs.CHAR_TIME_UUID)
+ writeToEsp32(
+ context = context,
+ dataString = formattedTime,
+ SERVICE_UUID = deviceUUIDs.SERVICE_UUID,
+ CHARACTERISTIC_UUID = deviceUUIDs.CHAR_TIME_UUID)
delay(150.milliseconds)
- writeToEsp32("$formattedDate", deviceUUIDs.SERVICE_UUID, deviceUUIDs.CHAR_DATE_UUID)
+ writeToEsp32(
+ context = context,
+ dataString ="$formattedDate",
+ SERVICE_UUID = deviceUUIDs.SERVICE_UUID,
+ CHARACTERISTIC_UUID = deviceUUIDs.CHAR_DATE_UUID)
}
}
}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/smart_watch_android/MainActivity.kt b/app/src/main/java/com/example/smart_watch_android/MainActivity.kt
index 88d1534..7d46369 100644
--- a/app/src/main/java/com/example/smart_watch_android/MainActivity.kt
+++ b/app/src/main/java/com/example/smart_watch_android/MainActivity.kt
@@ -1,7 +1,6 @@
package com.example.smart_watch_android
import android.Manifest
-import android.content.Intent
import android.os.Build
import android.os.Bundle
import androidx.activity.ComponentActivity
@@ -13,20 +12,17 @@ import androidx.annotation.RequiresPermission
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
-import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
-import com.example.smart_watch_android.BLE.BleManager
+import com.example.smart_watch_android.BLE.BLEManager
import com.example.smart_watch_android.Screens.AppNavigation
class MainActivity : ComponentActivity() {
- lateinit var bleManager: BleManager
-
+ private val viewModel: MainViewModel by viewModels()
@RequiresApi(Build.VERSION_CODES.S)
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
override fun onCreate(savedInstanceState: Bundle?,) {
super.onCreate(savedInstanceState)
- bleManager = BleManager(this)
- bleManager.init()
+ BLEManager.init(context = applicationContext, activity = this)
enableEdgeToEdge()
setContent {
MaterialTheme {
@@ -34,16 +30,9 @@ class MainActivity : ComponentActivity() {
modifier = Modifier.fillMaxSize(),
color = MaterialTheme.colorScheme.background
) {
- AppNavigation(bleManager = bleManager)
+ AppNavigation(viewModel)
}
}
}
}
-
- @RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
- override fun onDestroy() {
- super.onDestroy()
- bleManager.disconnectEsp32()
-
- }
}
diff --git a/app/src/main/java/com/example/smart_watch_android/MainViewModel.kt b/app/src/main/java/com/example/smart_watch_android/MainViewModel.kt
new file mode 100644
index 0000000..f8a50d6
--- /dev/null
+++ b/app/src/main/java/com/example/smart_watch_android/MainViewModel.kt
@@ -0,0 +1,17 @@
+package com.example.smart_watch_android
+
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.setValue
+import androidx.lifecycle.ViewModel
+
+class MainViewModel : ViewModel() {
+ var selectedDevice by mutableStateOf("device")
+ fun updateSelectedDevice(newName: String) {
+ selectedDevice = newName
+ }
+ var selectedDeviceAddress = ""
+ fun updateSelectedDeviceAddress(address: String) {
+ selectedDeviceAddress = address
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/example/smart_watch_android/Screens/AppNavigation.kt b/app/src/main/java/com/example/smart_watch_android/Screens/AppNavigation.kt
index 42d7701..468da28 100644
--- a/app/src/main/java/com/example/smart_watch_android/Screens/AppNavigation.kt
+++ b/app/src/main/java/com/example/smart_watch_android/Screens/AppNavigation.kt
@@ -4,17 +4,23 @@ import android.Manifest
import androidx.annotation.RequiresPermission
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.ui.platform.LocalContext
import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController
-import com.example.smart_watch_android.BLE.BleManager
+import com.example.smart_watch_android.BLE.BLEManager
+import com.example.smart_watch_android.MainViewModel
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
@Composable
-fun AppNavigation(bleManager: BleManager) {
+fun AppNavigation(viewModel: MainViewModel) {
+ val context = LocalContext.current
+ val isConnected by BLEManager.isConnected.collectAsState()
val navController = rememberNavController()
- LaunchedEffect(bleManager.isConnected) {
- if (bleManager.isConnected.value) {
+ LaunchedEffect(BLEManager.isConnected) {
+ if (isConnected) {
navController.navigate("control_panel") {
popUpTo("connect") { inclusive = true }
}
@@ -24,7 +30,7 @@ fun AppNavigation(bleManager: BleManager) {
}
}
}
- val startDestination = if (bleManager.isConnected.value) {
+ val startDestination = if (isConnected) {
"control_panel"
} else {
"connect"
@@ -36,17 +42,15 @@ fun AppNavigation(bleManager: BleManager) {
) {
// Connect Screen
composable("connect") {
- ConnectScreen(
- bleManager = bleManager
- )
+ ConnectScreen(viewModel)
}
composable("control_panel") {
ControlPanelScreen(
- bleManager = bleManager,
+ viewModel,
onDisconnectClicked = {
- bleManager.disconnectEsp32()
- }
+ BLEManager.disconnectEsp32(context = context)
+ },
)
}
}
diff --git a/app/src/main/java/com/example/smart_watch_android/Screens/ConnectScreen.kt b/app/src/main/java/com/example/smart_watch_android/Screens/ConnectScreen.kt
index 9830b90..9481a93 100644
--- a/app/src/main/java/com/example/smart_watch_android/Screens/ConnectScreen.kt
+++ b/app/src/main/java/com/example/smart_watch_android/Screens/ConnectScreen.kt
@@ -1,13 +1,17 @@
package com.example.smart_watch_android.Screens
import android.Manifest
+import android.content.res.Configuration
import android.util.Log
import androidx.annotation.RequiresPermission
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
@@ -27,15 +31,29 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalConfiguration
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
-import com.example.smart_watch_android.BLE.BleManager
-
+import com.example.smart_watch_android.BLE.BLEManager
+import com.example.smart_watch_android.MainViewModel
@RequiresPermission(Manifest.permission.BLUETOOTH_CONNECT)
@Composable
-fun ConnectScreen(bleManager: BleManager) {
+fun ConnectScreen(viewModel: MainViewModel) {
+ val context = LocalContext.current
var expanded by remember { mutableStateOf(false) }
- var selectedDevice by remember { mutableStateOf("device") }
+ val configuration = LocalConfiguration.current
+ val isLandscape = configuration.orientation == Configuration.ORIENTATION_LANDSCAPE
+ val fraction = 0.7f
+ val dynamicModifier = if (isLandscape) {
+ Modifier
+ .fillMaxHeight(fraction)
+ .aspectRatio(1f)
+ } else {
+ Modifier
+ .fillMaxWidth(fraction)
+ .aspectRatio(1f)
+ }
Column(
modifier = Modifier
.fillMaxSize()
@@ -44,29 +62,34 @@ fun ConnectScreen(bleManager: BleManager) {
horizontalAlignment = Alignment.CenterHorizontally
)
{
+ Box(
+ ){
+ Text("if the list is empty ensure you have bluetooth enabled!")
+ }
Box(
modifier = Modifier
.padding(16.dp)
) {
Button(
- onClick = { expanded = !expanded },
+ onClick = { expanded = !expanded},
shape = RoundedCornerShape(4.dp),
- modifier = Modifier.width(400.dp)
+ modifier = Modifier.fillMaxWidth(fraction),
+ colors = ButtonDefaults.buttonColors(Color(0xFF5E18BE))
) {
- Text(selectedDevice)
+ Text(viewModel.selectedDevice)
}
DropdownMenu(
expanded = expanded,
onDismissRequest = { expanded = false },
modifier = Modifier
- .width(400.dp)
+ .fillMaxWidth(0.6f)
) {
- bleManager.devices.forEach { item ->
+ BLEManager.devices.forEach { item ->
DropdownMenuItem(
text = { Text(item.deviceName) },
onClick = {
- selectedDevice = item.deviceName
- bleManager.deviceAddress = item.deviceMac
+ viewModel.updateSelectedDevice(item.deviceName)
+ viewModel.updateSelectedDeviceAddress(item.deviceMac)
Log.d("ConnectScreen", item.deviceMac)
expanded = false
}
@@ -75,13 +98,11 @@ fun ConnectScreen(bleManager: BleManager) {
}
}
-
-
Spacer(modifier = Modifier.height(64.dp))
Button(
- modifier = Modifier.size(400.dp),
- onClick = {bleManager.connectToEsp32() },
+ modifier = dynamicModifier,
+ onClick = {BLEManager.connectToEsp32(context, viewModel.selectedDeviceAddress) },
shape = CircleShape,
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF5E18BE))
) {
diff --git a/app/src/main/java/com/example/smart_watch_android/Screens/ControlPanelScreen.kt b/app/src/main/java/com/example/smart_watch_android/Screens/ControlPanelScreen.kt
index 573108d..db5081d 100644
--- a/app/src/main/java/com/example/smart_watch_android/Screens/ControlPanelScreen.kt
+++ b/app/src/main/java/com/example/smart_watch_android/Screens/ControlPanelScreen.kt
@@ -12,6 +12,7 @@ import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
@@ -19,15 +20,18 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
-import com.example.smart_watch_android.BLE.BleManager
+import com.example.smart_watch_android.BLE.BLEManager
import com.example.smart_watch_android.BLE.DeviceUUIDs
+import com.example.smart_watch_android.MainViewModel
@Composable
fun ControlPanelScreen(
- bleManager: BleManager,
+ viewModel: MainViewModel,
onDisconnectClicked: () -> Unit
) {
+ val context = LocalContext.current
var textInput by remember { mutableStateOf("") }
Column(
@@ -50,9 +54,12 @@ fun ControlPanelScreen(
Button(
onClick = {
if (textInput.isNotEmpty()) {
- bleManager.writeToEsp32(
- textInput, DeviceUUIDs.SERVICE_UUID, DeviceUUIDs.CHAR_MESSAGE_UUID
- )
+ BLEManager.writeToEsp32(
+ context = context,
+ dataString = textInput,
+ SERVICE_UUID = DeviceUUIDs.SERVICE_UUID,
+ CHARACTERISTIC_UUID = DeviceUUIDs.CHAR_MESSAGE_UUID,
+ )
textInput = ""
}
},
@@ -67,7 +74,9 @@ fun ControlPanelScreen(
Button(
onClick = {
- bleManager.syncTime()
+ BLEManager.syncTime(
+ context
+ )
},
colors = ButtonDefaults.buttonColors(containerColor = Color(0xFF50128F)),
modifier = Modifier.fillMaxWidth()