1+ package com.example.blockchainaccess
2+
3+ import android.os.Bundle
4+ import androidx.activity.ComponentActivity
5+ import androidx.activity.compose.setContent
6+ import androidx.activity.enableEdgeToEdge
7+ import androidx.compose.foundation.Image
8+ import androidx.compose.foundation.background
9+ import androidx.compose.foundation.layout.*
10+ import androidx.compose.ui.platform.LocalContext
11+ import androidx.compose.material3.MaterialTheme
12+ import androidx.compose.material3.Scaffold
13+ import androidx.compose.material3.Text
14+ import androidx.compose.material3.Button
15+ import androidx.compose.material3.OutlinedTextField // Correct import for OutlinedTextField
16+ import androidx.compose.material3.Divider // Correct import for Divider
17+ import androidx.compose.runtime.Composable
18+ import androidx.compose.material.icons.Icons
19+ import androidx.compose.material.icons.filled.Delete
20+ import androidx.compose.material3.Icon
21+ import androidx.compose.material3.IconButton
22+ import androidx.compose.ui.unit.dp
23+ import androidx.compose.ui.Modifier
24+ import androidx.compose.ui.Alignment
25+ import androidx.compose.runtime.*
26+ import kotlinx.coroutines.launch
27+ import com.example.blockchainaccess.ui.theme.BlockchainAccessTheme
28+ import androidx.compose.foundation.lazy.LazyColumn // Correct import for LazyColumn
29+ import androidx.compose.foundation.lazy.items // Correct import for LazyColumn items
30+ import androidx.compose.ui.graphics.Color
31+ import androidx.compose.ui.graphics.graphicsLayer
32+ import androidx.compose.ui.layout.ContentScale
33+ import androidx.compose.ui.res.painterResource
34+
35+ class WhitelistActivity : ComponentActivity () {
36+ override fun onCreate (savedInstanceState : Bundle ? ) {
37+ super .onCreate(savedInstanceState)
38+ enableEdgeToEdge()
39+ setContent {
40+ BlockchainAccessTheme {
41+ Scaffold (
42+ modifier = Modifier .fillMaxSize()
43+ ) { innerPadding ->
44+ WhitelistScreen (
45+ modifier = Modifier .padding(innerPadding)
46+ )
47+ }
48+ }
49+ }
50+ }
51+ }
52+
53+ @Composable
54+ fun WhitelistScreen (modifier : Modifier = Modifier ) {
55+ val context = LocalContext .current
56+ val scope = rememberCoroutineScope()
57+
58+ // Collect the whitelist Flow as state. The UI will automatically
59+ // recompose whenever the whitelist changes.
60+ val whitelist by SessionManager .getWhitelist(context).collectAsState(initial = emptySet())
61+
62+ // State for the text field
63+ var newId by remember { mutableStateOf(" " ) }
64+
65+ Column (
66+ modifier = modifier
67+ .fillMaxSize()
68+ .padding(16 .dp),
69+ horizontalAlignment = Alignment .CenterHorizontally
70+ ) {
71+ // Input section to add new addresses
72+ Row (
73+ modifier = Modifier .fillMaxWidth(),
74+ verticalAlignment = Alignment .CenterVertically
75+ ) {
76+ OutlinedTextField (
77+ value = newId,
78+ onValueChange = { newId = it },
79+ label = { Text (" New ID" ) },
80+ modifier = Modifier .weight(1f ),
81+ singleLine = true
82+ )
83+ Spacer (modifier = Modifier .width(8 .dp))
84+ Button (onClick = {
85+ if (newId.isNotBlank()) {
86+ scope.launch {
87+ SessionManager .addToWhitelist(context, newId)
88+ newId = " " // Clear the text field
89+ }
90+ }
91+ }) {
92+ Text (" Add" )
93+ }
94+ }
95+
96+ Spacer (modifier = Modifier .height(16 .dp))
97+
98+ // List of whitelisted ids
99+ if (whitelist.isEmpty()) {
100+ Text (" Whitelist is empty." )
101+ } else {
102+ LazyColumn (modifier = Modifier .fillMaxWidth()) {
103+ items(whitelist.toList()) { id ->
104+ WhitelistItem (
105+ id = id,
106+ onRemove = {
107+ scope.launch {
108+ SessionManager .removeFromWhitelist(context, id)
109+ }
110+ }
111+ )
112+ Divider ()
113+ }
114+ }
115+ }
116+ }
117+ }
118+
119+ @Composable
120+ fun WhitelistItem (id : String , onRemove : () -> Unit ) {
121+ Row (
122+ modifier = Modifier
123+ .fillMaxWidth()
124+ .padding(vertical = 8 .dp),
125+ verticalAlignment = Alignment .CenterVertically ,
126+ horizontalArrangement = Arrangement .SpaceBetween
127+ ) {
128+ Text (
129+ text = id,
130+ modifier = Modifier .weight(1f )
131+ )
132+ IconButton (onClick = onRemove) {
133+ Icon (
134+ imageVector = Icons .Default .Delete ,
135+ contentDescription = " Remove ID" ,
136+ tint = MaterialTheme .colorScheme.error
137+ )
138+ }
139+ }
140+ }
0 commit comments