|
@@ -1,54 +1,261 @@
|
|
package io.nexilis.alpha.ui.main
|
|
package io.nexilis.alpha.ui.main
|
|
|
|
|
|
|
|
+import androidx.compose.foundation.background
|
|
import androidx.compose.foundation.layout.*
|
|
import androidx.compose.foundation.layout.*
|
|
-import androidx.compose.foundation.rememberScrollState
|
|
|
|
-import androidx.compose.foundation.verticalScroll
|
|
|
|
-import androidx.compose.material3.Button
|
|
|
|
-import androidx.compose.material3.OutlinedTextField
|
|
|
|
|
|
+import androidx.compose.foundation.lazy.LazyColumn
|
|
|
|
+import androidx.compose.foundation.selection.selectable
|
|
|
|
+import androidx.compose.foundation.shape.CircleShape
|
|
|
|
+import androidx.compose.material.icons.Icons
|
|
|
|
+import androidx.compose.material.icons.filled.Close
|
|
|
|
+import androidx.compose.material.icons.filled.Info
|
|
|
|
+import androidx.compose.material.icons.filled.Person
|
|
|
|
+import androidx.compose.material.icons.filled.Search
|
|
|
|
+import androidx.compose.material.icons.filled.Verified
|
|
|
|
+import androidx.compose.material3.AlertDialog
|
|
|
|
+import androidx.compose.material3.ExperimentalMaterial3Api
|
|
|
|
+import androidx.compose.material3.Icon
|
|
|
|
+import androidx.compose.material3.IconButton
|
|
|
|
+import androidx.compose.material3.ListItem
|
|
|
|
+import androidx.compose.material3.MaterialTheme
|
|
|
|
+import androidx.compose.material3.Scaffold
|
|
|
|
+import androidx.compose.material3.SearchBar
|
|
import androidx.compose.material3.Text
|
|
import androidx.compose.material3.Text
|
|
|
|
+import androidx.compose.material3.TextButton
|
|
|
|
+import androidx.compose.material3.TopAppBar
|
|
|
|
+import androidx.compose.material3.TopAppBarDefaults
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.Composable
|
|
import androidx.compose.runtime.getValue
|
|
import androidx.compose.runtime.getValue
|
|
-import androidx.compose.runtime.livedata.observeAsState
|
|
|
|
|
|
+import androidx.compose.runtime.mutableIntStateOf
|
|
|
|
+import androidx.compose.runtime.mutableStateListOf
|
|
import androidx.compose.runtime.mutableStateOf
|
|
import androidx.compose.runtime.mutableStateOf
|
|
|
|
+import androidx.compose.runtime.remember
|
|
import androidx.compose.runtime.saveable.rememberSaveable
|
|
import androidx.compose.runtime.saveable.rememberSaveable
|
|
import androidx.compose.runtime.setValue
|
|
import androidx.compose.runtime.setValue
|
|
|
|
+import androidx.compose.runtime.snapshots.SnapshotStateList
|
|
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.TextRange
|
|
|
|
-import androidx.compose.ui.text.input.TextFieldValue
|
|
|
|
|
|
+import androidx.compose.ui.draw.clip
|
|
|
|
+import androidx.compose.ui.graphics.Color
|
|
|
|
+import androidx.compose.ui.graphics.vector.rememberVectorPainter
|
|
|
|
+import androidx.compose.ui.input.nestedscroll.nestedScroll
|
|
|
|
+import androidx.compose.ui.layout.ContentScale
|
|
|
|
+import androidx.compose.ui.platform.LocalContext
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.compose.ui.unit.dp
|
|
import androidx.hilt.navigation.compose.hiltViewModel
|
|
import androidx.hilt.navigation.compose.hiltViewModel
|
|
import androidx.navigation.NavHostController
|
|
import androidx.navigation.NavHostController
|
|
|
|
+import coil.compose.AsyncImage
|
|
|
|
+import coil.request.ImageRequest
|
|
|
|
+import io.nexilis.service.data.entities.Buddy
|
|
import io.nexilis.service.data.viewmodels.BuddyViewModel
|
|
import io.nexilis.service.data.viewmodels.BuddyViewModel
|
|
|
|
+import org.json.JSONArray
|
|
|
|
|
|
|
|
+@OptIn(ExperimentalMaterial3Api::class)
|
|
@Composable
|
|
@Composable
|
|
fun Friend(navController: NavHostController) {
|
|
fun Friend(navController: NavHostController) {
|
|
val viewModel: BuddyViewModel = hiltViewModel()
|
|
val viewModel: BuddyViewModel = hiltViewModel()
|
|
- val me by viewModel.me.observeAsState()
|
|
|
|
- var textUsername by rememberSaveable(stateSaver = TextFieldValue.Saver) {
|
|
|
|
- mutableStateOf(TextFieldValue("", TextRange(0, 7)))
|
|
|
|
- }
|
|
|
|
- Column(
|
|
|
|
|
|
+ var text by rememberSaveable { mutableStateOf("") }
|
|
|
|
+ var active by rememberSaveable { mutableStateOf(false) }
|
|
|
|
+ val list = remember { mutableStateListOf<Buddy>() }
|
|
|
|
+ val listSuggestions = remember { mutableStateListOf<Buddy>() }
|
|
|
|
+ val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior()
|
|
|
|
+ Scaffold(
|
|
modifier = Modifier
|
|
modifier = Modifier
|
|
- .padding(16.dp)
|
|
|
|
- .verticalScroll(rememberScrollState()), horizontalAlignment = Alignment.End
|
|
|
|
- ) {
|
|
|
|
- OutlinedTextField(
|
|
|
|
|
|
+ .nestedScroll(scrollBehavior.nestedScrollConnection),
|
|
|
|
+ topBar = {
|
|
|
|
+ TopAppBar(
|
|
|
|
+ title = { Text(text = "Add contact") },
|
|
|
|
+ navigationIcon = {
|
|
|
|
+ NavigationIcon(navController = navController, isHome = false)
|
|
|
|
+ },
|
|
|
|
+ scrollBehavior = scrollBehavior
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ ) { padding ->
|
|
|
|
+ Column(
|
|
modifier = Modifier
|
|
modifier = Modifier
|
|
- .fillMaxWidth()
|
|
|
|
- .imePadding(),
|
|
|
|
- value = textUsername,
|
|
|
|
- onValueChange = { textUsername = it },
|
|
|
|
- label = {
|
|
|
|
- Text(text = "pin")
|
|
|
|
|
|
+ .padding(padding)
|
|
|
|
+ .fillMaxSize()
|
|
|
|
+ ) {
|
|
|
|
+ SearchBar(
|
|
|
|
+ modifier = Modifier.align(Alignment.CenterHorizontally),
|
|
|
|
+ query = text,
|
|
|
|
+ onQueryChange = { text = it },
|
|
|
|
+ onSearch = {
|
|
|
|
+ active = false
|
|
|
|
+ if (text.isNotEmpty()) {
|
|
|
|
+ viewModel.searchFriend(text) { r, d ->
|
|
|
|
+ list.clear()
|
|
|
|
+ if (r && d.isNotEmpty()) {
|
|
|
|
+ val data = JSONArray(d)
|
|
|
|
+ for (i in 0 until data.length()) {
|
|
|
|
+ val t = data.getJSONObject(i)
|
|
|
|
+ val pin = t.optString("A00", "")
|
|
|
|
+ if (pin.isNotEmpty()) {
|
|
|
|
+ list.add(
|
|
|
|
+ Buddy(
|
|
|
|
+ f_pin = t.optString("A00", ""),
|
|
|
|
+ first_name = t.optString("A02", ""),
|
|
|
|
+ last_name = t.optString("A03", ""),
|
|
|
|
+ image_id = t.optString("A74", ""),
|
|
|
|
+ official_account = t.optString("oacc", "0")
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ active = active,
|
|
|
|
+ onActiveChange = {
|
|
|
|
+ active = it
|
|
|
|
+ if (it) {
|
|
|
|
+ viewModel.suggestFriend("0") { r, d ->
|
|
|
|
+ list.clear()
|
|
|
|
+ if (r && d.isNotEmpty()) {
|
|
|
|
+ val data = JSONArray(d)
|
|
|
|
+ for (i in 0 until data.length()) {
|
|
|
|
+ val t = data.getJSONObject(i)
|
|
|
|
+ val pin = t.optString("A00", "")
|
|
|
|
+ if (pin.isNotEmpty()) {
|
|
|
|
+ listSuggestions.add(
|
|
|
|
+ Buddy(
|
|
|
|
+ f_pin = t.optString("A00", ""),
|
|
|
|
+ first_name = t.optString("A02", ""),
|
|
|
|
+ last_name = t.optString("A03", ""),
|
|
|
|
+ image_id = t.optString("A74", ""),
|
|
|
|
+ official_account = t.optString("oacc", "0")
|
|
|
|
+ )
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ placeholder = { Text("Search name..") },
|
|
|
|
+ leadingIcon = { Icon(Icons.Default.Search, contentDescription = null) },
|
|
|
|
+ trailingIcon = {
|
|
|
|
+ if (active) {
|
|
|
|
+ IconButton(onClick = { text = "" }) {
|
|
|
|
+ Icon(Icons.Default.Close, contentDescription = null)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ ) {
|
|
|
|
+ SearchResultList(viewModel = viewModel, list = listSuggestions)
|
|
|
|
+ }
|
|
|
|
+ Spacer(modifier = Modifier.size(8.dp))
|
|
|
|
+ SearchResultList(viewModel = viewModel, list = list)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+@OptIn(ExperimentalMaterial3Api::class)
|
|
|
|
+@Composable
|
|
|
|
+fun SearchResultList(
|
|
|
|
+ viewModel: BuddyViewModel,
|
|
|
|
+ list: SnapshotStateList<Buddy>
|
|
|
|
+) {
|
|
|
|
+ var selectedItem by remember { mutableIntStateOf(0) }
|
|
|
|
+ val openAlertDialog = remember { mutableStateOf(false) }
|
|
|
|
+ LazyColumn(
|
|
|
|
+ verticalArrangement = Arrangement.spacedBy(8.dp)
|
|
|
|
+ ) {
|
|
|
|
+ items(count = list.size) { item ->
|
|
|
|
+ val buddy = list[item]
|
|
|
|
+ ListItem(
|
|
|
|
+ modifier = Modifier.selectable(selected = selectedItem == item, onClick = {
|
|
|
|
+ selectedItem = item
|
|
|
|
+ openAlertDialog.value = true
|
|
|
|
+ }),
|
|
|
|
+ headlineContent = {
|
|
|
|
+ Row {
|
|
|
|
+ Text(
|
|
|
|
+ "${buddy.first_name} ${buddy.last_name}".trim(),
|
|
|
|
+ style = MaterialTheme.typography.titleSmall
|
|
|
|
+ )
|
|
|
|
+ if (buddy.official_account != "0") {
|
|
|
|
+ val color: Color = when (buddy.official_account) {
|
|
|
|
+ "1", "3" -> {
|
|
|
|
+ Color(0xFF4c87ef)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ "2" -> {
|
|
|
|
+ Color(0xFF0cff00)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ "5" -> {
|
|
|
|
+ Color(0xFFE000FF)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ else -> {
|
|
|
|
+ Color(0xFF4c87ef)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ Icon(
|
|
|
|
+ imageVector = Icons.Default.Verified,
|
|
|
|
+ contentDescription = "",
|
|
|
|
+ tint = color
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ leadingContent = {
|
|
|
|
+ AsyncImage(
|
|
|
|
+ model = ImageRequest.Builder(LocalContext.current)
|
|
|
|
+ .data("https://digixplatform.com/filepalio/image/${buddy.image_id}")
|
|
|
|
+ .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
|
|
|
|
+ .crossfade(true)
|
|
|
|
+ .build(),
|
|
|
|
+ placeholder = rememberVectorPainter(image = Icons.Default.Person),
|
|
|
|
+ contentDescription = "",
|
|
|
|
+ contentScale = ContentScale.Crop,
|
|
|
|
+ modifier = Modifier
|
|
|
|
+ .size(48.dp)
|
|
|
|
+ .clip(CircleShape)
|
|
|
|
+ .background(Color.LightGray),
|
|
|
|
+// .padding(8.dp),
|
|
|
|
+ error = rememberVectorPainter(image = Icons.Default.Person),
|
|
|
|
+// colorFilter = ColorFilter.tint(Color.White)
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ )
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if (openAlertDialog.value) {
|
|
|
|
+ val buddy = list[selectedItem]
|
|
|
|
+ AlertDialog(
|
|
|
|
+ icon = {
|
|
|
|
+ Icon(Icons.Default.Info, contentDescription = "Example Icon")
|
|
|
|
+ },
|
|
|
|
+ title = {
|
|
|
|
+ Text(text = "Add contact")
|
|
},
|
|
},
|
|
- maxLines = 1
|
|
|
|
|
|
+ text = {
|
|
|
|
+ Text(text = "Do you want add ${buddy.first_name} to your contact?")
|
|
|
|
+ },
|
|
|
|
+ onDismissRequest = {
|
|
|
|
+ openAlertDialog.value = false
|
|
|
|
+ },
|
|
|
|
+ confirmButton = {
|
|
|
|
+ TextButton(
|
|
|
|
+ onClick = {
|
|
|
|
+ viewModel.addFriend(buddy.f_pin)
|
|
|
|
+ }
|
|
|
|
+ ) {
|
|
|
|
+ Text("Confirm")
|
|
|
|
+ }
|
|
|
|
+ },
|
|
|
|
+ dismissButton = {
|
|
|
|
+ TextButton(
|
|
|
|
+ onClick = {
|
|
|
|
+ openAlertDialog.value = false
|
|
|
|
+ }
|
|
|
|
+ ) {
|
|
|
|
+ Text("Dismiss")
|
|
|
|
+ }
|
|
|
|
+ }
|
|
)
|
|
)
|
|
- Spacer(modifier = Modifier.size(8.dp))
|
|
|
|
- Button(onClick = {
|
|
|
|
- me?.let { viewModel.addFriend(it.f_pin, textUsername.text) }
|
|
|
|
- }) {
|
|
|
|
- Text(text = "Add")
|
|
|
|
- }
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|