Skip to content

Commit 434e023

Browse files
authored
Merge pull request #964 from nextcloud/limit-photo-suggestions
Limit photo Suggestions to 250 photos, per request
2 parents c695943 + 8bd0185 commit 434e023

File tree

10 files changed

+100
-48
lines changed

10 files changed

+100
-48
lines changed

lib/Controller/PhotosController.php

Lines changed: 42 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@
1212

1313
namespace OCA\Maps\Controller;
1414

15+
use OC\User\NoUserException;
16+
use OCP\DB\Exception;
17+
use OCP\Files\InvalidPathException;
1518
use OCP\Files\IRootFolder;
19+
use OCP\Files\NotFoundException;
20+
use OCP\Files\NotPermittedException;
1621
use OCP\IRequest;
1722
use OCP\AppFramework\Http\TemplateResponse;
1823
use OCP\AppFramework\Http\DataResponse;
@@ -44,36 +49,55 @@ public function __construct($AppName,
4449
$this->root = $root;
4550
}
4651

47-
/**
48-
* @NoAdminRequired
49-
* @NoCSRFRequired
52+
/**
53+
* @NoAdminRequired
54+
* @NoCSRFRequired
55+
* @param null $myMapId
56+
* @param null $respectNoMediaAndNoimage
57+
* @param null $hideImagesOnCustomMaps
58+
* @param null $hideImagesInMapsFolder
5059
* @return DataResponse
51-
*/
52-
public function getPhotos($myMapId=null): DataResponse {
60+
* @throws Exception
61+
* @throws NoUserException
62+
* @throws NotFoundException
63+
* @throws NotPermittedException
64+
*/
65+
public function getPhotos($myMapId=null, $respectNoMediaAndNoimage=null, $hideImagesOnCustomMaps=null, $hideImagesInMapsFolder=null): DataResponse {
5366
$userFolder = $this->root->getUserFolder($this->userId);
5467
if (is_null($myMapId) || $myMapId === "") {
55-
$result = $this->geophotoService->getAll($this->userId, $userFolder);
68+
$result = $this->geophotoService->getAll($this->userId, $userFolder, $respectNoMediaAndNoimage??true, $hideImagesOnCustomMaps??false, $hideImagesInMapsFolder??true);
5669
} else {
5770
$folders = $userFolder->getById($myMapId);
5871
$folder = array_shift($folders);
59-
$result = $this->geophotoService->getAll($this->userId, $folder, true, false);
72+
$result = $this->geophotoService->getAll($this->userId, $folder, $respectNoMediaAndNoimage??true, $hideImagesOnCustomMaps??false, $hideImagesInMapsFolder??false);
6073
}
6174
return new DataResponse($result);
6275
}
6376

6477
/**
6578
* @NoAdminRequired
6679
* @NoCSRFRequired
80+
* @param int|null $myMapId
81+
* @param string|null $timezone
82+
* @param int $limit
83+
* @param int $offset
84+
* @param null $respectNoMediaAndNoimage
85+
* @param null $hideImagesOnCustomMaps
86+
* @param null $hideImagesInMapsFolder
6787
* @return DataResponse
88+
* @throws Exception
89+
* @throws NoUserException
90+
* @throws NotFoundException
91+
* @throws NotPermittedException
6892
*/
69-
public function getNonLocalizedPhotos($myMapId=null, $timezone=null): DataResponse {
93+
public function getNonLocalizedPhotos(?int $myMapId=null, ?string $timezone=null, int $limit=250, int $offset=0, $respectNoMediaAndNoimage=null, $hideImagesOnCustomMaps=null, $hideImagesInMapsFolder=null): DataResponse {
7094
$userFolder = $this->root->getUserFolder($this->userId);
7195
if (is_null($myMapId) || $myMapId === "") {
72-
$result = $this->geophotoService->getNonLocalized($this->userId, $userFolder, true, true, $timezone);
96+
$result = $this->geophotoService->getNonLocalized($this->userId, $userFolder, $respectNoMediaAndNoimage??true, $hideImagesOnCustomMaps??false, $hideImagesInMapsFolder??true, $timezone, $limit, $offset);
7397
} else {
7498
$folders = $userFolder->getById($myMapId);
7599
$folder = array_shift($folders);
76-
$result = $this->geophotoService->getNonLocalized($this->userId, $folder, true, false, $timezone);
100+
$result = $this->geophotoService->getNonLocalized($this->userId, $folder, $respectNoMediaAndNoimage??true, $hideImagesOnCustomMaps??false, $hideImagesInMapsFolder??false, $timezone, $limit, $offset);
77101
}
78102
return new DataResponse($result);
79103
}
@@ -85,14 +109,20 @@ public function getNonLocalizedPhotos($myMapId=null, $timezone=null): DataRespon
85109
* @param $lats
86110
* @param $lngs
87111
* @param bool $directory
112+
* @param null $myMapId
113+
* @param bool $relative
88114
* @return DataResponse
115+
* @throws NoUserException
116+
* @throws NotFoundException
117+
* @throws NotPermittedException
118+
* @throws InvalidPathException
89119
*/
90-
public function placePhotos($paths, $lats, $lngs, bool $directory=false, $myMapId=null, $relative=false): DataResponse {
120+
public function placePhotos($paths, $lats, $lngs, bool $directory=false, $myMapId=null, bool $relative=false): DataResponse {
91121
$userFolder = $this->root->getUserFolder($this->userId);
92122
if (!is_null($myMapId) and $myMapId !== '') {
93123
// forbid folder placement in my-maps
94124
if ($directory === 'true') {
95-
return 0;
125+
throw new NotPermittedException();
96126
}
97127
$folders = $userFolder->getById($myMapId);
98128
$folder = array_shift($folders);

lib/Controller/PublicPhotosController.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ public function getPhotos(): DataResponse {
123123
if ($isReadable) {
124124
$owner = $share->getShareOwner();
125125
$pre_path = $this->root->getUserFolder($owner)->getPath();
126-
$result = $this->geophotoService->getAll($owner, $folder, true, false);
126+
$result = $this->geophotoService->getAll($owner, $folder, true, false, false);
127127
$photos = array_map(function ($photo) use ($folder, $permissions, $pre_path) {
128128
$photo_object = (object) $photo;
129129
$photo_object->isCreatable = ($permissions & (1 << 2)) && $photo['isCreatable'];
@@ -148,15 +148,15 @@ public function getPhotos(): DataResponse {
148148
* @throws \OCP\Files\InvalidPathException
149149
* @throws \OC\User\NoUserException
150150
*/
151-
public function getNonLocalizedPhotos(): DataResponse {
151+
public function getNonLocalizedPhotos(?string $timezone=null, int $limit=250, int $offset=0): DataResponse {
152152
$share = $this->getShare();
153153
$permissions = $share->getPermissions();
154154
$folder = $this->getShareNode();
155155
$isReadable = (bool) ($permissions & (1 << 0));
156156
if ($isReadable) {
157157
$owner = $share->getShareOwner();
158158
$pre_path = $this->root->getUserFolder($owner)->getPath();
159-
$result = $this->geophotoService->getNonLocalized($owner, $folder, true, false);
159+
$result = $this->geophotoService->getNonLocalized($owner, $folder, true, false, false, $timezone, $limit, $offset);
160160
$photos = array_map(function ($photo) use ($folder, $permissions, $pre_path) {
161161
$photo_object = (object) $photo;
162162
$photo_object->isCreatable = ($permissions & (1 << 2)) && $photo['isCreatable'];

lib/DB/GeophotoMapper.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,14 @@ public function findAllNonLocalized($userId, $limit=null, $offset=null) {
131131
$qb->expr()->isNull('lat'),
132132
$qb->expr()->isNull('lng')
133133
)
134-
)->orderBy('date_taken', 'ASC');
134+
)->orderBy('date_taken', 'DESC');
135135
if (!is_null($offset)) {
136136
$qb->setFirstResult($offset);
137137
}
138138
if (!is_null($limit)) {
139139
$qb->setMaxResults($limit);
140140
}
141-
return $this->findEntities($qb);
141+
return array_reverse($this->findEntities($qb));
142142
}
143143

144144
/**

lib/Service/GeophotoService.php

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -88,23 +88,28 @@ public function clearCache(string $userId=''): bool {
8888

8989
/**
9090
* @param string $userId
91-
* @param $folder=null
92-
* @param bool $respectNomediaAndNoimage=true
93-
* @param bool $hideImagesOnCustomMaps=true
91+
* @param null $folder =null
92+
* @param bool $respectNomediaAndNoimage =true
93+
* @param bool $hideImagesOnCustomMaps =true
94+
* @param bool $hideImagesInMapsFolder
9495
* @return array
95-
* @throws \OCP\Files\NotFoundException
96-
* @throws \OCP\Files\NotPermittedException
97-
* @throws \OC\User\NoUserException
96+
* @throws Exception
97+
* @throws NoUserException
98+
* @throws NotFoundException
99+
* @throws NotPermittedException
98100
*/
99-
public function getAll(string $userId, $folder=null, bool $respectNomediaAndNoimage=true, bool $hideImagesOnCustomMaps=true): array {
101+
public function getAll(string $userId, $folder=null, bool $respectNomediaAndNoimage=true, bool $hideImagesOnCustomMaps=false, bool $hideImagesInMapsFolder=true): array {
100102
$userFolder = $this->getFolderForUser($userId);
101103
if (is_null($folder)) {
102104
$folder = $userFolder;
103105
}
104-
$key = $userId . ':' . $userFolder->getRelativePath($folder->getPath()) . ':' . (string) $respectNomediaAndNoimage . ':' . (string) $hideImagesOnCustomMaps;
106+
$key = $userId . ':' . $userFolder->getRelativePath($folder->getPath()) . ':' . (string) $respectNomediaAndNoimage . ':' . (string) $hideImagesOnCustomMaps . ':' . (string) $hideImagesInMapsFolder;
105107
$filesById = $this->photosCache->get($key);
106108
if ($filesById === null) {
107109
$ignoredPaths = $respectNomediaAndNoimage ? $this->getIgnoredPaths($userId, $folder, $hideImagesOnCustomMaps) : [];
110+
if ($hideImagesInMapsFolder) {
111+
$ignoredPaths[] = "/Maps";
112+
}
108113
$photoEntities = $this->photoMapper->findAll($userId);
109114

110115
$filesById = [];
@@ -170,24 +175,30 @@ public function getAll(string $userId, $folder=null, bool $respectNomediaAndNoim
170175
* @param null $folder =null
171176
* @param bool $respectNomediaAndNoimage
172177
* @param bool $hideImagesOnCustomMaps
178+
* @param bool $hideImagesInMapsFolder
173179
* @param string|null $timezone locale time zone used by images
180+
* @param int $limit
181+
* @param int $offset
174182
* @return array with geodatas of all nonLocalizedPhotos
175183
* @throws Exception
184+
* @throws NoUserException
176185
* @throws NotFoundException
177186
* @throws NotPermittedException
178-
* @throws NoUserException
179187
*/
180-
public function getNonLocalized (string $userId, $folder=null, bool $respectNomediaAndNoimage=true, bool $hideImagesOnCustomMaps=true, string $timezone=null): array {
188+
public function getNonLocalized (string $userId, $folder=null, bool $respectNomediaAndNoimage=true, bool $hideImagesOnCustomMaps=false, bool $hideImagesInMapsFolder=true, string $timezone=null, int $limit=250, int $offset=0): array {
181189
$userFolder = $this->getFolderForUser($userId);
182190
if (is_null($folder)) {
183191
$folder = $userFolder;
184192
}
185-
$key = $userId . ':' . $userFolder->getRelativePath($folder->getPath()) . ':' . (string) $respectNomediaAndNoimage . ':' . (string) $hideImagesOnCustomMaps . ':' . (string) $timezone;
186-
$filesById = $this->nonLocalizedPhotosCache->get($key);
187-
if ($filesById === null) {
193+
// $key = $userId . ':' . $userFolder->getRelativePath($folder->getPath()) . ':' . (string) $respectNomediaAndNoimage . ':' . (string) $hideImagesOnCustomMaps . ':' . (string) $hideImageInMapsFolder . ':' . (string) $timezone . ':' . (string) $limit . ':' . (string) $offset;
194+
// $filesById = $this->nonLocalizedPhotosCache->get($key);
195+
// if ($filesById === null) {
188196
$ignoredPaths = $respectNomediaAndNoimage ? $this->getIgnoredPaths($userId, $folder, $hideImagesOnCustomMaps) : [];
197+
if ($hideImagesInMapsFolder) {
198+
$ignoredPaths[] = "/Maps";
199+
}
189200
$foo = $this->loadTimeorderedPointSets($userId, $folder, $respectNomediaAndNoimage, $hideImagesOnCustomMaps);
190-
$photoEntities = $this->photoMapper->findAllNonLocalized($userId);
201+
$photoEntities = $this->photoMapper->findAllNonLocalized($userId, $limit, $offset);
191202
$filesById = [];
192203
$cache = $folder->getStorage()->getCache();
193204
$previewEnableMimetypes = $this->getPreviewEnabledMimetypes();
@@ -255,8 +266,8 @@ public function getNonLocalized (string $userId, $folder=null, bool $respectNome
255266
}
256267
}
257268
}
258-
$this->nonLocalizedPhotosCache->set($key, $filesById, 60 * 60 * 24);
259-
}
269+
// $this->nonLocalizedPhotosCache->set($key, $filesById, 60 * 60 * 24);
270+
// }
260271
return $filesById;
261272
}
262273

src/components/PhotoSuggestionsSidebarTab.vue

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@
9393
@click="$emit('cancel')">
9494
{{ !photoSuggestions.includes(null) ? t('maps', 'Cancel') : t('maps', 'Quit') }}
9595
</NcButton>
96+
<NcButton
97+
@click="$emit('load-more')">
98+
{{ t('maps', 'Load more') }}
99+
</NcButton>
96100
<NcButton
97101
v-show="photoSuggestions.length > 0"
98102
type="primary"

src/components/Sidebar.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
:photo-suggestions-selected-indices="photoSuggestionsSelectedIndices"
2020
:photo-suggestions-timezone="photoSuggestionsTimezone"
2121
:loading="photosLoading"
22+
@load-more="$emit('load-more-photo-suggestions')"
2223
@change-timezone="$emit('change-photo-suggestions-timezone',$event)"
2324
@select-all="$emit('select-all-photo-suggestions')"
2425
@clear-selection="$emit('clear-photo-suggestions-selection',$event)"

src/components/map/TrackLayer.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,11 @@
3232
:icon="firstPointMarkerIcon"
3333
:lat-lng="firstPoint" />
3434
<LMarker v-for="(point, i) in wayPoints"
35-
:key="i"
35+
:key="'waypoint:'.concat(i)"
3636
:icon="wayPointMarkerIcon"
3737
:lat-lng="point" />
3838
<LFeatureGroup v-for="(line, i) in lines"
39-
:key="i"
39+
:key="'line'.concat(i)"
4040
@mouseover="trackLineMouseover($event, line)">
4141
<LPolyline
4242
color="black"

src/network.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,12 +314,14 @@ export async function clearPhotoCache(token = null) {
314314
return axios.get(url)
315315
}
316316

317-
export async function getPhotoSuggestions(myMapId = null, token = null, timezone = null) {
317+
export async function getPhotoSuggestions(myMapId = null, token = null, timezone = null, limit = null, offset = null) {
318318
const url = generateUrl('apps/maps' + (token ? '/s/' + token : '') + '/photos/nonlocalized')
319319
const conf = {
320320
params: {
321321
myMapId,
322322
timezone,
323+
limit,
324+
offset,
323325
},
324326
}
325327
return axios.get(url, conf)

src/views/App.vue

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@
193193
@active-changed="onActiveSidebarTabChanged"
194194
@close="onCloseSidebar"
195195
@opened="onOpenedSidebar"
196+
@load-more-photo-suggestions="getPhotoSuggestions"
196197
@select-all-photo-suggestions="onSelectAllPhotoSuggestions"
197198
@clear-photo-suggestions-selection="onClearPhotoSuggestionsSelection"
198199
@cancel-photo-suggestions="onCancelPhotoSuggestions"
@@ -290,6 +291,8 @@ export default {
290291
photoSuggestions: [],
291292
photoSuggestionsSelectedIndices: [],
292293
photoSuggestionsTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
294+
photoSuggestionsLimit: 250,
295+
photoSuggestionsOffset: 0,
293296
// contacts
294297
contactsLoading: false,
295298
contactsEnabled: optionsController.contactsEnabled,
@@ -1070,19 +1073,20 @@ export default {
10701073
this.photoSuggestions = []
10711074
},
10721075
getPhotoSuggestions() {
1073-
if (!this.photosEnabled) {
1076+
if (!this.photosEnabled || this.photosLoading) {
10741077
return
10751078
}
10761079
this.photosLoading = true
1077-
network.getPhotoSuggestions(this.myMapId, getToken(), this.photoSuggestionsTimezone).then((response) => {
1078-
this.photoSuggestions = response.data.sort((a, b) => {
1080+
network.getPhotoSuggestions(this.myMapId, getToken(), this.photoSuggestionsTimezone, this.photoSuggestionsLimit, this.photoSuggestionsOffset).then((response) => {
1081+
this.photoSuggestions.unshift(...response.data.sort((a, b) => {
10791082
if (a.dateTaken < b.dateTaken) {
10801083
return -1
10811084
} else if (a.dateTaken > b.dateTaken) {
10821085
return 1
10831086
}
10841087
return 0
1085-
})
1088+
}))
1089+
this.photoSuggestionsOffset += this.photoSuggestionsLimit
10861090
}).catch((error) => {
10871091
console.error(error)
10881092
}).then(() => {

tests/Unit/Controller/PhotosControllerTest.php

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public function testAddGetPhotos() {
213213
$this->assertCount(1, $data);
214214
$this->assertEquals('/nc.jpg', $data[0]->path);
215215

216-
//Test .nomedia repected
216+
//Test .nomedia respected
217217
$this->GeoPhotosService->clearCache();
218218
$file = $userfolder->newFile('.maps.nomedia');
219219
$resp = $this->photosController->getPhotos();
@@ -223,7 +223,7 @@ public function testAddGetPhotos() {
223223
$this->assertCount(0, $data);
224224
$file->delete();
225225

226-
//Test .noimage repected
226+
//Test .noimage respected
227227
$this->GeoPhotosService->clearCache();
228228
$file = $userfolder->newFile('.maps.noimage');
229229
$resp = $this->photosController->getPhotos();
@@ -233,10 +233,10 @@ public function testAddGetPhotos() {
233233
$this->assertCount(0, $data);
234234
$file->delete();
235235

236-
//Test .maps repected
236+
//Test .maps respected
237237
$this->GeoPhotosService->clearCache();
238238
$file = $userfolder->newFile('.index.maps');
239-
$resp = $this->photosController->getPhotos();
239+
$resp = $this->photosController->getPhotos(null, null, true);
240240
$status = $resp->getStatus();
241241
$this->assertEquals(200, $status);
242242
$data = $resp->getData();
@@ -272,7 +272,7 @@ public function testAddGetPhotos() {
272272
$this->assertCount(1, $data);
273273
$this->assertEquals('/nut.jpg', $data[0]->path);
274274

275-
//Test .nomedia repected
275+
//Test .nomedia respected
276276
$this->GeoPhotosService->clearCache();
277277
$file = $userfolder->newFile('.maps.nomedia');
278278
$resp = $this->photosController->getNonLocalizedPhotos();
@@ -282,7 +282,7 @@ public function testAddGetPhotos() {
282282
$this->assertCount(0, $data);
283283
$file->delete();
284284

285-
//Test .noimage repected
285+
//Test .noimage respected
286286
$this->GeoPhotosService->clearCache();
287287
$file = $userfolder->newFile('.maps.noimage');
288288
$resp = $this->photosController->getNonLocalizedPhotos();
@@ -292,10 +292,10 @@ public function testAddGetPhotos() {
292292
$this->assertCount(0, $data);
293293
$file->delete();
294294

295-
//Test .index.maps repected
295+
//Test .index.maps respected
296296
$this->GeoPhotosService->clearCache();
297297
$file = $userfolder->newFile('.index.maps');
298-
$resp = $this->photosController->getNonLocalizedPhotos();
298+
$resp = $this->photosController->getNonLocalizedPhotos(null, null, 250, 0, true, true);
299299
$status = $resp->getStatus();
300300
$this->assertEquals(200, $status);
301301
$data = $resp->getData();

0 commit comments

Comments
 (0)