Skip to content

Commit b3efae0

Browse files
committed
[FEAT] Proper network requets, Login window
1 parent 2b15bb3 commit b3efae0

6 files changed

Lines changed: 363 additions & 40 deletions

File tree

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
</intent-filter>
2727
</activity>
2828
<activity android:name=".CreateProfileActivity" />
29+
<activity android:name=".LoginActivity" />
2930
<activity android:name=".UserActivity" />
3031
<activity
3132
android:name=".WhitelistActivity"

app/src/main/java/com/example/blockchainaccess/CreateProfileActivity.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,19 @@ fun CreateProfileScreen(name: String, modifier: Modifier = Modifier) {
149149
) {
150150
Text("Create Profile", color = Color.White)
151151
}
152+
Button(
153+
onClick = { context.startActivity(
154+
Intent(context, LoginActivity::class.java)
155+
) },
156+
shape = RoundedCornerShape(50),
157+
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary),
158+
elevation = ButtonDefaults.buttonElevation(defaultElevation = 6.dp),
159+
modifier = Modifier
160+
.fillMaxWidth(0.5f)
161+
.padding(vertical = 8.dp)
162+
) {
163+
Text("Already have an account.", color = Color.White)
164+
}
152165
}
153166
Box(
154167
modifier = Modifier
Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
package com.example.blockchainaccess
2+
3+
import android.annotation.SuppressLint
4+
import android.os.Bundle
5+
import android.content.Intent
6+
import androidx.activity.ComponentActivity
7+
import androidx.activity.compose.setContent
8+
import androidx.activity.enableEdgeToEdge
9+
import androidx.compose.foundation.Image
10+
import androidx.compose.foundation.layout.*
11+
import androidx.compose.ui.platform.LocalContext
12+
import androidx.compose.foundation.shape.RoundedCornerShape
13+
import androidx.compose.foundation.background
14+
import androidx.compose.material3.ButtonDefaults
15+
import androidx.compose.material3.MaterialTheme
16+
import androidx.compose.material3.Scaffold
17+
import androidx.compose.material3.Text
18+
import androidx.compose.material3.Button
19+
import androidx.compose.material3.DropdownMenu
20+
import androidx.compose.material3.DropdownMenuItem
21+
import androidx.compose.material3.TextField
22+
import androidx.compose.runtime.Composable
23+
import androidx.compose.ui.graphics.Color
24+
import androidx.compose.ui.graphics.graphicsLayer
25+
import androidx.compose.ui.text.font.FontWeight
26+
import androidx.compose.ui.text.input.PasswordVisualTransformation
27+
import androidx.compose.ui.text.style.TextAlign
28+
import androidx.compose.ui.unit.dp
29+
import androidx.compose.ui.unit.sp
30+
import androidx.compose.ui.Alignment
31+
import androidx.compose.ui.Modifier
32+
import android.content.Context
33+
import androidx.compose.runtime.*
34+
import androidx.compose.ui.tooling.preview.Preview
35+
import androidx.compose.ui.layout.ContentScale
36+
import androidx.compose.ui.res.painterResource
37+
import com.example.blockchainaccess.ui.theme.BlockchainAccessTheme
38+
import kotlinx.coroutines.*
39+
import android.widget.Toast
40+
41+
class LoginActivity : ComponentActivity() {
42+
override fun onCreate(savedInstanceState: Bundle?) {
43+
super.onCreate(savedInstanceState)
44+
enableEdgeToEdge()
45+
setContent {
46+
BlockchainAccessTheme {
47+
Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding ->
48+
LoginScreen(
49+
name = "Android",
50+
modifier = Modifier.padding(innerPadding)
51+
)
52+
}
53+
}
54+
}
55+
}
56+
}
57+
58+
@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter")
59+
@Composable
60+
fun LoginScreen(name: String, modifier: Modifier = Modifier) {
61+
val context = LocalContext.current
62+
val coroutineScope = rememberCoroutineScope()
63+
var username by remember { mutableStateOf("") }
64+
var password by remember { mutableStateOf("") }
65+
var selectedPort by remember { mutableStateOf("8081") }
66+
var showPortDropdown by remember { mutableStateOf(false) }
67+
Scaffold {
68+
Box(
69+
modifier = modifier
70+
.fillMaxSize()
71+
) {
72+
Image(
73+
painter = painterResource(id = R.drawable.wavy),
74+
contentDescription = null,
75+
contentScale = ContentScale.Crop,
76+
modifier = Modifier
77+
.fillMaxSize()
78+
.graphicsLayer(alpha = 0.5f)
79+
)
80+
Box(
81+
modifier = Modifier
82+
.fillMaxSize()
83+
.background(Color.Black.copy(alpha = 0.6f))
84+
)
85+
Column(
86+
modifier = Modifier
87+
.fillMaxSize()
88+
.padding(top = 28.dp, start = 0.dp, bottom = 100.dp, end = 0.dp),
89+
horizontalAlignment = Alignment.CenterHorizontally,
90+
verticalArrangement = Arrangement.Center
91+
) {
92+
Column(
93+
modifier = Modifier.fillMaxWidth(),
94+
horizontalAlignment = Alignment.Start // Align text to the left
95+
) {
96+
Text(
97+
text = "Welcome!",
98+
color = Color.White,
99+
fontSize = 20.sp,
100+
fontWeight = FontWeight.Bold,
101+
textAlign = TextAlign.Left,
102+
modifier = Modifier.padding(28.dp, 0.dp, 0.dp, 0.dp)
103+
)
104+
Text(
105+
text = "Sign in to your profile profile, provided you are authorized by the system administrator.",
106+
color = Color.White.copy(alpha = 0.8f),
107+
fontSize = 14.sp,
108+
textAlign = TextAlign.Left,
109+
modifier = Modifier.padding(28.dp, 8.dp, 10.dp, 50.dp)
110+
)
111+
}
112+
TextField(
113+
value = username,
114+
onValueChange = { username = it },
115+
label = { Text("Username") },
116+
modifier = Modifier
117+
.fillMaxWidth(0.88f)
118+
.padding(vertical = 6.dp)
119+
)
120+
121+
TextField(
122+
value = password,
123+
onValueChange = { password = it },
124+
label = { Text("Password") },
125+
visualTransformation = PasswordVisualTransformation(),
126+
modifier = Modifier
127+
.fillMaxWidth(0.88f)
128+
.padding(vertical = 6.dp)
129+
)
130+
Spacer(modifier = Modifier.height(34.dp))
131+
Button(
132+
onClick = { login(context, username,password,selectedPort, coroutineScope) },
133+
shape = RoundedCornerShape(50),
134+
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary),
135+
elevation = ButtonDefaults.buttonElevation(defaultElevation = 6.dp),
136+
modifier = Modifier
137+
.fillMaxWidth(0.5f)
138+
.padding(vertical = 8.dp)
139+
) {
140+
Text("Sign in", color = Color.White)
141+
}
142+
}
143+
Box(
144+
modifier = Modifier
145+
.align(Alignment.BottomStart)
146+
.padding(16.dp)
147+
) {
148+
Button(onClick = { showPortDropdown = true }) {
149+
Text(text = "Port: $selectedPort")
150+
}
151+
DropdownMenu(
152+
expanded = showPortDropdown,
153+
onDismissRequest = { showPortDropdown = false }
154+
) {
155+
val ports = listOf("8081", "8082", "8083", "8084")
156+
ports.forEach { port ->
157+
DropdownMenuItem(
158+
text = { Text(port) },
159+
onClick = {
160+
selectedPort = port
161+
showPortDropdown = false
162+
// Reset session when port changes
163+
coroutineScope.launch {
164+
SessionManager.clearSession(context)
165+
}
166+
Toast.makeText(context, "Session reset. Please log in again.", Toast.LENGTH_SHORT).show()
167+
}
168+
)
169+
}
170+
}
171+
}
172+
}
173+
}
174+
}
175+
176+
@Preview
177+
@Composable
178+
fun PreviewLoginScreen() {
179+
BlockchainAccessTheme {
180+
LoginScreen("Android")
181+
}
182+
}
183+
184+
fun login(
185+
context: Context,
186+
username: String,
187+
password: String,
188+
port: String,
189+
coroutineScope: CoroutineScope
190+
) {
191+
if (username.isBlank() || password.isBlank()) {
192+
Toast.makeText(context, "All fields must be filled.", Toast.LENGTH_SHORT).show()
193+
return
194+
}
195+
196+
197+
coroutineScope.launch(Dispatchers.IO) {
198+
199+
val result = NetworkClient.loginToProfile(username, password, port)
200+
201+
202+
withContext(Dispatchers.Main) {
203+
result.fold(
204+
onSuccess = { (id, whitelist) ->
205+
Toast.makeText(context, "Logged in successfully!", Toast.LENGTH_SHORT).show()
206+
207+
SessionManager.saveSession(context, id, username, port)
208+
209+
SessionManager.saveWhitelist(context, whitelist)
210+
211+
val intent = Intent(context, UserActivity::class.java)
212+
context.startActivity(intent)
213+
},
214+
onFailure = { error ->
215+
Toast.makeText(context, error.message ?: "Unknown error", Toast.LENGTH_SHORT).show()
216+
}
217+
)
218+
}
219+
}
220+
}

app/src/main/java/com/example/blockchainaccess/MainActivity.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ fun Greeting(name: String, modifier: Modifier = Modifier) {
9494
)
9595
}
9696
Button(
97-
onClick = { /* Handle sign in */ },
97+
onClick = { context.startActivity(Intent(context, LoginActivity::class.java)) },
9898
shape = RoundedCornerShape(50),
9999
colors = ButtonDefaults.buttonColors(containerColor = MaterialTheme.colorScheme.primary),
100100
elevation = ButtonDefaults.buttonElevation(defaultElevation = 6.dp),

0 commit comments

Comments
 (0)