diff --git a/qml/pages/SettingsPage.qml b/qml/pages/SettingsPage.qml index c90d302..b07b712 100644 --- a/qml/pages/SettingsPage.qml +++ b/qml/pages/SettingsPage.qml @@ -6,6 +6,7 @@ Page { property string testResult: "" property bool testOk: false + property bool testing: false SilicaFlickable { anchors.fill: parent @@ -58,9 +59,20 @@ Page { Button { anchors.horizontalCenter: parent.horizontalCenter text: "Prova connessione" + enabled: !page.testing onClicked: testConnection() } + Item { + width: parent.width + height: page.testing ? Theme.itemSizeSmall : 0 + BusyIndicator { + anchors.horizontalCenter: parent.horizontalCenter + running: page.testing + size: BusyIndicatorSize.Small + } + } + Label { x: Theme.horizontalPageMargin width: parent.width - 2 * Theme.horizontalPageMargin @@ -75,12 +87,17 @@ Page { } function testConnection() { - var base = appSettings.baseUrl + var base = appSettings.serverUrl.trim() if (base.length === 0) { page.testResult = "Inserisci l'indirizzo del server" page.testOk = false return } + // normalizza: senza schema aggiunge https:// e lo salva nel campo + if (base.indexOf("http://") !== 0 && base.indexOf("https://") !== 0) + base = "https://" + base + appSettings.serverUrl = base + page.testing = true page.testResult = "Verifica in corso…" apiClient.getFeed(base + "/opds") } @@ -90,12 +107,14 @@ Page { onFeedReady: { if (pageStack.currentPage !== page) return + page.testing = false page.testOk = true page.testResult = "Connessione OK: " + entries.length + " sezioni trovate" } onFeedError: { if (pageStack.currentPage !== page) return + page.testing = false page.testOk = false page.testResult = message } diff --git a/src/apiclient.cpp b/src/apiclient.cpp index ec7f6ae..846b3d7 100644 --- a/src/apiclient.cpp +++ b/src/apiclient.cpp @@ -4,6 +4,7 @@ #include "settings.h" #include +#include #include #include #include @@ -11,6 +12,7 @@ #include #include #include +#include #include ApiClient::ApiClient(Settings *settings, QObject *parent) @@ -56,24 +58,37 @@ QNetworkReply *ApiClient::startGet(const QUrl &url) static_cast &)>( &QNetworkReply::ignoreSslErrors)); } + + // timeout di sicurezza (30 s): senza, una richiesta verso un host irraggiungibile + // resta appesa all'infinito + QTimer *timer = new QTimer(reply); + timer->setSingleShot(true); + timer->setInterval(30000); + connect(timer, &QTimer::timeout, reply, &QNetworkReply::abort); + timer->start(); return reply; } void ApiClient::getFeed(const QString &url) { + qDebug() << "getFeed request:" << url; QNetworkReply *reply = startGet(QUrl(url)); connect(reply, &QNetworkReply::finished, this, [this, reply]() { reply->deleteLater(); const int status = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); if (reply->error() != QNetworkReply::NoError || status >= 400) { QString message; - if (status == 401) + if (reply->error() == QNetworkReply::OperationCanceledError) + message = QStringLiteral("Timeout: il server non risponde (30 s)"); + else if (status == 401) message = QStringLiteral( "Autenticazione richiesta (401). Controlla utente e password."); else if (status == 404) message = QStringLiteral("Endpoint non trovato (404). Controlla l'indirizzo."); else message = reply->errorString(); + qDebug() << "getFeed ERROR status:" << status + << "error:" << reply->error() << "-" << message; emit feedError(message); return; } @@ -84,8 +99,11 @@ void ApiClient::getFeed(const QString &url) QString feedTitle; QString parseError; if (OpdsParser::parse(body, &entries, &nextUrl, &feedTitle, &parseError)) { + qDebug() << "getFeed OK status:" << status + << "entries:" << entries.size(); emit feedReady(entries, resolveUrl(nextUrl), feedTitle); } else { + qDebug() << "getFeed parse error:" << parseError; emit feedError(parseError.isEmpty() ? QStringLiteral("Risposta non valida dal server") : parseError);