diff --git a/components/views/files/file/File.vue b/components/views/files/file/File.vue index 5a6c1e6799..ca0623d2c4 100644 --- a/components/views/files/file/File.vue +++ b/components/views/files/file/File.vue @@ -119,7 +119,7 @@ export default Vue.extend({ * @description Open rename modal */ rename() { - this.$store.commit('ui/setRenameItem', this.item.name) + this.$store.commit('ui/setRenameItem', this.item) this.$store.commit('ui/toggleModal', { name: ModalWindows.RENAME_FILE, state: !this.ui.modals[ModalWindows.RENAME_FILE], diff --git a/components/views/files/list/row/Row.vue b/components/views/files/list/row/Row.vue index 9c5779e4de..f644f3dde1 100644 --- a/components/views/files/list/row/Row.vue +++ b/components/views/files/list/row/Row.vue @@ -95,7 +95,7 @@ export default Vue.extend({ * @description Open rename modal */ rename() { - this.$store.commit('ui/setRenameItem', this.item.name) + this.$store.commit('ui/setRenameItem', this.item) this.$store.commit('ui/toggleModal', { name: ModalWindows.RENAME_FILE, state: !this.ui.modals[ModalWindows.RENAME_FILE], diff --git a/components/views/files/rename/Rename.vue b/components/views/files/rename/Rename.vue index 4892db05b6..f6a188ffd6 100644 --- a/components/views/files/rename/Rename.vue +++ b/components/views/files/rename/Rename.vue @@ -4,6 +4,8 @@ import Vue from 'vue' import { mapState, mapGetters } from 'vuex' import { SaveIcon } from 'satellite-lucide-icons' +import { RootState } from '~/types/store/store' +import { Directory } from '~/libraries/Files/Directory' export default Vue.extend({ components: { @@ -18,15 +20,27 @@ export default Vue.extend({ data() { return { text: '' as string, + currentName: '' as string, + parent: null as Directory | null, error: '' as string, } }, computed: { - ...mapState(['ui']), + ...mapState({ + renameItem: (state) => (state as RootState).ui.renameItem, + }), ...mapGetters('ui', ['isFilesIndexLoading']), }, mounted() { - this.text = this.ui.renameCurrentName + if (!this.renameItem) { + this.error = this.$t('pages.files.errors.lost') as string + return + } + // extract data we need from store and then clear to avoid vuex outside mutation error + this.text = this.renameItem.name + this.currentName = this.renameItem.name + this.parent = this.renameItem.parent + this.$store.commit('ui/setRenameItem', undefined) this.$nextTick(() => { // extension string including . const extString = this.text.slice( @@ -49,7 +63,7 @@ export default Vue.extend({ */ async rename() { try { - this.$FileSystem.renameChild(this.ui.renameCurrentName, this.text) + this.$FileSystem.renameChild(this.currentName, this.text, this.parent) } catch (e: any) { this.error = this.$t(e?.message) as string return diff --git a/components/views/files/view/View.vue b/components/views/files/view/View.vue index 6b307f42ad..dd74e10a6f 100644 --- a/components/views/files/view/View.vue +++ b/components/views/files/view/View.vue @@ -10,7 +10,6 @@ import { XIcon, LinkIcon, } from 'satellite-lucide-icons' -import { Fil } from '~/libraries/Files/Fil' import { RootState } from '~/types/store/store' export default Vue.extend({ @@ -22,24 +21,19 @@ export default Vue.extend({ XIcon, LinkIcon, }, - data() { - return { - file: undefined as Fil | undefined, - } - }, computed: { ...mapState({ - ui: (state) => (state as RootState).ui, + file: (state) => (state as RootState).ui.filePreview, + fileDownloadList: (state) => (state as RootState).ui.fileDownloadList, blockNsfw: (state) => (state as RootState).settings.blockNsfw, }), ...mapGetters('ui', ['isFilesIndexLoading']), isDownloading(): boolean { - return this.ui.fileDownloadList.includes(this.file?.name) + return this.file?.name + ? this.fileDownloadList.includes(this.file.name) + : false }, }, - created() { - this.file = this.$FileSystem.getChild(this.ui.filePreview) as Fil - }, methods: { /** * @method download diff --git a/libraries/Files/FilSystem.ts b/libraries/Files/FilSystem.ts index 63edb15ca0..33b6fe6373 100644 --- a/libraries/Files/FilSystem.ts +++ b/libraries/Files/FilSystem.ts @@ -367,18 +367,26 @@ export class FilSystem { /** * @method addChild * @argument {Item} child item to add to the filesystem + * @argument {Directory | null} parentDir optional parent directory, this is needed for special routes like recent files * @returns {boolean} returns truthy if the child was added */ - public addChild(child: Item): boolean { + public addChild(child: Item, parentDir?: Directory): boolean { + if (parentDir) { + return parentDir.addChild(child) + } return this.currentDirectory.addChild(child) } /** * @method getChild * @argument {string} childName name of the child to fetch - * @returns {Directory | Item} returns directory or Fil + * @argument {Directory | null} parentDir optional parent directory, this is needed for special routes like recent files + * @returns {Item} Directory or Fil in question */ - public getChild(childName: string): Item { + public getChild(childName: string, parentDir?: Directory | null): Item { + if (parentDir) { + return parentDir.getChild(childName) + } return this.currentDirectory.getChild(childName) } @@ -396,9 +404,13 @@ export class FilSystem { /** * @method removeChild * @argument {string} childName name of the child to remove + * @argument {Directory | null} parentDir optional parent directory, this is needed for special routes like recent files * @returns {boolean} returns truthy if child was removed */ - public removeChild(childName: string): boolean { + public removeChild(childName: string, parentDir?: Directory | null): boolean { + if (parentDir) { + return parentDir.removeChild(childName) + } return this.currentDirectory.removeChild(childName) } @@ -406,17 +418,22 @@ export class FilSystem { * @method removeChild * @argument {string} currentName name of the child to remove * @argument {string} newName + * @argument {Directory | null} parentDir optional parent directory, this is needed for special routes like recent files * @returns {Item | null} returns new item or null if no item exists */ - public renameChild(currentName: string, newName: string): Item | null { - const item = this.getChild(currentName) + public renameChild( + currentName: string, + newName: string, + parentDir?: Directory | null, + ): Item | null { + const item = this.getChild(currentName, parentDir) if (!item) { return null } item.name = newName - this.removeChild(currentName) - this.addChild(item) + this.removeChild(currentName, parentDir) + this.addChild(item, parentDir) return item } diff --git a/locales/en-US.js b/locales/en-US.js index 0052a618c8..757681cd4d 100644 --- a/locales/en-US.js +++ b/locales/en-US.js @@ -190,6 +190,7 @@ export default { in_progress: 'Upload already in progress, try again later', enable_consent: 'Please consent to file scanning in your privacy settings', + lost: 'Cannot find file, please try again later', }, }, unlock: { diff --git a/pages/files/browse/index.vue b/pages/files/browse/index.vue index c2a2fafb48..929334a7c0 100644 --- a/pages/files/browse/index.vue +++ b/pages/files/browse/index.vue @@ -73,7 +73,7 @@ export default Vue.extend({ */ handle(item: Item) { if (item instanceof Fil) { - this.$store.commit('ui/setFilePreview', item.name) + this.$store.commit('ui/setFilePreview', item) } if (item instanceof Directory) { this.fileSystem.openDirectory(item.name) @@ -110,7 +110,7 @@ export default Vue.extend({ ) await this.$FileSystem.removeFile(item.id) } - this.$FileSystem.removeChild(item.name) + this.$FileSystem.removeChild(item.name, item.parent) this.$store.commit( 'ui/setFilesUploadStatus', this.$t('pages.files.status.index'), diff --git a/store/ui/__snapshots__/state.test.ts.snap b/store/ui/__snapshots__/state.test.ts.snap index bfcbffe8c1..511de442b4 100644 --- a/store/ui/__snapshots__/state.test.ts.snap +++ b/store/ui/__snapshots__/state.test.ts.snap @@ -73,7 +73,7 @@ Object { "y": 0, }, "recentGlyphs": Array [], - "renameCurrentName": undefined, + "renameItem": undefined, "replyChatbarContent": Object { "from": "", "id": "", diff --git a/store/ui/mutations.test.ts b/store/ui/mutations.test.ts index e7b8df07e9..2288952e4e 100644 --- a/store/ui/mutations.test.ts +++ b/store/ui/mutations.test.ts @@ -5,6 +5,7 @@ import { DataStateType } from '~/store/dataState/types' import { CaptureMouseTypes } from '~/store/settings/types' import { FlairColors, ThemeNames } from '~/store/ui/types' import { Fil } from '~/libraries/Files/Fil' +import { DIRECTORY_TYPE } from '~/libraries/Files/types/directory' // So we don't have annoying snapshot fails. (https://stackoverflow.com/questions/42935903/jest-snapshot-testing-how-to-ignore-part-of-the-snapshot-file-in-jest-test-resu) Date.now = jest.fn(() => 1645617999076) @@ -2511,6 +2512,7 @@ describe('mutations', () => { }, isLoadingFileIndex: true, fileDownloadList: ['string'], + renameItem: {}, } test('togglePinned', () => { @@ -3100,8 +3102,14 @@ describe('mutations', () => { }) test('setRenameItem', () => { const localizedState = { ...initialState } - mutations.default.setRenameItem(localizedState, 'new name') - expect(localizedState.renameCurrentName).toBe('new name') + const mockDirectoryData = { + name: 'Test Directory', + liked: false, + shared: false, + type: DIRECTORY_TYPE.DEFAULT, + } + mutations.default.setRenameItem(localizedState, mockDirectoryData) + expect(localizedState.renameItem).toBe(mockDirectoryData) }) test('setSettingsRoute', () => { const localizedState = { ...initialState } diff --git a/store/ui/mutations.ts b/store/ui/mutations.ts index f690de845f..9ee483e672 100644 --- a/store/ui/mutations.ts +++ b/store/ui/mutations.ts @@ -13,6 +13,7 @@ import { MessageGroup } from '~/types/messaging' import { Channel } from '~/types/ui/server' import { Fil } from '~/libraries/Files/Fil' import { ImageMessage } from '~/types/textile/mailbox' +import { Item } from '~/libraries/Files/abstracts/Item.abstract' export default { togglePinned(state: UIState, visible: boolean) { @@ -51,8 +52,8 @@ export default { fullscreen(state: UIState, fullscreen: boolean) { state.fullscreen = fullscreen }, - setFilePreview(state: UIState, name: string) { - state.filePreview = name + setFilePreview(state: UIState, file: Fil) { + state.filePreview = file }, setChatImageOverlay(state: UIState, image: ImageMessage | undefined) { state.chatImageOverlay = image @@ -347,8 +348,8 @@ export default { setChatbarFocus(state: UIState, status: boolean) { state.chatbarFocus = status }, - setRenameItem(state: UIState, name: string) { - state.renameCurrentName = name + setRenameItem(state: UIState, name: Item) { + state.renameItem = name }, setFileSort(state: UIState, sort: FileSort) { state.fileSort = sort diff --git a/store/ui/state.ts b/store/ui/state.ts index f63a4fcf44..187ba805b9 100644 --- a/store/ui/state.ts +++ b/store/ui/state.ts @@ -74,7 +74,7 @@ const InitialUIState = (): UIState => ({ flair: Flairs[0], }, filesUploadStatus: '', - renameCurrentName: undefined, + renameItem: undefined, filePreview: undefined, fileDownloadList: [], chatImageOverlay: undefined, diff --git a/store/ui/types.ts b/store/ui/types.ts index fe76e7f9c1..34258f36a2 100644 --- a/store/ui/types.ts +++ b/store/ui/types.ts @@ -3,6 +3,8 @@ import { ImageMessage } from '~/types/textile/mailbox' import { FileSortEnum } from '~/libraries/Enums/enums' import { Glyph } from '~/types/ui/glyph' import { Channel } from '~/types/ui/server' +import { Fil } from '~/libraries/Files/Fil' +import { Item } from '~/libraries/Files/abstracts/Item.abstract' export enum ThemeNames { DEFAULT = 'default', MOONLESS = 'moonless_night', @@ -203,8 +205,8 @@ export interface UIState { flair: Flair } filesUploadStatus: string - renameCurrentName?: string - filePreview?: string + renameItem?: Item + filePreview?: Fil fileDownloadList: string[] chatImageOverlay?: ImageMessage fileSort: FileSort