11package com.enaboapps.switchify.screens.pc
22
3+ import android.Manifest
4+ import android.content.Intent
5+ import android.net.Uri
6+ import android.os.Build
7+ import android.provider.Settings
38import androidx.compose.foundation.layout.Arrangement
49import androidx.compose.foundation.layout.BoxWithConstraints
510import androidx.compose.foundation.layout.Column
@@ -16,6 +21,9 @@ import androidx.compose.runtime.Composable
1621import androidx.compose.runtime.LaunchedEffect
1722import androidx.compose.runtime.collectAsState
1823import androidx.compose.runtime.getValue
24+ import androidx.compose.runtime.mutableStateOf
25+ import androidx.compose.runtime.saveable.rememberSaveable
26+ import androidx.compose.runtime.setValue
1927import androidx.compose.ui.Modifier
2028import androidx.compose.ui.platform.LocalContext
2129import androidx.compose.ui.res.stringResource
@@ -25,6 +33,7 @@ import androidx.compose.ui.unit.dp
2533import androidx.lifecycle.viewmodel.compose.viewModel
2634import androidx.navigation.NavController
2735import com.enaboapps.switchify.R
36+ import com.enaboapps.switchify.components.ActionButton
2837import com.enaboapps.switchify.components.BaseView
2938import com.enaboapps.switchify.components.PreferenceComponentBase
3039import com.enaboapps.switchify.components.ScrollableView
@@ -34,17 +43,34 @@ import com.enaboapps.switchify.pc.PcConnectionViewModel
3443import com.enaboapps.switchify.pc.PcRowState
3544import com.enaboapps.switchify.pc.PcRowStatus
3645import com.enaboapps.switchify.theme.Dimens
46+ import com.google.accompanist.permissions.ExperimentalPermissionsApi
47+ import com.google.accompanist.permissions.PermissionState
48+ import com.google.accompanist.permissions.isGranted
49+ import com.google.accompanist.permissions.rememberPermissionState
50+ import com.google.accompanist.permissions.shouldShowRationale
3751
3852private val PcConnectionCompactRowWidth = 380 .dp
3953
54+ @OptIn(ExperimentalPermissionsApi ::class )
4055@Composable
4156fun PcConnectionScreen (navController : NavController ) {
4257 val context = LocalContext .current
4358 val viewModel: PcConnectionViewModel = viewModel { PcConnectionViewModel (context.applicationContext) }
4459 val uiState by viewModel.uiState.collectAsState()
4560
46- LaunchedEffect (Unit ) {
47- viewModel.startDiscovery()
61+ val permissionState: PermissionState ? = if (Build .VERSION .SDK_INT >= Build .VERSION_CODES .TIRAMISU ) {
62+ rememberPermissionState(Manifest .permission.NEARBY_WIFI_DEVICES )
63+ } else {
64+ null
65+ }
66+ val permissionGranted = permissionState?.status?.isGranted ? : true
67+ var hasRequestedPermission by rememberSaveable { mutableStateOf(false ) }
68+
69+ LaunchedEffect (permissionGranted) {
70+ viewModel.setPermissionRequired(! permissionGranted)
71+ if (permissionGranted) {
72+ viewModel.startDiscovery()
73+ }
4874 }
4975
5076 BaseView (
@@ -54,25 +80,57 @@ fun PcConnectionScreen(navController: NavController) {
5480 ) {
5581 ScrollableView {
5682 Column (verticalArrangement = Arrangement .spacedBy(Dimens .spaceM)) {
57- Section (titleResId = R .string.pc_connection_nearby_section) {
58- Column (modifier = Modifier .padding(vertical = Dimens .spaceS)) {
59- Text (
60- text = uiState.discoveryStatusText,
61- style = MaterialTheme .typography.bodyMedium,
62- color = MaterialTheme .colorScheme.onSurfaceVariant,
63- modifier = Modifier .padding(horizontal = Dimens .spaceM, vertical = Dimens .spaceS)
64- )
65- uiState.discoveredPcs.forEach { row ->
66- PcConnectionPreferenceRow (
67- title = row.title,
68- summary = row.summary,
69- onClick = { row.perform(viewModel) },
70- actions = {
71- PcNearbyRowActions (row = row, viewModel = viewModel)
83+ if (uiState.permissionRequired) {
84+ Section (titleResId = R .string.pc_connection_permission_section) {
85+ Column (modifier = Modifier .padding(vertical = Dimens .spaceS)) {
86+ Text (
87+ text = stringResource(R .string.pc_connection_permission_message),
88+ style = MaterialTheme .typography.bodyMedium,
89+ color = MaterialTheme .colorScheme.onSurfaceVariant,
90+ modifier = Modifier .padding(horizontal = Dimens .spaceM, vertical = Dimens .spaceS)
91+ )
92+ ActionButton (
93+ textResId = R .string.pc_connection_permission_action,
94+ applyPadding = false ,
95+ modifier = Modifier
96+ .fillMaxWidth()
97+ .padding(horizontal = Dimens .spaceM, vertical = Dimens .spaceS),
98+ onClick = {
99+ val state = permissionState ? : return @ActionButton
100+ if (! hasRequestedPermission || state.status.shouldShowRationale) {
101+ hasRequestedPermission = true
102+ state.launchPermissionRequest()
103+ } else {
104+ val intent = Intent (Settings .ACTION_APPLICATION_DETAILS_SETTINGS ).apply {
105+ data = Uri .fromParts(" package" , context.packageName, null )
106+ }
107+ context.startActivity(intent)
108+ }
72109 }
73110 )
74111 }
75112 }
113+ } else {
114+ Section (titleResId = R .string.pc_connection_nearby_section) {
115+ Column (modifier = Modifier .padding(vertical = Dimens .spaceS)) {
116+ Text (
117+ text = uiState.discoveryStatusText,
118+ style = MaterialTheme .typography.bodyMedium,
119+ color = MaterialTheme .colorScheme.onSurfaceVariant,
120+ modifier = Modifier .padding(horizontal = Dimens .spaceM, vertical = Dimens .spaceS)
121+ )
122+ uiState.discoveredPcs.forEach { row ->
123+ PcConnectionPreferenceRow (
124+ title = row.title,
125+ summary = row.summary,
126+ onClick = { row.perform(viewModel) },
127+ actions = {
128+ PcNearbyRowActions (row = row, viewModel = viewModel)
129+ }
130+ )
131+ }
132+ }
133+ }
76134 }
77135 if (uiState.savedPairings.isNotEmpty()) {
78136 Section (titleResId = R .string.pc_connection_paired_section) {
0 commit comments