folder-share: add node share fake API
parent
53ebf7d18f
commit
4e6a2a1329
|
@ -103,6 +103,10 @@ class ApiBase extends Controller
|
|||
|
||||
// Public shared folder
|
||||
if ($share = $this->getShareNode()) { // can throw
|
||||
if (!$share instanceof Folder) {
|
||||
throw new \Exception('Share is not a folder');
|
||||
}
|
||||
|
||||
$root->addFolder($share);
|
||||
|
||||
return $root;
|
||||
|
@ -229,8 +233,15 @@ class ApiBase extends Controller
|
|||
if ($share = $this->getShareNode()) {
|
||||
// Public shares may allow editing
|
||||
// Just use the same permissions as the share
|
||||
if ($share instanceof File) {
|
||||
return $share;
|
||||
}
|
||||
if ($share instanceof Folder) {
|
||||
return $this->getOneFileFromFolder($share, $id, $share->getPermissions());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
|
@ -301,7 +312,7 @@ class ApiBase extends Controller
|
|||
|
||||
// Get node from share
|
||||
$node = $share->getNode(); // throws exception if not found
|
||||
if (!$node instanceof Folder || !$node->isReadable() || !$node->isShareable()) {
|
||||
if (!$node->isReadable() || !$node->isShareable()) {
|
||||
throw new \Exception('Share not found or invalid');
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace OCA\Memories\Controller;
|
||||
|
||||
use OCA\Memories\AppInfo\Application;
|
||||
use OCA\Memories\Db\TimelineQuery;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\AppFramework\AuthPublicShareController;
|
||||
use OCP\AppFramework\Http\Template\PublicTemplateResponse;
|
||||
|
@ -12,6 +13,7 @@ use OCP\EventDispatcher\IEventDispatcher;
|
|||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IRequest;
|
||||
use OCP\ISession;
|
||||
use OCP\IURLGenerator;
|
||||
|
@ -31,6 +33,7 @@ class PublicController extends AuthPublicShareController
|
|||
protected IShareManager $shareManager;
|
||||
protected IUserManager $userManager;
|
||||
protected IAppManager $appManager;
|
||||
protected IDBConnection $db;
|
||||
protected IConfig $config;
|
||||
|
||||
protected IShare $share;
|
||||
|
@ -47,6 +50,7 @@ class PublicController extends AuthPublicShareController
|
|||
IShareManager $shareManager,
|
||||
IUserManager $userManager,
|
||||
IAppManager $appManager,
|
||||
IDBConnection $db,
|
||||
IConfig $config
|
||||
) {
|
||||
parent::__construct($AppName, $request, $session, $urlGenerator);
|
||||
|
@ -57,6 +61,7 @@ class PublicController extends AuthPublicShareController
|
|||
$this->shareManager = $shareManager;
|
||||
$this->userManager = $userManager;
|
||||
$this->appManager = $appManager;
|
||||
$this->db = $db;
|
||||
$this->config = $config;
|
||||
}
|
||||
|
||||
|
@ -106,11 +111,6 @@ class PublicController extends AuthPublicShareController
|
|||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
if (!($share->getNode() instanceof \OCP\Files\Folder)) {
|
||||
// TODO: single file share
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
// Redirect to main app if user owns this share
|
||||
$this->redirectIfOwned($share);
|
||||
|
||||
|
@ -124,8 +124,14 @@ class PublicController extends AuthPublicShareController
|
|||
// Share info
|
||||
$this->initialState->provideInitialState('no_download', $share->getHideDownload());
|
||||
|
||||
// Share file id only if not a folder
|
||||
$node = $share->getNode();
|
||||
if ($node instanceof \OCP\Files\File) {
|
||||
$this->initialState->provideInitialState('single_item', $this->getSingleItemInitialState($node));
|
||||
}
|
||||
|
||||
$response = new PublicTemplateResponse($this->appName, 'main');
|
||||
$response->setHeaderTitle($share->getNode()->getName());
|
||||
$response->setHeaderTitle($node->getName());
|
||||
$response->setFooterVisible(false); // wth is that anyway?
|
||||
$response->setContentSecurityPolicy(PageController::getCSP());
|
||||
$response->cacheFor(0);
|
||||
|
@ -241,4 +247,13 @@ class PublicController extends AuthPublicShareController
|
|||
|
||||
exit;
|
||||
}
|
||||
|
||||
/** Get initial state of single item */
|
||||
private function getSingleItemInitialState(\OCP\Files\File $file): string
|
||||
{
|
||||
$timelineQuery = new TimelineQuery($this->db);
|
||||
$photo = $timelineQuery->getSingleItem($file->getId());
|
||||
|
||||
return json_encode($photo);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,8 +18,14 @@ class TimelineQuery
|
|||
use TimelineQueryPeopleFaceRecognition;
|
||||
use TimelineQueryPeopleRecognize;
|
||||
use TimelineQueryPlaces;
|
||||
use TimelineQuerySingleItem;
|
||||
use TimelineQueryTags;
|
||||
|
||||
public const TIMELINE_SELECT = [
|
||||
'm.isvideo', 'm.video_duration', 'm.datetaken', 'm.dayid', 'm.w', 'm.h', 'm.liveid',
|
||||
'f.etag', 'f.path', 'f.name AS basename', 'mimetypes.mimetype',
|
||||
];
|
||||
|
||||
protected IDBConnection $connection;
|
||||
|
||||
public function __construct(IDBConnection $connection)
|
||||
|
|
|
@ -153,13 +153,12 @@ trait TimelineQueryDays
|
|||
// We don't actually use m.datetaken here, but postgres
|
||||
// needs that all fields in ORDER BY are also in SELECT
|
||||
// when using DISTINCT on selected fields
|
||||
$query->select($fileid, 'm.isvideo', 'm.video_duration', 'm.datetaken', 'm.dayid', 'm.w', 'm.h', 'm.liveid')
|
||||
$query->select($fileid, ...TimelineQuery::TIMELINE_SELECT)
|
||||
->from('memories', 'm')
|
||||
;
|
||||
|
||||
// JOIN with filecache for existing files
|
||||
$query = $this->joinFilecache($query, $root, $recursive, $archive);
|
||||
$query->addSelect('f.etag', 'f.path', 'f.name AS basename');
|
||||
|
||||
// SELECT rootid if not a single folder
|
||||
if ($recursive && !$root->isEmpty()) {
|
||||
|
@ -168,7 +167,6 @@ trait TimelineQueryDays
|
|||
|
||||
// JOIN with mimetypes to get the mimetype
|
||||
$query->join('f', 'mimetypes', 'mimetypes', $query->expr()->eq('f.mimetype', 'mimetypes.id'));
|
||||
$query->addSelect('mimetypes.mimetype');
|
||||
|
||||
// Filter by dayid unless wildcard
|
||||
if (null !== $day_ids) {
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace OCA\Memories\Db;
|
||||
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
trait TimelineQuerySingleItem
|
||||
{
|
||||
protected IDBConnection $connection;
|
||||
|
||||
public function getSingleItem(int $fileId)
|
||||
{
|
||||
$query = $this->connection->getQueryBuilder();
|
||||
$query->select('m.fileid', ...TimelineQuery::TIMELINE_SELECT)
|
||||
->from('memories', 'm')
|
||||
->where($query->expr()->eq('m.fileid', $query->createNamedParameter($fileId, IQueryBuilder::PARAM_INT)))
|
||||
;
|
||||
|
||||
// JOIN filecache for etag
|
||||
$query->innerJoin('m', 'filecache', 'f', $query->expr()->eq('f.fileid', 'm.fileid'));
|
||||
|
||||
// JOIN with mimetypes to get the mimetype
|
||||
$query->join('f', 'mimetypes', 'mimetypes', $query->expr()->eq('f.mimetype', 'mimetypes.id'));
|
||||
|
||||
unset($row['datetaken'], $row['path']);
|
||||
|
||||
return $query->executeQuery()->fetch();
|
||||
}
|
||||
}
|
|
@ -766,6 +766,8 @@ export default defineComponent({
|
|||
data = await dav.getPlacesData();
|
||||
} else if (this.$route.name === "tags" && !this.$route.params.name) {
|
||||
data = await dav.getTagsData();
|
||||
} else if (dav.isSingleItem()) {
|
||||
data = await dav.getSingleItemData();
|
||||
} else {
|
||||
// Try the cache
|
||||
try {
|
||||
|
|
|
@ -9,3 +9,4 @@ export * from "./dav/onthisday";
|
|||
export * from "./dav/tags";
|
||||
export * from "./dav/other";
|
||||
export * from "./dav/places";
|
||||
export * from "./dav/single-item";
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import { IDay } from "../../types";
|
||||
import { loadState } from "@nextcloud/initial-state";
|
||||
|
||||
const singleItem = JSON.parse(loadState("memories", "single_item", "{}"));
|
||||
|
||||
export function isSingleItem(): boolean {
|
||||
return Boolean(singleItem?.fileid);
|
||||
}
|
||||
|
||||
export async function getSingleItemData(): Promise<IDay[]> {
|
||||
if (!singleItem?.fileid) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
dayid: singleItem.dayid,
|
||||
count: 1,
|
||||
detail: [singleItem],
|
||||
},
|
||||
] as any[];
|
||||
}
|
Loading…
Reference in New Issue