From a66434afa8883d254dddf1051d8ea03e13a23995 Mon Sep 17 00:00:00 2001 From: Chris Josten Date: Tue, 2 Jan 2024 19:51:27 +0100 Subject: [PATCH] QuickConnect: init This adds a page in the settings page that allows the user to enter a quick connect code to allow another device to log in. --- core/include/JellyfinQt/apiclient.h | 9 +++ core/include/JellyfinQt/support/loader.h | 21 +++++ core/src/apiclient.cpp | 21 +++++ rpm/harbour-sailfin.changes | 1 + sailfish/CMakeLists.txt | 3 +- sailfish/qml/pages/QuickConnectDialog.qml | 86 +++++++++++++++++++++ sailfish/qml/pages/SettingsPage.qml | 5 ++ sailfish/translations/harbour-sailfin-de.ts | 30 +++++++ sailfish/translations/harbour-sailfin-ru.ts | 30 +++++++ sailfish/translations/harbour-sailfin.ts | 39 +++++++++- 10 files changed, 242 insertions(+), 3 deletions(-) create mode 100644 sailfish/qml/pages/QuickConnectDialog.qml diff --git a/core/include/JellyfinQt/apiclient.h b/core/include/JellyfinQt/apiclient.h index 00175df..b01add8 100644 --- a/core/include/JellyfinQt/apiclient.h +++ b/core/include/JellyfinQt/apiclient.h @@ -209,6 +209,14 @@ signals: void supportedCommandsChanged(); void onlineChanged(); + /** + * @brief Emitted after submitQuickConnectCode succeeded + */ + void quickConnectAccepted(); + /** + * @brief Emitted after submitQuickConnectCode failed + */ + void quickConnectRejected(); /** * @brief onUserDataChanged Emitted when the user data of an item is changed on the server. @@ -233,6 +241,7 @@ public slots: */ void setupConnection(); void authenticate(QString username, QString password, bool storeCredentials = false); + void submitQuickConnectCode(const QString &code); /** * @brief Logs the user out and clears the session. diff --git a/core/include/JellyfinQt/support/loader.h b/core/include/JellyfinQt/support/loader.h index 3afd33d..f9b1106 100644 --- a/core/include/JellyfinQt/support/loader.h +++ b/core/include/JellyfinQt/support/loader.h @@ -256,6 +256,27 @@ public: } }; +// Specialisation for endpoints that return "true" or "false" as response. +template +class HttpLoaderBase : public Loader { +public: + explicit HttpLoaderBase(Jellyfin::ApiClient *apiClient) + : Loader (apiClient) {} + + typename Loader::ResultType parseResponse(int statusCode, QByteArray response) { + QString text = QString::fromUtf8(response); + + if (text == QStringLiteral("true")) { + return true; + } else if (text == QStringLiteral("false")) { + return false; + } else { + this->stopWithError(QStringLiteral("Could not parse boolean response: %1").arg(text)); + return std::nullopt; + } + } +}; + /** * Implementation of Loader that loads Items over HTTP diff --git a/core/src/apiclient.cpp b/core/src/apiclient.cpp index b69f3b5..6ccb740 100644 --- a/core/src/apiclient.cpp +++ b/core/src/apiclient.cpp @@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include #include "JellyfinQt/dto/clientcapabilitiesdto.h" +#include "JellyfinQt/loader/http/quickconnect.h" #include "JellyfinQt/support/jsonconv.h" #include "JellyfinQt/viewmodel/settings.h" #include "JellyfinQt/websocket.h" @@ -428,6 +429,26 @@ void ApiClient::authenticate(QString username, QString password, bool storeCrede setDefaultErrorHandler(rep); } +void ApiClient::submitQuickConnectCode(const QString &code) { + using QQAuthorizeLoader = Loader::HTTP::AuthorizeLoader; + Loader::AuthorizeParams params; + params.setCode(code); + + QQAuthorizeLoader *loader = new QQAuthorizeLoader(this); + loader->setParameters(params); + loader->load(); + + loader->connect(loader, &QQAuthorizeLoader::error, this, [this, loader](QString message) { + qDebug() << "QQ error: " << message; + emit this->quickConnectRejected(); + loader->deleteLater(); + }); + loader->connect(loader, &QQAuthorizeLoader::ready, this, [this, loader]() { + emit this->quickConnectAccepted(); + loader->deleteLater(); + }); +} + void ApiClient::deleteSession() { QNetworkReply *rep = post("/Sessions/Logout"); connect(rep, &QNetworkReply::finished, this, [rep, this] { diff --git a/rpm/harbour-sailfin.changes b/rpm/harbour-sailfin.changes index a815143..cea75f9 100644 --- a/rpm/harbour-sailfin.changes +++ b/rpm/harbour-sailfin.changes @@ -16,6 +16,7 @@ - New features - Allow remote controlling other Jellyfin clients. See the pulley item on the main screen named "Remote Control" + - Let other devices log in using the Quick Connect feature of Jellyfin. - New layout for artist pages - New layout for the music library - New layout for playlist pages diff --git a/sailfish/CMakeLists.txt b/sailfish/CMakeLists.txt index 2b1b18d..b10a161 100644 --- a/sailfish/CMakeLists.txt +++ b/sailfish/CMakeLists.txt @@ -25,7 +25,7 @@ set(sailfin_QML_SOURCES qml/components/music/SongDelegate.qml qml/components/videoplayer/VideoError.qml qml/components/videoplayer/VideoHud.qml - qml/components/ContributorsSection.qml + qml/components/ContributorsSection.qml qml/components/IconListItem.qml qml/components/ItemChildrenShowcase.qml qml/components/JItem.qml @@ -49,6 +49,7 @@ set(sailfin_QML_SOURCES qml/harbour-sailfin.qml qml/pages/ConnectingPage.qml qml/pages/ControllableDevicesPage.qml + qml/pages/QuickConnectDialog.qml qml/pages/SettingsPage.qml qml/pages/VideoPage.qml qml/pages/itemdetails/BaseDetailPage.qml diff --git a/sailfish/qml/pages/QuickConnectDialog.qml b/sailfish/qml/pages/QuickConnectDialog.qml new file mode 100644 index 0000000..20ed45e --- /dev/null +++ b/sailfish/qml/pages/QuickConnectDialog.qml @@ -0,0 +1,86 @@ +import QtQuick 2.6 +import Sailfish.Silica 1.0 + +Dialog { + id: qqDialog + canAccept: qqCode.length > 0 + acceptDestination: ConnectingPage { + id: loadingPage + onStatusChanged: { + if (status == PageStatus.Active) { + submit() + } + } + + Connections { + target: apiClient + onQuickConnectAccepted: pageStack.pop(pageStack.previousPage(qqDialog)) + onQuickConnectRejected: { + qqCode.errorHighlight = true + pageStack.pop(qqDialog) + } + } + + function submit() { + console.log("Accepted QuickConnect with code", qqCode.text) + apiClient.submitQuickConnectCode(qqCode.text) + } + } + + Column { + width: parent.width + DialogHeader { + //: Dialog title + title: "Quick Connect" + //: Accept button on dialog for submitting a Quick Connect code + defaultAcceptText: qsTr("Allow login") + } + + + Label { + anchors { + left: parent.left + right: parent.right + leftMargin: Theme.horizontalPageMargin + rightMargin: Theme.horizontalPageMargin + } + color: Theme.highlightColor + wrapMode: Text.WordWrap + //: Instructions on page that tells the user a bit about how Quick Connect works + text: qsTr("To log a device in with Quick Connect, select the Quick Connect button and enter the displayed code in the field below.") + } + + TextField { + id: qqCode + //: Label for textfield for entering the Quick Connect codeyy + label: qsTr("Quick Connect code") + focus: true + //: Placeholder text for textfield for entering the Quick Connect codeyy + placeholderText: qsTr("Quick Connect code") + inputMethodHints: Qt.ImhDigitsOnly + EnterKey.iconSource: "image://theme/icon-m-enter-accept" + EnterKey.onClicked: accept() + onTextChanged: { + if (errorHighlight) { + errorHighlight = false + } + } + } + + Label { + id: errorText + visible: qqCode.errorHighlight + anchors { + left: parent.left + right: parent.right + leftMargin: Theme.horizontalPageMargin + rightMargin: Theme.horizontalPageMargin + } + color: Theme.errorColor + //: Error message shown below the textfield when it is not connected + text: qsTr("The Quick Connect code was not accepted") + } + } + + +} diff --git a/sailfish/qml/pages/SettingsPage.qml b/sailfish/qml/pages/SettingsPage.qml index a70449c..2596bac 100644 --- a/sailfish/qml/pages/SettingsPage.qml +++ b/sailfish/qml/pages/SettingsPage.qml @@ -106,6 +106,11 @@ Page { Item { width: 1; height: Theme.paddingLarge; } ButtonLayout { + Button { + //: This is a name used by Jellyfin and seems to be untranslated in other languages + text: qsTr("Quick Connect") + onClicked: pageStack.push(Qt.resolvedUrl("QuickConnectDialog.qml")) + } Button { text: qsTr("Log out") onClicked: remorse.execute(qsTr("Logging out"), apiClient.deleteSession) diff --git a/sailfish/translations/harbour-sailfin-de.ts b/sailfish/translations/harbour-sailfin-de.ts index 3cdf6c4..651becf 100644 --- a/sailfish/translations/harbour-sailfin-de.ts +++ b/sailfish/translations/harbour-sailfin-de.ts @@ -441,6 +441,31 @@ Page title for the list of all artists within the music library + + QuickConnectDialog + + Quick Connect code + Label for textfield for entering the Quick Connect codeyy +---------- +Placeholder text for textfield for entering the Quick Connect codeyy + + + + Allow login + Accept button on dialog for submitting a Quick Connect code + + + + To log a device in with Quick Connect, select the Quick Connect button and enter the displayed code in the field below. + Instructions on page that tells the user a bit about how Quick Connect works + + + + The Quick Connect code was not accepted + Error message shown below the textfield when it is not connected + + + SeasonPage @@ -507,6 +532,11 @@ Page title for the list of all artists within the music library About Sailfin settings menu itemy + + Quick Connect + This is a name used by Jellyfin and seems to be untranslated in other languages + + SongDelegate diff --git a/sailfish/translations/harbour-sailfin-ru.ts b/sailfish/translations/harbour-sailfin-ru.ts index 920ee83..51eaece 100644 --- a/sailfish/translations/harbour-sailfin-ru.ts +++ b/sailfish/translations/harbour-sailfin-ru.ts @@ -433,6 +433,31 @@ Page title for the list of all artists within the music library + + QuickConnectDialog + + Quick Connect code + Label for textfield for entering the Quick Connect codeyy +---------- +Placeholder text for textfield for entering the Quick Connect codeyy + + + + Allow login + Accept button on dialog for submitting a Quick Connect code + + + + To log a device in with Quick Connect, select the Quick Connect button and enter the displayed code in the field below. + Instructions on page that tells the user a bit about how Quick Connect works + + + + The Quick Connect code was not accepted + Error message shown below the textfield when it is not connected + + + SeasonPage @@ -488,6 +513,11 @@ Page title for the list of all artists within the music library Settings list item for settings related to streaming Настройки стриминга + + Quick Connect + This is a name used by Jellyfin and seems to be untranslated in other languages + + SongDelegate diff --git a/sailfish/translations/harbour-sailfin.ts b/sailfish/translations/harbour-sailfin.ts index 60d8f96..c9607ee 100644 --- a/sailfish/translations/harbour-sailfin.ts +++ b/sailfish/translations/harbour-sailfin.ts @@ -16,7 +16,12 @@ - <p><b>Sailfin version %1</b><br/>Copyright © Chris Josten 2020–%2</p><p>Sailfin is Free Software licensed under the <a href='lgpl'>LGPL-v2.1</a> or later, at your choice. Parts of the code of Sailfin are from other libraries. <a href='3rdparty'>View their licenses here</a>.</p> + <p><b>Sailfin version %1</b><br/>Copyright © Chris Josten 2020–%2</p><p>Sailfin is Free Software licensed under the <a href='lgpl'>LGPL-v2.1</a> or later, at your choice. You can <a href="github">view its source code on GitHub</a>. Parts of the code of Sailfin are from other libraries. <a href='3rdparty'>View their licenses here</a>.</p> + + + + Contributors + SectionHeader @@ -414,6 +419,31 @@ Page title for the list of all artists within the music library + + QuickConnectDialog + + Quick Connect code + Label for textfield for entering the Quick Connect codeyy +---------- +Placeholder text for textfield for entering the Quick Connect codeyy + + + + Allow login + Accept button on dialog for submitting a Quick Connect code + + + + To log a device in with Quick Connect, select the Quick Connect button and enter the displayed code in the field below. + Instructions on page that tells the user a bit about how Quick Connect works + + + + The Quick Connect code was not accepted + Error message shown below the textfield when it is not connected + + + SeasonPage @@ -445,7 +475,7 @@ Page title for the list of all artists within the music library About Sailfin About Sailfin settings menu itemy - About Sailfin1 + About Sailfin Session @@ -469,6 +499,11 @@ Page title for the list of all artists within the music library Debug information settings menu itemy + + Quick Connect + This is a name used by Jellyfin and seems to be untranslated in other languages + + SongDelegate