feat(search): revive unified search - #10639
Conversation
|
@kra-mo as discussed |
kra-mo
left a comment
There was a problem hiding this comment.
Since this is already a fixed-height dialog, there is no reason to show a filter button in the initial state. Instead, the filters should just always be visible.
There should also be some indication that a search is happening through a circular progress indicator like on the web. Right now, the search button seems to disappear while you're searching?
And are you struggling to click some of the buttons in the screen recording? I guess that is known, then :)
Alternatively, we could make it variable-height, like Spotlight, which might also be nice. |
Hi, |
Yes, instead of having a funnel button.
Sure, makes sense |
|
@kra-mo should be fine now Bildschirmaufnahme.2026-08-22.um.16.11.20.mov |
69c9e0a to
5cfeaea
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5cfeaeaac6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| else if (event.key === Qt.Key_Home) moveSelection(UnifiedSearchResultsListModel.First) | ||
| else if (event.key === Qt.Key_End) moveSelection(UnifiedSearchResultsListModel.Last) |
There was a problem hiding this comment.
Preserve Home and End for editing the query
When the search field contains text, these handlers consume every Home/End key press (including Shift+Home/End) and mark the event accepted, so users can no longer move or extend the text cursor to the beginning or end of the query. Reserve these shortcuts for result navigation only under an explicit modifier or when focus is in the results list.
Useful? React with 👍 / 👎.
860dcd2 to
7920816
Compare
Ah. I think it tries to put the progress indicator where the search icon is. |
kra-mo
left a comment
There was a problem hiding this comment.
Sure. It's an improvement over what there is atm.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 08df11544b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| auto *const job = new JsonApiJob(account, QStringLiteral("ocs/v2.php/apps/files_sharing/api/v1/sharees")); | ||
| QUrlQuery query; | ||
| query.addQueryItem(QStringLiteral("search"), _searchTerm); | ||
| query.addQueryItem(QStringLiteral("shareType"), QStringLiteral("0")); |
There was a problem hiding this comment.
Send itemType with people lookups
For every non-empty People query, this bypasses the repository's OcsShareeJob::getSharees contract and omits the itemType parameter that the existing wrapper always adds and ShareeModel::fetch() supplies as either file or folder. Servers that enforce that Sharee API parameter will reject the request, leaving the new People picker in its error state; add an appropriate itemType and make the fake endpoint test reject requests that omit it so the real failure path is covered.
AGENTS.md reference: AGENTS.md:L33-L35
Useful? React with 👍 / 👎.
|
@copilot resolve the merge conflicts in this pull request |
Modernize the account-scoped search window with provider, date, and people filters, connected-service results, and aggregate and provider detail views. Introduce cancellable per-provider search state, stable reveal ordering, stale-response protection, pagination, scoped retries, and persistent keyboard selection. Align the search UI with shared wizard styling and add coverage for the search models, QML behavior, people lookup, and image handling. Signed-off-by: Rello <github@scherello.de> Assisted-by: Codex:GPT-5
Assisted-by: Codex:GPT-5 Signed-off-by: Rello <github@scherello.de>
Show the loading indicator on the trailing side of the search field without replacing the permanent search icon. Signed-off-by: Rello <github@scherello.de> Assisted-by: Codex:GPT-5
5d490ea to
ba58f8b
Compare
|
|
||
| QVariant UnifiedSearchPeopleModel::data(const QModelIndex &index, int role) const | ||
| { | ||
| if (!checkIndex(index, CheckIndexOption::IndexIsValid)) return {}; |
There was a problem hiding this comment.
| if (!checkIndex(index, CheckIndexOption::IndexIsValid)) return {}; | |
| Q_ASSERT(!checkIndex(index, CheckIndexOption::IndexIsValid)); |
| if (_job) { | ||
| disconnect(_job, nullptr, this, nullptr); | ||
| if (const auto job = qobject_cast<JsonApiJob *>(_job.data()); job && job->reply() && job->reply()->isRunning()) job->reply()->abort(); | ||
| _job->deleteLater(); |
There was a problem hiding this comment.
I would assume the job to delete itself
I think this is not crashing because:
- the job had time to delete itself and the QPointer would have been null
- the job is still valid and 2 calls to deleteLater are not causing 2 deletions
| [[nodiscard]] QString searchTerm() const; | ||
| [[nodiscard]] bool busy() const; | ||
| [[nodiscard]] QString errorString() const; | ||
| Q_INVOKABLE void retry(); |
| explicit UnifiedSearchResultsListModel(AccountState *accountState, | ||
| QObject *parent = nullptr, | ||
| int debounceInterval = 300, | ||
| int revealInterval = 1000); |
There was a problem hiding this comment.
usually we keep QObject *parent parameter the last one
that is a convention to follow
| explicit UnifiedSearchResultsListModel(AccountState *accountState, | |
| QObject *parent = nullptr, | |
| int debounceInterval = 300, | |
| int revealInterval = 1000); | |
| explicit UnifiedSearchResultsListModel(AccountState *accountState, | |
| int debounceInterval = 300, | |
| int revealInterval = 1000, | |
| QObject *parent = nullptr); |
| if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { | ||
| return {}; | ||
| } |
There was a problem hiding this comment.
| if (!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)) { | |
| return {}; | |
| } | |
| Q_ASSERT(!checkIndex(index, QAbstractItemModel::CheckIndexOption::IndexIsValid)); |
| if (const auto job = qobject_cast<JsonApiJob *>(jobObject.data()); job && job->reply() && job->reply()->isRunning()) { | ||
| job->reply()->abort(); | ||
| } | ||
| jobObject->deleteLater(); |
There was a problem hiding this comment.
msut be removed
our jobs self delete when they are finished
| if (const auto job = qobject_cast<JsonApiJob *>(_providerDiscoveryJob.data()); job && job->reply() && job->reply()->isRunning()) { | ||
| job->reply()->abort(); | ||
| } | ||
| _providerDiscoveryJob->deleteLater(); |
There was a problem hiding this comment.
must be removed
our JsonApiJob class will delete itself
| import QtQuick | ||
| import QtQuick.Controls.Basic as BasicControls | ||
| import QtQuick.Layouts | ||
| import Qt5Compat.GraphicalEffects |
There was a problem hiding this comment.
should not be used as this is deprecated and only provided for porting apps from Qt5 to Qt6
| import QtQuick.Controls | ||
| import QtQuick.Controls.Basic as BasicControls | ||
| import QtQuick.Layouts | ||
| import Qt5Compat.GraphicalEffects |
There was a problem hiding this comment.
should not be used as this is deprecated and only provided for porting apps from Qt5 to Qt6
|
|
Artifact containing the AppImage: nextcloud-appimage-pr-10639.zip Digest: To test this change/fix you can download the above artifact file, unzip it, and run it. Please make sure to quit your existing Nextcloud app and backup your data. |





Server Reference: nextcloud/server#60241
Assisted-by: Codex:GPT-5
Bildschirmaufnahme.2026-08-21.um.11.22.02.mov