Add Qt6 desktop uploader
A native Qt6/C++ desktop client for the gallery's POST /upload API, in desktop/ with its own flake (kept separate from the Go server module the same way android/ is). Single-photo parity with the Android app: - multipart upload with preemptive HTTP Basic auth and retry-aware outcome classification (uploadclient) - JPEG/PNG metadata stripped byte-for-byte to drop embedded GPS, EXIF orientation baked in, and a quality/scale valve for the 20M nginx cap; HEIC decodes via the qtimageformats plugin (imageprep) - base URL / username in QSettings, password in the system keychain via qtkeychain; https required and a trailing /upload stripped (settings) - settings and post screens in a QStackedWidget (mainwindow) Native Wayland or xcb is selected at runtime. Bulk upload, EXIF capture-date prefill, and moving image prep off the UI thread are left as follow-ups.
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QSettings>
|
||||
#include <QString>
|
||||
|
||||
// Persists the non-secret settings (base URL, username, last post) in a
|
||||
// QSettings INI under ~/.config, and the password in the system keychain
|
||||
// (libsecret / kwallet via QtKeychain). The password never lands on disk in the
|
||||
// clear, mirroring the Android app's Keystore sealing.
|
||||
class Settings
|
||||
{
|
||||
public:
|
||||
struct LastPost {
|
||||
QString slug;
|
||||
QString url;
|
||||
QString caption;
|
||||
QDateTime postedAt;
|
||||
bool valid() const { return !slug.isEmpty(); }
|
||||
};
|
||||
|
||||
Settings();
|
||||
|
||||
QString baseUrl() const;
|
||||
void setBaseUrl(const QString &value);
|
||||
|
||||
QString username() const;
|
||||
void setUsername(const QString &value);
|
||||
|
||||
// Keychain access is synchronous here (a local event loop): the app does
|
||||
// nothing until the credential is in hand, and there is no background retry
|
||||
// worker as on Android that would need it off the UI thread.
|
||||
QString readPassword() const;
|
||||
void writePassword(const QString &value) const;
|
||||
|
||||
bool isConfigured() const;
|
||||
|
||||
LastPost lastPost() const;
|
||||
void setLastPost(const LastPost &value);
|
||||
|
||||
// Returns an error message, or an empty string when the URL is usable.
|
||||
// https is required: Basic auth would otherwise send the password in the
|
||||
// clear.
|
||||
static QString validateBaseUrl(const QString &raw);
|
||||
|
||||
// Trims trailing slashes and a trailing "/upload" (the endpoint path a user
|
||||
// pasting the upload URL would leave on — the client appends it itself).
|
||||
static QString normalizeBaseUrl(const QString &raw);
|
||||
|
||||
private:
|
||||
mutable QSettings m_settings;
|
||||
};
|
||||
Reference in New Issue
Block a user