diff options
Diffstat (limited to 'apps/files/src')
-rw-r--r-- | apps/files/src/components/FileEntry.vue | 46 | ||||
-rw-r--r-- | apps/files/src/components/FileEntry/FileEntryPreview.vue | 12 | ||||
-rw-r--r-- | apps/files/src/components/FilesListTableFooter.vue | 8 | ||||
-rw-r--r-- | apps/files/src/components/FilesListTableHeader.vue | 12 | ||||
-rw-r--r-- | apps/files/src/components/FilesListVirtual.vue | 19 | ||||
-rw-r--r-- | apps/files/src/store/renaming.ts | 10 | ||||
-rw-r--r-- | apps/files/src/store/userconfig.ts | 1 | ||||
-rw-r--r-- | apps/files/src/types.ts | 1 | ||||
-rw-r--r-- | apps/files/src/views/Settings.vue | 5 |
9 files changed, 112 insertions, 2 deletions
diff --git a/apps/files/src/components/FileEntry.vue b/apps/files/src/components/FileEntry.vue index 9642c4709d8..d66c3fa0ed7 100644 --- a/apps/files/src/components/FileEntry.vue +++ b/apps/files/src/components/FileEntry.vue @@ -49,6 +49,15 @@ :opened.sync="openedMenu" :source="source" /> + <!-- Mime --> + <td v-if="isMimeAvailable" + :title="mime" + class="files-list__row-mime" + data-cy-files-list-row-mime + @click="openDetailsIfAvailable"> + <span>{{ mime }}</span> + </td> + <!-- Size --> <td v-if="!compact && isSizeAvailable" :style="sizeOpacity" @@ -85,9 +94,10 @@ </template> <script lang="ts"> -import { formatFileSize } from '@nextcloud/files' +import { FileType, formatFileSize } from '@nextcloud/files' import { useHotKey } from '@nextcloud/vue/composables/useHotKey' import { defineComponent } from 'vue' +import { t } from '@nextcloud/l10n' import NcDateTime from '@nextcloud/vue/components/NcDateTime' import { useNavigation } from '../composables/useNavigation.ts' @@ -123,6 +133,10 @@ export default defineComponent({ ], props: { + isMimeAvailable: { + type: Boolean, + default: false, + }, isSizeAvailable: { type: Boolean, default: false, @@ -186,6 +200,36 @@ export default defineComponent({ return this.currentView.columns || [] }, + mime() { + if (this.source.type === FileType.Folder) { + return this.t('files', 'Folder') + } + + if (!this.source.mime || this.source.mime === 'application/octet-stream') { + return t('files', 'Unknown file type') + } + + if (window.OC?.MimeTypeList?.names?.[this.source.mime]) { + return window.OC.MimeTypeList.names[this.source.mime] + } + + const baseType = this.source.mime.split('/')[0] + const ext = this.source?.extension?.toUpperCase().replace(/^\./, '') || '' + if (baseType === 'image') { + return t('files', '{ext} image', { ext }) + } + if (baseType === 'video') { + return t('files', '{ext} video', { ext }) + } + if (baseType === 'audio') { + return t('files', '{ext} audio', { ext }) + } + if (baseType === 'text') { + return t('files', '{ext} text', { ext }) + } + + return this.source.mime + }, size() { const size = this.source.size if (size === undefined || isNaN(size) || size < 0) { diff --git a/apps/files/src/components/FileEntry/FileEntryPreview.vue b/apps/files/src/components/FileEntry/FileEntryPreview.vue index 2d5844f851f..506677b49af 100644 --- a/apps/files/src/components/FileEntry/FileEntryPreview.vue +++ b/apps/files/src/components/FileEntry/FileEntryPreview.vue @@ -21,6 +21,7 @@ class="files-list__row-icon-blurhash" aria-hidden="true" /> <img v-if="backgroundFailed !== true" + :key="source.fileid" ref="previewImg" alt="" class="files-list__row-icon-preview" @@ -147,6 +148,17 @@ export default defineComponent({ return null } + if (this.source.attributes['has-preview'] !== true + && this.source.mime !== undefined + && this.source.mime !== 'application/octet-stream' + ) { + const previewUrl = generateUrl('/core/mimeicon?mime={mime}', { + mime: this.source.mime, + }) + const url = new URL(window.location.origin + previewUrl) + return url.href + } + try { const previewUrl = this.source.attributes.previewUrl || (this.isPublic diff --git a/apps/files/src/components/FilesListTableFooter.vue b/apps/files/src/components/FilesListTableFooter.vue index 63d692c100d..9e8cdc159ee 100644 --- a/apps/files/src/components/FilesListTableFooter.vue +++ b/apps/files/src/components/FilesListTableFooter.vue @@ -21,6 +21,10 @@ <!-- Actions --> <td class="files-list__row-actions" /> + <!-- Mime --> + <td v-if="isMimeAvailable" + class="files-list__column files-list__row-mime" /> + <!-- Size --> <td v-if="isSizeAvailable" class="files-list__column files-list__row-size"> @@ -60,6 +64,10 @@ export default defineComponent({ type: View, required: true, }, + isMimeAvailable: { + type: Boolean, + default: false, + }, isMtimeAvailable: { type: Boolean, default: false, diff --git a/apps/files/src/components/FilesListTableHeader.vue b/apps/files/src/components/FilesListTableHeader.vue index 341d5e1347d..23e631199eb 100644 --- a/apps/files/src/components/FilesListTableHeader.vue +++ b/apps/files/src/components/FilesListTableHeader.vue @@ -24,6 +24,14 @@ <!-- Actions --> <th class="files-list__row-actions" /> + <!-- Mime --> + <th v-if="isMimeAvailable" + class="files-list__column files-list__row-mime" + :class="{ 'files-list__column--sortable': isMimeAvailable }" + :aria-sort="ariaSortForMode('mime')"> + <FilesListTableHeaderButton :name="t('files', 'File type')" mode="mime" /> + </th> + <!-- Size --> <th v-if="isSizeAvailable" class="files-list__column files-list__row-size" @@ -83,6 +91,10 @@ export default defineComponent({ ], props: { + isMimeAvailable: { + type: Boolean, + default: false, + }, isMtimeAvailable: { type: Boolean, default: false, diff --git a/apps/files/src/components/FilesListVirtual.vue b/apps/files/src/components/FilesListVirtual.vue index 93f567f25a4..8fdc87b154c 100644 --- a/apps/files/src/components/FilesListVirtual.vue +++ b/apps/files/src/components/FilesListVirtual.vue @@ -9,6 +9,7 @@ :data-sources="nodes" :grid-mode="userConfig.grid_view" :extra-props="{ + isMimeAvailable, isMtimeAvailable, isSizeAvailable, nodes, @@ -39,6 +40,7 @@ <!-- Table header and sort buttons --> <FilesListTableHeader ref="thead" :files-list-width="fileListWidth" + :is-mime-available="isMimeAvailable" :is-mtime-available="isMtimeAvailable" :is-size-available="isSizeAvailable" :nodes="nodes" /> @@ -48,6 +50,7 @@ <template #footer> <FilesListTableFooter :current-view="currentView" :files-list-width="fileListWidth" + :is-mime-available="isMimeAvailable" :is-mtime-available="isMtimeAvailable" :is-size-available="isSizeAvailable" :nodes="nodes" @@ -155,6 +158,16 @@ export default defineComponent({ return this.userConfigStore.userConfig }, + isMimeAvailable() { + if (!this.userConfig.show_mime_column) { + return false + } + // Hide mime column on narrow screens + if (this.fileListWidth < 1024) { + return false + } + return this.nodes.some(node => node.mime !== undefined || node.mime !== 'application/octet-stream') + }, isMtimeAvailable() { // Hide mtime column on narrow screens if (this.fileListWidth < 768) { @@ -829,10 +842,12 @@ export default defineComponent({ margin-inline-end: 7px; } + .files-list__row-mime, .files-list__row-mtime, .files-list__row-size { color: var(--color-text-maxcontrast); } + .files-list__row-size { width: calc(var(--row-height) * 1.5); // Right align content/text @@ -843,6 +858,10 @@ export default defineComponent({ width: calc(var(--row-height) * 2); } + .files-list__row-mime { + width: calc(var(--row-height) * 2.5); + } + .files-list__row-column-custom { width: calc(var(--row-height) * 2); } diff --git a/apps/files/src/store/renaming.ts b/apps/files/src/store/renaming.ts index 2ac9e06ba16..fc61be3bd3b 100644 --- a/apps/files/src/store/renaming.ts +++ b/apps/files/src/store/renaming.ts @@ -14,6 +14,7 @@ import { defineStore } from 'pinia' import logger from '../logger' import Vue, { defineAsyncComponent, ref } from 'vue' import { useUserConfigStore } from './userconfig' +import { fetchNode } from '../services/WebdavClient' export const useRenamingStore = defineStore('renaming', () => { /** @@ -48,7 +49,7 @@ export const useRenamingStore = defineStore('renaming', () => { } isRenaming.value = true - const node = renamingNode.value + let node = renamingNode.value Vue.set(node, 'status', NodeStatus.LOADING) const userConfig = useUserConfigStore() @@ -86,6 +87,13 @@ export const useRenamingStore = defineStore('renaming', () => { }, }) + // Update mime type if extension changed + // as other related informations might have changed + // on the backend but it is really hard to know on the front + if (oldExtension !== newExtension) { + node = await fetchNode(node.path) + } + // Success 🎉 emit('files:node:updated', node) emit('files:node:renamed', node) diff --git a/apps/files/src/store/userconfig.ts b/apps/files/src/store/userconfig.ts index d84a5e0d935..d136561c2e5 100644 --- a/apps/files/src/store/userconfig.ts +++ b/apps/files/src/store/userconfig.ts @@ -17,6 +17,7 @@ const initialUserConfig = loadState<UserConfig>('files', 'config', { sort_favorites_first: true, sort_folders_first: true, grid_view: false, + show_mime_column: true, show_dialog_file_extension: true, }) diff --git a/apps/files/src/types.ts b/apps/files/src/types.ts index 4bf8a557f49..db3de13d4eb 100644 --- a/apps/files/src/types.ts +++ b/apps/files/src/types.ts @@ -58,6 +58,7 @@ export interface UserConfig { sort_favorites_first: boolean sort_folders_first: boolean grid_view: boolean + show_mime_column: boolean } export interface UserConfigStore { userConfig: UserConfig diff --git a/apps/files/src/views/Settings.vue b/apps/files/src/views/Settings.vue index 872b8a8e6d3..a9967fdbef9 100644 --- a/apps/files/src/views/Settings.vue +++ b/apps/files/src/views/Settings.vue @@ -24,6 +24,11 @@ @update:checked="setConfig('show_hidden', $event)"> {{ t('files', 'Show hidden files') }} </NcCheckboxRadioSwitch> + <NcCheckboxRadioSwitch data-cy-files-settings-setting="show_mime_column" + :checked="userConfig.show_mime_column" + @update:checked="setConfig('show_mime_column', $event)"> + {{ t('files', 'Show file type column') }} + </NcCheckboxRadioSwitch> <NcCheckboxRadioSwitch data-cy-files-settings-setting="crop_image_previews" :checked="userConfig.crop_image_previews" @update:checked="setConfig('crop_image_previews', $event)"> |