mirror of
https://github.com/rhunk/SnapEnhance.git
synced 2025-05-29 21:10:20 +02:00
feat: better friend add list
- alert dialogs
This commit is contained in:
parent
5fbfd5030c
commit
7703d3f007
@ -81,13 +81,14 @@ import me.rhunk.snapenhance.core.config.PropertyPair
|
|||||||
import me.rhunk.snapenhance.core.config.PropertyValue
|
import me.rhunk.snapenhance.core.config.PropertyValue
|
||||||
import me.rhunk.snapenhance.ui.manager.Section
|
import me.rhunk.snapenhance.ui.manager.Section
|
||||||
import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper
|
import me.rhunk.snapenhance.ui.util.ActivityLauncherHelper
|
||||||
|
import me.rhunk.snapenhance.ui.util.AlertDialogs
|
||||||
import me.rhunk.snapenhance.ui.util.chooseFolder
|
import me.rhunk.snapenhance.ui.util.chooseFolder
|
||||||
import me.rhunk.snapenhance.ui.util.openFile
|
import me.rhunk.snapenhance.ui.util.openFile
|
||||||
import me.rhunk.snapenhance.ui.util.saveFile
|
import me.rhunk.snapenhance.ui.util.saveFile
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
class FeaturesSection : Section() {
|
class FeaturesSection : Section() {
|
||||||
private val dialogs by lazy { Dialogs(context.translation) }
|
private val alertDialogs by lazy { AlertDialogs(context.translation) }
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val MAIN_ROUTE = "feature_root"
|
const val MAIN_ROUTE = "feature_root"
|
||||||
@ -217,7 +218,7 @@ class FeaturesSection : Section() {
|
|||||||
registerDialogOnClickCallback()
|
registerDialogOnClickCallback()
|
||||||
|
|
||||||
dialogComposable = {
|
dialogComposable = {
|
||||||
dialogs.UniqueSelectionDialog(property)
|
alertDialogs.UniqueSelectionDialog(property)
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
@ -234,10 +235,10 @@ class FeaturesSection : Section() {
|
|||||||
dialogComposable = {
|
dialogComposable = {
|
||||||
when (dataType) {
|
when (dataType) {
|
||||||
DataProcessors.Type.STRING_MULTIPLE_SELECTION -> {
|
DataProcessors.Type.STRING_MULTIPLE_SELECTION -> {
|
||||||
dialogs.MultipleSelectionDialog(property)
|
alertDialogs.MultipleSelectionDialog(property)
|
||||||
}
|
}
|
||||||
DataProcessors.Type.STRING, DataProcessors.Type.INTEGER, DataProcessors.Type.FLOAT -> {
|
DataProcessors.Type.STRING, DataProcessors.Type.INTEGER, DataProcessors.Type.FLOAT -> {
|
||||||
dialogs.KeyboardInputDialog(property) { showDialog = false }
|
alertDialogs.KeyboardInputDialog(property) { showDialog = false }
|
||||||
}
|
}
|
||||||
else -> {}
|
else -> {}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,41 @@
|
|||||||
package me.rhunk.snapenhance.ui.manager.sections.social
|
package me.rhunk.snapenhance.ui.manager.sections.social
|
||||||
|
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Spacer
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Search
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.CardDefaults
|
||||||
import androidx.compose.material3.CircularProgressIndicator
|
import androidx.compose.material3.CircularProgressIndicator
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.LaunchedEffect
|
import androidx.compose.runtime.LaunchedEffect
|
||||||
|
import androidx.compose.runtime.MutableState
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.mutableStateOf
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.input.ImeAction
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.compose.ui.window.Dialog
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import androidx.compose.ui.window.DialogProperties
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@ -37,16 +52,73 @@ class AddFriendDialog(
|
|||||||
private val context: RemoteSideContext,
|
private val context: RemoteSideContext,
|
||||||
private val section: SocialSection,
|
private val section: SocialSection,
|
||||||
) {
|
) {
|
||||||
|
@Composable
|
||||||
|
private fun ListCardEntry(name: String, exists: Boolean, stateChanged: (state: Boolean) -> Unit = { }) {
|
||||||
|
var state by remember { mutableStateOf(exists) }
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable {
|
||||||
|
state = !state
|
||||||
|
stateChanged(state)
|
||||||
|
}
|
||||||
|
.padding(4.dp),
|
||||||
|
verticalAlignment = androidx.compose.ui.Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = name,
|
||||||
|
fontSize = 15.sp,
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
)
|
||||||
|
|
||||||
|
androidx.compose.material3.Checkbox(
|
||||||
|
checked = state,
|
||||||
|
onCheckedChange = {
|
||||||
|
state = it
|
||||||
|
stateChanged(state)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ListCardEntry(name: String, modifier: Modifier = Modifier) {
|
private fun DialogHeader(searchKeyword: MutableState<String>) {
|
||||||
Card(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding(5.dp)
|
.fillMaxWidth()
|
||||||
.then(modifier),
|
.padding(10.dp),
|
||||||
) {
|
) {
|
||||||
Text(text = name, modifier = Modifier.padding(10.dp))
|
Text(
|
||||||
|
text = "Add Friend or Group",
|
||||||
|
fontSize = 23.sp,
|
||||||
|
fontWeight = FontWeight.ExtraBold,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(alignment = Alignment.CenterHorizontally)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(10.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
TextField(
|
||||||
|
value = searchKeyword.value,
|
||||||
|
onValueChange = { searchKeyword.value = it },
|
||||||
|
label = {
|
||||||
|
Text(text = "Search")
|
||||||
|
},
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f)
|
||||||
|
.padding(end = 10.dp),
|
||||||
|
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Text, imeAction = ImeAction.Done),
|
||||||
|
leadingIcon = {
|
||||||
|
Icon(Icons.Filled.Search, contentDescription = "Search")
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,52 +156,118 @@ class AddFriendDialog(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Dialog(onDismissRequest = {
|
Dialog(
|
||||||
timeoutJob?.cancel()
|
onDismissRequest = {
|
||||||
dismiss()
|
timeoutJob?.cancel()
|
||||||
}) {
|
dismiss()
|
||||||
Card {
|
},
|
||||||
if (hasFetchError) {
|
properties = DialogProperties(usePlatformDefaultWidth = false)
|
||||||
Text(text = "Failed to load friends and groups. Make sure Snapchat is installed and logged in.")
|
) {
|
||||||
return@Card
|
Card(
|
||||||
}
|
colors = CardDefaults.elevatedCardColors(),
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(all = 20.dp)
|
||||||
|
) {
|
||||||
if (cachedGroups == null || cachedFriends == null) {
|
if (cachedGroups == null || cachedFriends == null) {
|
||||||
CircularProgressIndicator(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.padding()
|
.fillMaxSize()
|
||||||
.size(30.dp),
|
.padding(10.dp),
|
||||||
strokeWidth = 3.dp,
|
verticalArrangement = Arrangement.Center,
|
||||||
color = MaterialTheme.colorScheme.onPrimary
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
)
|
) {
|
||||||
|
if (hasFetchError) {
|
||||||
|
Text(
|
||||||
|
text = "Failed to fetch data",
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp, top = 10.dp)
|
||||||
|
)
|
||||||
|
return@Card
|
||||||
|
}
|
||||||
|
CircularProgressIndicator(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding()
|
||||||
|
.size(30.dp),
|
||||||
|
strokeWidth = 3.dp,
|
||||||
|
color = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
||||||
return@Card
|
return@Card
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val searchKeyword = remember { mutableStateOf("") }
|
||||||
|
|
||||||
|
val filteredGroups = cachedGroups!!.takeIf { searchKeyword.value.isNotBlank() }?.filter {
|
||||||
|
it.name.contains(searchKeyword.value, ignoreCase = true)
|
||||||
|
} ?: cachedGroups!!
|
||||||
|
|
||||||
|
val filteredFriends = cachedFriends!!.takeIf { searchKeyword.value.isNotBlank() }?.filter {
|
||||||
|
it.mutableUsername.contains(searchKeyword.value, ignoreCase = true) ||
|
||||||
|
it.displayName?.contains(searchKeyword.value, ignoreCase = true) == true
|
||||||
|
} ?: cachedFriends!!
|
||||||
|
|
||||||
|
DialogHeader(searchKeyword)
|
||||||
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier
|
||||||
|
.fillMaxSize()
|
||||||
|
.padding(10.dp)
|
||||||
) {
|
) {
|
||||||
item {
|
item {
|
||||||
Text(text = "Groups", fontSize = 20.sp)
|
if (filteredGroups.isEmpty()) return@item
|
||||||
Spacer(modifier = Modifier.padding(5.dp))
|
Text(text = "Groups",
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp, top = 10.dp)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
items(cachedGroups!!.size) {
|
|
||||||
ListCardEntry(name = cachedGroups!![it].name, modifier = Modifier.clickable {
|
items(filteredGroups.size) {
|
||||||
context.bridgeService.triggerGroupSync(cachedGroups!![it].conversationId)
|
val group = filteredGroups[it]
|
||||||
|
|
||||||
|
ListCardEntry(
|
||||||
|
name = group.name,
|
||||||
|
exists = remember { context.modDatabase.getGroupInfo(group.conversationId) != null }
|
||||||
|
) { state ->
|
||||||
|
if (state) {
|
||||||
|
context.bridgeService.triggerGroupSync(cachedGroups!![it].conversationId)
|
||||||
|
} else {
|
||||||
|
context.modDatabase.deleteGroup(group.conversationId)
|
||||||
|
}
|
||||||
context.modDatabase.executeAsync {
|
context.modDatabase.executeAsync {
|
||||||
section.onResumed()
|
section.onResumed()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
item {
|
item {
|
||||||
Text(text = "Friends", fontSize = 20.sp)
|
if (filteredFriends.isEmpty()) return@item
|
||||||
Spacer(modifier = Modifier.padding(5.dp))
|
Text(text = "Friends",
|
||||||
|
fontSize = 20.sp,
|
||||||
|
fontWeight = FontWeight.Bold,
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp, top = 10.dp)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
items(cachedFriends!!.size) {
|
|
||||||
ListCardEntry(name = cachedFriends!![it].displayName ?: cachedFriends!![it].mutableUsername, modifier = Modifier.clickable {
|
items(filteredFriends.size) {
|
||||||
context.bridgeService.triggerFriendSync(cachedFriends!![it].userId)
|
val friend = filteredFriends[it]
|
||||||
|
|
||||||
|
ListCardEntry(
|
||||||
|
name = friend.displayName?.takeIf { name -> name.isNotBlank() } ?: friend.mutableUsername,
|
||||||
|
exists = remember { context.modDatabase.getFriendInfo(friend.userId) != null }
|
||||||
|
) { state ->
|
||||||
|
if (state) {
|
||||||
|
context.bridgeService.triggerFriendSync(cachedFriends!![it].userId)
|
||||||
|
} else {
|
||||||
|
context.modDatabase.deleteFriend(friend.userId)
|
||||||
|
}
|
||||||
context.modDatabase.executeAsync {
|
context.modDatabase.executeAsync {
|
||||||
section.onResumed()
|
section.onResumed()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import androidx.compose.ui.unit.sp
|
import androidx.compose.ui.unit.sp
|
||||||
import androidx.navigation.NavController
|
import androidx.navigation.NavController
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.rhunk.snapenhance.RemoteSideContext
|
import me.rhunk.snapenhance.RemoteSideContext
|
||||||
import me.rhunk.snapenhance.core.messaging.MessagingRuleType
|
import me.rhunk.snapenhance.core.messaging.MessagingRuleType
|
||||||
@ -36,25 +37,19 @@ class ScopeContent(
|
|||||||
private val context: RemoteSideContext,
|
private val context: RemoteSideContext,
|
||||||
private val section: SocialSection,
|
private val section: SocialSection,
|
||||||
private val navController: NavController,
|
private val navController: NavController,
|
||||||
private val scope: SocialScope,
|
val scope: SocialScope,
|
||||||
private val id: String
|
private val id: String
|
||||||
) {
|
) {
|
||||||
@Composable
|
fun deleteScope(coroutineScope: CoroutineScope) {
|
||||||
private fun DeleteScopeEntityButton() {
|
when (scope) {
|
||||||
val coroutineScope = rememberCoroutineScope()
|
SocialScope.FRIEND -> context.modDatabase.deleteFriend(id)
|
||||||
OutlinedButton(onClick = {
|
SocialScope.GROUP -> context.modDatabase.deleteGroup(id)
|
||||||
when (scope) {
|
}
|
||||||
SocialScope.FRIEND -> context.modDatabase.deleteFriend(id)
|
context.modDatabase.executeAsync {
|
||||||
SocialScope.GROUP -> context.modDatabase.deleteGroup(id)
|
coroutineScope.launch {
|
||||||
|
section.onResumed()
|
||||||
|
navController.popBackStack()
|
||||||
}
|
}
|
||||||
context.modDatabase.executeAsync {
|
|
||||||
coroutineScope.launch {
|
|
||||||
section.onResumed()
|
|
||||||
navController.navigate(SocialSection.MAIN_ROUTE)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}) {
|
|
||||||
Text(text = "Delete ${scope.key}")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +248,6 @@ class ScopeContent(
|
|||||||
Text(text = group.name, maxLines = 1)
|
Text(text = group.name, maxLines = 1)
|
||||||
Text(text = "participantsCount: ${group.participantsCount}", maxLines = 1)
|
Text(text = "participantsCount: ${group.participantsCount}", maxLines = 1)
|
||||||
Spacer(modifier = Modifier.height(16.dp))
|
Spacer(modifier = Modifier.height(16.dp))
|
||||||
DeleteScopeEntityButton()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -4,6 +4,7 @@ import androidx.compose.foundation.ExperimentalFoundationApi
|
|||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.RowScope
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
@ -15,9 +16,12 @@ import androidx.compose.foundation.pager.rememberPagerState
|
|||||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
import androidx.compose.material.icons.Icons
|
import androidx.compose.material.icons.Icons
|
||||||
import androidx.compose.material.icons.rounded.Add
|
import androidx.compose.material.icons.rounded.Add
|
||||||
|
import androidx.compose.material.icons.rounded.DeleteForever
|
||||||
import androidx.compose.material3.Card
|
import androidx.compose.material3.Card
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
import androidx.compose.material3.FloatingActionButton
|
import androidx.compose.material3.FloatingActionButton
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
import androidx.compose.material3.Tab
|
import androidx.compose.material3.Tab
|
||||||
@ -32,8 +36,11 @@ import androidx.compose.runtime.rememberCoroutineScope
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
import androidx.navigation.NavGraphBuilder
|
import androidx.navigation.NavGraphBuilder
|
||||||
import androidx.navigation.compose.composable
|
import androidx.navigation.compose.composable
|
||||||
import androidx.navigation.navigation
|
import androidx.navigation.navigation
|
||||||
@ -42,6 +49,7 @@ import me.rhunk.snapenhance.core.messaging.MessagingFriendInfo
|
|||||||
import me.rhunk.snapenhance.core.messaging.MessagingGroupInfo
|
import me.rhunk.snapenhance.core.messaging.MessagingGroupInfo
|
||||||
import me.rhunk.snapenhance.core.messaging.SocialScope
|
import me.rhunk.snapenhance.core.messaging.SocialScope
|
||||||
import me.rhunk.snapenhance.ui.manager.Section
|
import me.rhunk.snapenhance.ui.manager.Section
|
||||||
|
import me.rhunk.snapenhance.ui.util.AlertDialogs
|
||||||
import me.rhunk.snapenhance.ui.util.BitmojiImage
|
import me.rhunk.snapenhance.ui.util.BitmojiImage
|
||||||
import me.rhunk.snapenhance.ui.util.pagerTabIndicatorOffset
|
import me.rhunk.snapenhance.ui.util.pagerTabIndicatorOffset
|
||||||
import me.rhunk.snapenhance.util.snap.BitmojiSelfie
|
import me.rhunk.snapenhance.util.snap.BitmojiSelfie
|
||||||
@ -89,6 +97,35 @@ class SocialSection : Section() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
override fun TopBarActions(rowScope: RowScope) {
|
||||||
|
var deleteConfirmDialog by remember { mutableStateOf(false) }
|
||||||
|
val coroutineScope = rememberCoroutineScope()
|
||||||
|
|
||||||
|
if (deleteConfirmDialog) {
|
||||||
|
currentScopeContent?.let { scopeContent ->
|
||||||
|
Dialog(onDismissRequest = { deleteConfirmDialog = false }) {
|
||||||
|
remember { AlertDialogs(context.translation) }.ConfirmDialog(
|
||||||
|
title = "Are you sure you want to delete this ${scopeContent.scope.key.lowercase()}?",
|
||||||
|
onDismiss = { deleteConfirmDialog = false },
|
||||||
|
onConfirm = { scopeContent.deleteScope(coroutineScope); deleteConfirmDialog = false }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (navController.currentBackStackEntry?.destination?.route != MAIN_ROUTE) {
|
||||||
|
IconButton(
|
||||||
|
onClick = { deleteConfirmDialog = true },
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Rounded.DeleteForever,
|
||||||
|
contentDescription = null
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun ScopeList(scope: SocialScope) {
|
private fun ScopeList(scope: SocialScope) {
|
||||||
@ -154,8 +191,8 @@ class SocialSection : Section() {
|
|||||||
.padding(10.dp)
|
.padding(10.dp)
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
Text(text = friend.displayName ?: friend.mutableUsername, maxLines = 1)
|
Text(text = friend.displayName ?: friend.mutableUsername, maxLines = 1, fontWeight = FontWeight.Bold)
|
||||||
Text(text = friend.userId, maxLines = 1)
|
Text(text = friend.userId, maxLines = 1, fontSize = 12.sp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@ import kotlinx.coroutines.Dispatchers
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.rhunk.snapenhance.Logger
|
import me.rhunk.snapenhance.Logger
|
||||||
import me.rhunk.snapenhance.ui.setup.screens.SetupScreen
|
import me.rhunk.snapenhance.ui.setup.screens.SetupScreen
|
||||||
|
import me.rhunk.snapenhance.ui.util.AlertDialogs
|
||||||
|
|
||||||
class MappingsScreen : SetupScreen() {
|
class MappingsScreen : SetupScreen() {
|
||||||
@Composable
|
@Composable
|
||||||
@ -35,21 +36,8 @@ class MappingsScreen : SetupScreen() {
|
|||||||
Dialog(onDismissRequest = {
|
Dialog(onDismissRequest = {
|
||||||
infoText = null
|
infoText = null
|
||||||
}) {
|
}) {
|
||||||
Surface(
|
remember { AlertDialogs(context.translation) }.InfoDialog(title = infoText!!) {
|
||||||
modifier = Modifier.padding(16.dp).fillMaxWidth(),
|
infoText = null
|
||||||
shape = RoundedCornerShape(16.dp),
|
|
||||||
) {
|
|
||||||
Column(
|
|
||||||
modifier = Modifier.padding(16.dp)
|
|
||||||
) {
|
|
||||||
Text(text = infoText!!)
|
|
||||||
Button(onClick = {
|
|
||||||
infoText = null
|
|
||||||
},
|
|
||||||
modifier = Modifier.padding(top = 5.dp).align(alignment = androidx.compose.ui.Alignment.End)) {
|
|
||||||
Text(text = "OK")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -87,7 +75,9 @@ class MappingsScreen : SetupScreen() {
|
|||||||
}) {
|
}) {
|
||||||
if (isGenerating) {
|
if (isGenerating) {
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
modifier = Modifier.padding().size(30.dp),
|
modifier = Modifier
|
||||||
|
.padding()
|
||||||
|
.size(30.dp),
|
||||||
strokeWidth = 3.dp,
|
strokeWidth = 3.dp,
|
||||||
color = MaterialTheme.colorScheme.onPrimary
|
color = MaterialTheme.colorScheme.onPrimary
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package me.rhunk.snapenhance.ui.manager.sections.features
|
package me.rhunk.snapenhance.ui.util
|
||||||
|
|
||||||
import androidx.compose.foundation.ScrollState
|
import androidx.compose.foundation.ScrollState
|
||||||
import androidx.compose.foundation.clickable
|
import androidx.compose.foundation.clickable
|
||||||
@ -36,7 +36,7 @@ import me.rhunk.snapenhance.core.config.DataProcessors
|
|||||||
import me.rhunk.snapenhance.core.config.PropertyPair
|
import me.rhunk.snapenhance.core.config.PropertyPair
|
||||||
|
|
||||||
|
|
||||||
class Dialogs(
|
class AlertDialogs(
|
||||||
private val translation: LocaleWrapper,
|
private val translation: LocaleWrapper,
|
||||||
){
|
){
|
||||||
@Composable
|
@Composable
|
||||||
@ -54,6 +54,70 @@ class Dialogs(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun ConfirmDialog(
|
||||||
|
title: String,
|
||||||
|
data: String? = null,
|
||||||
|
onConfirm: () -> Unit,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
) {
|
||||||
|
DefaultDialogCard {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp)
|
||||||
|
)
|
||||||
|
if (data != null) {
|
||||||
|
Text(
|
||||||
|
text = data,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
) {
|
||||||
|
Button(onClick = { onDismiss() }) {
|
||||||
|
Text(text = translation["button.cancel"])
|
||||||
|
}
|
||||||
|
Button(onClick = { onConfirm() }) {
|
||||||
|
Text(text = translation["button.ok"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun InfoDialog(
|
||||||
|
title: String,
|
||||||
|
data: String? = null,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
) {
|
||||||
|
DefaultDialogCard {
|
||||||
|
Text(
|
||||||
|
text = title,
|
||||||
|
style = MaterialTheme.typography.bodyLarge,
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp)
|
||||||
|
)
|
||||||
|
if (data != null) {
|
||||||
|
Text(
|
||||||
|
text = data,
|
||||||
|
style = MaterialTheme.typography.bodyMedium,
|
||||||
|
modifier = Modifier.padding(bottom = 10.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
horizontalArrangement = Arrangement.SpaceEvenly,
|
||||||
|
) {
|
||||||
|
Button(onClick = { onDismiss() }) {
|
||||||
|
Text(text = translation["button.ok"])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TranslatedText(property: PropertyPair<*>, key: String, modifier: Modifier = Modifier) {
|
fun TranslatedText(property: PropertyPair<*>, key: String, modifier: Modifier = Modifier) {
|
||||||
Text(
|
Text(
|
Loading…
x
Reference in New Issue
Block a user