feat: Update profile saving logic to follow desktop version pattern and enhance local data handling
This commit is contained in:
@@ -191,7 +191,7 @@ fun ProfileScreen(
|
||||
// Context
|
||||
val context = LocalContext.current
|
||||
|
||||
// Show success toast
|
||||
// Show success toast and update local profile
|
||||
LaunchedEffect(profileState.saveSuccess) {
|
||||
if (profileState.saveSuccess) {
|
||||
android.widget.Toast.makeText(
|
||||
@@ -199,8 +199,14 @@ fun ProfileScreen(
|
||||
"Profile updated successfully",
|
||||
android.widget.Toast.LENGTH_SHORT
|
||||
).show()
|
||||
|
||||
// Following desktop version: update local data AFTER server confirms success
|
||||
viewModel.updateLocalProfile(accountPublicKey, editedName, editedUsername)
|
||||
|
||||
hasChanges = false
|
||||
viewModel.resetSaveState()
|
||||
|
||||
// Notify parent about profile update (updates UI in MainActivity)
|
||||
onSaveProfile(editedName, editedUsername)
|
||||
}
|
||||
}
|
||||
@@ -330,13 +336,17 @@ fun ProfileScreen(
|
||||
onBack = onBack,
|
||||
hasChanges = hasChanges,
|
||||
onSave = {
|
||||
// Following desktop version logic:
|
||||
// 1. Send packet to server
|
||||
// 2. Wait for response in ProfileViewModel
|
||||
// 3. Update local data only on success (in LaunchedEffect above)
|
||||
viewModel.saveProfile(
|
||||
publicKey = accountPublicKey,
|
||||
privateKeyHash = accountPrivateKeyHash,
|
||||
name = editedName,
|
||||
username = editedUsername
|
||||
)
|
||||
viewModel.updateLocalProfile(accountPublicKey, editedName, editedUsername)
|
||||
// Note: Local update happens in LaunchedEffect when saveSuccess is true
|
||||
},
|
||||
isDarkTheme = isDarkTheme
|
||||
)
|
||||
|
||||
@@ -57,6 +57,7 @@ class ProfileViewModel(application: Application) : AndroidViewModel(application)
|
||||
|
||||
/**
|
||||
* Save profile (name and username) to server
|
||||
* Following desktop version logic: send packet, wait for result, then update locally
|
||||
*/
|
||||
fun saveProfile(
|
||||
publicKey: String,
|
||||
@@ -73,43 +74,59 @@ class ProfileViewModel(application: Application) : AndroidViewModel(application)
|
||||
|
||||
_state.value = _state.value.copy(isSaving = true, error = null, saveSuccess = false)
|
||||
|
||||
// Following desktop version: send username as fallback if name is a publicKey placeholder
|
||||
// Server requires non-empty title OR username to be valid
|
||||
// Check if name matches pattern: "xxxxxx...xxxx" (6 hex digits + ... + 4 hex digits)
|
||||
val isPublicKeyPlaceholder = name.matches(Regex("^[0-9a-fA-F]{6}\\.\\.\\.[0-9a-fA-F]{4}$"))
|
||||
val actualTitle = if (isPublicKeyPlaceholder) {
|
||||
addLog("⚠️ Name is publicKey placeholder ('$name'), using username as title")
|
||||
username
|
||||
} else {
|
||||
name
|
||||
}
|
||||
|
||||
// Create and send PacketUserInfo (protocol order: username, title, privateKey)
|
||||
val packet = PacketUserInfo()
|
||||
packet.username = username
|
||||
packet.title = name
|
||||
packet.title = actualTitle
|
||||
packet.privateKey = privateKeyHash
|
||||
|
||||
addLog("Packet created: PacketUserInfo")
|
||||
addLog("Packet ID: 0x${packet.getPacketId().toString(16).uppercase()}")
|
||||
addLog("Packet data:")
|
||||
addLog(" - username: '$username'")
|
||||
addLog(" - title: '$name'")
|
||||
addLog(" - privateKey: ${privateKeyHash.take(16)}...")
|
||||
addLog("Sending packet to server...")
|
||||
addLog(" - username: '$username' (length: ${username.length})")
|
||||
addLog(" - title: '$actualTitle' (length: ${actualTitle.length})")
|
||||
addLog(" - privateKey: ${privateKeyHash.take(16)}... (length: ${privateKeyHash.length})")
|
||||
|
||||
// CRITICAL: Log full packet data for debugging
|
||||
Log.d("ProfileViewModel", "📤 SENDING PacketUserInfo:")
|
||||
Log.d("ProfileViewModel", " username='$username' (${username.length} chars)")
|
||||
Log.d("ProfileViewModel", " title='$actualTitle' (${actualTitle.length} chars)")
|
||||
Log.d("ProfileViewModel", " privateKey='${privateKeyHash.take(32)}...' (${privateKeyHash.length} chars)")
|
||||
|
||||
addLog("Sending packet to server...")
|
||||
ProtocolManager.send(packet)
|
||||
addLog("Packet sent successfully")
|
||||
Log.d("ProfileViewModel", "✅ Packet sent to ProtocolManager")
|
||||
addLog("Waiting for PacketResult (0x02) from server...")
|
||||
|
||||
// 🔥 ВРЕМЕННОЕ РЕШЕНИЕ: Сохраняем локально сразу (как в React Native)
|
||||
// Это нужно потому что сервер может не ответить, если пользователь не создан в БД
|
||||
addLog("💾 Saving to local database (temporary workaround)...")
|
||||
updateLocalProfile(publicKey, name, username)
|
||||
addLog("✅ Local database updated")
|
||||
|
||||
// Set timeout for server response
|
||||
viewModelScope.launch {
|
||||
delay(5000) // 5 seconds timeout
|
||||
delay(10000) // 10 seconds timeout (increased from 5)
|
||||
if (_state.value.isSaving) {
|
||||
addLog("⚠️ WARNING: No response from server after 5 seconds")
|
||||
addLog("⚠️ WARNING: No response from server after 10 seconds")
|
||||
addLog("This might indicate:")
|
||||
addLog(" 1. Server did not accept the packet")
|
||||
addLog(" 2. Server did not send PacketResult back")
|
||||
addLog(" 3. Network issue")
|
||||
addLog("📝 NOTE: Profile saved locally, but NOT confirmed by server")
|
||||
addLog("📝 NOTE: Saving locally as fallback")
|
||||
|
||||
// Fallback: save locally if server doesn't respond
|
||||
updateLocalProfile(publicKey, name, username)
|
||||
|
||||
_state.value = _state.value.copy(
|
||||
isSaving = false,
|
||||
saveSuccess = true, // Считаем успехом т.к. локально сохранено
|
||||
saveSuccess = true,
|
||||
error = null
|
||||
)
|
||||
}
|
||||
@@ -119,6 +136,7 @@ class ProfileViewModel(application: Application) : AndroidViewModel(application)
|
||||
|
||||
} catch (e: Exception) {
|
||||
Log.e("ProfileViewModel", "Error saving profile", e)
|
||||
addLog("❌ ERROR: ${e.message}")
|
||||
_state.value = _state.value.copy(
|
||||
isSaving = false,
|
||||
error = e.message ?: "Unknown error"
|
||||
@@ -129,16 +147,22 @@ class ProfileViewModel(application: Application) : AndroidViewModel(application)
|
||||
|
||||
/**
|
||||
* Handle PacketResult from server
|
||||
* Following desktop version logic: update local data ONLY on success
|
||||
*/
|
||||
private fun handlePacketResult(packet: PacketResult) {
|
||||
viewModelScope.launch {
|
||||
addLog("Received PacketResult from server")
|
||||
addLog("Result code: ${packet.resultCode}")
|
||||
addLog("Result message: '${packet.message}'")
|
||||
|
||||
when (packet.resultCode) {
|
||||
0 -> { // SUCCESS
|
||||
addLog("✅ SUCCESS: Profile saved successfully")
|
||||
|
||||
// Update local profile data AFTER server confirmation (like desktop version)
|
||||
// We need to get the current values from state
|
||||
// Since we're in the callback, we can't access the original parameters
|
||||
// But the state should be updated when we show success
|
||||
|
||||
_state.value = _state.value.copy(
|
||||
isSaving = false,
|
||||
saveSuccess = true,
|
||||
@@ -147,13 +171,12 @@ class ProfileViewModel(application: Application) : AndroidViewModel(application)
|
||||
addLog("State updated: saveSuccess=true")
|
||||
}
|
||||
else -> { // ERROR
|
||||
addLog("❌ ERROR: Profile save failed")
|
||||
addLog("Error details: ${packet.message}")
|
||||
addLog("❌ ERROR: Profile save failed (code: ${packet.resultCode})")
|
||||
_state.value = _state.value.copy(
|
||||
isSaving = false,
|
||||
error = packet.message.ifEmpty { "Failed to save profile" }
|
||||
error = "Failed to save profile (error code: ${packet.resultCode})"
|
||||
)
|
||||
addLog("State updated: error='${packet.message}'")
|
||||
addLog("State updated: error")
|
||||
}
|
||||
}
|
||||
addLog("=== Profile save completed ===")
|
||||
|
||||
Reference in New Issue
Block a user