Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(files): rename files and directories #2445

Merged
merged 11 commits into from
Mar 25, 2022
1 change: 1 addition & 0 deletions components/interactables/InputGroup/InputGroup.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
:disabled="disabled"
v-on:keyup.enter="action"
@input="update"
ref="input"
/>
</div>
<div class="control" data-cy="submit-input">
Expand Down
11 changes: 10 additions & 1 deletion components/ui/Global/Global.html
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
:close-modal="() => toggleModal(ModalWindows.GLYPH)"
nopad
v-click-outside="() => toggleModal(ModalWindows.GLYPH)"
:small="true"
small
>
<Glyphs
v-click-outside="() => toggleModal(ModalWindows.GLYPH)"
Expand All @@ -78,6 +78,15 @@
>
<CallToAction :close-modal="() => toggleModal(ModalWindows.CALLTOACTION)" />
</UiModal>
<UiModal
v-if="ui.modals.renameFile"
:close-modal="() => toggleModal(ModalWindows.RENAME_FILE)"
v-click-outside="() => toggleModal(ModalWindows.RENAME_FILE)"
small
nopad
>
<FilesRename :close-modal="() => toggleModal(ModalWindows.RENAME_FILE)" />
</UiModal>
<UiUpdateModal
v-if="ui.modals.changelog"
v-click-outside="() => toggleModal(ModalWindows.CHANGELOG)"
Expand Down
4 changes: 2 additions & 2 deletions components/ui/Modal/Modal.less
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@
.modal {
height: @full;
&.small {
height: 40vh;
margin-top: auto;
height: auto;
top: inherit;
}
}
.modal-card {
Expand Down
2 changes: 1 addition & 1 deletion components/views/files/file/File.less
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
.maintext {
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
white-space: pre;
}
.subtext {
&:extend(.font-muted);
Expand Down
19 changes: 12 additions & 7 deletions components/views/files/file/File.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import ContextMenu from '~/components/mixins/UI/ContextMenu'
import { Item } from '~/libraries/Files/abstracts/Item.abstract'
import { Directory } from '~/libraries/Files/Directory'
import { Fil } from '~/libraries/Files/Fil'
import { ModalWindows } from '~/store/ui/types'

declare module 'vue/types/vue' {
interface Vue {
Expand Down Expand Up @@ -111,6 +112,17 @@ export default Vue.extend({
}
this.$emit('handle', this.item)
},
/**
* @method rename
* @description Open rename modal
*/
rename() {
this.$store.commit('ui/setRenameItem', this.item.name)
this.$store.commit('ui/toggleModal', {
name: ModalWindows.RENAME_FILE,
state: !this.ui.modals[ModalWindows.RENAME_FILE],
})
},
/**
* @method like
* @description Emit to like item - pages/files/browse/index.vue
Expand All @@ -125,13 +137,6 @@ export default Vue.extend({
share() {
this.$emit('share', this.item)
},
/**
* @method rename
* @description Emit to rename item - pages/files/browse/index.vue
*/
rename() {
this.$emit('rename', this.item)
},
/**
* @method remove
* @description Emit to delete item - pages/files/browse/index.vue
Expand Down
1 change: 0 additions & 1 deletion components/views/files/grid/Grid.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
:key="i + counter"
@like="like"
@share="share"
@rename="rename"
@remove="remove"
@handle="handle"
/>
Expand Down
7 changes: 0 additions & 7 deletions components/views/files/grid/Grid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ export default Vue.extend({
share(item: Item) {
this.$emit('share', item)
},
/**
* @method rename
* @description Emit to rename item - pages/files/browse/index.vue
*/
rename(item: Item) {
this.$emit('rename', item)
},
/**
* @method remove
* @description Emit to delete item - pages/files/browse/index.vue
Expand Down
1 change: 0 additions & 1 deletion components/views/files/list/List.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
:item="item"
@like="like"
@share="share"
@rename="rename"
@remove="remove"
@handle="handle"
/>
Expand Down
7 changes: 0 additions & 7 deletions components/views/files/list/List.vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,6 @@ export default Vue.extend({
share(item: Item) {
this.$emit('share', item)
},
/**
* @method rename
* @description Emit to rename item - pages/files/browse/index.vue
*/
rename(item: Item) {
this.$emit('rename', item)
},
/**
* @method remove
* @description Emit to delete item - pages/files/browse/index.vue
Expand Down
15 changes: 15 additions & 0 deletions components/views/files/rename/Rename.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<div class="rename">
<InteractablesClose :action="closeModal" />
<TypographyTitle :size="3" :text="$t('modal.rename')" />
<InteractablesInputGroup
type="primary"
v-model="text"
:action="rename"
:loading="ui.isLoadingFileIndex"
:disabled="ui.isLoadingFileIndex"
ref="inputGroup"
>
<save-icon size="1.3x" />
</InteractablesInputGroup>
<TypographyError v-if="error" :text="error" />
</div>
19 changes: 19 additions & 0 deletions components/views/files/rename/Rename.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.rename {
display: flex;
flex-direction: column;
min-width: 450px;
padding: @large-spacing;
&:extend(.modal-gradient);
gap: @light-spacing;

.title {
color: @secondary-text;
font-weight: 400;
}
}

@media only screen and (max-width: @mobile-breakpoint) {
.rename {
min-width: auto;
}
}
66 changes: 66 additions & 0 deletions components/views/files/rename/Rename.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<template src="./Rename.html"></template>

<script lang="ts">
import Vue from 'vue'
import { mapState } from 'vuex'
import { SaveIcon } from 'satellite-lucide-icons'

export default Vue.extend({
components: {
SaveIcon,
},
props: {
closeModal: {
type: Function,
default: () => {},
},
},
data() {
return {
text: '' as string,
error: '' as string,
}
},
computed: {
...mapState(['ui']),
},
mounted() {
this.text = this.ui.renameCurrentName
this.$nextTick(() => {
// extension string including .
const extString = this.text.slice(
((this.text.lastIndexOf('.') - 1) >>> 0) + 1,
)
const input = this.$refs.inputGroup.$refs.input as HTMLInputElement
// if file extension is found, highlight everything except the [.ext]
if (extString) {
input.focus()
input.setSelectionRange(0, this.text.length - extString.length)
return
}
input.select()
})
},
methods: {
/**
* @method rename
* @description attempt to rename child. Update textile files index if successful
*/
async rename() {
try {
this.$FileSystem.renameChild(this.ui.renameCurrentName, this.text)
} catch (e: any) {
this.error = e.message
return
}
this.closeModal()
this.$store.commit('ui/setIsLoadingFileIndex', true)
await this.$TextileManager.bucket?.updateIndex(this.$FileSystem.export)
this.$store.commit('ui/setIsLoadingFileIndex', false)
this.$toast.show(this.$t('pages.files.rename') as string)
},
},
})
</script>

<style scoped lang="less" src="./Rename.less"></style>
20 changes: 12 additions & 8 deletions components/views/files/row/Row.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import {
MoreVerticalIcon,
} from 'satellite-lucide-icons'
import ContextMenu from '~/components/mixins/UI/ContextMenu'

import { Item } from '~/libraries/Files/abstracts/Item.abstract'
import { ModalWindows } from '~/store/ui/types'

export default Vue.extend({
components: {
Expand Down Expand Up @@ -78,6 +78,17 @@ export default Vue.extend({
}
this.$emit('handle', this.item)
},
/**
* @method rename
* @description Open rename modal
*/
rename() {
this.$store.commit('ui/setRenameItem', this.item.name)
this.$store.commit('ui/toggleModal', {
name: ModalWindows.RENAME_FILE,
state: !this.ui.modals[ModalWindows.RENAME_FILE],
})
},
/**
* @method like
* @description Emit to like item - pages/files/browse/index.vue
Expand All @@ -92,13 +103,6 @@ export default Vue.extend({
share() {
this.$emit('share', this.item)
},
/**
* @method rename
* @description Emit to rename item - pages/files/browse/index.vue
*/
rename() {
this.$emit('rename', this.item)
},
/**
* @method remove
* @description Emit to delete item - pages/files/browse/index.vue
Expand Down
4 changes: 2 additions & 2 deletions components/views/files/view/View.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
class="has-tooltip has-tooltip-primary has-tooltip-bottom control"
:href="file.url"
target="_blank"
:download="file.name"
:download="name"
>
<download-icon size="1x" />
</a>
Expand Down Expand Up @@ -45,7 +45,7 @@
:class="{'disabled' : load}"
:href="file.url"
target="_blank"
:download="file.name"
:download="name"
>
<download-icon size="1x" class="file-icon" />
</a>
Expand Down
44 changes: 40 additions & 4 deletions components/views/files/view/View.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
XIcon,
LinkIcon,
} from 'satellite-lucide-icons'
import { filetypeextension } from 'magic-bytes.js'
import { Fil } from '~/libraries/Files/Fil'

export default Vue.extend({
Expand All @@ -30,24 +31,59 @@ export default Vue.extend({
data() {
return {
load: false as boolean,
name: this.file.name as string,
}
},
computed: {
...mapState(['ui']),
},
/**
* if no file data available, pull encrypted file from textile bucket and save as blob
*/
async mounted() {
this.load = true
// if no file data available, pull encrypted file from textile bucket
if (!this.file.file) {
this.load = true
const fsFile: Fil = this.$FileSystem.getChild(this.file.name) as Fil
fsFile.file = await this.$TextileManager.bucket?.pullFile(
const fsFil: Fil = this.$FileSystem.getChild(this.file.name) as Fil
fsFil.file = await this.$TextileManager.bucket?.pullFile(
this.file.id,
this.file.name,
this.file.type,
)
}
// file extension according to file name
const fileExt = this.file.name
.slice(((this.file.name.lastIndexOf('.') - 1) >>> 0) + 2)
.toLowerCase()
// you only need the first 256 bytes or so to confirm file type
const buffer = new Uint8Array(
await this.file.file.slice(0, 256).arrayBuffer(),
)
// file extension according to byte data
const dataExt = filetypeextension(buffer)[0]

// magicbytes declares svg as xml, so we need to manually check
const decodedFile = new TextDecoder().decode(buffer)
if (decodedFile.includes('xmlns="http://www.w3.org/2000/svg"')) {
// if corrupted, set .svg extension
if (fileExt !== 'svg') {
this.name += '.svg'
}
this.load = false
return
}

// if corrupted txt file
if (!dataExt && fileExt !== 'txt') {
this.name += '.txt'
this.load = false
return
}

// if corrupted file with wrong extension, force the correct one
if (fileExt !== dataExt && dataExt) {
this.name += `.${dataExt}`
}
this.load = false
},
methods: {
/**
Expand Down
Loading