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 }