Control: tags -1 patch

Please find a debdiff attached.
diff -Nru piperka-client-0.2.2/debian/changelog 
piperka-client-0.2.2/debian/changelog
--- piperka-client-0.2.2/debian/changelog       2019-05-20 21:50:39.000000000 
+0200
+++ piperka-client-0.2.2/debian/changelog       2026-04-06 11:34:53.000000000 
+0200
@@ -1,3 +1,10 @@
+piperka-client (0.2.2-1.1) unstable; urgency=medium
+
+  * Non-maintainer upload
+  * Update to Qt6 (Closes: #1132848)
+
+ -- Bastian Germann <[email protected]>  Mon, 06 Apr 2026 11:34:53 +0200
+
 piperka-client (0.2.2-1) unstable; urgency=medium
 
   * New upstream version 0.2.2
diff -Nru piperka-client-0.2.2/debian/control 
piperka-client-0.2.2/debian/control
--- piperka-client-0.2.2/debian/control 2019-05-20 21:04:47.000000000 +0200
+++ piperka-client-0.2.2/debian/control 2026-04-06 11:34:53.000000000 +0200
@@ -2,7 +2,7 @@
 Section: web
 Priority: optional
 Maintainer: Kari Pahula <[email protected]>
-Build-Depends: debhelper (>= 11), libqt5webview5-dev
+Build-Depends: debhelper (>= 11), qt6-webview-dev
 Standards-Version: 4.1.3
 Homepage: https://piperka.net/
 Vcs-Browser: https://gitlab.com/piperka/client
@@ -10,7 +10,7 @@
 
 Package: piperka-client
 Architecture: any
-Depends: ${shlibs:Depends}, ${misc:Depends}, qml-module-qtquick-controls, 
qml-module-qtquick-controls2, qml-module-qtwebview
+Depends: ${shlibs:Depends}, ${misc:Depends}, qml6-module-qtquick-controls, 
qml6-module-qtwebview
 Description: Mobile oriented web comics reader client
  Piperka is a web comic tracking and bookmarking service with over
  5000 comics listed on it.  It doesn't host any web comics by itself
diff -Nru piperka-client-0.2.2/debian/patches/Qt-6-compatibility.patch 
piperka-client-0.2.2/debian/patches/Qt-6-compatibility.patch
--- piperka-client-0.2.2/debian/patches/Qt-6-compatibility.patch        
1970-01-01 01:00:00.000000000 +0100
+++ piperka-client-0.2.2/debian/patches/Qt-6-compatibility.patch        
2026-04-06 11:34:53.000000000 +0200
@@ -0,0 +1,826 @@
+Origin: backport, 5ffcaf9fa2d3f2d755f4485b1e44b3c56c614837
+From: Kari Pahula <[email protected]>
+Date: Sat, 29 Oct 2022 13:09:03 +0300
+Subject: Qt 6 compatibility and port 0.3 changes to the generic version
+---
+diff --git a/generic/android/AndroidManifest.xml 
b/generic/android/AndroidManifest.xml
+index 2247897..d59c275 100644
+--- a/generic/android/AndroidManifest.xml
++++ b/generic/android/AndroidManifest.xml
+@@ -1,5 +1,5 @@
+ <?xml version="1.0"?>
+-<manifest package="net.piperka.client" 
xmlns:android="http://schemas.android.com/apk/res/android"; 
android:versionName="0.2.2" android:versionCode="2" 
android:installLocation="auto">
++<manifest package="net.piperka.client" 
xmlns:android="http://schemas.android.com/apk/res/android"; 
android:versionName="0.3.1" android:versionCode="3" 
android:installLocation="auto">
+     <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="28"/>
+ 
+     <!-- The following comment will be replaced upon deployment with default 
permissions based on the dependencies of the application.
+@@ -12,17 +12,15 @@
+ 
+     <supports-screens android:largeScreens="true" 
android:normalScreens="true" android:anyDensity="true" 
android:smallScreens="true"/>
+ 
+-    <application android:hardwareAccelerated="true" 
android:name="org.qtproject.qt5.android.bindings.QtApplication" 
android:label="Piperka Client" android:icon="@drawable/icon">
++    <application android:hardwareAccelerated="true" 
android:name="org.qtproject.qt5.android.bindings.QtApplication" 
android:label="Piperka Client" android:icon="@drawable/icon" 
android:usesCleartextTraffic="true">
+         <activity 
android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
 android:name="org.qtproject.qt5.android.bindings.QtActivity" 
android:label="Piperka Client" android:screenOrientation="unspecified" 
android:launchMode="singleTop">
+             <intent-filter>
+                 <action android:name="android.intent.action.MAIN"/>
+                 <category android:name="android.intent.category.LAUNCHER"/>
+             </intent-filter>
+-
+             <!-- Application arguments -->
+             <!-- meta-data android:name="android.app.arguments" 
android:value="arg1 arg2 arg3"/ -->
+             <!-- Application arguments -->
+-
+             <meta-data android:name="android.app.lib_name" android:value="-- 
%%INSERT_APP_LIB_NAME%% --"/>
+             <meta-data android:name="android.app.qt_sources_resource_id" 
android:resource="@array/qt_sources"/>
+             <meta-data android:name="android.app.repository" 
android:value="default"/>
+@@ -46,7 +44,6 @@
+             <meta-data android:value="@string/fatal_error_msg" 
android:name="android.app.fatal_error_msg"/>
+             <meta-data android:value="@string/unsupported_android_version" 
android:name="android.app.unsupported_android_version"/>
+             <!--  Messages maps -->
+-
+             <!-- Splash screen -->
+             <!-- Orientation-specific (portrait/landscape) data is checked 
first. If not available for current orientation,
+                  then android.app.splash_screen_drawable. For best results, 
use together with splash_screen_sticky and
+@@ -57,7 +54,6 @@
+             <!-- meta-data android:name="android.app.splash_screen_drawable" 
android:resource="@drawable/logo"/ -->
+             <!-- meta-data android:name="android.app.splash_screen_sticky" 
android:value="true"/ -->
+             <!-- Splash screen -->
+-
+             <!-- Background running -->
+             <!-- Warning: changing this value to true may cause unexpected 
crashes if the
+                           application still try to draw after
+@@ -65,11 +61,9 @@
+                           signal is sent! -->
+             <meta-data android:name="android.app.background_running" 
android:value="false"/>
+             <!-- Background running -->
+-
+             <!-- auto screen scale factor -->
+             <meta-data android:name="android.app.auto_screen_scale_factor" 
android:value="false"/>
+             <!-- auto screen scale factor -->
+-
+             <!-- extract android style -->
+             <!-- available android:values :
+                 * default - In most cases this will be the same as "full", 
but it can also be something else if needed, e.g., for compatibility reasons
+@@ -79,10 +73,8 @@
+                 -->
+             <meta-data android:name="android.app.extract_android_style" 
android:value="default"/>
+             <!-- extract android style -->
+-    </activity>
+-
+-    <!-- For adding service(s) please check: 
https://wiki.qt.io/AndroidServices -->
+-
++        </activity>
++        <!-- For adding service(s) please check: 
https://wiki.qt.io/AndroidServices -->
+     </application>
+ 
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+diff --git a/generic/isrgrootx1.pem b/generic/isrgrootx1.pem
+new file mode 120000
+index 0000000..b1c4d4c
+--- /dev/null
++++ b/generic/isrgrootx1.pem
+@@ -0,0 +1 @@
++../harbour/isrgrootx1.pem
+\ No newline at end of file
+diff --git a/generic/piperka-client.pro b/generic/piperka-client.pro
+index ad0844b..5b198cc 100644
+--- a/generic/piperka-client.pro
++++ b/generic/piperka-client.pro
+@@ -55,19 +57,36 @@ VERSION = $$system("grep -E '^\*' ../CHANGES | head -n 1 | 
sed -r 's/^.+ ([0-9.]
+ 
+ DEFINES += APP_VERSION=\\\"$$VERSION\\\" CLIENT_NAME=\\\"GenericPiperka\\\"
+ 
++RESOURCES += \
++    resources.qrc
++
+ QT += network qml quick webview
+ 
+ contains(ANDROID_TARGET_ARCH,armeabi-v7a) {
+     ANDROID_PACKAGE_SOURCE_DIR = \
+         $$PWD/android
++    ANDROID_EXTRA_LIBS= \
++        $$PWD/libs-arm/libcrypto_1_1.so \
++        $$PWD/libs-arm/libssl_1_1.so
+ }
+ 
+ contains(ANDROID_TARGET_ARCH,arm64-v8a) {
+     ANDROID_PACKAGE_SOURCE_DIR = \
+         $$PWD/android
++    ANDROID_EXTRA_LIBS= \
++        $$PWD/libs-arm64/libcrypto_1_1.so \
++        $$PWD/libs-arm64/libssl_1_1.so
+ }
+ 
+ contains(ANDROID_TARGET_ARCH,x86) {
+     ANDROID_PACKAGE_SOURCE_DIR = \
+         $$PWD/android
+ }
++
++contains(ANDROID_TARGET_ARCH,x86_64) {
++    ANDROID_PACKAGE_SOURCE_DIR = \
++        $$PWD/android
++    ANDROID_EXTRA_LIBS= \
++        $$PWD/libs-x86_64/libcrypto_1_1.so \
++        $$PWD/libs-x86_64/libssl_1_1.so
++}
+diff --git a/generic/qml/LoginPage.qml b/generic/qml/LoginPage.qml
+index d337cd3..6b1d1c6 100644
+--- a/generic/qml/LoginPage.qml
++++ b/generic/qml/LoginPage.qml
+@@ -17,7 +17,7 @@
+ ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ **************************************************************************/
+ 
+-import QtQuick 2.9
++import QtQuick 2.15
+ import QtQuick.Controls 2.4
+ 
+ Item {
+@@ -44,7 +44,7 @@ Item {
+                 id: back
+                 text: "<"
+                 onClicked: pageStack.pop()
+-                visible: platform.explicitBackButtons
++                visible: platform ? true : platform.explicitBackButtons
+             }
+ 
+             Text {
+@@ -59,8 +59,8 @@ Item {
+             width: parent.width
+             inputMethodHints: Qt.ImhNoAutoUppercase
+             placeholderText: qsTr("User name")
+-            text: user.storedLoginName
+-            validator: RegExpValidator { regExp: /.{2,}/ }
++            text: user ? user.storedLoginName : ""
++            validator: RegularExpressionValidator { regularExpression: 
/.{2,}/ }
+             onAccepted: passwordField.focus = true
+         }
+ 
+@@ -69,7 +69,7 @@ Item {
+             echoMode: TextInput.Password
+             width: parent.width
+             placeholderText: qsTr("Password")
+-            validator: RegExpValidator { regExp: /.{2,}/ }
++            validator: RegularExpressionValidator { regularExpression: 
/.{2,}/ }
+             onAccepted: dialog.login()
+         }
+ 
+@@ -77,18 +77,18 @@ Item {
+             id: rememberField
+             text: qsTr("Remember me")
+             width: parent.width
+-            checked: user.rememberMe
++            checked: user && user.rememberMe
+         }
+ 
+         CheckBox {
+             id: importBookmarks
+             width: parent.width
+             text: qsTr("Import bookmarks")
+-            visible: user.localBookmarks()
++            visible: user && user.localBookmarks()
+         }
+ 
+         Text {
+-            visible: user.localBookmarks()
++            visible: user && user.localBookmarks()
+             text: qsTr("Importing bookmarks will overwrite the ones on 
server. Not importing will discard local bookmarks.")
+         }
+ 
+diff --git a/generic/qml/MainPage.qml b/generic/qml/MainPage.qml
+index 838a423..4d36817 100644
+--- a/generic/qml/MainPage.qml
++++ b/generic/qml/MainPage.qml
+@@ -17,7 +17,7 @@
+ ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ **************************************************************************/
+ 
+-import QtQuick 2.9
++import QtQuick 2.15
+ import QtQuick.Controls 2.4
+ 
+ ApplicationWindow
+@@ -25,34 +25,36 @@ ApplicationWindow
+     id: appWindow
+     visible: true
+     title: "Piperka"
++    width: appWindow.width
++    height: appWindow.height
+ 
+     BusyIndicator {
+         id: busy
+         anchors.centerIn: parent
+-        running: user.loading || updatesModel.subscriptionFlag
++        running: !user || user.loading || !updatesModel || 
updatesModel.subscriptionFlag
+     }
+ 
+     Connections {
+         target: user
+ 
+-        onLoginFailed: {
++        function onLoginFailed() {
+             pageStack.push(Qt.resolvedUrl("LoginPage.qml"))
+         }
+ 
+-        onCreateAccountNameReserved: {
++        function onCreateAccountNameReserved() {
+             pageStack.push(Qt.resolvedUrl("NewAccountPage.qml"))
+         }
+ 
+-        onNetworkError: {
++        function onNetworkError() {
+             pageStack.push(Qt.resolvedUrl("NetworkErrorPage.qml"))
+         }
+ 
+-        onForceLogout: {
++        function onForceLogout() {
+             pageStack.push(Qt.resolvedUrl("ForceLogout.qml"))
+         }
+ 
+-        onSilentSyncFailureChanged: {
+-            syncFailedLabel.text = user.silentSyncFailure == 1 ?
++        function onSilentSyncFailureChanged() {
++            syncFailedLabel.text = user.silentSyncFailure === 1 ?
+                         qsTr("The last scheduled sync failed. The client will 
retry hourly.") :
+                         user.silentSyncFailure > 1 ?
+                             qsTr("Last %L1 scheduled syncs failed. The client 
will retry hourly.").arg(user.silentSyncFailure) : "";
+@@ -64,15 +66,18 @@ ApplicationWindow
+     StackView {
+         id: pageStack
+         initialItem: mainFlickable
++        anchors.fill: parent
+ 
+         focus: true
+         Keys.onBackPressed: pop()
+ 
+-        Flickable {
++        ListView {
+             id: mainFlickable
+             contentWidth: parent.width
+-            contentHeight: mainColumn.height
+-            Column {
++            //anchors.bottom: parent.bottom
++            contentHeight: appWindow.height
++            model: scheduleModel
++            header: Column {
+                 id: mainColumn
+                 width: appWindow.width
+                 spacing: 5
+@@ -83,7 +88,7 @@ ApplicationWindow
+                     anchors.right: parent.right
+                     Connections {
+                         target: user
+-                        onLoggedChange: {
++                        function onLoggedChange() {
+                             if (user.name) {
+                                 header.text = user.name + " — Piperka"
+                             } else {
+@@ -105,20 +110,20 @@ ApplicationWindow
+                     }
+ 
+                     Button {
+-                        visible: !user.logged
++                        visible: user && !user.logged
+                         id: loginButton
+                         text: qsTr("Login")
+                         onClicked: 
pageStack.push(Qt.resolvedUrl("LoginPage.qml"))
+                     }
+ 
+                     Button {
+-                        visible: !user.logged
++                        visible: user && !user.logged
+                         text: qsTr("Create account")
+                         onClicked: 
pageStack.push(Qt.resolvedUrl("NewAccountPage.qml"))
+                     }
+ 
+                     Button {
+-                        visible: user.logged
++                        visible: user && user.logged
+                         text: qsTr("Logout")
+                         onClicked: logoutPopup.open()
+                     }
+@@ -126,7 +131,7 @@ ApplicationWindow
+ 
+ 
+                 Button {
+-                    enabled: !user.loading
++                    enabled: user && !user.loading
+                     anchors {
+                         left: parent.left
+                         right: parent.right
+@@ -144,7 +149,7 @@ ApplicationWindow
+                         right: parent.right
+                     }
+ 
+-                    text: qsTr("Recommendations") + ((user.recSubscriptions 
&& user.logged) ? "" : " *")
++                    text: qsTr("Recommendations") + ((user && 
user.recSubscriptions && user.logged) ? "" : " *")
+                     onClicked: {
+                         if (user.recSubscriptions && user.logged)
+                             
pageStack.push(Qt.resolvedUrl("RecommendPage.qml"))
+@@ -154,21 +159,21 @@ ApplicationWindow
+                 }
+ 
+                 Button {
+-                    enabled: !updatesModel.noUnread && !user.loading
++                    enabled: updatesModel && !updatesModel.noUnread && 
!user.loading
+                     anchors {
+                         left: parent.left
+                         right: parent.right
+                     }
+ 
+                     text: qsTr("Updates")+
+-                          (!updatesModel.noUnread ?
++                          (updatesModel && !updatesModel.noUnread ?
+                                (" ("+updatesModel.unreadPages+" / 
"+updatesModel.rowCount()+")") : "")
+ 
+                     onClicked: 
pageStack.push(Qt.resolvedUrl("UpdatesPage.qml"))
+                 }
+ 
+                 Button {
+-                    enabled: !updatesModel.noUnread && !user.loading
++                    enabled: updatesModel && !updatesModel.noUnread && 
!user.loading
+                     anchors {
+                         left: parent.left
+                         right: parent.right
+@@ -180,6 +185,7 @@ ApplicationWindow
+                         pageModel.loadComic(updatesModel.firstCid());
+                         pageModel.autoBookmark = true;
+                         pageModel.autoSwitch = true;
++                        pageModel.quickLoad = true;
+                         pageStack.push(Qt.resolvedUrl("ReaderPage.qml"))
+                     }
+                 }
+@@ -187,10 +193,11 @@ ApplicationWindow
+                 Label {
+                     width: parent.width
+                     wrapMode: Text.WordWrap
+-                    text: user.noSubscriptions ?
++                    text: user && user.noSubscriptions ?
+                               qsTr("Select comics to read from the browse 
comics page.") :
+                               qsTr("You have no unread comics. Wait for 
updates or subscribe to more comics.")
+-                    visible: updatesModel.noUnread
++                    visible: updatesModel
++                             && updatesModel.noUnread
+                              && !updatesModel.subscriptionFlag
+                              && !user.loading
+                 }
+@@ -200,7 +207,45 @@ ApplicationWindow
+                     width: parent.width
+                     wrapMode: Text.WordWrap
+                     text: ""
+-                    visible: user.silentSyncFailure > 0
++                    visible: user && user.silentSyncFailure > 0
++                }
++
++                Item {
++                    height: 10
++                    width: parent.width
++                }
++
++                Label {
++                    id: scheduleLabel
++                    visible: scheduleModel && !scheduleModel.noSchedule
++                    width: parent.width
++                    x: 10
++                    text: qsTr("Expected updates")
++                    font.pixelSize: 15
++                }
++                Item {
++                    height: 5
++                    width: parent.width
++                }
++            }
++
++            delegate: Item {
++                visible: user.silentSyncFailure === 0
++                height: projected.height+10
++                Label {
++                    id: projected
++                    x: 5
++                    anchors.verticalCenter: parent.verticalCenter
++                    text: projected_update+"h"
++                }
++
++                Label {
++                    text: title
++                    anchors {
++                        left: projected.right
++                        leftMargin: 10
++                        verticalCenter: parent.verticalCenter
++                    }
+                 }
+             }
+         }
+@@ -270,9 +315,9 @@ ApplicationWindow
+             }
+ 
+             Button {
+-                text: user.syncAvailable ? qsTr("Synchronize now") : 
qsTr("Please wait")
++                text: user && user.syncAvailable ? qsTr("Synchronize now") : 
qsTr("Please wait")
+                 onClicked: user.syncNow(true);
+-                enabled: user.syncAvailable && !user.loading
++                enabled: user && user.syncAvailable && !user.loading
+             }
+         }
+     }
+diff --git a/generic/qml/NewAccountPage.qml b/generic/qml/NewAccountPage.qml
+index aeae745..1b76a7f 100644
+--- a/generic/qml/NewAccountPage.qml
++++ b/generic/qml/NewAccountPage.qml
+@@ -17,7 +17,7 @@
+ ** 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ **************************************************************************/
+ 
+-import QtQuick 2.9
++import QtQuick 2.15
+ import QtQuick.Controls 2.4
+ import net.piperka 0.1
+ 
+@@ -65,7 +65,7 @@ Item {
+             width: parent.width
+             inputMethodHints: Qt.ImhNoAutoUppercase
+             placeholderText: qsTr("User name")
+-            validator: RegExpValidator { regExp: /^.{2,}/ }
++            validator: RegularExpressionValidator { regularExpression: 
/.{2,}/ }
+             onAccepted: emailField.focus = true
+         }
+ 
+@@ -82,7 +82,7 @@ Item {
+             id: passwordField
+             width: parent.width
+             placeholderText: qsTr("Password")
+-            validator: RegExpValidator { regExp: /^.{4,}/ }
++            validator: RegularExpressionValidator { regularExpression: 
/.{4,}/ }
+             objectName: "newAccountPassword"
+             text: user.storedCreatePassword
+             onAccepted: passwordFieldAgain.focus = true
+diff --git a/generic/qml/PageDetailPage.qml b/generic/qml/PageDetailPage.qml
+index 09b9c67..642cfea 100644
+--- a/generic/qml/PageDetailPage.qml
++++ b/generic/qml/PageDetailPage.qml
+@@ -72,6 +72,16 @@ ListView {
+                 height: 5
+             }
+ 
++            Label {
++                width: parent.width
++                text: comicModel.getTitle(pageModel.cid)
++                anchors {
++                    left: parent.left
++                    leftMargin: 5
++                    right: parent.right
++                }
++            }
++
+             Row {
+                 width: parent.width
+                 spacing: 5
+@@ -195,9 +205,9 @@ ListView {
+                 text: qsTr("Set bookmark")
+                 onClicked: {
+                     if (currentMarker)
+-                        user.subscribe(pageModel.cid(), false);
++                        user.subscribe(pageModel.cid, false);
+                     else
+-                        user.subscribeAt(pageModel.cid(), ord);
++                        user.subscribeAt(pageModel.cid, ord);
+                 }
+             }
+         }
+diff --git a/generic/qml/ReaderPage.qml b/generic/qml/ReaderPage.qml
+index 51d10f6..3986b31 100644
+--- a/generic/qml/ReaderPage.qml
++++ b/generic/qml/ReaderPage.qml
+@@ -26,6 +26,7 @@ Item {
+     id: readerPage
+     width: appWindow.width
+     height: appWindow.height
++    property bool isReader: true
+ 
+     BusyIndicator {
+         anchors.centerIn: parent
+@@ -46,6 +47,16 @@ Item {
+         visible: !pageModel.allRead
+     }
+ 
++    Component.onCompleted: {
++        if (pageModel.quickLoad) {
++            titlePeekOpacity.start();
++            titlePeek.height = 10;
++
++            titlePeekHideTimer.restart();
++            pageModel.quickLoad = false;
++        }
++    }
++
+     Item {
+         id: naviRow
+         anchors {
+@@ -54,6 +65,82 @@ Item {
+             bottom: parent.bottom
+         }
+         height: prev.height
++        property bool pressing: false;
++        property int seenCid: -1;
++        property bool usedMark: false;
++        property bool loadingNext: false;
++
++        Connections {
++            target: user
++
++            function onLoadingChanged() {
++                if (!user.loading)
++                    naviRow.loadingNext = false;
++                }
++            }
++
++        Item {
++            id: titlePeek
++            anchors {
++                left: parent.left
++                right: next.left
++                bottom: parent.bottom
++                top: parent.top
++            }
++            opacity: 0
++
++            Label {
++                text: if (naviRow.pressing) {
++                          qsTr("Next")+": 
"+comicModel.getTitle(pageModel.getNextCid());
++                      } else if (naviRow.usedMark) {
++                          qsTr("Bookmark updated");
++                      } else {
++                          comicModel.getTitle(pageModel.cid);
++                      }
++
++                anchors {
++                    left: parent.left
++                    leftMargin: 5
++                    right: parent.right
++                    rightMargin: 5
++                    verticalCenter: parent.verticalCenter
++                }
++
++                elide: Text.ElideRight
++            }
++
++            NumberAnimation {
++                id: titlePeekOpacity
++                target: titlePeek
++                properties: "opacity"
++                from: 0
++                to: 1
++                duration: 500
++                easing.type: Easing.InOutQuad
++            }
++
++            NumberAnimation {
++                id: titlePeekOpacityHide
++                target: titlePeek
++                properties: "opacity"
++                from: 1
++                to: 0
++                duration: 500
++                easing.type: Easing.InOutQuad
++                onStopped: {
++                    naviRow.usedMark = false;
++                }
++            }
++
++            Timer {
++                id: titlePeekHideTimer
++                interval: 2500
++                onTriggered: {
++                    titlePeekOpacityHide.start();
++                }
++            }
++        }
++
+ 
+         Button {
+             anchors.left: parent.left
+@@ -61,14 +148,34 @@ Item {
+             text: "⇐"
+             enabled: !pageModel.allRead && pageModel.cursor.row > 0
+             onClicked: pageModel.setCursor(pageModel.cursor.row-1)
++            opacity: Math.pow(1-titlePeek.opacity, 4)
+         }
+ 
+         Button {
+             anchors.left: prev.right
++            id: mark
++            text: "🔖"
++            enabled: pageModel && pageModel.subscription.row === 
pageModel.cursor.row
++            visible: pageModel && pageModel.autoBookmark &&
++                     (pageModel.subscription.row === pageModel.cursor.row
++                      || naviRow.loadingNext && pageModel.subscription.row 
=== pageModel.cursor.row-1)
++            onClicked: {
++                naviRow.usedMark = true;
++                naviRow.loadingNext = false;
++                titlePeekOpacity.start();
++                titlePeekHideTimer.restart();
++                user.subscribeAt(pageModel.cid, pageModel.cursor.row+1)
++            }
++            opacity: Math.pow(1-titlePeek.opacity,4)
++        }
++
++        Button {
++            anchors.left: mark.right
+             id: back
+             text: "<"
+             onClicked: pageStack.pop()
+             visible: platform.explicitBackButtons
++            opacity: Math.pow(1-titlePeek.opacity,4)
+         }
+ 
+         Button {
+@@ -77,17 +184,19 @@ Item {
+                 right: next.left
+             }
+             id: options
+-            text: (1+pageModel.cursor.row) + "/" + (pageModel.rowCount-1)
+-            enabled: !pageModel.allRead
++            text: pageModel ? ((1+pageModel.cursor.row) + "/" + 
(pageModel.rowCount-1)) : "Loading"
++            enabled: pageModel && !pageModel.allRead
++            opacity: Math.pow(1-titlePeek.opacity, 4)
+             onClicked: pageStack.push(Qt.resolvedUrl("PageDetailPage.qml"))
+         }
+ 
+         Button {
+             anchors.right: parent.right
+             id: next
+-            text: pageModel.nextIsSwitch ? "↵" : "⇒"
+-            enabled: pageModel.haveNext
++            text: pageModel && pageModel.nextIsSwitch ? "↵" : "⇒"
++            enabled: pageModel && pageModel.haveNext
+             onClicked: {
++                naviRow.usedMark = false;
+                 if (pageModel.nextIsSwitch) {
+                     if (!pageModel.switchNext()) {
+                         var depth = pageStack.depth
+@@ -96,9 +205,33 @@ Item {
+                             pageStack.pop(StackView.Immediate)
+                         }
+                         pageStack.push(Qt.resolvedUrl("AllReadPage.qml"), 
StackView.Immediate);
++                    } else if (naviRow.seenCid !== pageModel.cid) {
++                        titlePeekOpacity.start();
++                        titlePeekHideTimer.restart();
+                     }
+-                } else
++                } else {
++                    if (pageModel.autoBookmark)
++                        naviRow.loadingNext = true;
+                     pageModel.setCursorNext()
++                }
++            }
++
++            onPressAndHold: {
++                if (pageModel.nextIsSwitch) {
++                    titlePeekHideTimer.stop();
++                    titlePeekOpacity.start();
++                    titlePeek.height = 10;
++                    naviRow.pressing = true;
++                    naviRow.seenCid = pageModel.getNextCid()
++                }
++            }
++            onReleased: {
++                if (naviRow.pressing) {
++                    naviRow.pressing = false;
++                    titlePeekOpacity.stop();
++                    titlePeek.opacity = 0;
++                    titlePeek.height = 0;
++                }
+             }
+         }
+     }
+diff --git a/generic/qml/UpdatesPage.qml b/generic/qml/UpdatesPage.qml
+index 86572ce..491aa72 100644
+--- a/generic/qml/UpdatesPage.qml
++++ b/generic/qml/UpdatesPage.qml
+@@ -53,13 +53,13 @@ ListView {
+                 id: back
+                 text: "<"
+                 onClicked: pageStack.pop()
+-                visible: platform.explicitBackButtons
++                visible: !platform || platform.explicitBackButtons
+             }
+ 
+             CheckBox {
+                 id: offsetBack
+                 text: qsTr("Offset back by one")
+-                checked: user.offsetBack
++                checked: user && user.offsetBack
+                 onClicked: user.offsetBack = offsetBack.checked
+             }
+ 
+@@ -81,7 +81,7 @@ ListView {
+                         left: label.right
+                         right: parent.right
+                     }
+-                    currentIndex: updatesModel.sortType
++                    currentIndex: updatesModel ? updatesModel.sortType : 1
+                     model: ListModel {
+                         ListElement {
+                             text: qsTr("Least new pages first")
+@@ -94,7 +94,8 @@ ListView {
+                         }
+                     }
+                     onCurrentIndexChanged: {
+-                        updatesModel.sortType = sortType.currentIndex
++                        if (updatesModel)
++                            updatesModel.sortType = sortType.currentIndex;
+                     }
+                 }
+             }
+diff --git a/generic/resources.qrc b/generic/resources.qrc
+new file mode 120000
+index 0000000..2e9e7aa
+--- /dev/null
++++ b/generic/resources.qrc
+@@ -0,0 +1 @@
++../harbour/resources.qrc
+\ No newline at end of file
+diff --git a/generic/src/piperka-client.cpp b/generic/src/piperka-client.cpp
+index f2139b7..09ea7f0 100644
+--- a/generic/src/piperka-client.cpp
++++ b/generic/src/piperka-client.cpp
+@@ -20,6 +20,7 @@
+ #include <QtGui/QGuiApplication>
+ #include <QtQml/QQmlContext>
+ #include <QtQuick/QQuickView>
++#include <QtWebView/QtWebView>
+ #include <QCommandLineParser>
+ #include <QQmlApplicationEngine>
+ 
+@@ -30,7 +31,7 @@ int main(int argc, char *argv[])
+ {
+     QCoreApplication::setOrganizationName("piperka.net");
+     QCoreApplication::setApplicationName("piperka-client");
+-    QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
++    QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
+     QGuiApplication app(argc, argv);
+     QCoreApplication::setApplicationName("piperka-client");
+     QCoreApplication::setApplicationVersion(APP_VERSION);
+diff --git a/src/updates.cpp b/src/updates.cpp
+index 7355e52..0567538 100644
+--- a/src/updates.cpp
++++ b/src/updates.cpp
+@@ -128,7 +128,7 @@ bool UpdatesModel::filterAcceptsRow(int sourceRow, const 
QModelIndex &sourcePare
+ {
+     QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
+     QVariant unread = sourceModel()->data(index, ComicModel::UnreadCountRole);
+-    return unread.isValid() && unread > 0;
++    return unread.isValid() && unread.toInt() > 0;
+ }
+ 
+ bool UpdatesModel::lessThan(const QModelIndex &source_left, const QModelIndex 
&source_right) const
+diff --git a/src/user.cpp b/src/user.cpp
+index 228c8a5..4ff101f 100644
+--- a/src/user.cpp
++++ b/src/user.cpp
+@@ -266,7 +266,7 @@ void User::resetStoredAccountDetails()
+ 
+ void User::syncNow(bool interactive)
+ {
+-    lastSync.start();
++    lastSync = QTime::currentTime();
+     if (interactive && m_syncAvailable) {
+         m_syncAvailable = false;
+         syncAvailableTimer.start(interactiveSyncInterval);
+@@ -286,7 +286,7 @@ void User::syncNow(bool interactive)
+ 
+ void User::unlockSync()
+ {
+-    if (lastSync.elapsed() > unlockSyncInterval)
++    if (QTime::currentTime().msecsTo(lastSync) > unlockSyncInterval)
+         syncNow(false);
+ }
+ 
+diff --git a/src/download.cpp b/src/download.cpp
+index 086eeb5..68075ab 100644
+--- a/src/download.cpp
++++ b/src/download.cpp
+@@ -46,11 +46,11 @@ void addBookmarksToPostData(QByteArray &postData, const 
QMap<int, int> &bm)
+     for (QMap<int, int>::const_iterator iter = bm.cbegin(); iter != 
bm.cend(); ++iter) {
+         postData.append("&bm=");
+         if (iter.value() == -1)
+-            postData.append(QString::number(iter.key()));
++            postData.append(QString::number(iter.key()).toLatin1());
+         else
+-            postData.append(QString::number(iter.key()))
++            postData.append(QString::number(iter.key()).toLatin1())
+                     .append('+')
+-                    .append(QString::number(iter.value()));
++                    .append(QString::number(iter.value()).toLatin1());
+     }
+ 
+ }
+@@ -65,7 +65,7 @@ Download::Download(QObject *parent)
+ #endif
+     userAgent
+             .append(" (")
+-            .append(QSysInfo::prettyProductName())
++            .append(QSysInfo::prettyProductName().toUtf8())
+             .append(")");
+ }
+ 
diff -Nru piperka-client-0.2.2/debian/patches/qt6.patch 
piperka-client-0.2.2/debian/patches/qt6.patch
--- piperka-client-0.2.2/debian/patches/qt6.patch       1970-01-01 
01:00:00.000000000 +0100
+++ piperka-client-0.2.2/debian/patches/qt6.patch       2026-04-06 
11:34:53.000000000 +0200
@@ -0,0 +1,169 @@
+Origin: https://gitlab.com/piperka/client/-/merge_requests/3
+From: Bastian Germann <[email protected]>
+Date: Mon, 6 Apr 2026 11:31:36 +0200
+Subject: Port project to Qt6 across generic and Sailfish targets
+
+- migrate Sailfish packaging metadata from Qt5 to Qt6
+  (qtc6 builder, Qt6Core/Qml/Quick, sailfishsilica-qt6)
+- update spec macros/install steps to qmake6 equivalents
+- switch Harbour reader page from QtWebKit/SilicaWebView to QtWebView
+- add Qt module declarations for harbour build (including webview)
+- make optional android OpenSSL .pri include conditional in generic .pro
+- replace deprecated foreach usage with range-based for loops in C++
+---
+diff --git a/harbour/qml/pages/ReaderPage.qml 
b/harbour/qml/pages/ReaderPage.qml
+index 52aa74f..866e3db 100644
+--- a/harbour/qml/pages/ReaderPage.qml
++++ b/harbour/qml/pages/ReaderPage.qml
+@@ -18,7 +18,7 @@
+ 
+ import QtQuick 2.2
+ import Sailfish.Silica 1.0
+-import QtWebKit 3.0
++import QtWebView 1.1
+ 
+ Page {
+     id: readerPage
+@@ -31,7 +31,7 @@ Page {
+         running: user.loading
+     }
+ 
+-    SilicaWebView {
++    WebView {
+         id: webView
+ 
+         anchors {
+diff --git a/harbour/rpm/harbour-piperka.spec 
b/harbour/rpm/harbour-piperka.spec
+index 4d4b71c..f6a4f1e 100644
+--- a/harbour/rpm/harbour-piperka.spec
++++ b/harbour/rpm/harbour-piperka.spec
+@@ -9,7 +9,7 @@ Name:       harbour-piperka
+ # << macros
+ 
+ %{!?qtc_qmake:%define qtc_qmake %qmake}
+-%{!?qtc_qmake5:%define qtc_qmake5 %qmake5}
++%{!?qtc_qmake6:%define qtc_qmake6 %qmake6}
+ %{!?qtc_make:%define qtc_make make}
+ %{?qtc_builddir:%define _builddir %qtc_builddir}
+ Summary:    Piperka Client
+@@ -20,11 +20,11 @@ License:    LICENSE
+ URL:        https://piperka.net/
+ Source0:    %{name}-%{version}.tar.bz2
+ Source100:  harbour-piperka.yaml
+-Requires:   sailfishsilica-qt5 >= 0.10.9
++Requires:   sailfishsilica-qt6 >= 0.10.9
+ BuildRequires:  pkgconfig(sailfishapp) >= 1.0.2
+-BuildRequires:  pkgconfig(Qt5Core)
+-BuildRequires:  pkgconfig(Qt5Qml)
+-BuildRequires:  pkgconfig(Qt5Quick)
++BuildRequires:  pkgconfig(Qt6Core)
++BuildRequires:  pkgconfig(Qt6Qml)
++BuildRequires:  pkgconfig(Qt6Quick)
+ BuildRequires:  desktop-file-utils
+ 
+ %description
+@@ -41,7 +41,7 @@ Piperka Client app — Read web comics and follow their updates
+ # >> build pre
+ # << build pre
+ 
+-%qtc_qmake5  \
++%qtc_qmake6  \
+     VERSION=%{version} \
+     RELEASE=%{release}
+ 
+@@ -54,7 +54,7 @@ Piperka Client app — Read web comics and follow their updates
+ rm -rf %{buildroot}
+ # >> install pre
+ # << install pre
+-%qmake5_install
++%qmake6_install
+ 
+ # >> install post
+ # << install post
+diff --git a/harbour/rpm/harbour-piperka.yaml 
b/harbour/rpm/harbour-piperka.yaml
+index 0e0a551..d3ee531 100644
+--- a/harbour/rpm/harbour-piperka.yaml
++++ b/harbour/rpm/harbour-piperka.yaml
+@@ -14,9 +14,9 @@ Sources:
+ Description: |
+   Piperka Client app — Read web comics and follow their updates
+ Configure: none
+-# The qtc5 builder inserts macros to allow QtCreator to have fine
++# The qtc6 builder inserts macros to allow QtCreator to have fine
+ # control over qmake/make execution
+-Builder: qtc5
++Builder: qtc6
+ QMakeOptions:
+ - VERSION=%{version}
+ - RELEASE=%{release}
+@@ -25,9 +25,9 @@ QMakeOptions:
+ # This is the preferred way of specifying build dependencies for your package.
+ PkgConfigBR:
+   - sailfishapp >= 1.0.2
+-  - Qt5Core
+-  - Qt5Qml
+-  - Qt5Quick
++  - Qt6Core
++  - Qt6Qml
++  - Qt6Quick
+ 
+ # Build dependencies without a pkgconfig setup can be listed here
+ # PkgBR:
+@@ -35,7 +35,7 @@ PkgConfigBR:
+ 
+ # Runtime dependencies which are not automatically detected
+ Requires:
+-  - sailfishsilica-qt5 >= 0.10.9 
++  - sailfishsilica-qt6 >= 0.10.9
+ 
+ # All installed files
+ Files:
+diff --git a/src/comic.cpp b/src/comic.cpp
+index 1637549..89fe8f6 100644
+--- a/src/comic.cpp
++++ b/src/comic.cpp
+@@ -162,11 +162,11 @@ void ComicModel::finishComicsListSync()
+ {
+     if (!loadPending && !syncPending) {
+         if (toAdd.empty()) {
+-            foreach(QPointer<Subscription> subs, 
pendingSubscriptions.values()) {
++            for (const QPointer<Subscription> &subs : 
pendingSubscriptions.values()) {
+                 setSubscription(subs);
+             }
+         } else {
+-            foreach(QPointer<Subscription> subs, pendingSubscriptionRefresh) {
++            for (const QPointer<Subscription> &subs : 
pendingSubscriptionRefresh) {
+                 pendingSubscriptions.insert(subs->cid(), subs);
+             }
+ 
+diff --git a/src/user.cpp b/src/user.cpp
+index 4aa22f4..7ce8f5c 100644
+--- a/src/user.cpp
++++ b/src/user.cpp
+@@ -440,7 +440,7 @@ void User::deleteSubscriptions()
+ {
+     subs_set.clear();
+     QList<Subscription *> subs = findChildren<Subscription *>();
+-    foreach(Subscription *sub, subs) {
++    for (Subscription *sub : subs) {
+         emit sub->unsubscribing();
+         sub->deleteLater();
+     }
+@@ -494,7 +494,7 @@ void User::fetchSubscriptions()
+         if (reply->error() != QNetworkReply::NoError) {
+             // Emit all old subscriptions for comic model
+             QList<Subscription *> subs = findChildren<Subscription *>();
+-            foreach(Subscription *sub, subs) {
++            for (Subscription *sub : subs) {
+                 emit refreshSubscription(QPointer<Subscription>(sub));
+             }
+             emit fetchSubscriptionsEnd();
+@@ -528,7 +528,7 @@ void User::fetchSubscriptions()
+                 addSubscription(array);
+             }
+         }
+-        foreach(int cid, oldSubsCids) {
++        for (int cid : oldSubsCids) {
+             Subscription *subs = subs_set.take(cid);
+             if (subs) {
+                 emit subs->unsubscribing();
diff -Nru piperka-client-0.2.2/debian/patches/series 
piperka-client-0.2.2/debian/patches/series
--- piperka-client-0.2.2/debian/patches/series  1970-01-01 01:00:00.000000000 
+0100
+++ piperka-client-0.2.2/debian/patches/series  2026-04-06 11:34:53.000000000 
+0200
@@ -0,0 +1,2 @@
+Qt-6-compatibility.patch
+qt6.patch
diff -Nru piperka-client-0.2.2/debian/rules piperka-client-0.2.2/debian/rules
--- piperka-client-0.2.2/debian/rules   2019-05-20 21:18:14.000000000 +0200
+++ piperka-client-0.2.2/debian/rules   2026-04-06 11:34:53.000000000 +0200
@@ -1,9 +1,9 @@
 #!/usr/bin/make -f
 
-export QT_SELECT=qt5
+export QT_SELECT=qt6
 
 %:
-       dh $@ --buildsystem=qmake --sourcedirectory=generic
+       dh $@ --buildsystem=qmake6 --sourcedirectory=generic
 
 override_dh_install:
        dh_install

Reply via email to