version number Signed-off-by: galeon <dertiellis@gmail.com>
11 KiB
Main.qml
Главное окно, оно же точка входа: main.cpp загружает его через
engine.loadFromModule("BiLauncher", "Main"). Корень — Window 1280×720.
Что в нём есть:
- единственный экземпляр
LauncherBackendи все обработчики его сигналов; - экран запуска: фон, кнопка игры по центру, список профилей, кнопка активной сборки, кнопки папки модов, настроек и сезонных сборок;
- плашка сообщений и две панели прогресса (ProgressPanel);
- диалоги, которые не вынесены в отдельные файлы: новый профиль, редактирование профиля, код двухфакторной аутентификации, настройки запуска.
Отдельными файлами сделаны BuildsDialog,
SeasonalBuildsDialog, JavaPickerDialog и
MicrosoftLoginDialog. Окно передаёт им бэкенд через свойство backend.
Стиль Qt Quick Controls — Basic (выставлен в main.cpp), и почти у каждого контрола здесь своё
оформление.
Раскладка
Всё стоит на якорях вокруг кнопки запуска: список профилей слева сверху от неё, кнопка активной сборки справа сверху, кнопки папки и настроек под списком профилей. Кнопка сезонных сборок стоит в правом нижнем углу, потому что остальные углы заняты.
В левом верхнем углу фона стоит подпись launcherVersion — «Версия: 1.0.1-dev». Текст из
app.label.version, номер из Qt.application.version, то есть из LAUNCHER_VERSION
(см. main.cpp).
Обе панели прогресса (загрузки и смены сборки) стоят в левом нижнем углу на одних и тех же якорях. Одновременно они не появляются: пока лаунчер занят загрузкой, бэкенд не начнёт смену сборки, и наоборот. Панель смены сборки отменить нельзя.
У заголовков и подвалов всех диалогов корнем служит Item с явным implicitHeight. У
Rectangle implicitHeight всегда 0, и Dialog не смог бы посчитать свою высоту.
Функции
showToast(text, color, timeout) — показать сообщение в плашке. timeout в миллисекундах,
по умолчанию 4000. 0 значит «держать до следующего сообщения». Так показываются шаги запуска,
чтобы сообщение не исчезало посреди долгой операции.
openMicrosoftLogin(url) — открыть окно входа Microsoft. Окно создаётся при первом вызове
через Qt.createComponent() и хранится в microsoftLoginDialog. Объявить его прямо в файле
нельзя: MicrosoftLoginDialog.qml есть в модуле только в сборках с WebEngine, и в остальных
сломалось бы всё главное окно. Если компонент не создался, вход отменяется у бэкенда и показывается
сообщение.
formatMb(bytes) — байты в мегабайты с одним знаком после запятой, для панели загрузки.
Сигналы бэкенда
| Сигнал | Что делает окно |
|---|---|
launched |
зелёное сообщение «запущено» |
launchProgress |
сообщение без таймаута |
launchError |
красное сообщение на 8 секунд |
twoFactorRequired |
открывает диалог кода |
gameFinished |
сообщение о закрытии игры; если код не 0 или процесс упал, красное и с кодом |
microsoftLoginUrlReady |
openMicrosoftLogin() |
microsoftLoginSucceeded |
сообщение. Выбор в списке профилей не трогает: новый профиль уже выбран тем, кто его создал, а повторный вход мог быть не для последнего профиля |
microsoftLoginFailed |
красное сообщение на 8 секунд |
microsoftReloginRequired |
сразу startMicrosoftLogin() для этого профиля |
gameOutput |
console.log |
seasonalInstallFinished |
сообщение «сборка установлена, можно играть» |
javaRuntimeInstalled |
обновляет строку Java в настройках |
Кнопка запуска выключена, пока busy или gameRunning. Список профилей выключен, пока busy;
кнопка активной сборки — пока busy или gameRunning. Так во время загрузки и установки (в том
числе сезонной сборки) доступна только отмена на панели загрузки.
Профили
Выпадающий список профилей переделан целиком. Наверху всплывающей панели закреплена кнопка
«+ Добавить профиль», под ней список. У каждой строки при наведении появляются карандаш (открывает
редактирование через openFor()) и корзина (removeProfile()).
Типы входа во всех списках идут в одном порядке: 0 — offline, 1 — elyby, 2 — microsoft.
Модель берётся из Loc.t.profile.authTypes, и порядок в каталоге важен, потому что код сравнивает
currentIndex с 1 и 2. Без WebEngine третий пункт отрезается через .slice(0, 2). В окне
редактирования он остаётся, если профиль уже лицензионный: иначе в сборке без WebEngine такой
профиль молча стал бы офлайновым.
Новый профиль. addProfile(), новый профиль выбирается в списке. Если тип «Microsoft», сразу
начинается вход, потому что без него такой профиль бесполезен. Скрытые поля при сохранении не
читаются: в них мог остаться текст, набранный до смены типа.
Редактирование. Дополнительные свойства диалога: editIndex, msProfile, msLinked (есть ли
сессия Microsoft), msName (ник из аккаунта). Ник показывается отдельным полем только для чтения,
а не подставляется в поле логина. Иначе привязка оборвалась бы при первом же вводе в это поле у
обычного профиля. Кнопка входа сначала сохраняет профиль с типом microsoft через
updateProfile() и только потом вызывает startMicrosoftLogin(). Тип могли переключить только
что, и без этого токены достались бы профилю другого типа.
Двухфакторная аутентификация
Диалог показывает имя профиля (profileName) и поле для кода. «Подтвердить» вызывает
submitTwoFactorCode(), «Отмена» — cancelPendingLaunch(). Если отмену не вызвать, запуск так и
повиснет.
Настройки
settingsDialog.load() читает settings() и detectedJava(), раскладывает значения по полям и
открывает диалог. «Сохранить» собирает всё в одну карту и отдаёт в updateSettings().
- Язык стоит первым, потому что относится ко всему приложению, а не к запуску игры. В модели
переведённые подписи, рядом лежит непереводимый список
codes(system,ru,en). Язык применяется по «Сохранить» и сразу, без перезапуска. - Папка игры, а под полем — путь, который получится на самом деле (
resolvedGameDir). Путь хранится в свойстве, а не записывается в текст напрямую, иначе подпись не обновилась бы при смене языка. - Java. Поле открывает JavaPickerDialog с текущим выбором и требованием
активной сборки (
requiredJavaMajor()). Крестик сбрасывает выбор, и тогда Java ищется в системе. Выбор хранится вjavaRuntimeIdи записывается только по «Сохранить».javaRuntimeInfoобновляется при сменеjavaRuntimeIdи поjavaRuntimeInstalled, потому чтоjavaRuntimeInfo()— обычный вызов, а не привязка. Если сборка выбрана, запуск идёт ею, а путь из соседнего поля остаётся запасным вариантом. - Память, размер окна, аргументы JVM, полноэкранный режим.
- Ниже для справки список найденных в системе java.
Окно выбора Java объявлено рядом с диалогом настроек, а не внутри него. Оно шире настроек и центрируется по окну лаунчера.
Кнопки
- папка —
openMinecraftFolder()(открываетmods); - настройки —
settingsDialog.load(); - сезонные сборки —
seasonalDialog.openCatalog(); - активная сборка —
buildsDialog.open().
Все тексты окна берутся из Loc.t, литералов в разметке нет.
При создании этого документа использовался ИИ.