Group months in album
parent
6feffe70ea
commit
80a76a5a48
|
@ -133,6 +133,21 @@ class ApiBase extends Controller
|
||||||
return $folder;
|
return $folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function isRecursive()
|
||||||
|
{
|
||||||
|
return null === $this->request->getParam('folder');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isArchive()
|
||||||
|
{
|
||||||
|
return null !== $this->request->getParam('archive');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function isMonthView()
|
||||||
|
{
|
||||||
|
return null !== $this->request->getParam('monthView');
|
||||||
|
}
|
||||||
|
|
||||||
protected function getShareToken()
|
protected function getShareToken()
|
||||||
{
|
{
|
||||||
return $this->request->getParam('folder_share');
|
return $this->request->getParam('folder_share');
|
||||||
|
|
|
@ -49,25 +49,26 @@ class DaysController extends ApiBase
|
||||||
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Params
|
|
||||||
$recursive = null === $this->request->getParam('folder');
|
|
||||||
$archive = null !== $this->request->getParam('archive');
|
|
||||||
|
|
||||||
// Run actual query
|
// Run actual query
|
||||||
try {
|
try {
|
||||||
$list = $this->timelineQuery->getDays(
|
$list = $this->timelineQuery->getDays(
|
||||||
$folder,
|
$folder,
|
||||||
$uid,
|
$uid,
|
||||||
$recursive,
|
$this->isRecursive(),
|
||||||
$archive,
|
$this->isArchive(),
|
||||||
$this->getTransformations(true),
|
$this->getTransformations(true),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Preload some day responses
|
if ($this->isMonthView()) {
|
||||||
$this->preloadDays($list, $uid, $folder, $recursive, $archive);
|
// Group days together into months
|
||||||
|
$list = $this->timelineQuery->daysToMonths($list);
|
||||||
|
} else {
|
||||||
|
// Preload some day responses
|
||||||
|
$this->preloadDays($list, $uid, $folder);
|
||||||
|
}
|
||||||
|
|
||||||
// Add subfolder info if querying non-recursively
|
// Add subfolder info if querying non-recursively
|
||||||
if (!$recursive) {
|
if (!$this->isRecursive()) {
|
||||||
array_unshift($list, $this->getSubfoldersEntry($folder));
|
array_unshift($list, $this->getSubfoldersEntry($folder));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,18 +89,18 @@ class DaysController extends ApiBase
|
||||||
$uid = $this->getUid();
|
$uid = $this->getUid();
|
||||||
|
|
||||||
// Check for wildcard
|
// Check for wildcard
|
||||||
$day_ids = [];
|
$dayIds = [];
|
||||||
if ('*' === $id) {
|
if ('*' === $id) {
|
||||||
$day_ids = null;
|
$dayIds = null;
|
||||||
} else {
|
} else {
|
||||||
// Split at commas and convert all parts to int
|
// Split at commas and convert all parts to int
|
||||||
$day_ids = array_map(function ($part) {
|
$dayIds = array_map(function ($part) {
|
||||||
return (int) $part;
|
return (int) $part;
|
||||||
}, explode(',', $id));
|
}, explode(',', $id));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if $day_ids is empty
|
// Check if $dayIds is empty
|
||||||
if (null !== $day_ids && 0 === \count($day_ids)) {
|
if (null !== $dayIds && 0 === \count($dayIds)) {
|
||||||
return new JSONResponse([], Http::STATUS_OK);
|
return new JSONResponse([], Http::STATUS_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -112,21 +113,29 @@ class DaysController extends ApiBase
|
||||||
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Params
|
// Convert to actual dayIds if month view
|
||||||
$recursive = null === $this->request->getParam('folder');
|
if ($this->isMonthView()) {
|
||||||
$archive = null !== $this->request->getParam('archive');
|
$dayIds = $this->timelineQuery->monthIdToDayIds($dayIds[0]);
|
||||||
|
}
|
||||||
|
|
||||||
// Run actual query
|
// Run actual query
|
||||||
try {
|
try {
|
||||||
$list = $this->timelineQuery->getDay(
|
$list = $this->timelineQuery->getDay(
|
||||||
$folder,
|
$folder,
|
||||||
$uid,
|
$uid,
|
||||||
$day_ids,
|
$dayIds,
|
||||||
$recursive,
|
$this->isRecursive(),
|
||||||
$archive,
|
$this->isArchive(),
|
||||||
$this->getTransformations(false),
|
$this->getTransformations(false),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Force month id for dayId for month view
|
||||||
|
if ($this->isMonthView()) {
|
||||||
|
foreach ($list as &$photo) {
|
||||||
|
$photo['dayid'] = (int) $dayIds[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return new JSONResponse($list, Http::STATUS_OK);
|
return new JSONResponse($list, Http::STATUS_OK);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
|
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_INTERNAL_SERVER_ERROR);
|
||||||
|
@ -252,13 +261,11 @@ class DaysController extends ApiBase
|
||||||
/**
|
/**
|
||||||
* Preload a few "day" at the start of "days" response.
|
* Preload a few "day" at the start of "days" response.
|
||||||
*
|
*
|
||||||
* @param array $days the days array
|
* @param array $days the days array
|
||||||
* @param string $uid User ID or blank for public shares
|
* @param string $uid User ID or blank for public shares
|
||||||
* @param null|Folder $folder the folder to search in
|
* @param null|Folder $folder the folder to search in
|
||||||
* @param bool $recursive search in subfolders
|
|
||||||
* @param bool $archive search in archive folder only
|
|
||||||
*/
|
*/
|
||||||
private function preloadDays(array &$days, string $uid, &$folder, bool $recursive, bool $archive)
|
private function preloadDays(array &$days, string $uid, &$folder)
|
||||||
{
|
{
|
||||||
$transforms = $this->getTransformations(false);
|
$transforms = $this->getTransformations(false);
|
||||||
$preloaded = 0;
|
$preloaded = 0;
|
||||||
|
@ -283,8 +290,8 @@ class DaysController extends ApiBase
|
||||||
$folder,
|
$folder,
|
||||||
$uid,
|
$uid,
|
||||||
$preloadDayIds,
|
$preloadDayIds,
|
||||||
$recursive,
|
$this->isRecursive(),
|
||||||
$archive,
|
$this->isArchive(),
|
||||||
$transforms,
|
$transforms,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -78,6 +78,44 @@ trait TimelineQueryAlbums
|
||||||
return $albums;
|
return $albums;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert days response to months response.
|
||||||
|
* The dayId is used to group the days into months.
|
||||||
|
*/
|
||||||
|
public function daysToMonths(array &$days)
|
||||||
|
{
|
||||||
|
$months = [];
|
||||||
|
foreach ($days as &$day) {
|
||||||
|
$dayId = $day['dayid'];
|
||||||
|
$time = $dayId * 86400;
|
||||||
|
$monthid = strtotime(date('Ym', $time).'01') / 86400;
|
||||||
|
|
||||||
|
if (empty($months) || $months[\count($months) - 1]['dayid'] !== $monthid) {
|
||||||
|
$months[] = [
|
||||||
|
'dayid' => $monthid,
|
||||||
|
'count' => 0,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
$months[\count($months) - 1]['count'] += $day['count'];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $months;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Convert list of month IDs to list of dayIds */
|
||||||
|
public function monthIdToDayIds(int $monthId)
|
||||||
|
{
|
||||||
|
$dayIds = [];
|
||||||
|
$firstDay = (int) $monthId;
|
||||||
|
$lastDay = strtotime(date('Ymt', $firstDay * 86400)) / 86400;
|
||||||
|
for ($i = $firstDay; $i <= $lastDay; ++$i) {
|
||||||
|
$dayIds[] = (string) $i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dayIds;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get album if allowed. Also check if album is shared with user.
|
* Get album if allowed. Also check if album is shared with user.
|
||||||
*
|
*
|
||||||
|
|
|
@ -78,7 +78,7 @@ trait TimelineQueryDays
|
||||||
*
|
*
|
||||||
* @param null|Folder $folder The folder to get the day from
|
* @param null|Folder $folder The folder to get the day from
|
||||||
* @param string $uid The user id
|
* @param string $uid The user id
|
||||||
* @param int[] $dayid The day id
|
* @param int[] $day_ids The day ids to fetch
|
||||||
* @param bool $recursive If the query should be recursive
|
* @param bool $recursive If the query should be recursive
|
||||||
* @param bool $archive If the query should include only the archive folder
|
* @param bool $archive If the query should include only the archive folder
|
||||||
* @param array $queryTransforms The query transformations to apply
|
* @param array $queryTransforms The query transformations to apply
|
||||||
|
|
|
@ -256,6 +256,10 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
||||||
return window.innerWidth <= 600;
|
return window.innerWidth <= 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isMonthView() {
|
||||||
|
return this.$route.name === "albums";
|
||||||
|
}
|
||||||
|
|
||||||
allowBreakout() {
|
allowBreakout() {
|
||||||
return this.isMobileLayout() && !this.config_squareThumbs;
|
return this.isMobileLayout() && !this.config_squareThumbs;
|
||||||
}
|
}
|
||||||
|
@ -534,6 +538,11 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
||||||
query.set("folder_share", this.$route.params.token);
|
query.set("folder_share", this.$route.params.token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Month view
|
||||||
|
if (this.isMonthView()) {
|
||||||
|
query.set("monthView", "1");
|
||||||
|
}
|
||||||
|
|
||||||
// Create query string and append to URL
|
// Create query string and append to URL
|
||||||
const queryStr = query.toString();
|
const queryStr = query.toString();
|
||||||
if (queryStr) {
|
if (queryStr) {
|
||||||
|
@ -582,7 +591,12 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
||||||
// The reason this function is separate from processDays is
|
// The reason this function is separate from processDays is
|
||||||
// because this call is terribly slow even on desktop
|
// because this call is terribly slow even on desktop
|
||||||
const dateTaken = utils.dayIdToDate(head.dayId);
|
const dateTaken = utils.dayIdToDate(head.dayId);
|
||||||
const name = utils.getLongDateStr(dateTaken, true);
|
let name: string;
|
||||||
|
if (this.isMonthView()) {
|
||||||
|
name = utils.getMonthDateStr(dateTaken);
|
||||||
|
} else {
|
||||||
|
name = utils.getLongDateStr(dateTaken, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Cache and return
|
// Cache and return
|
||||||
head.name = name;
|
head.name = name;
|
||||||
|
@ -782,6 +796,13 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
|
||||||
|
|
||||||
// Aggregate fetch requests
|
// Aggregate fetch requests
|
||||||
this.fetchDayQueue.push(dayId);
|
this.fetchDayQueue.push(dayId);
|
||||||
|
|
||||||
|
// Only single queries allowed for month vie
|
||||||
|
if (this.isMonthView()) {
|
||||||
|
return this.fetchDayExpire();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defer for aggregation
|
||||||
if (!this.fetchDayTimer) {
|
if (!this.fetchDayTimer) {
|
||||||
this.fetchDayTimer = window.setTimeout(() => {
|
this.fetchDayTimer = window.setTimeout(() => {
|
||||||
this.fetchDayTimer = null;
|
this.fetchDayTimer = null;
|
||||||
|
|
|
@ -51,6 +51,15 @@ export function getLongDateStr(date: Date, skipYear = false, time = false) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Get month and year string */
|
||||||
|
export function getMonthDateStr(date: Date) {
|
||||||
|
return date.toLocaleDateString(getCanonicalLocale(), {
|
||||||
|
month: "long",
|
||||||
|
year: "numeric",
|
||||||
|
timeZone: "UTC",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/** Get text like "5 years ago" from a date */
|
/** Get text like "5 years ago" from a date */
|
||||||
export function getFromNowStr(date: Date) {
|
export function getFromNowStr(date: Date) {
|
||||||
// Get fromNow in correct locale
|
// Get fromNow in correct locale
|
||||||
|
|
Loading…
Reference in New Issue