diff --git a/CHANGELOG.md b/CHANGELOG.md index d5965f6ff..d47dfee48 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,9 @@ This file is manually updated. Please file an issue if something is missing. ## v4.6.1, v3.6.1 - **Feature**: Native sharing from the viewer (images only) -- **Feature**: Deep linking to photos +- **Feature**: Deep linking to photos on opening viewer - **Feature**: Password protected folder shares ([#165](https://github.com/pulsejet/memories/issues/165)) +- **Feature**: Folders view will now show only folders with photos ([#163](https://github.com/pulsejet/memories/issues/163)) - Improvements to viewer UX ## v4.6.0, v3.6.0 (2022-11-06) diff --git a/lib/Controller/DaysController.php b/lib/Controller/DaysController.php index d46ab8db7..b45ebe6c3 100644 --- a/lib/Controller/DaysController.php +++ b/lib/Controller/DaysController.php @@ -25,13 +25,16 @@ use OCP\AppFramework\Http; use OCP\AppFramework\Http\JSONResponse; -use OCP\Files\FileInfo; use OCP\Files\Folder; class DaysController extends ApiBase { + use FoldersTrait; + /** * @NoAdminRequired + * @NoCSRFRequired + * * * @PublicPage */ @@ -167,41 +170,6 @@ public function dayPost(): JSONResponse return $this->day($id); } - /** - * Get subfolders entry for days response. - */ - public function getSubfoldersEntry(Folder &$folder) - { - // Ugly: get the view of the folder with reflection - // This is unfortunately the only way to get the contents of a folder - // matching a MIME type without using SEARCH, which is deep - $rp = new \ReflectionProperty('\OC\Files\Node\Node', 'view'); - $rp->setAccessible(true); - $view = $rp->getValue($folder); - - // Get the subfolders - $folders = $view->getDirectoryContent($folder->getPath(), FileInfo::MIMETYPE_FOLDER, $folder); - - // Sort by name - usort($folders, function ($a, $b) { - return strnatcmp($a->getName(), $b->getName()); - }); - - // Process to response type - return [ - 'dayid' => \OCA\Memories\Util::$TAG_DAYID_FOLDERS, - 'count' => \count($folders), - 'detail' => array_map(function ($node) { - return [ - 'fileid' => $node->getId(), - 'name' => $node->getName(), - 'isfolder' => 1, - 'path' => $node->getPath(), - ]; - }, $folders, []), - ]; - } - /** * Get transformations depending on the request. * diff --git a/lib/Controller/FoldersTrait.php b/lib/Controller/FoldersTrait.php new file mode 100644 index 000000000..633a9afb3 --- /dev/null +++ b/lib/Controller/FoldersTrait.php @@ -0,0 +1,55 @@ +getById($fileInfo->getId()); + if (count($folder) === 0) { + return []; + } + return $this->timelineQuery->getFolderPreviews($folder[0]); + } + + /** + * Get subfolders entry for days response. + */ + public function getSubfoldersEntry(Folder &$folder) + { + // Ugly: get the view of the folder with reflection + // This is unfortunately the only way to get the contents of a folder + // matching a MIME type without using SEARCH, which is deep + $rp = new \ReflectionProperty('\OC\Files\Node\Node', 'view'); + $rp->setAccessible(true); + $view = $rp->getValue($folder); + + // Get the subfolders + $folders = $view->getDirectoryContent($folder->getPath(), FileInfo::MIMETYPE_FOLDER, $folder); + + // Sort by name + usort($folders, function ($a, $b) { + return strnatcmp($a->getName(), $b->getName()); + }); + + // Process to response type + return [ + 'dayid' => \OCA\Memories\Util::$TAG_DAYID_FOLDERS, + 'count' => \count($folders), + 'detail' => array_map(function (&$node) use (&$folder) { + return [ + 'fileid' => $node->getId(), + 'name' => $node->getName(), + 'isfolder' => 1, + 'path' => $node->getPath(), + 'previews' => $this->getFolderPreviews($folder, $node), + ]; + }, $folders, []), + ]; + } +} \ No newline at end of file diff --git a/lib/Db/TimelineQuery.php b/lib/Db/TimelineQuery.php index 1b998a74b..f500fc84a 100644 --- a/lib/Db/TimelineQuery.php +++ b/lib/Db/TimelineQuery.php @@ -14,6 +14,7 @@ class TimelineQuery use TimelineQueryFaces; use TimelineQueryFilters; use TimelineQueryTags; + use TimelineQueryFolders; protected IDBConnection $connection; diff --git a/lib/Db/TimelineQueryFolders.php b/lib/Db/TimelineQueryFolders.php new file mode 100644 index 000000000..e514a3667 --- /dev/null +++ b/lib/Db/TimelineQueryFolders.php @@ -0,0 +1,42 @@ +connection->getQueryBuilder(); + + // SELECT all photos + $query->select('f.fileid', 'f.etag')->from('memories', 'm'); + + // WHERE these photos are in the user's requested folder recursively + $query = $this->joinFilecache($query, $folder, true, false); + + // ORDER descending by fileid + $query->orderBy('f.fileid', 'DESC'); + + // MAX 4 + $query->setMaxResults(4); + + // FETCH tag previews + $cursor = $this->executeQueryWithCTEs($query); + $ans = $cursor->fetchAll(); + + // Post-process + foreach ($ans as &$row) { + $row['fileid'] = (int) $row['fileid']; + } + + return $ans; + } +} diff --git a/src/components/Timeline.vue b/src/components/Timeline.vue index 911616b3d..c3e112d60 100644 --- a/src/components/Timeline.vue +++ b/src/components/Timeline.vue @@ -938,11 +938,14 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) { data.forEach(utils.convertFlags); // Filter out items we don't want to show at all - if (!this.config_showHidden) { - // Hidden folders + if (!this.config_showHidden && dayId === this.TagDayID.FOLDERS) { + // Hidden folders and folders without previews data = data.filter( (p) => - !(p.flag & this.c.FLAG_IS_FOLDER && (p).name.startsWith(".")) + !( + p.flag & this.c.FLAG_IS_FOLDER && + ((p).name.startsWith(".") || !(p).previews.length) + ) ); } diff --git a/src/components/frame/Folder.vue b/src/components/frame/Folder.vue index 1e36e4141..47a827634 100644 --- a/src/components/frame/Folder.vue +++ b/src/components/frame/Folder.vue @@ -3,8 +3,8 @@ draggable="false" class="folder fill-block" :class="{ - hasPreview: previewFileInfos.length > 0, - onePreview: previewFileInfos.length === 1, + hasPreview: previews.length > 0, + onePreview: previews.length === 1, hasError: error, }" :to="target" @@ -15,17 +15,11 @@
-
+
@@ -34,11 +28,10 @@