Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 1 addition & 45 deletions apps/files/src/components/FileEntry.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
class="files-list__row-mtime"
data-cy-files-list-row-mtime
@click="openDetailsIfAvailable">
<NcDateTime v-if="mtime" :timestamp="mtime" :ignore-seconds="true" />
<NcDateTime v-if="source.mtime" :timestamp="source.mtime" :ignore-seconds="true" />
<span v-else>{{ t('files', 'Unknown date') }}</span>
</td>

Expand All @@ -105,7 +105,6 @@
<script lang="ts">
import { defineComponent } from 'vue'
import { formatFileSize } from '@nextcloud/files'
import moment from '@nextcloud/moment'

import { useNavigation } from '../composables/useNavigation'
import { useActionsMenuStore } from '../store/actionsmenu.ts'
Expand Down Expand Up @@ -139,18 +138,10 @@ export default defineComponent({
],

props: {
isMtimeAvailable: {
type: Boolean,
default: false,
},
isSizeAvailable: {
type: Boolean,
default: false,
},
compact: {
type: Boolean,
default: false,
},
},

setup() {
Expand Down Expand Up @@ -222,41 +213,6 @@ export default defineComponent({
color: `color-mix(in srgb, var(--color-main-text) ${ratio}%, var(--color-text-maxcontrast))`,
}
},
mtimeOpacity() {
const maxOpacityTime = 31 * 24 * 60 * 60 * 1000 // 31 days

const mtime = this.source.mtime?.getTime?.()
if (!mtime) {
return {}
}

// 1 = today, 0 = 31 days ago
const ratio = Math.round(Math.min(100, 100 * (maxOpacityTime - (Date.now() - mtime)) / maxOpacityTime))
if (ratio < 0) {
return {}
}
return {
color: `color-mix(in srgb, var(--color-main-text) ${ratio}%, var(--color-text-maxcontrast))`,
}
},
mtime() {
// If the mtime is not a valid date, return it as is
if (this.source.mtime && !isNaN(this.source.mtime.getDate())) {
return this.source.mtime
}

if (this.source.crtime && !isNaN(this.source.crtime.getDate())) {
return this.source.crtime
}

return null
},
mtimeTitle() {
if (this.source.mtime) {
return moment(this.source.mtime).format('LLL')
}
return ''
},
},

methods: {
Expand Down
12 changes: 12 additions & 0 deletions apps/files/src/components/FileEntryGrid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,15 @@
@click.native="execDefaultAction" />
</td>

<!-- Mtime -->
<td v-if="!compact && isMtimeAvailable"
:style="mtimeOpacity"
class="files-list__row-mtime"
data-cy-files-list-row-mtime
@click="openDetailsIfAvailable">
<NcDateTime v-if="source.mtime" :timestamp="source.mtime" :ignore-seconds="true" />
</td>

<!-- Actions -->
<FileEntryActions ref="actions"
:class="`files-list__row-actions-${uniqueId}`"
Expand All @@ -77,6 +86,8 @@
<script lang="ts">
import { defineComponent } from 'vue'

import NcDateTime from '@nextcloud/vue/dist/Components/NcDateTime.js'

import { useNavigation } from '../composables/useNavigation'
import { useActionsMenuStore } from '../store/actionsmenu.ts'
import { useDragAndDropStore } from '../store/dragging.ts'
Expand All @@ -97,6 +108,7 @@ export default defineComponent({
FileEntryCheckbox,
FileEntryName,
FileEntryPreview,
NcDateTime,
},

mixins: [
Expand Down
26 changes: 24 additions & 2 deletions apps/files/src/components/FileEntryMixin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ export default defineComponent({
type: Number,
default: 0,
},
isMtimeAvailable: {
type: Boolean,
default: false,
},
compact: {
type: Boolean,
default: false,
},
},

provide() {
Expand Down Expand Up @@ -179,8 +187,22 @@ export default defineComponent({
},
},

isRenaming() {
return this.renamingStore.renamingNode === this.source
mtimeOpacity() {
const maxOpacityTime = 31 * 24 * 60 * 60 * 1000 // 31 days

const mtime = this.source.mtime?.getTime?.()
if (!mtime) {
return {}
}

// 1 = today, 0 = 31 days ago
const ratio = Math.round(Math.min(100, 100 * (maxOpacityTime - (Date.now() - mtime)) / maxOpacityTime))
if (ratio < 0) {
return {}
}
return {
color: `color-mix(in srgb, var(--color-main-text) ${ratio}%, var(--color-text-maxcontrast))`,
}
},

/**
Expand Down
104 changes: 76 additions & 28 deletions apps/files/src/components/FilesListVirtual.vue
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ export default defineComponent({

--checkbox-padding: calc((var(--row-height) - var(--checkbox-size)) / 2);
--checkbox-size: 24px;
--clickable-area: 44px;
--clickable-area: var(--default-clickable-area);
--icon-preview-size: 32px;

overflow: auto;
Expand Down Expand Up @@ -747,40 +747,58 @@ export default defineComponent({
<style lang="scss">
// Grid mode
tbody.files-list__tbody.files-list__tbody--grid {
--clickable-area: 34px;
--half-clickable-area: calc(var(--clickable-area) / 2);
--row-width: 160px;
// We use half of the clickable area as visual balance margin
--row-height: calc(var(--row-width) - var(--half-clickable-area));
--icon-preview-size: calc(var(--row-width) - var(--clickable-area));
--item-padding: 16px;
--icon-preview-size: 166px;
--name-height: 34px;
--mtime-height: calc(var(--font-size-small, 13px) + var(--default-grid-baseline));
--row-width: calc(var(--icon-preview-size) + var(--item-padding) * 2);
--row-height: calc(var(--icon-preview-size) + var(--name-height) + var(--mtime-height) + var(--item-padding) * 2);
--checkbox-padding: 0px;

display: grid;
grid-template-columns: repeat(auto-fill, var(--row-width));
grid-gap: 15px;
row-gap: 15px;

align-content: center;
align-items: center;
justify-content: space-around;
justify-items: center;
margin: 16px;
width: calc(100% - 32px);

tr {
display: flex;
flex-direction: column;
width: var(--row-width);
height: calc(var(--row-height) + var(--clickable-area));
height: var(--row-height);
border: none;
border-radius: var(--border-radius);
border-radius: var(--border-radius-large);
padding: var(--item-padding);
}

// Checkbox in the top left
.files-list__row-checkbox {
position: absolute;
z-index: 9;
top: 0;
left: 0;
top: calc(var(--item-padding)/2);
left: calc(var(--item-padding)/2);
overflow: hidden;
width: var(--clickable-area);
height: var(--clickable-area);
border-radius: var(--half-clickable-area);
--checkbox-container-size: 44px;
width: var(--checkbox-container-size);
height: var(--checkbox-container-size);

// Add a background to the checkbox so we do not see the image through it.
.checkbox-radio-switch__content::after {
content: '';
width: 16px;
height: 16px;
position: absolute;
left: 50%;
margin-left: -8px;
z-index: -1;
background: var(--color-main-background);
}
}

// Star icon in the top right
Expand All @@ -796,32 +814,62 @@ tbody.files-list__tbody.files-list__tbody--grid {
}

.files-list__row-name {
display: grid;
justify-content: stretch;
width: 100%;
height: 100%;
grid-auto-rows: var(--row-height) var(--clickable-area);
display: flex;
flex-direction: column;
width: var(--icon-preview-size);
height: calc(var(--icon-preview-size) + var(--name-height));
// Ensure that the name outline is visible.
overflow: visible;

span.files-list__row-icon {
width: 100%;
height: 100%;
// Visual balance, we use half of the clickable area
// as a margin around the preview
padding-top: var(--half-clickable-area);
width: var(--icon-preview-size);
height: var(--icon-preview-size);
}

.files-list__row-name-link {
height: var(--name-height);
padding-inline: 0 !important;
}

.files-list__row-name-text {
margin: 0;
padding-right: 0;
// Ensure that the outline is not too close to the text.
margin-left: -4px;
padding: 0px 4px;
}
}

.files-list__row-mtime {
width: var(--icon-preview-size);
height: var(--mtime-height);
font-size: var(--font-size-small, 13px);
}

.files-list__row-actions {
--default-clickable-area: var(--clickable-area);

position: absolute;
right: 0;
bottom: 0;
width: var(--clickable-area);
height: var(--clickable-area);
width: var(--clickable-area);
inset-inline-end: calc(var(--half-clickable-area) / 2);
inset-block-end: calc(var(--mtime-height) / 2);
}
}

@media screen and (max-width: 768px) {
// there is no mtime
tbody.files-list__tbody.files-list__tbody--grid {
--mtime-height: 0px;

// so we move the action to the name
.files-list__row-actions {
inset-block-end: var(--item-padding);
}

// and we need to keep space on the name for the actions
.files-list__row-name-text {
padding-inline-end: var(--clickable-area) !important;
}
}
}
</style>
8 changes: 4 additions & 4 deletions apps/files/src/components/VirtualList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -123,13 +123,13 @@ export default Vue.extend({

itemHeight() {
// Align with css in FilesListVirtual
// 138px + 44px (name) + 15px (grid gap)
return this.gridMode ? (138 + 44 + 15) : 55
// 166px + 32px (name) + 16px (mtime) + 16px (padding)
return this.gridMode ? (166 + 32 + 16 + 16) : 55
},
// Grid mode only
itemWidth() {
// 160px + 15px grid gap
return 160 + 15
// 166px + 16px padding
return 166 + 16
},

rowCount() {
Expand Down
4 changes: 2 additions & 2 deletions dist/files-main.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/files-main.js.map

Large diffs are not rendered by default.

Loading