fix: use local time for time buckets and improve memories (#4072)

* fix: timezone bucket timezones

* chore: open api

* fix: interpret local time in utc

* fix: tests

* fix: refactor memory lane

* fix(web): use local date in memory viewer

* chore: set localDateTime non-null

* fix: filter out memories from the current year

* wip: move localDateTime to asset

* fix: correct sorting from db

* fix: migration

* fix: web typo

* fix: formatting

* fix: e2e

* chore: localDateTime is non-null

* chore: more non-nulliness

* fix: asset stub

* fix: tests

* fix: use extract and index for day of year

* fix: don't show memories before today

* fix: cleanup

* fix: tests

* fix: only use localtime for tz

* fix: display memories in client timezone

* fix: tests

* fix: svelte tests

* fix: bugs

* chore: open api

---------

Co-authored-by: Jonathan Jogenfors <jonathan@jogenfors.se>
This commit is contained in:
Jason Rasmussen
2023-10-04 18:11:11 -04:00
committed by GitHub
parent 126dd45751
commit 192e950567
32 changed files with 337 additions and 147 deletions

View File

@@ -669,6 +669,12 @@ export interface AssetResponseDto {
* @memberof AssetResponseDto
*/
'livePhotoVideoId'?: string | null;
/**
*
* @type {string}
* @memberof AssetResponseDto
*/
'localDateTime': string;
/**
*
* @type {string}
@@ -6340,13 +6346,16 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
},
/**
*
* @param {string} timestamp Get pictures for +24 hours from this time going back x years
* @param {number} day
* @param {number} month
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getMemoryLane: async (timestamp: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'timestamp' is not null or undefined
assertParamExists('getMemoryLane', 'timestamp', timestamp)
getMemoryLane: async (day: number, month: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
// verify required parameter 'day' is not null or undefined
assertParamExists('getMemoryLane', 'day', day)
// verify required parameter 'month' is not null or undefined
assertParamExists('getMemoryLane', 'month', month)
const localVarPath = `/asset/memory-lane`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@@ -6368,10 +6377,12 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
// http bearer authentication required
await setBearerAuthToObject(localVarHeaderParameter, configuration)
if (timestamp !== undefined) {
localVarQueryParameter['timestamp'] = (timestamp as any instanceof Date) ?
(timestamp as any).toISOString() :
timestamp;
if (day !== undefined) {
localVarQueryParameter['day'] = day;
}
if (month !== undefined) {
localVarQueryParameter['month'] = month;
}
@@ -7152,12 +7163,13 @@ export const AssetApiFp = function(configuration?: Configuration) {
},
/**
*
* @param {string} timestamp Get pictures for +24 hours from this time going back x years
* @param {number} day
* @param {number} month
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getMemoryLane(timestamp: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MemoryLaneResponseDto>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getMemoryLane(timestamp, options);
async getMemoryLane(day: number, month: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MemoryLaneResponseDto>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getMemoryLane(day, month, options);
return createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration);
},
/**
@@ -7443,7 +7455,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
* @throws {RequiredError}
*/
getMemoryLane(requestParameters: AssetApiGetMemoryLaneRequest, options?: AxiosRequestConfig): AxiosPromise<Array<MemoryLaneResponseDto>> {
return localVarFp.getMemoryLane(requestParameters.timestamp, options).then((request) => request(axios, basePath));
return localVarFp.getMemoryLane(requestParameters.day, requestParameters.month, options).then((request) => request(axios, basePath));
},
/**
*
@@ -7888,11 +7900,18 @@ export interface AssetApiGetMapMarkersRequest {
*/
export interface AssetApiGetMemoryLaneRequest {
/**
* Get pictures for +24 hours from this time going back x years
* @type {string}
*
* @type {number}
* @memberof AssetApiGetMemoryLane
*/
readonly timestamp: string
readonly day: number
/**
*
* @type {number}
* @memberof AssetApiGetMemoryLane
*/
readonly month: number
}
/**
@@ -8398,7 +8417,7 @@ export class AssetApi extends BaseAPI {
* @memberof AssetApi
*/
public getMemoryLane(requestParameters: AssetApiGetMemoryLaneRequest, options?: AxiosRequestConfig) {
return AssetApiFp(this.configuration).getMemoryLane(requestParameters.timestamp, options).then((request) => request(this.axios, this.basePath));
return AssetApiFp(this.configuration).getMemoryLane(requestParameters.day, requestParameters.month, options).then((request) => request(this.axios, this.basePath));
}
/**

View File

@@ -87,8 +87,10 @@
onMount(async () => {
if (!$memoryStore) {
const localTime = new Date();
const { data } = await api.assetApi.getMemoryLane({
timestamp: DateTime.local().startOf('day').toISO() || '',
month: localTime.getMonth() + 1,
day: localTime.getDate(),
});
$memoryStore = data;
}
@@ -212,7 +214,7 @@
<div class="absolute left-8 top-4 text-sm font-medium text-white">
<p>
{DateTime.fromISO(currentMemory.assets[0].fileCreatedAt).toLocaleString(DateTime.DATE_FULL)}
{DateTime.fromISO(currentMemory.assets[0].localDateTime).toLocaleString(DateTime.DATE_FULL)}
</p>
<p>
{currentAsset.exifInfo?.city || ''}

View File

@@ -126,7 +126,8 @@
<section id="asset-group-by-date" class="flex flex-wrap gap-x-12" bind:clientHeight={actualBucketHeight}>
{#each assetsGroupByDate as groupAssets, groupIndex (groupAssets[0].id)}
{@const groupTitle = formatGroupTitle(DateTime.fromISO(groupAssets[0].fileCreatedAt).startOf('day'))}
{@const asset = groupAssets[0]}
{@const groupTitle = formatGroupTitle(DateTime.fromISO(asset.localDateTime).startOf('day'))}
<!-- Asset Group By Date -->
<!-- svelte-ignore a11y-no-static-element-interactions -->

View File

@@ -1,6 +1,5 @@
<script lang="ts">
import { onMount } from 'svelte';
import { DateTime } from 'luxon';
import { api } from '@api';
import ChevronLeft from 'svelte-material-icons/ChevronLeft.svelte';
import ChevronRight from 'svelte-material-icons/ChevronRight.svelte';
@@ -11,8 +10,10 @@
$: shouldRender = $memoryStore?.length > 0;
onMount(async () => {
const localTime = new Date();
const { data } = await api.assetApi.getMemoryLane({
timestamp: DateTime.local().startOf('day').toISO() || '',
month: localTime.getMonth() + 1,
day: localTime.getDate(),
});
$memoryStore = data;
});

View File

@@ -45,7 +45,7 @@ export function splitBucketIntoDateGroups(
): AssetResponseDto[][] {
return lodash
.chain(assets)
.groupBy((a) => new Date(a.fileCreatedAt).toLocaleDateString(locale, groupDateFormat))
.groupBy((asset) => new Date(asset.localDateTime).toLocaleDateString(locale, groupDateFormat))
.sortBy((group) => assets.indexOf(group[0]))
.value();
}