Skip to content

Commit 0142738

Browse files
feat: set creation_time on file creation and render recently created icon
Signed-off-by: Cristian Scheid <cristianscheid@gmail.com>
1 parent 85d5e5c commit 0142738

5 files changed

Lines changed: 115 additions & 4 deletions

File tree

apps/files/src/components/FileEntry/FileEntryPreview.vue

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ export default Vue.extend({
8080
LinkIcon,
8181
NetworkIcon,
8282
TagIcon,
83+
RecentlyCreatedIcon,
8384
},
8485
8586
props: {
@@ -118,6 +119,29 @@ export default Vue.extend({
118119
return this.source.attributes.favorite === 1
119120
},
120121
122+
isRecentlyCreated(): boolean {
123+
if (this.source.attributes.upload_time) {
124+
return false
125+
}
126+
127+
const creationDate = this.source.attributes.creationdate
128+
? new Date(this.source.attributes.creationdate)
129+
: null
130+
131+
if (!creationDate) {
132+
return false
133+
}
134+
135+
const oneDayAgo = new Date()
136+
oneDayAgo.setDate(oneDayAgo.getDate() - 1)
137+
138+
return creationDate > oneDayAgo
139+
},
140+
141+
isRecentView(): boolean {
142+
return this.$route?.params?.view === 'recent'
143+
},
144+
121145
userConfig(): UserConfig {
122146
return this.userConfigStore.userConfig
123147
},
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<!--
2+
- SPDX-FileCopyrightText: 2026 Nextcloud GmbH and Nextcloud contributors
3+
- SPDX-License-Identifier: AGPL-3.0-or-later
4+
-->
5+
<template>
6+
<NcIconSvgWrapper class="recently-created-marker-icon" :name="t('files', 'Recently created')" :svg="PlusSvg" />
7+
</template>
8+
9+
<script lang="ts">
10+
import PlusSvg from '@mdi/svg/svg/plus.svg?raw'
11+
import { translate as t } from '@nextcloud/l10n'
12+
import { defineComponent } from 'vue'
13+
import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
14+
15+
/**
16+
* A recently created icon to be used for overlaying recently created entries like the file preview / icon
17+
* It has a stroke around the icon to ensure enough contrast for accessibility.
18+
*
19+
* If the background has a hover state you might want to also apply it to the stroke like this:
20+
* ```scss
21+
* .parent:hover :deep(.favorite-marker-icon svg path) {
22+
* stroke: var(--color-background-hover);
23+
* }
24+
* ```
25+
*/
26+
export default defineComponent({
27+
name: 'RecentlyCreatedIcon',
28+
components: {
29+
NcIconSvgWrapper,
30+
},
31+
32+
data() {
33+
return {
34+
PlusSvg,
35+
}
36+
},
37+
38+
async mounted() {
39+
await this.$nextTick()
40+
// MDI default viewBox is "0 0 24 24" but we add a stroke of 10px so we must adjust it
41+
const el = this.$el.querySelector('svg')
42+
el?.setAttribute?.('viewBox', '-4 -4 30 30')
43+
},
44+
45+
methods: {
46+
t,
47+
},
48+
})
49+
</script>
50+
51+
<style lang="scss" scoped>
52+
.recently-created-marker-icon {
53+
color: var(--color-element-success);
54+
// Override NcIconSvgWrapper defaults (clickable area)
55+
min-width: unset !important;
56+
min-height: unset !important;
57+
58+
:deep() {
59+
svg {
60+
// We added a stroke for a11y so we must increase the size to include the stroke
61+
width: 20px !important;
62+
height: 20px !important;
63+
64+
// Override NcIconSvgWrapper defaults of 20px
65+
max-width: unset !important;
66+
max-height: unset !important;
67+
68+
// Show a border around the icon for better contrast
69+
path {
70+
stroke: var(--color-main-background);
71+
stroke-width: 8px;
72+
stroke-linejoin: round;
73+
paint-order: stroke;
74+
}
75+
}
76+
}
77+
}
78+
</style>

apps/files/src/components/FilesListVirtual.vue

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,7 @@ export default defineComponent({
584584
& > span {
585585
justify-content: flex-start;
586586
587-
&:not(.files-list__row-icon-favorite) svg {
587+
&:not(.files-list__row-icon-favorite):not(.files-list__row-icon-recently-created) svg {
588588
width: var(--icon-preview-size);
589589
height: var(--icon-preview-size);
590590
}
@@ -616,7 +616,8 @@ export default defineComponent({
616616
}
617617
}
618618
619-
&-favorite {
619+
&-favorite,
620+
&-recently-created {
620621
position: absolute;
621622
top: 0px;
622623
right: -10px;
@@ -813,8 +814,9 @@ export default defineComponent({
813814
}
814815
}
815816
816-
// Star icon in the top right
817-
.files-list__row-icon-favorite {
817+
// Icon in the top right
818+
.files-list__row-icon-favorite,
819+
.files-list__row-icon-recently-created {
818820
position: absolute;
819821
top: 0;
820822
right: 0;

lib/private/Files/Cache/Cache.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,12 @@ public function getFolderContentsById($fileId) {
230230
* @throws \RuntimeException
231231
*/
232232
public function put($file, array $data) {
233+
// do not carry over creation_time to file versions, as each new version would otherwise
234+
// create a filecache_extended entry with the same creation_time as the original file
235+
if (str_starts_with($file, 'files_versions/')) {
236+
unset($data['creation_time']);
237+
}
238+
233239
if (($id = $this->getId($file)) > -1) {
234240
$this->update($id, $data);
235241
return $id;

lib/private/Files/Node/Folder.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ public function newFile($path, $content = null) {
186186
throw new NotPermittedException('Could not create path "' . $fullPath . '"');
187187
}
188188
$node = new File($this->root, $this->view, $fullPath, null, $this);
189+
$this->view->putFileInfo($fullPath, ['creation_time' => time()]);
189190
$this->sendHooks(['postWrite', 'postCreate'], [$node]);
190191
return $node;
191192
}

0 commit comments

Comments
 (0)