pragma ComponentBehavior: Bound import QtQuick import QtQuick.Controls 2.15 import QtWebEngine // Вход в аккаунт Microsoft — то же самое, что делает официальный лаунчер: // страница входа показывается внутри приложения, а лаунчер ждёт, когда браузер // уйдёт на redirect_uri с кодом авторизации в адресе. Dialog { id: msLogin required property var backend // Окно ничего не знает про тосты главного окна: о неудаче сообщает сигналом. signal failed(string message) // Код уже отдан backend — второй раз по тому же адресу не реагируем: // WebEngineView успевает сообщить об urlChanged несколько раз. property bool codeTaken: false anchors.centerIn: parent modal: true width: 560 height: 680 padding: 0 closePolicy: Popup.NoAutoClose function openAt(url) { codeTaken = false web.url = url open() } // Разбор адреса живёт в C++: правила совпадения должны совпадать с теми, // по которым сервис строит сам redirect_uri. function handleUrl(url) { if (codeTaken) return const info = backend.inspectMicrosoftRedirect(String(url)) if (!info.matched) return codeTaken = true close() if (info.code !== "") { backend.finishMicrosoftLogin(info.code) } else { backend.cancelMicrosoftLogin() msLogin.failed(info.error !== "" ? info.error : "Вход в Microsoft не завершён") } } background: Rectangle { color: "#1e1e1e" radius: 10 border.color: "#91B315" border.width: 1 } header: Item { implicitHeight: 52 Text { anchors.centerIn: parent text: "Вход в аккаунт Microsoft" color: "#ffffff" font.pixelSize: 17 font.bold: true } Rectangle { anchors.bottom: parent.bottom width: parent.width height: 1 color: "#333333" } } contentItem: Item { // Профиль без storageName — значит без диска: куки живут только пока // работает лаунчер и в общий браузер не попадают. За выбор аккаунта в // пределах сессии отвечает prompt=select_account в адресе входа. WebEngineProfilePrototype { id: msProfile } WebEngineView { id: web anchors.fill: parent anchors.margins: 12 profile: msProfile.instance() onUrlChanged: msLogin.handleUrl(url) } BusyIndicator { anchors.centerIn: parent running: web.loading visible: running } } footer: Item { implicitHeight: 60 Rectangle { anchors.top: parent.top width: parent.width height: 1 color: "#333333" } Button { anchors.centerIn: parent text: "Отмена" width: 110; height: 36 contentItem: Text { text: parent.text color: "#ffffff" horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter } background: Rectangle { color: parent.pressed ? "#444444" : "#333333" radius: 6 } onClicked: { msLogin.codeTaken = true msLogin.close() msLogin.backend.cancelMicrosoftLogin() } } } }