mirror of
https://github.com/nextcloud/server.git
synced 2026-04-24 15:53:36 -04:00
Merge pull request #46307 from nextcloud/artonge/feat/improve_grid_view
This commit is contained in:
commit
a98a0eb7cd
7 changed files with 98 additions and 63 deletions
|
|
@ -121,18 +121,10 @@ export default defineComponent({
|
|||
],
|
||||
|
||||
props: {
|
||||
isMtimeAvailable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isSizeAvailable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
setup() {
|
||||
|
|
@ -204,23 +196,7 @@ 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))`,
|
||||
}
|
||||
},
|
||||
mtimeTitle() {
|
||||
if (this.source.mtime) {
|
||||
return moment(this.source.mtime).format('LLL')
|
||||
|
|
|
|||
|
|
@ -46,6 +46,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}`"
|
||||
|
|
@ -60,6 +69,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'
|
||||
|
|
@ -80,6 +91,7 @@ export default defineComponent({
|
|||
FileEntryCheckbox,
|
||||
FileEntryName,
|
||||
FileEntryPreview,
|
||||
NcDateTime,
|
||||
},
|
||||
|
||||
mixins: [
|
||||
|
|
|
|||
|
|
@ -37,6 +37,14 @@ export default defineComponent({
|
|||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
isMtimeAvailable: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
compact: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
|
|
@ -148,8 +156,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))`,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -316,7 +316,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;
|
||||
|
|
@ -687,39 +687,56 @@ export default defineComponent({
|
|||
// Grid mode
|
||||
tbody.files-list__tbody.files-list__tbody--grid {
|
||||
--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: 208px;
|
||||
--name-height: 32px;
|
||||
--mtime-height: 16px;
|
||||
--row-width: calc(var(--icon-preview-size));
|
||||
--row-height: calc(var(--icon-preview-size) + var(--name-height) + var(--mtime-height));
|
||||
--checkbox-padding: 0px;
|
||||
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, var(--row-width));
|
||||
grid-gap: 15px;
|
||||
row-gap: 15px;
|
||||
gap: 22px;
|
||||
|
||||
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);
|
||||
padding: var(--item-padding);
|
||||
box-sizing: content-box
|
||||
}
|
||||
|
||||
// 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: 14px;
|
||||
z-index: -1;
|
||||
background: var(--color-main-background);
|
||||
}
|
||||
}
|
||||
|
||||
// Star icon in the top right
|
||||
|
|
@ -735,36 +752,44 @@ 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-icon-preview {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
a.files-list__row-name-link {
|
||||
// Minus action menu
|
||||
width: calc(100% - var(--clickable-area));
|
||||
height: var(--clickable-area);
|
||||
height: var(--name-height);
|
||||
}
|
||||
|
||||
.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: calc(var(--default-font-size) - 4px);
|
||||
}
|
||||
|
||||
.files-list__row-actions {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
right: calc(var(--half-clickable-area) / 2);
|
||||
bottom: calc(var(--mtime-height) / 2);
|
||||
width: var(--clickable-area);
|
||||
height: var(--clickable-area);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -127,13 +127,13 @@ export default Vue.extend({
|
|||
|
||||
itemHeight() {
|
||||
// Align with css in FilesListVirtual
|
||||
// 138px + 44px (name) + 15px (grid gap)
|
||||
return this.gridMode ? (138 + 44 + 15) : 55
|
||||
// 208px + 32px (name) + 16px (mtime) + 16px (padding) + 22px (grid gap)
|
||||
return this.gridMode ? (208 + 32 + 16 + 16 + 22) : 55
|
||||
},
|
||||
// Grid mode only
|
||||
itemWidth() {
|
||||
// 160px + 15px grid gap
|
||||
return 160 + 15
|
||||
// 208px + 16px padding + 22px grid gap
|
||||
return 208 + 16 + 22
|
||||
},
|
||||
|
||||
rowCount() {
|
||||
|
|
|
|||
4
dist/files-main.js
vendored
4
dist/files-main.js
vendored
File diff suppressed because one or more lines are too long
2
dist/files-main.js.map
vendored
2
dist/files-main.js.map
vendored
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue