ManageRuleFeature.kt (8856B) - raw
1 package me.rhunk.snapenhance.ui.manager.pages.features 2 3 import androidx.compose.foundation.clickable 4 import androidx.compose.foundation.layout.* 5 import androidx.compose.material3.Button 6 import androidx.compose.material3.OutlinedButton 7 import androidx.compose.material3.RadioButton 8 import androidx.compose.material3.Text 9 import androidx.compose.runtime.* 10 import androidx.compose.ui.Alignment 11 import androidx.compose.ui.Modifier 12 import androidx.compose.ui.text.font.FontWeight 13 import androidx.compose.ui.unit.dp 14 import androidx.compose.ui.unit.sp 15 import androidx.navigation.NavBackStackEntry 16 import kotlinx.coroutines.asCoroutineDispatcher 17 import kotlinx.coroutines.launch 18 import me.rhunk.snapenhance.common.data.MessagingRuleType 19 import me.rhunk.snapenhance.common.data.RuleState 20 import me.rhunk.snapenhance.common.ui.rememberAsyncMutableState 21 import me.rhunk.snapenhance.common.ui.rememberAsyncUpdateDispatcher 22 import me.rhunk.snapenhance.storage.clearRuleIds 23 import me.rhunk.snapenhance.storage.getRuleIds 24 import me.rhunk.snapenhance.storage.setRule 25 import me.rhunk.snapenhance.ui.manager.Routes 26 import me.rhunk.snapenhance.ui.manager.pages.social.AddFriendDialog 27 import me.rhunk.snapenhance.ui.manager.pages.social.AddFriendDialog.Actions 28 import me.rhunk.snapenhance.ui.util.AlertDialogs 29 import me.rhunk.snapenhance.ui.util.Dialog 30 31 class ManageRuleFeature : Routes.Route() { 32 @Composable 33 fun SelectRuleTypeRadio( 34 checked: Boolean, 35 text: String, 36 onStateChanged: (Boolean) -> Unit, 37 selectedBlock: @Composable () -> Unit = {}, 38 ) { 39 Box(modifier = Modifier.clickable { 40 onStateChanged(!checked) 41 }) { 42 Column( 43 modifier = Modifier 44 .padding(10.dp), 45 verticalArrangement = Arrangement.spacedBy(4.dp), 46 ) { 47 Row( 48 modifier = Modifier 49 .fillMaxWidth(), 50 horizontalArrangement = Arrangement.spacedBy(4.dp), 51 verticalAlignment = Alignment.CenterVertically, 52 ) { 53 RadioButton(selected = checked, onClick = null) 54 Text(text) 55 } 56 if (checked) { 57 Column(modifier = Modifier 58 .offset(x = 15.dp) 59 .padding(4.dp), verticalArrangement = Arrangement.spacedBy(4.dp)) { 60 selectedBlock() 61 } 62 } 63 } 64 } 65 } 66 67 override val content: @Composable (NavBackStackEntry) -> Unit = content@{ navBackStackEntry -> 68 val currentRuleType = navBackStackEntry.arguments?.getString("rule_type")?.let { 69 MessagingRuleType.getByName(it) 70 } ?: return@content 71 72 var ruleState by remember { 73 mutableStateOf(context.config.root.rules.getRuleState(currentRuleType)) 74 } 75 76 val propertyKeyPair = remember { 77 context.config.root.rules.getPropertyPair(currentRuleType.key) 78 } 79 80 val updateDispatcher = rememberAsyncUpdateDispatcher() 81 val currentRuleIds by rememberAsyncMutableState(defaultValue = mutableListOf(), updateDispatcher = updateDispatcher) { 82 context.database.getRuleIds(currentRuleType.key) 83 } 84 85 fun setRuleState(newState: RuleState?) { 86 ruleState = newState 87 propertyKeyPair.value.setAny(newState?.key) 88 context.coroutineScope.launch { 89 context.config.writeConfig(dispatchConfigListener = false) 90 } 91 } 92 93 var addFriendDialog by remember { mutableStateOf(null as AddFriendDialog?) } 94 95 LaunchedEffect(addFriendDialog) { 96 if (addFriendDialog == null) { 97 updateDispatcher.dispatch() 98 } 99 } 100 101 fun showAddFriendDialog() { 102 addFriendDialog = AddFriendDialog( 103 context = context, 104 pinnedIds = currentRuleIds, 105 actionHandler = Actions( 106 onFriendState = { friend, state -> 107 context.database.setRule(friend.userId, currentRuleType.key, state) 108 if (state) { 109 currentRuleIds.add(friend.userId) 110 } else { 111 currentRuleIds.remove(friend.userId) 112 } 113 }, 114 onGroupState = { group, state -> 115 context.database.setRule(group.conversationId, currentRuleType.key, state) 116 if (state) { 117 currentRuleIds.add(group.conversationId) 118 } else { 119 currentRuleIds.remove(group.conversationId) 120 } 121 }, 122 getFriendState = { friend -> 123 currentRuleIds.contains(friend.userId) 124 }, 125 getGroupState = { group -> 126 currentRuleIds.contains(group.conversationId) 127 } 128 ) 129 ) 130 } 131 132 if (addFriendDialog != null) { 133 addFriendDialog?.Content { 134 addFriendDialog = null 135 } 136 } 137 138 Column( 139 modifier = Modifier.fillMaxSize() 140 ) { 141 Column( 142 modifier = Modifier.padding(10.dp), 143 verticalArrangement = Arrangement.spacedBy(4.dp), 144 ) { 145 Text( 146 text = remember { 147 context.translation[propertyKeyPair.key.propertyName()] 148 }, 149 fontSize = 20.sp, 150 ) 151 Text( 152 text = remember { 153 context.translation[propertyKeyPair.key.propertyDescription()] 154 }, 155 fontWeight = FontWeight.Light, 156 fontSize = 12.sp, 157 lineHeight = 16.sp, 158 ) 159 } 160 161 SelectRuleTypeRadio(checked = ruleState == null, text = translation["disable_state_option"], onStateChanged = { 162 setRuleState(null) 163 }) { 164 Text(text = translation["disable_state_subtext"], fontWeight = FontWeight.Light, fontSize = 12.sp) 165 } 166 SelectRuleTypeRadio(checked = ruleState == RuleState.WHITELIST, text = translation["whitelist_state_option"], onStateChanged = { 167 setRuleState(RuleState.WHITELIST) 168 }) { 169 Text(text = translation.format("whitelist_state_subtext", "count" to currentRuleIds.size.toString()), fontWeight = FontWeight.Light, fontSize = 12.sp) 170 OutlinedButton(onClick = { 171 showAddFriendDialog() 172 }) { 173 Text(text = translation["whitelist_state_button"]) 174 } 175 } 176 SelectRuleTypeRadio(checked = ruleState == RuleState.BLACKLIST, text = translation["blacklist_state_option"], onStateChanged = { 177 setRuleState(RuleState.BLACKLIST) 178 }) { 179 Text(text = translation.format("blacklist_state_subtext", "count" to currentRuleIds.size.toString()), fontWeight = FontWeight.Light, fontSize = 12.sp) 180 OutlinedButton(onClick = { showAddFriendDialog() }) { 181 Text(text = translation["blacklist_state_button"]) 182 } 183 } 184 185 Row( 186 modifier = Modifier.fillMaxWidth().padding(5.dp), 187 horizontalArrangement = Arrangement.SpaceEvenly 188 ) { 189 var confirmationDialog by remember { mutableStateOf(false) } 190 191 if (confirmationDialog) { 192 Dialog(onDismissRequest = { 193 confirmationDialog = false 194 }) { 195 remember { AlertDialogs(context.translation) }.ConfirmDialog( 196 title = translation["dialog_clear_confirmation_text"], 197 onDismiss = { confirmationDialog = false }, 198 onConfirm = { 199 context.database.clearRuleIds(currentRuleType.key) 200 context.coroutineScope.launch(context.database.executor.asCoroutineDispatcher()) { 201 updateDispatcher.dispatch() 202 } 203 confirmationDialog = false 204 } 205 ) 206 } 207 } 208 209 Button(onClick = { confirmationDialog = true }) { 210 Text(text = translation["clear_list_button"]) 211 } 212 } 213 } 214 } 215 }