@@ -66,11 +66,17 @@ public function getOrder(string $route, array $routeParameters): ?int {
66
66
}
67
67
68
68
/**
69
+ * Search for user's conversations
70
+ *
71
+ * Cursor is the conversation token
72
+ * Results are sorted by display name and then conversation token
73
+ *
69
74
* @inheritDoc
70
75
*/
71
76
public function search (IUser $ user , ISearchQuery $ query ): SearchResult {
72
77
$ rooms = $ this ->manager ->getRoomsForUser ($ user ->getUID ());
73
78
79
+ $ cursorKey = null ;
74
80
$ result = [];
75
81
foreach ($ rooms as $ room ) {
76
82
if ($ room ->getType () === Room::TYPE_CHANGELOG ) {
@@ -82,18 +88,19 @@ public function search(IUser $user, ISearchQuery $query): SearchResult {
82
88
$ parameters ['token ' ] === $ room ->getToken () &&
83
89
str_starts_with ($ query ->getRoute (), Application::APP_ID . '. ' )) {
84
90
// Don't search the current conversation.
85
- //User most likely looks for other things with the same name
91
+ // User most likely looks for other things with the same name
86
92
continue ;
87
93
}
88
94
95
+ $ displayName = $ room ->getDisplayName ($ user ->getUID ());
89
96
if ($ room ->getType () === Room::TYPE_ONE_TO_ONE || $ room ->getType () === Room::TYPE_ONE_TO_ONE_FORMER ) {
90
97
$ otherUserId = str_replace (
91
98
json_encode ($ user ->getUID ()),
92
99
'' ,
93
100
$ room ->getName ()
94
101
);
95
102
if (stripos ($ otherUserId , $ query ->getTerm ()) === false
96
- && stripos ($ room -> getDisplayName ( $ user -> getUID ()) , $ query ->getTerm ()) === false ) {
103
+ && stripos ($ displayName , $ query ->getTerm ()) === false ) {
97
104
// Neither name nor displayname (one-to-one) match, skip
98
105
continue ;
99
106
}
@@ -103,7 +110,7 @@ public function search(IUser $user, ISearchQuery $query): SearchResult {
103
110
104
111
$ entry = new SearchResultEntry (
105
112
$ this ->avatarService ->getAvatarUrl ($ room ),
106
- $ room -> getDisplayName ( $ user -> getUID ()) ,
113
+ $ displayName ,
107
114
'' ,
108
115
$ this ->url ->linkToRouteAbsolute ('spreed.Page.showCall ' , ['token ' => $ room ->getToken ()]),
109
116
'' ,
@@ -112,12 +119,62 @@ public function search(IUser $user, ISearchQuery $query): SearchResult {
112
119
113
120
$ entry ->addAttribute ('conversation ' , $ room ->getToken ());
114
121
115
- $ result [] = $ entry ;
122
+ $ result [strtolower ($ displayName . '# ' . $ room ->getToken ())] = $ entry ;
123
+
124
+ if ($ query ->getCursor () === $ room ->getToken ()) {
125
+ $ cursorKey = strtolower ($ displayName . '# ' . $ room ->getToken ());
126
+ }
127
+ }
128
+
129
+ if (count ($ result ) <= $ query ->getLimit ()) {
130
+ return SearchResult::complete (
131
+ $ this ->l ->t ('Conversations ' ),
132
+ array_values ($ result ),
133
+ );
116
134
}
135
+ ksort ($ result );
136
+
137
+ $ newCursorWithName = '# ' ;
138
+ if ($ cursorKey ) {
139
+ $ foundCursor = false ;
140
+ $ filteredResults = [];
141
+ $ lastPossibleCursor = '# ' ;
142
+ foreach ($ result as $ key => $ entry ) {
143
+ if ($ cursorKey === $ key ) {
144
+ $ foundCursor = true ;
145
+ continue ;
146
+ }
147
+ if (!$ foundCursor ) {
148
+ continue ;
149
+ }
150
+
151
+ if (count ($ filteredResults ) === $ query ->getLimit ()) {
152
+ // We already have enough results, but there are more,
153
+ // so we add the cursor for the next request.
154
+ $ newCursorWithName = $ lastPossibleCursor ;
155
+ break ;
156
+ }
157
+
158
+ $ filteredResults [] = $ entry ;
159
+ $ lastPossibleCursor = $ key ;
160
+ }
161
+ } else {
162
+ $ filteredResults = array_slice ($ result , 0 , $ query ->getLimit ());
163
+ // Next page starts at the last result
164
+ $ newCursorWithName = array_key_last ($ filteredResults );
165
+ }
166
+
167
+ // Cursor is the token only (to survive renamed),
168
+ // but the array key is `display name#token`, so we split by the #
169
+ // and get the last part which is the token.
170
+ // If it's empty, there is no cursor for a next page
171
+ $ parts = explode ('# ' , $ newCursorWithName );
172
+ $ newCursor = end ($ parts );
117
173
118
- return SearchResult::complete (
174
+ return SearchResult::paginated (
119
175
$ this ->l ->t ('Conversations ' ),
120
- $ result
176
+ array_values ($ filteredResults ),
177
+ $ newCursor
121
178
);
122
179
}
123
180
}
0 commit comments