android: allow users to update taildrop directory (#658)
-Modify Permissions view to navigate to Taildrop dir view and Notifications view, and to reflect state -Add Taildrop dir view which navigates to directory selector -Add Notifications view which navigates to Taildrop notifications setting Updates tailscale/tailscale#15263 Signed-off-by: kari-ts <kari@tailscale.com>pull/654/head
parent
a14d4c7184
commit
87f0e9754b
@ -0,0 +1,93 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package com.tailscale.ipn.ui.view
|
||||
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.tailscale.ipn.R
|
||||
import com.tailscale.ipn.ui.model.Permissions
|
||||
import com.tailscale.ipn.ui.theme.exitNodeToggleButton
|
||||
|
||||
@Composable
|
||||
fun NotificationsView(backToPermissionsView: BackNavigation, openApplicationSettings: () -> Unit) {
|
||||
val permissions = Permissions.withGrantedStatus
|
||||
|
||||
// Find the notification permission
|
||||
val notificationPermission =
|
||||
permissions.find { (permission, _) ->
|
||||
permission.title == R.string.permission_post_notifications
|
||||
}
|
||||
val granted = notificationPermission?.second ?: false
|
||||
val permission = notificationPermission?.first
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
Header(titleRes = R.string.permission_post_notifications, onBack = backToPermissionsView)
|
||||
}) { innerPadding ->
|
||||
LazyColumn(modifier = Modifier.padding(innerPadding)) {
|
||||
item {
|
||||
if (permission != null) {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
stringResource(permission.title),
|
||||
style = MaterialTheme.typography.titleMedium)
|
||||
},
|
||||
supportingContent = {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
Text(
|
||||
text = stringResource(permission.description),
|
||||
style = MaterialTheme.typography.bodyMedium)
|
||||
Spacer(modifier = Modifier.height(12.dp))
|
||||
Text(
|
||||
text = stringResource(R.string.notification_settings_explanation),
|
||||
style = MaterialTheme.typography.bodyMedium)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
item("spacer") {
|
||||
Spacer(modifier = Modifier.height(16.dp)) // soft break instead of divider
|
||||
}
|
||||
|
||||
item {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = stringResource(R.string.permission_post_notifications),
|
||||
style = MaterialTheme.typography.titleMedium)
|
||||
},
|
||||
supportingContent = {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
Text(
|
||||
text =
|
||||
if (granted) stringResource(R.string.on)
|
||||
else stringResource(R.string.off),
|
||||
style = MaterialTheme.typography.bodyMedium)
|
||||
Button(
|
||||
colors = MaterialTheme.colorScheme.exitNodeToggleButton,
|
||||
onClick = openApplicationSettings,
|
||||
modifier = Modifier.fillMaxWidth().padding(top = 12.dp)) {
|
||||
Text(stringResource(R.string.open_notification_settings))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,79 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
package com.tailscale.ipn.ui.view
|
||||
|
||||
import android.net.Uri
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ListItem
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.tailscale.ipn.R
|
||||
import com.tailscale.ipn.ui.theme.exitNodeToggleButton
|
||||
import com.tailscale.ipn.ui.util.Lists
|
||||
import com.tailscale.ipn.ui.util.friendlyDirName
|
||||
import com.tailscale.ipn.ui.viewModel.PermissionsViewModel
|
||||
|
||||
@Composable
|
||||
fun TaildropDirView(
|
||||
backToPermissionsView: BackNavigation,
|
||||
openDirectoryLauncher: ActivityResultLauncher<Uri?>,
|
||||
permissionsViewModel: PermissionsViewModel = viewModel()
|
||||
) {
|
||||
Scaffold(
|
||||
topBar = {
|
||||
Header(titleRes = R.string.taildrop_dir_access, onBack = backToPermissionsView)
|
||||
}) { innerPadding ->
|
||||
LazyColumn(modifier = Modifier.padding(innerPadding)) {
|
||||
item {
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
stringResource(R.string.taildrop_dir_access),
|
||||
style = MaterialTheme.typography.titleMedium)
|
||||
},
|
||||
supportingContent = {
|
||||
Text(
|
||||
text = stringResource(R.string.permission_taildrop_dir),
|
||||
style = MaterialTheme.typography.bodyMedium)
|
||||
})
|
||||
}
|
||||
|
||||
item("divider0") { Lists.SectionDivider() }
|
||||
|
||||
item {
|
||||
val currentDir = permissionsViewModel.currentDir.value
|
||||
val displayPath = currentDir?.let { friendlyDirName(it) } ?: "No access"
|
||||
|
||||
ListItem(
|
||||
headlineContent = {
|
||||
Text(
|
||||
text = stringResource(R.string.dir_access),
|
||||
style = MaterialTheme.typography.titleMedium)
|
||||
},
|
||||
supportingContent = {
|
||||
Column(modifier = Modifier.fillMaxWidth()) {
|
||||
Text(text = displayPath, style = MaterialTheme.typography.bodyMedium)
|
||||
Button(
|
||||
colors = MaterialTheme.colorScheme.exitNodeToggleButton,
|
||||
onClick = { openDirectoryLauncher.launch(null) },
|
||||
modifier = Modifier.fillMaxWidth().padding(top = 12.dp)) {
|
||||
Text(stringResource(R.string.pick_dir))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:height="24dp"
|
||||
android:width="24dp"
|
||||
android:viewportHeight="24"
|
||||
android:viewportWidth="24"
|
||||
android:tint="#000000">
|
||||
|
||||
<!-- Folder outline -->
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z" />
|
||||
|
||||
<!-- Flipped arrow, shifted downward by 1dp (in viewport units) -->
|
||||
<group
|
||||
android:translateY="2">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M16,10.99l-1.41,-1.41L13,11.16V7h-2v4.16L9.41,9.58 8,10.99 12.01,15 16,10.99z" />
|
||||
</group>
|
||||
</vector>
|
||||
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M20,6h-8l-2,-2L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,8c0,-1.1 -0.9,-2 -2,-2zM20,18L4,18L4,8h16v10z"/>
|
||||
|
||||
</vector>
|
||||
@ -0,0 +1,5 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||
|
||||
<path android:fillColor="@android:color/white" android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zM18,16v-5c0,-3.07 -1.63,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.64,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2zM16,17L8,17v-6c0,-2.48 1.51,-4.5 4,-4.5s4,2.02 4,4.5v6z"/>
|
||||
|
||||
</vector>
|
||||
Loading…
Reference in New Issue