#pragma once #include #include class QNetworkAccessManager; // Talks to the gallery's POST /upload endpoint, which sits behind nginx HTTP // Basic auth. The credentials go out preemptively in the Authorization header // on every request (never via QNetworkAccessManager's authenticationRequired // signal, which only fires on a 401 and would replay a multipart body already // streamed off disk). // // Asynchronous: results arrive via signals so the UI stays responsive during an // upload over a slow link. class UploadClient : public QObject { Q_OBJECT public: enum class Result { Success, // uploaded; slug/url populated AuthFailed, // wrong credentials — a retry will not help Rejected, // server said no for a reason a retry won't change Transient, // network trouble or a 5xx — worth retrying }; UploadClient(QString baseUrl, QString username, QString password, QObject *parent = nullptr); // The filename matters: server.go derives the slug from it, so re-sending // the same name overwrites the same post instead of duplicating it. void upload(const QString &filePath, const QString &fileName, const QString &caption, const QString &date); // Credential check via GET /upload (same Basic-auth gate the POST uses). // /health is not usable: nginx only proxies location /upload. void testConnection(); signals: void uploadFinished(UploadClient::Result result, const QString &slug, const QString &url, const QString &message); // errorMessage is empty on success. void testFinished(const QString &errorMessage); private: QByteArray authHeader() const; QString m_base; QString m_username; QString m_password; QNetworkAccessManager *m_net; };