diff --git a/appinfo/routes.php b/appinfo/routes.php
index dcf300ea..3d0821e2 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -14,6 +14,7 @@ return [
['name' => 'page#favorites', 'url' => '/favorites', 'verb' => 'GET'],
['name' => 'page#videos', 'url' => '/videos', 'verb' => 'GET'],
['name' => 'page#archive', 'url' => '/archive', 'verb' => 'GET'],
+ ['name' => 'page#thisday', 'url' => '/thisday', 'verb' => 'GET'],
// API
['name' => 'api#days', 'url' => '/api/days', 'verb' => 'GET'],
diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php
index 5ade7ec2..3f62dfa7 100644
--- a/lib/Controller/PageController.php
+++ b/lib/Controller/PageController.php
@@ -96,4 +96,12 @@ class PageController extends Controller {
public function archive() {
return $this->main();
}
+
+ /**
+ * @NoAdminRequired
+ * @NoCSRFRequired
+ */
+ public function thisday() {
+ return $this->main();
+ }
}
diff --git a/src/App.vue b/src/App.vue
index 15932ae2..55e702dd 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -23,6 +23,10 @@
:title="t('memories', 'Archive')">
+
+
+
@@ -69,6 +73,7 @@ import FolderIcon from 'vue-material-design-icons/Folder.vue'
import Star from 'vue-material-design-icons/Star.vue'
import Video from 'vue-material-design-icons/Video.vue'
import ArchiveIcon from 'vue-material-design-icons/PackageDown.vue';
+import CalendarIcon from 'vue-material-design-icons/Calendar.vue';
@Component({
components: {
@@ -86,6 +91,7 @@ import ArchiveIcon from 'vue-material-design-icons/PackageDown.vue';
Star,
Video,
ArchiveIcon,
+ CalendarIcon,
},
})
export default class App extends Mixins(GlobalMixin) {
diff --git a/src/components/Timeline.vue b/src/components/Timeline.vue
index 01eba971..9033c822 100644
--- a/src/components/Timeline.vue
+++ b/src/components/Timeline.vue
@@ -519,6 +519,7 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
return this.$route.name === 'timeline' ||
this.$route.name === 'favorites' ||
this.$route.name === 'videos' ||
+ this.$route.name === 'thisday' ||
this.$route.name === 'archive';
}
@@ -559,8 +560,14 @@ export default class Timeline extends Mixins(GlobalMixin, UserConfig) {
try {
this.loading++;
const startState = this.state;
- const res = await axios.get(generateUrl(this.appendQuery(url), params));
- const data = res.data;
+
+ let data: IDay[] = [];
+ if (this.$route.name === 'thisday') {
+ data = await dav.getOnThisDayData();
+ } else {
+ data = (await axios.get(generateUrl(this.appendQuery(url), params))).data;
+ }
+
if (this.state !== startState) return;
await this.processDays(data);
} catch (err) {
diff --git a/src/router.ts b/src/router.ts
index ff0a63b3..3a7345ad 100644
--- a/src/router.ts
+++ b/src/router.ts
@@ -90,5 +90,14 @@
rootTitle: t('memories', 'Archive'),
}),
},
+
+ {
+ path: '/thisday',
+ component: Timeline,
+ name: 'thisday',
+ props: route => ({
+ rootTitle: t('memories', 'On this day'),
+ }),
+ },
],
})
\ No newline at end of file
diff --git a/src/services/DavRequests.ts b/src/services/DavRequests.ts
index 005ad75c..697560cf 100644
--- a/src/services/DavRequests.ts
+++ b/src/services/DavRequests.ts
@@ -4,7 +4,7 @@ import { encodePath } from '@nextcloud/paths'
import { showError } from '@nextcloud/dialogs'
import { translate as t, translatePlural as n } from '@nextcloud/l10n'
import { genFileInfo } from './FileUtils'
-import { IFileInfo } from '../types';
+import { IDay, IFileInfo, IPhoto } from '../types';
import axios from '@nextcloud/axios'
import client from './DavClient';
@@ -368,4 +368,60 @@ export async function downloadFilesByIds(fileIds: number[]) {
});
yield* runInParallel(calls, 10);
+}
+
+/**
+ * Get the onThisDay data
+ * Query for last 120 years; should be enough
+ */
+export async function getOnThisDayData() {
+ const diffs: { [dayId: number]: number } = {};
+ const now = new Date();
+ const nowUTC = new Date(now.getTime() - now.getTimezoneOffset() * 60000);
+
+ // Populate dayIds
+ for (let i = 1; i <= 120; i++) {
+ // +- 3 days from this day
+ for (let j = -3; j <= 3; j++) {
+ const d = new Date(nowUTC);
+ d.setFullYear(d.getFullYear() - i);
+ d.setDate(d.getDate() + j);
+ const dayId = Math.floor(d.getTime() / 1000 / 86400)
+ diffs[dayId] = i;
+ }
+ }
+
+ // Query for photos
+ let data: IPhoto[] = [];
+ try {
+ const res = await axios.post(generateUrl('/apps/memories/api/days/BODY'), {
+ body_ids: Object.keys(diffs).join(','),
+ });
+ data = res.data;
+ } catch (e) {
+ throw e;
+ }
+
+ // Group photos by day
+ const ans: IDay[] = [];
+ const prevDayId = Number.MIN_SAFE_INTEGER;
+ for (const photo of data) {
+ if (!photo.dayid) continue;
+
+ // This works because the response is sorted by date taken
+ if (photo.dayid !== prevDayId) {
+ ans.push({
+ dayid: photo.dayid,
+ count: 0,
+ detail: [],
+ });
+ }
+
+ // Add to last day
+ const day = ans[ans.length - 1];
+ day.detail.push(photo);
+ day.count++;
+ }
+
+ return ans;
}
\ No newline at end of file