diff --git a/README.md b/README.md
index f6b4c4c..6eca6a7 100644
--- a/README.md
+++ b/README.md
@@ -52,12 +52,10 @@
Лаунчер использует **текстовый интерфейс (TUI)**:
-- `W` / `S` (или `Ц` / `Ы`) — перемещение по меню
+- `W` / `S` (или `Ц` / `Ы`) или `↑` / `↓` — перемещение по меню
- `ENTER` — выбор пункта
- `ESC` или пункт «Назад» — возврат назад
-> **Важно:** Стрелки ↑/↓ могут вызывать баги и краши. Используйте только `W`/`S`.
-
Если вы случайно кликнули мышкой в окне лаунчера и он «заморозился» — просто нажмите **любую клавишу** на клавиатуре.
### Расположение сборок
diff --git a/launcher/pom.xml b/launcher/pom.xml
index 032c307..7551767 100644
--- a/launcher/pom.xml
+++ b/launcher/pom.xml
@@ -45,6 +45,11 @@
jansi
2.4.1
+
+ org.jline
+ jline
+ 3.24.1
+
me.tongfei
progressbar
diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LoginMenu.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LoginMenu.java
index ebdff19..6a106a6 100644
--- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LoginMenu.java
+++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LoginMenu.java
@@ -149,7 +149,6 @@ public class LoginMenu {
* если недоступно (IDE/терминал без TTY) — читаем обычным способом.
*/
private String readPassword(String prompt) throws IOException {
- // Создаём временный терминал для ввода пароля
org.jline.terminal.Terminal passTerminal = org.jline.terminal.TerminalBuilder.builder()
.system(true)
.jna(true)
@@ -165,6 +164,15 @@ public class LoginMenu {
while (true) {
int key = passTerminal.reader().read();
+ if (key == 27) {
+ // Escape sequence — consume remaining bytes (arrow keys, etc.)
+ int next = passTerminal.reader().read(50);
+ if (next == 91) { // '[' — arrow key sequence
+ passTerminal.reader().read(50); // consume 'A'/'B'/'C'/'D'
+ }
+ continue;
+ }
+
if (key == 13 || key == 10) { // Enter
passTerminal.writer().println();
break;
@@ -177,7 +185,7 @@ public class LoginMenu {
} else if (key == 3) { // Ctrl+C
passTerminal.writer().println();
System.exit(0);
- } else if (key >= 32 && key < 127) { // Печатные символы
+ } else if (key >= 32 && key < 127) { // Printable characters
password.append((char) key);
passTerminal.writer().print('*');
passTerminal.writer().flush();
diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/ui/ArrowMenu.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/ui/ArrowMenu.java
index 2d948b0..1a1720c 100644
--- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/ui/ArrowMenu.java
+++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/ui/ArrowMenu.java
@@ -36,17 +36,30 @@ public class ArrowMenu {
printPagedMenu();
int key = terminal.reader().read();
- if (key == 'w' || key == 'W' || key == 'ц' || key == 'Ц') { // Up
+ if (key == 'w' || key == 'W' || key == 'ц' || key == 'Ц'
+ || key == 'k' || key == 'K' || key == 'л' || key == 'Л') { // Up / Arrow Up
selected = (selected - 1 + options.size()) % options.size();
- }
- else if (key == 's' || key == 'S' || key == 'ы' || key == 'Ы') { // Down
+ }
+ else if (key == 's' || key == 'S' || key == 'ы' || key == 'Ы'
+ || key == 'j' || key == 'J' || key == 'о' || key == 'О') { // Down / Arrow Down
selected = (selected + 1) % options.size();
- }
+ }
else if (key == 13 || key == 10) { // Enter
return selected;
- }
- else if (key == 27) { // Esc
- return -1;
+ }
+ else if (key == 27) { // Esc or arrow escape seq
+ int next = terminal.reader().read(50);
+ if (next == 91) { // '[' — start of arrow escape sequence
+ int arrow = terminal.reader().read(50);
+ if (arrow == 65) { // 'A' — Up arrow
+ selected = (selected - 1 + options.size()) % options.size();
+ } else if (arrow == 66) { // 'B' — Down arrow
+ selected = (selected + 1) % options.size();
+ }
+ // else — unknown escape seq, ignore
+ } else {
+ return -1; // genuine Esc
+ }
}
}
} finally {
@@ -83,7 +96,7 @@ public class ArrowMenu {
// Подсказка внизу (фиксированная)
sb.append("\n")
- .append(ZAnsi.white("W/S (Ц/Ы) - перемещение | Enter - выбрать | Esc - назад"));
+ .append(ZAnsi.white("W/S (Ц/Ы) или ↑/↓ - перемещение | Enter - выбрать | Esc - назад"));
System.out.print(sb);
}