Refactor card management to support asynchronous operations and improve error handling
Signed-off-by: Dmitrii <computer@yawaflua.tech> Took 3 minutes
This commit is contained in:
@@ -9,7 +9,6 @@ import net.minecraft.text.Text;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class ChatListener {
|
||||
@@ -57,8 +56,7 @@ public class ChatListener {
|
||||
if (client.player != null) {
|
||||
String playerUuid = client.player.getUuidAsString();
|
||||
|
||||
CompletableFuture
|
||||
.supplyAsync(() -> BankUiService.instance().addCard(cardId, tokenId, playerUuid))
|
||||
BankUiService.instance().addCardAsync(cardId, tokenId, playerUuid)
|
||||
.thenAccept(msg -> {
|
||||
if (client == null) {
|
||||
return;
|
||||
|
||||
@@ -26,6 +26,7 @@ import net.minecraft.text.Text;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -166,25 +167,13 @@ public class SPMegaClient implements ClientModInitializer {
|
||||
}
|
||||
UiNotifications.instance().render(drawContext, client.textRenderer, scaledWidth, scaledHeight);
|
||||
});
|
||||
// CompletableFuture.supplyAsync(() -> BackendAuthenticator.authenticate(client))
|
||||
// .thenAccept(authResult -> {
|
||||
// if (authResult) {
|
||||
// System.out.println("SPMega: Authenticated on backend successfully.");
|
||||
// } else {
|
||||
// System.err.println("SPMega: Authentication on backend failed");
|
||||
// }
|
||||
// })
|
||||
// .exceptionally(ex -> {
|
||||
// System.err.println("SPMega: Authentication error: " + ex.getMessage());
|
||||
// return null;
|
||||
// });
|
||||
|
||||
}
|
||||
);
|
||||
|
||||
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
|
||||
if (client.player != null) {
|
||||
BankUiService.instance().refreshOnServerJoin(client.player.getUuidAsString());
|
||||
BankUiService.instance().refreshOnServerJoinAsync(client.player.getUuidAsString());
|
||||
}
|
||||
});
|
||||
|
||||
@@ -238,8 +227,13 @@ public class SPMegaClient implements ClientModInitializer {
|
||||
});
|
||||
|
||||
new ChatListener().register();
|
||||
BackendAuthenticator.authenticate(MinecraftClient.getInstance());
|
||||
CompletableFuture.runAsync(() -> BackendAuthenticator.authenticate(MinecraftClient.getInstance()))
|
||||
.exceptionally(throwable -> {
|
||||
System.err.println("[SPMEGA] Error during async authenticate: " + throwable.getMessage());
|
||||
return null;
|
||||
});
|
||||
System.out.println("Author of SPMega make it with 4 cans of monster");
|
||||
System.out.println("If u want to see more updates - give me like 10 shekels for monster plzzz");
|
||||
System.out.println("Initialized beshalom! Tieie tovim!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class AddCardScreen extends Screen {
|
||||
@@ -85,8 +84,7 @@ public class AddCardScreen extends Screen {
|
||||
addButton.active = false;
|
||||
cancelButton.active = false;
|
||||
|
||||
CompletableFuture
|
||||
.supplyAsync(() -> bankUiService.addCard(cardId, cardToken, playerUuid))
|
||||
bankUiService.addCardAsync(cardId, cardToken, playerUuid)
|
||||
.thenAccept(message -> {
|
||||
if (this.client == null) {
|
||||
return;
|
||||
|
||||
@@ -9,7 +9,6 @@ import net.minecraft.text.Text;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class CardScreen extends Screen {
|
||||
private final Screen parent;
|
||||
@@ -46,25 +45,30 @@ public class CardScreen extends Screen {
|
||||
}
|
||||
|
||||
this.addDrawableChild(ButtonWidget.builder(Text.literal("Удалить"), button -> {
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
bankUiService.removeSelectedCard();
|
||||
return true;
|
||||
});
|
||||
notifications.showMessage(bankUiService.getLastMessage());
|
||||
this.clearAndInit();
|
||||
bankUiService.removeSelectedCardAsync()
|
||||
.thenAccept(message -> {
|
||||
if (this.client != null) {
|
||||
this.client.execute(() -> {
|
||||
notifications.showMessage(message);
|
||||
this.clearAndInit();
|
||||
});
|
||||
}
|
||||
});
|
||||
}).dimensions(rightX, startY, columnWidth, 20).build());
|
||||
|
||||
this.addDrawableChild(ButtonWidget.builder(Text.literal("Обновить"), button -> {
|
||||
String playerUuid = this.client != null && this.client.player != null
|
||||
? this.client.player.getUuidAsString()
|
||||
: "";
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
bankUiService.refreshSelectedCard(playerUuid);
|
||||
return true;
|
||||
});
|
||||
String message = bankUiService.getLastMessage().isBlank() ? "Карта обновлена" : bankUiService.getLastMessage();
|
||||
notifications.showMessage(message);
|
||||
this.clearAndInit();
|
||||
bankUiService.refreshSelectedCardAsync(playerUuid)
|
||||
.thenAccept(message -> {
|
||||
if (this.client != null) {
|
||||
this.client.execute(() -> {
|
||||
notifications.showMessage(message);
|
||||
this.clearAndInit();
|
||||
});
|
||||
}
|
||||
});
|
||||
}).dimensions(rightX, startY + 24, columnWidth, 20).build());
|
||||
|
||||
this.addDrawableChild(ButtonWidget.builder(Text.literal("Добавить новую"), button -> {
|
||||
|
||||
@@ -12,7 +12,6 @@ import net.minecraft.text.Text;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -382,8 +381,7 @@ public class PaymentScreen extends Screen {
|
||||
}
|
||||
lastRecipientLookup = username;
|
||||
|
||||
CompletableFuture
|
||||
.supplyAsync(() -> bankUiService.loadRecipientCards(username))
|
||||
bankUiService.loadRecipientCardsAsync(username)
|
||||
.thenAccept(cards -> {
|
||||
if (this.client == null) {
|
||||
return;
|
||||
|
||||
+31
-40
@@ -84,12 +84,11 @@ public class BackendAuthenticator {
|
||||
}
|
||||
|
||||
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
|
||||
if (json.has("sessionId")) {
|
||||
return json.get("sessionId").getAsString();
|
||||
} else {
|
||||
if (!json.has("sessionId")) {
|
||||
System.err.println("[SPMEGA] Invalid response from start endpoint: " + response.body());
|
||||
throw new IOException("Invalid response from start endpoint: " + response.body());
|
||||
}
|
||||
return json.get("sessionId").getAsString();
|
||||
}
|
||||
|
||||
private static boolean sendAuthRequestToBackend(UUID uuid, String serverId) throws IOException, InterruptedException {
|
||||
@@ -123,28 +122,27 @@ public class BackendAuthenticator {
|
||||
}
|
||||
|
||||
JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
|
||||
if (json.has("token")) {
|
||||
String token = json.get("token").getAsString();
|
||||
if (config != null) {
|
||||
ModConfig updated = new ModConfig(
|
||||
config.apiDomain(),
|
||||
token,
|
||||
config.allowBackend(),
|
||||
config.signQuickPayEnabled(),
|
||||
config.gpsEnabled(),
|
||||
config.gpsPosition()
|
||||
);
|
||||
SPMega.setConfig(updated);
|
||||
System.out.println("[SPMEGA] Backend auth successful, saved token.");
|
||||
return true;
|
||||
} else {
|
||||
System.err.println("[SPMEGA] Config is null, cannot save token.");
|
||||
throw new IOException("Config is null, cannot save token.");
|
||||
}
|
||||
} else {
|
||||
if (!json.has("token")) {
|
||||
System.err.println("[SPMEGA] Invalid response from validate endpoint: " + response.body());
|
||||
throw new IOException("Invalid response from validate endpoint: " + response.body());
|
||||
}
|
||||
if (config == null) {
|
||||
System.err.println("[SPMEGA] Config is null, cannot save token.");
|
||||
throw new IOException("Config is null, cannot save token.");
|
||||
}
|
||||
|
||||
String token = json.get("token").getAsString();
|
||||
ModConfig updated = new ModConfig(
|
||||
config.apiDomain(),
|
||||
token,
|
||||
config.allowBackend(),
|
||||
config.signQuickPayEnabled(),
|
||||
config.gpsEnabled(),
|
||||
config.gpsPosition()
|
||||
);
|
||||
SPMega.setConfig(updated);
|
||||
System.out.println("[SPMEGA] Backend auth successful, saved token.");
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void sendCardToBackend(String cardId, String cardToken) {
|
||||
@@ -223,19 +221,13 @@ public class BackendAuthenticator {
|
||||
List<CardCredentials> cards = new ArrayList<>();
|
||||
for (com.google.gson.JsonElement el : cardsArray) {
|
||||
JsonObject cardJson = el.getAsJsonObject();
|
||||
String cardId = "";
|
||||
if (cardJson.has("cardId") && !cardJson.get("cardId").isJsonNull()) {
|
||||
cardId = cardJson.get("cardId").getAsString();
|
||||
} else if (cardJson.has("id") && !cardJson.get("id").isJsonNull()) {
|
||||
cardId = cardJson.get("id").getAsString();
|
||||
}
|
||||
String cardId = cardJson.has("cardId") && !cardJson.get("cardId").isJsonNull()
|
||||
? cardJson.get("cardId").getAsString()
|
||||
: (cardJson.has("id") && !cardJson.get("id").isJsonNull() ? cardJson.get("id").getAsString() : "");
|
||||
|
||||
String cardToken = "";
|
||||
if (cardJson.has("cardToken") && !cardJson.get("cardToken").isJsonNull()) {
|
||||
cardToken = cardJson.get("cardToken").getAsString();
|
||||
} else if (cardJson.has("token") && !cardJson.get("token").isJsonNull()) {
|
||||
cardToken = cardJson.get("token").getAsString();
|
||||
}
|
||||
String cardToken = cardJson.has("cardToken") && !cardJson.get("cardToken").isJsonNull()
|
||||
? cardJson.get("cardToken").getAsString()
|
||||
: (cardJson.has("token") && !cardJson.get("token").isJsonNull() ? cardJson.get("token").getAsString() : "");
|
||||
|
||||
if (!cardId.isEmpty() && !cardToken.isEmpty()) {
|
||||
cards.add(new CardCredentials(cardId, cardToken));
|
||||
@@ -299,10 +291,10 @@ public class BackendAuthenticator {
|
||||
String url = apiDomain + "/api/v1/transactions";
|
||||
|
||||
JsonObject jsonPayload = new JsonObject();
|
||||
jsonPayload.addProperty("senderCardId", senderCardId);
|
||||
jsonPayload.addProperty("cardToUse", senderCardId);
|
||||
jsonPayload.addProperty("cardId", senderCardId);
|
||||
jsonPayload.addProperty("receiver", receiver);
|
||||
jsonPayload.addProperty("recipient", receiver);
|
||||
jsonPayload.addProperty("receiverCard", receiver);
|
||||
jsonPayload.addProperty("receiverName", receiver);
|
||||
jsonPayload.addProperty("amount", amount);
|
||||
jsonPayload.addProperty("comment", comment);
|
||||
String requestBody = jsonPayload.toString();
|
||||
@@ -316,11 +308,10 @@ public class BackendAuthenticator {
|
||||
.build();
|
||||
|
||||
HttpResponse<String> response = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
if (response.statusCode() == 200 || response.statusCode() == 201 || response.statusCode() == 204) {
|
||||
return true;
|
||||
} else {
|
||||
if (response.statusCode() != 200 && response.statusCode() != 201 && response.statusCode() != 204) {
|
||||
throw new IOException("Server returned status code " + response.statusCode() + ": " + response.body());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static List<BankDatabase.LocalTransaction> fetchTransactionsFromBackend(String cardId) throws IOException, InterruptedException {
|
||||
|
||||
@@ -5,6 +5,8 @@ import git.yawaflua.tech.spmega.SPMega;
|
||||
import git.yawaflua.tech.spmega.api.SPWorldsApiClient;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -17,7 +19,7 @@ public final class BankUiService {
|
||||
private final String apiDomain = "https://spworlds.ru";
|
||||
|
||||
private int selectedCardIndex;
|
||||
private String lastMessage = "";
|
||||
private volatile String lastMessage = "";
|
||||
|
||||
private BankUiService() {
|
||||
this.database = new BankDatabase(FabricLoader.getInstance().getConfigDir().resolve("spmega.db"));
|
||||
@@ -54,11 +56,20 @@ public final class BankUiService {
|
||||
return normalized.substring(normalized.length() - 5);
|
||||
}
|
||||
|
||||
public synchronized List<CardViewModel> getCards() {
|
||||
private void runOnMainThread(Runnable runnable) {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
if (client == null || client.isOnThread()) {
|
||||
runnable.run();
|
||||
} else {
|
||||
client.execute(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
public List<CardViewModel> getCards() {
|
||||
return Collections.unmodifiableList(cards);
|
||||
}
|
||||
|
||||
public synchronized CardViewModel getSelectedCard() {
|
||||
public CardViewModel getSelectedCard() {
|
||||
if (cards.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -66,7 +77,7 @@ public final class BankUiService {
|
||||
return cards.get(selectedCardIndex);
|
||||
}
|
||||
|
||||
public synchronized int getSelectedCardIndex() {
|
||||
public int getSelectedCardIndex() {
|
||||
if (cards.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
@@ -74,7 +85,7 @@ public final class BankUiService {
|
||||
return selectedCardIndex;
|
||||
}
|
||||
|
||||
public synchronized void setSelectedCardIndex(int index) {
|
||||
public void setSelectedCardIndex(int index) {
|
||||
if (cards.isEmpty()) {
|
||||
selectedCardIndex = 0;
|
||||
return;
|
||||
@@ -82,7 +93,7 @@ public final class BankUiService {
|
||||
selectedCardIndex = Math.floorMod(index, cards.size());
|
||||
}
|
||||
|
||||
public synchronized CardViewModel cycleSelectedCard(int direction) {
|
||||
public CardViewModel cycleSelectedCard(int direction) {
|
||||
if (cards.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -90,200 +101,219 @@ public final class BankUiService {
|
||||
return cards.get(selectedCardIndex);
|
||||
}
|
||||
|
||||
public synchronized String getLastMessage() {
|
||||
public String getLastMessage() {
|
||||
return lastMessage;
|
||||
}
|
||||
|
||||
public synchronized void syncCardsWithBackend(String playerUuid) {
|
||||
try {
|
||||
List<CardCredentials> backendCards = BackendAuthenticator.fetchCardsFromBackend();
|
||||
boolean changed = false;
|
||||
for (CardCredentials creds : backendCards) {
|
||||
if (database.getCredentials(creds.cardId()) == null) {
|
||||
database.upsertCardCredentials(creds.cardId(), creds.cardToken());
|
||||
refreshCard(creds.cardId(), creds.cardToken(), playerUuid, false, false);
|
||||
changed = true;
|
||||
public CompletableFuture<Void> syncCardsWithBackendAsync(String playerUuid) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
List<CardCredentials> backendCards = BackendAuthenticator.fetchCardsFromBackend();
|
||||
boolean changed = false;
|
||||
for (CardCredentials creds : backendCards) {
|
||||
if (database.getCredentials(creds.cardId()) == null) {
|
||||
database.upsertCardCredentials(creds.cardId(), creds.cardToken());
|
||||
refreshCardSync(creds.cardId(), creds.cardToken(), playerUuid, false, false);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
reloadCardsFromDb();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("[SPMEGA] Failed to sync cards with backend: " + e.getMessage());
|
||||
}
|
||||
if (changed) {
|
||||
reloadCardsFromDb();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("[SPMEGA] Failed to sync cards with backend: " + e.getMessage());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized void refreshOnServerJoin(String playerUuid) {
|
||||
syncCardsWithBackend(playerUuid);
|
||||
public CompletableFuture<Void> refreshOnServerJoinAsync(String playerUuid) {
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
List<CardCredentials> backendCards = BackendAuthenticator.fetchCardsFromBackend();
|
||||
for (CardCredentials creds : backendCards) {
|
||||
if (database.getCredentials(creds.cardId()) == null) {
|
||||
database.upsertCardCredentials(creds.cardId(), creds.cardToken());
|
||||
refreshCardSync(creds.cardId(), creds.cardToken(), playerUuid, false, false);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("[SPMEGA] Failed to sync cards with backend: " + e.getMessage());
|
||||
}
|
||||
|
||||
List<StoredCard> storedCards = database.loadCards();
|
||||
for (StoredCard card : storedCards) {
|
||||
refreshCard(card.cardId(), card.cardToken(), playerUuid, false, false);
|
||||
}
|
||||
reloadCardsFromDb();
|
||||
List<StoredCard> storedCards = database.loadCards();
|
||||
for (StoredCard card : storedCards) {
|
||||
refreshCardSync(card.cardId(), card.cardToken(), playerUuid, false, false);
|
||||
}
|
||||
reloadCardsFromDb();
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized List<String> loadRecipientCards(String username) {
|
||||
public CompletableFuture<List<String>> loadRecipientCardsAsync(String username) {
|
||||
CardCredentials credentials = getSelectedCredentials();
|
||||
if (credentials == null || username == null || username.isBlank()) {
|
||||
return List.of();
|
||||
return CompletableFuture.completedFuture(List.of());
|
||||
}
|
||||
|
||||
try {
|
||||
List<SPWorldsApiClient.PlayerCard> apiCards = apiClient.getPlayerCards(username, toApiAuth(credentials));
|
||||
List<String> numbers = new ArrayList<>();
|
||||
for (SPWorldsApiClient.PlayerCard apiCard : apiCards) {
|
||||
if (apiCard.number() != null && !apiCard.number().isBlank()) {
|
||||
numbers.add(apiCard.name() + " : " + apiCard.number());
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
List<SPWorldsApiClient.PlayerCard> apiCards = apiClient.getPlayerCards(username, toApiAuth(credentials));
|
||||
List<String> numbers = new ArrayList<>();
|
||||
for (SPWorldsApiClient.PlayerCard apiCard : apiCards) {
|
||||
if (apiCard.number() != null && !apiCard.number().isBlank()) {
|
||||
numbers.add(apiCard.name() + " : " + apiCard.number());
|
||||
}
|
||||
}
|
||||
lastMessage = "";
|
||||
return numbers;
|
||||
} catch (Exception exception) {
|
||||
lastMessage = "Не удалось получить карты игрока: " + exception.getMessage();
|
||||
return List.of();
|
||||
}
|
||||
lastMessage = "";
|
||||
return numbers;
|
||||
} catch (Exception exception) {
|
||||
lastMessage = "Не удалось получить карты игрока: " + exception.getMessage();
|
||||
return List.of();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized String addCard(String cardIdRaw, String cardTokenRaw, String playerUuid) {
|
||||
public CompletableFuture<String> addCardAsync(String cardIdRaw, String cardTokenRaw, String playerUuid) {
|
||||
String cardId = cardIdRaw == null ? "" : cardIdRaw.trim();
|
||||
String cardToken = cardTokenRaw == null ? "" : cardTokenRaw.trim();
|
||||
|
||||
if (cardId.isEmpty() || cardToken.isEmpty()) {
|
||||
lastMessage = "Укажи cardId и cardToken";
|
||||
return lastMessage;
|
||||
return CompletableFuture.completedFuture("Укажи cardId и cardToken");
|
||||
}
|
||||
|
||||
try {
|
||||
UUID.fromString(cardId);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
lastMessage = "cardId должен быть UUID";
|
||||
return CompletableFuture.completedFuture("cardId должен быть UUID");
|
||||
}
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
database.upsertCardCredentials(cardId, cardToken);
|
||||
boolean refreshed = refreshCardSync(cardId, cardToken, playerUuid, true, true);
|
||||
if (!refreshed) {
|
||||
database.deleteCard(cardId);
|
||||
}
|
||||
reloadCardsFromDb();
|
||||
|
||||
if (refreshed && lastMessage.isBlank()) {
|
||||
return "Карта добавлена";
|
||||
}
|
||||
return lastMessage;
|
||||
}
|
||||
|
||||
database.upsertCardCredentials(cardId, cardToken);
|
||||
boolean refreshed = refreshCard(cardId, cardToken, playerUuid, true, true);
|
||||
if (!refreshed) {
|
||||
database.deleteCard(cardId);
|
||||
}
|
||||
reloadCardsFromDb();
|
||||
|
||||
if (refreshed && lastMessage.isBlank()) {
|
||||
lastMessage = "Карта добавлена";
|
||||
}
|
||||
return lastMessage;
|
||||
});
|
||||
}
|
||||
|
||||
public synchronized void removeSelectedCard() {
|
||||
public CompletableFuture<String> removeSelectedCardAsync() {
|
||||
CardViewModel selected = getSelectedCard();
|
||||
if (selected == null) {
|
||||
lastMessage = "Нет карты для удаления";
|
||||
return;
|
||||
return CompletableFuture.completedFuture("Нет карты для удаления");
|
||||
}
|
||||
|
||||
String cardId = selected.id();
|
||||
database.deleteCard(cardId);
|
||||
ModConfig config = SPMega.getConfig();
|
||||
if (config.allowBackend())
|
||||
BackendAuthenticator.deleteCardOnBackend(cardId);
|
||||
|
||||
reloadCardsFromDb();
|
||||
if (selectedCardIndex >= cards.size()) {
|
||||
selectedCardIndex = Math.max(0, cards.size() - 1);
|
||||
}
|
||||
lastMessage = "Карта удалена";
|
||||
}
|
||||
|
||||
public synchronized void refreshSelectedCard(String playerUuid) {
|
||||
CardViewModel selected = getSelectedCard();
|
||||
if (selected == null) {
|
||||
lastMessage = "Нет карты для обновления";
|
||||
return;
|
||||
}
|
||||
|
||||
CardCredentials credentials = database.getCredentials(selected.id());
|
||||
if (credentials == null) {
|
||||
lastMessage = "Не найдены креды карты";
|
||||
return;
|
||||
}
|
||||
|
||||
refreshCard(credentials.cardId(), credentials.cardToken(), playerUuid, false, false);
|
||||
reloadCardsFromDb();
|
||||
}
|
||||
|
||||
public synchronized boolean submitPayment(PaymentDraft draft) {
|
||||
CardCredentials credentials = database.getCredentials(draft.senderCardId());
|
||||
if (credentials == null) {
|
||||
lastMessage = "Не найдены креды карты отправителя";
|
||||
return false;
|
||||
}
|
||||
|
||||
git.yawaflua.tech.spmega.ModConfig config = git.yawaflua.tech.spmega.SPMega.getConfig();
|
||||
boolean useBackend = config != null && config.allowBackend();
|
||||
|
||||
try {
|
||||
long newBalance = 0;
|
||||
if (useBackend) {
|
||||
BackendAuthenticator.createTransactionOnBackend(
|
||||
draft.senderCardId(),
|
||||
draft.recipient(),
|
||||
draft.amount(),
|
||||
draft.comment()
|
||||
);
|
||||
try {
|
||||
refreshCard(credentials.cardId(), credentials.cardToken(), "", false, false);
|
||||
StoredCard updatedCard = database.loadCards().stream()
|
||||
.filter(c -> c.cardId().equals(credentials.cardId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (updatedCard != null) {
|
||||
newBalance = updatedCard.balance();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("[SPMEGA] Failed to refresh card balance after transaction: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
SPWorldsApiClient.TransactionResult result = apiClient.createTransaction(
|
||||
toApiAuth(credentials),
|
||||
draft.recipient(),
|
||||
draft.amount(),
|
||||
draft.comment()
|
||||
);
|
||||
newBalance = result.balance();
|
||||
database.updateCardBalance(credentials.cardId(), newBalance);
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
database.deleteCard(cardId);
|
||||
ModConfig config = SPMega.getConfig();
|
||||
if (config != null && config.allowBackend()) {
|
||||
BackendAuthenticator.deleteCardOnBackend(cardId);
|
||||
}
|
||||
|
||||
database.insertTransferHistory(
|
||||
credentials.cardId(),
|
||||
draft.recipient(),
|
||||
draft.amount(),
|
||||
draft.comment(),
|
||||
newBalance,
|
||||
"SUCCESS"
|
||||
);
|
||||
|
||||
reloadCardsFromDb();
|
||||
lastMessage = "Перевод выполнен";
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
database.insertTransferHistory(
|
||||
credentials.cardId(),
|
||||
draft.recipient(),
|
||||
draft.amount(),
|
||||
draft.comment(),
|
||||
null,
|
||||
"FAILED: " + trimMessage(exception.getMessage())
|
||||
);
|
||||
lastMessage = "Ошибка перевода: " + exception.getMessage();
|
||||
return false;
|
||||
runOnMainThread(() -> {
|
||||
if (selectedCardIndex >= cards.size()) {
|
||||
selectedCardIndex = Math.max(0, cards.size() - 1);
|
||||
}
|
||||
});
|
||||
return "Карта удалена";
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<String> refreshSelectedCardAsync(String playerUuid) {
|
||||
CardViewModel selected = getSelectedCard();
|
||||
if (selected == null) {
|
||||
return CompletableFuture.completedFuture("Нет карты для обновления");
|
||||
}
|
||||
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
CardCredentials credentials = database.getCredentials(selected.id());
|
||||
if (credentials == null) {
|
||||
return "Не найдены креды карты";
|
||||
}
|
||||
|
||||
refreshCardSync(credentials.cardId(), credentials.cardToken(), playerUuid, false, false);
|
||||
reloadCardsFromDb();
|
||||
return lastMessage.isBlank() ? "Карта обновлена" : lastMessage;
|
||||
});
|
||||
}
|
||||
|
||||
public CompletableFuture<Boolean> submitPaymentAsync(PaymentDraft draft) {
|
||||
return CompletableFuture.supplyAsync(() -> submitPayment(draft));
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
CardCredentials credentials = database.getCredentials(draft.senderCardId());
|
||||
if (credentials == null) {
|
||||
lastMessage = "Не найдены креды карты отправителя";
|
||||
return false;
|
||||
}
|
||||
|
||||
git.yawaflua.tech.spmega.ModConfig config = git.yawaflua.tech.spmega.SPMega.getConfig();
|
||||
boolean useBackend = config != null && config.allowBackend();
|
||||
|
||||
try {
|
||||
long newBalance = 0;
|
||||
if (useBackend) {
|
||||
BackendAuthenticator.createTransactionOnBackend(
|
||||
draft.senderCardId(),
|
||||
draft.recipient(),
|
||||
draft.amount(),
|
||||
draft.comment()
|
||||
);
|
||||
try {
|
||||
refreshCardSync(credentials.cardId(), credentials.cardToken(), "", false, false);
|
||||
StoredCard updatedCard = database.loadCards().stream()
|
||||
.filter(c -> c.cardId().equals(credentials.cardId()))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (updatedCard != null) {
|
||||
newBalance = updatedCard.balance();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("[SPMEGA] Failed to refresh card balance after transaction: " + e.getMessage());
|
||||
}
|
||||
} else {
|
||||
SPWorldsApiClient.TransactionResult result = apiClient.createTransaction(
|
||||
toApiAuth(credentials),
|
||||
draft.recipient(),
|
||||
draft.amount(),
|
||||
draft.comment()
|
||||
);
|
||||
newBalance = result.balance();
|
||||
database.updateCardBalance(credentials.cardId(), newBalance);
|
||||
}
|
||||
|
||||
database.insertTransferHistory(
|
||||
credentials.cardId(),
|
||||
draft.recipient(),
|
||||
draft.amount(),
|
||||
draft.comment(),
|
||||
newBalance,
|
||||
"SUCCESS"
|
||||
);
|
||||
|
||||
reloadCardsFromDb();
|
||||
lastMessage = "Перевод выполнен";
|
||||
return true;
|
||||
} catch (Exception exception) {
|
||||
database.insertTransferHistory(
|
||||
credentials.cardId(),
|
||||
draft.recipient(),
|
||||
draft.amount(),
|
||||
draft.comment(),
|
||||
null,
|
||||
"FAILED: " + trimMessage(exception.getMessage())
|
||||
);
|
||||
lastMessage = "Ошибка перевода: " + exception.getMessage();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private boolean refreshCard(
|
||||
private boolean refreshCardSync(
|
||||
String cardId,
|
||||
String cardToken,
|
||||
String playerUuid,
|
||||
@@ -319,12 +349,9 @@ public final class BankUiService {
|
||||
}
|
||||
}
|
||||
git.yawaflua.tech.spmega.ModConfig config = git.yawaflua.tech.spmega.SPMega.getConfig();
|
||||
if (config.allowBackend())
|
||||
CompletableFuture.supplyAsync(() -> {
|
||||
BackendAuthenticator.sendCardToBackend(cardId, cardToken);
|
||||
return true;
|
||||
}
|
||||
);
|
||||
if (config != null && config.allowBackend()) {
|
||||
BackendAuthenticator.sendCardToBackend(cardId, cardToken);
|
||||
}
|
||||
|
||||
lastMessage = "";
|
||||
return true;
|
||||
@@ -336,22 +363,23 @@ public final class BankUiService {
|
||||
|
||||
private void reloadCardsFromDb() {
|
||||
List<StoredCard> storedCards = database.loadCards();
|
||||
cards.clear();
|
||||
runOnMainThread(() -> {
|
||||
cards.clear();
|
||||
for (StoredCard stored : storedCards) {
|
||||
String cardNumber = stored.cardNumber() == null || stored.cardNumber().isBlank()
|
||||
? extractLastDigits(stored.cardId())
|
||||
: stored.cardNumber();
|
||||
String cardName = stored.cardName() == null || stored.cardName().isBlank() ? "Карта" : stored.cardName();
|
||||
String title = cardNumber + ": " + cardName;
|
||||
cards.add(new CardViewModel(stored.cardId(), title, stored.balance()));
|
||||
}
|
||||
|
||||
for (StoredCard stored : storedCards) {
|
||||
String cardNumber = stored.cardNumber() == null || stored.cardNumber().isBlank()
|
||||
? extractLastDigits(stored.cardId())
|
||||
: stored.cardNumber();
|
||||
String cardName = stored.cardName() == null || stored.cardName().isBlank() ? "Карта" : stored.cardName();
|
||||
String title = cardNumber + ": " + cardName;
|
||||
cards.add(new CardViewModel(stored.cardId(), title, stored.balance()));
|
||||
}
|
||||
|
||||
if (cards.isEmpty()) {
|
||||
selectedCardIndex = 0;
|
||||
} else {
|
||||
selectedCardIndex = Math.floorMod(selectedCardIndex, cards.size());
|
||||
}
|
||||
if (cards.isEmpty()) {
|
||||
selectedCardIndex = 0;
|
||||
} else {
|
||||
selectedCardIndex = Math.floorMod(selectedCardIndex, cards.size());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private CardCredentials getSelectedCredentials() {
|
||||
|
||||
Reference in New Issue
Block a user