Fetch server Apps in AccountState (moved from ownCloudGui)

- Add a new class AccountApp to keep them in an AccountAppList
  and also save properties like ID and Icon URL.

- Clear the app list upon re-fetch to avoid endlessly growing lists
  like in the previous implementation in ownCloudGui.

Signed-off-by: Michael Schuster <michael@schuster.ms>
This commit is contained in:
Michael Schuster 2020-01-15 16:23:46 +01:00
Родитель b57b8cfb66
Коммит cb328d6cea
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 00819E3BF4177B28
4 изменённых файлов: 137 добавлений и 106 удалений

Просмотреть файл

@ -20,6 +20,7 @@
#include "creds/httpcredentials.h"
#include "logger.h"
#include "configfile.h"
#include "ocsnavigationappsjob.h"
#include <QSettings>
#include <QTimer>
@ -27,6 +28,7 @@
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QNetworkRequest>
#include <QBuffer>
@ -259,6 +261,9 @@ void AccountState::checkConnectivity()
// Use a small authed propfind as a minimal ping when we're
// already connected.
conValidator->checkAuthentication();
// Get the Apps available on the server.
fetchNavigationApps();
} else {
// Check the server and then the auth.
@ -316,6 +321,9 @@ void AccountState::slotConnectionValidatorResult(ConnectionValidator::Status sta
if (_state != Connected) {
setState(Connected);
setTalkCapability();
// Get the Apps available on the server.
fetchNavigationApps();
}
break;
case ConnectionValidator::Undefined:
@ -428,4 +436,96 @@ std::unique_ptr<QSettings> AccountState::settings()
return s;
}
void AccountState::fetchNavigationApps(){
OcsNavigationAppsJob *job = new OcsNavigationAppsJob(_account);
job->addRawHeader("If-None-Match", navigationAppsEtagResponseHeader());
connect(job, &OcsNavigationAppsJob::appsJobFinished, this, &AccountState::slotNavigationAppsFetched);
connect(job, &OcsNavigationAppsJob::etagResponseHeaderReceived, this, &AccountState::slotEtagResponseHeaderReceived);
connect(job, &OcsNavigationAppsJob::ocsError, this, &AccountState::slotOcsError);
job->getNavigationApps();
}
void AccountState::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
if(statusCode == 200){
qCDebug(lcAccountState) << "New navigation apps ETag Response Header received " << value;
setNavigationAppsEtagResponseHeader(value);
}
}
void AccountState::slotOcsError(int statusCode, const QString &message)
{
qCDebug(lcAccountState) << "Error " << statusCode << " while fetching new navigation apps: " << message;
}
void AccountState::slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode)
{
if(_account){
if (statusCode == 304) {
qCWarning(lcAccountState) << "Status code " << statusCode << " Not Modified - No new navigation apps.";
} else {
_apps.clear();
_hasTalk = false;
if(!reply.isEmpty()){
printf("%s\n", reply.toJson().toStdString().c_str());
auto element = reply.object().value("ocs").toObject().value("data");
auto navLinks = element.toArray();
if(navLinks.size() > 0){
foreach (const QJsonValue &value, navLinks) {
auto navLink = value.toObject();
AccountApp *app = new AccountApp(navLink.value("name").toString(), QUrl(navLink.value("href").toString()),
navLink.value("id").toString(), QUrl(navLink.value("icon").toString()));
_apps << app;
}
}
}
emit hasFetchedNavigationApps();
}
}
}
AccountAppList AccountState::appList() const
{
return _apps;
}
/*-------------------------------------------------------------------------------------*/
AccountApp::AccountApp(const QString &name, const QUrl &url,
const QString &id, const QUrl &iconUrl,
QObject *parent)
: QObject(parent)
, _name(name)
, _url(url)
, _id(id)
, _iconUrl(iconUrl)
{
}
QString AccountApp::name() const
{
return _name;
}
QUrl AccountApp::url() const
{
return _url;
}
QString AccountApp::id() const
{
return _id;
}
QUrl AccountApp::iconUrl() const
{
return _iconUrl;
}
/*-------------------------------------------------------------------------------------*/
} // namespace OCC

Просмотреть файл

@ -29,9 +29,11 @@ namespace OCC {
class AccountState;
class Account;
class AccountApp;
class RemoteWipe;
typedef QExplicitlySharedDataPointer<AccountState> AccountStatePtr;
typedef QList<AccountApp*> AccountAppList;
/**
* @brief Extra info about an ownCloud server account.
@ -103,6 +105,8 @@ public:
bool hasTalk() const;
AccountAppList appList() const;
/** A user-triggered sign out which disconnects, stops syncs
* for the account and forgets the password. */
void signOutByUi();
@ -164,10 +168,12 @@ public slots:
private:
void setState(State state);
void setTalkCapability();
void fetchNavigationApps();
signals:
void stateChanged(int state);
void isConnectedChanged();
void hasFetchedNavigationApps();
protected Q_SLOTS:
void slotConnectionValidatorResult(ConnectionValidator::Status status, const QStringList &errors);
@ -179,6 +185,10 @@ protected Q_SLOTS:
void slotCredentialsFetched(AbstractCredentials *creds);
void slotCredentialsAsked(AbstractCredentials *creds);
void slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode);
void slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode);
void slotOcsError(int statusCode, const QString &message);
private:
AccountPtr _account;
State _state;
@ -209,7 +219,34 @@ private:
*/
RemoteWipe *_remoteWipe;
/**
* Holds the App names and URLs available on the server
*/
AccountAppList _apps;
};
class AccountApp : public QObject
{
Q_OBJECT
public:
AccountApp(const QString &name, const QUrl &url,
const QString &id, const QUrl &iconUrl,
QObject* parent = 0);
QString name() const;
QUrl url() const;
QString id() const;
QUrl iconUrl() const;
private:
QString _name;
QUrl _url;
QString _id;
QUrl _iconUrl;
};
}
Q_DECLARE_METATYPE(OCC::AccountState *)

Просмотреть файл

@ -14,7 +14,6 @@
#include "application.h"
#include "owncloudgui.h"
#include "ocsnavigationappsjob.h"
#include "theme.h"
#include "folderman.h"
#include "progressdispatcher.h"
@ -46,10 +45,6 @@
#include <QX11Info>
#endif
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QQmlEngine>
#include <QQmlComponent>
#include <QQmlApplicationEngine>
@ -68,7 +63,6 @@ ownCloudGui::ownCloudGui(Application *parent)
#ifdef WITH_LIBCLOUDPROVIDERS
, _bus(QDBusConnection::sessionBus())
#endif
, _recentActionsMenu(nullptr)
, _app(parent)
{
_tray = Systray::instance();
@ -369,7 +363,6 @@ void ownCloudGui::slotShowOptionalTrayMessage(const QString &title, const QStrin
slotShowTrayMessage(title, msg);
}
/*
* open the folder with the given Alias
*/
@ -393,93 +386,6 @@ void ownCloudGui::slotFolderOpenAction(const QString &alias)
}
}
void ownCloudGui::slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode){
if(statusCode == 200){
qCDebug(lcApplication) << "New navigation apps ETag Response Header received " << value;
auto account = qvariant_cast<AccountStatePtr>(sender()->property(propertyAccountC));
account->setNavigationAppsEtagResponseHeader(value);
}
}
void ownCloudGui::fetchNavigationApps(AccountStatePtr account){
OcsNavigationAppsJob *job = new OcsNavigationAppsJob(account->account());
job->setProperty(propertyAccountC, QVariant::fromValue(account));
job->addRawHeader("If-None-Match", account->navigationAppsEtagResponseHeader());
connect(job, &OcsNavigationAppsJob::appsJobFinished, this, &ownCloudGui::slotNavigationAppsFetched);
connect(job, &OcsNavigationAppsJob::etagResponseHeaderReceived, this, &ownCloudGui::slotEtagResponseHeaderReceived);
connect(job, &OcsNavigationAppsJob::ocsError, this, &ownCloudGui::slotOcsError);
job->getNavigationApps();
}
void ownCloudGui::buildNavigationAppsMenu(AccountStatePtr account, QMenu *accountMenu){
auto navLinks = _navApps.value(account);
_navLinksMenu->clear();
_navLinksMenu->setEnabled(navLinks.size() > 0);
if(navLinks.size() > 0){
// when there is only one account add the nav links above the settings
QAction *actionBefore = _actionSettings;
// when there is more than one account add the nav links above pause/unpause folder or logout action
if(AccountManager::instance()->accounts().size() > 1){
foreach(QAction *action, accountMenu->actions()){
// pause/unpause folder and logout actions have propertyAccountC
if(auto actionAccount = qvariant_cast<AccountStatePtr>(action->property(propertyAccountC))){
if(actionAccount == account){
actionBefore = action;
break;
}
}
}
}
// Create submenu with links
foreach (const QJsonValue &value, navLinks) {
auto navLink = value.toObject();
QAction *action = new QAction(navLink.value("name").toString(), this);
QUrl href(navLink.value("href").toString());
connect(action, &QAction::triggered, this, [href] { QDesktopServices::openUrl(href); });
_navLinksMenu->addAction(action);
}
}
}
void ownCloudGui::slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode)
{
if(auto account = qvariant_cast<AccountStatePtr>(sender()->property(propertyAccountC))){
if (statusCode == 304) {
qCWarning(lcApplication) << "Status code " << statusCode << " Not Modified - No new navigation apps.";
} else {
if(!reply.isEmpty()){
auto element = reply.object().value("ocs").toObject().value("data");
auto navLinks = element.toArray();
_navApps.insert(account, navLinks);
}
}
// TODO see pull #523
auto accountList = AccountManager::instance()->accounts();
if(accountList.size() > 1){
// the list of apps will be displayed under the account that it belongs to
foreach (QMenu *accountMenu, _accountMenus) {
if(accountMenu->title() == account->account()->displayName()){
buildNavigationAppsMenu(account, accountMenu);
break;
}
}
} else if(accountList.size() == 1){
//buildNavigationAppsMenu(account, _contextMenu.data());
}
}
}
void ownCloudGui::slotOcsError(int statusCode, const QString &message)
{
emit serverError(statusCode, message);
}
void ownCloudGui::slotUpdateProgress(const QString &folder, const ProgressInfo &progress)
{
Q_UNUSED(folder);

Просмотреть файл

@ -91,8 +91,6 @@ public slots:
void slotOpenPath(const QString &path);
void slotAccountStateChanged();
void slotTrayMessageIfServerUnsupported(Account *account);
void slotNavigationAppsFetched(const QJsonDocument &reply, int statusCode);
void slotEtagResponseHeaderReceived(const QByteArray &value, int statusCode);
/**
@ -106,9 +104,6 @@ public slots:
void slotRemoveDestroyedShareDialogs();
protected slots:
void slotOcsError(int statusCode, const QString &message);
private slots:
void slotLogin();
void slotLogout();
@ -118,8 +113,6 @@ private slots:
private:
void setPauseOnAllFoldersHelper(bool pause);
void fetchNavigationApps(AccountStatePtr account);
void buildNavigationAppsMenu(AccountStatePtr account, QMenu *accountMenu);
QPointer<Systray> _tray;
QPointer<SettingsDialog> _settingsDialog;
@ -129,8 +122,6 @@ private:
QDBusConnection _bus;
#endif
QMenu *_recentActionsMenu;
QVector<QMenu *> _accountMenus;
QMap<QString, QPointer<ShareDialog>> _shareDialogs;
QAction *_actionNewAccountWizard;
@ -138,9 +129,6 @@ private:
QAction *_actionEstimate;
QMenu *_navLinksMenu;
QMap<AccountStatePtr, QJsonArray> _navApps;
QList<QAction *> _recentItemsActions;
Application *_app;
};