Compare commits

...

6 Commits

Author SHA1 Message Date
Oleg Lobanov
d0b359561f chore(release): 2.4.0 2020-07-07 16:53:51 +02:00
Fabian Fritzsche
453636dfe2 fix: add preview bypass for .gif files (#1012) 2020-07-07 16:47:11 +02:00
Oleg Lobanov
b1605aa6d3 Merge pull request #1014 from ramiresviana/full-screen-editor 2020-07-06 17:06:12 +02:00
Oleg Lobanov
23503b80a4 Merge pull request #1015 from ramiresviana/prompt-key-shortcut-conflict 2020-07-06 17:03:05 +02:00
Ramires Viana
0d69fbd9a3 fix: prompt key shortcut conflict 2020-07-04 14:19:03 +00:00
Ramires Viana
0d665e528f feat: full screen editor 2020-07-04 03:11:51 +00:00
9 changed files with 171 additions and 42 deletions

View File

@@ -2,6 +2,19 @@
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [2.4.0](https://github.com/filebrowser/filebrowser/compare/v2.3.0...v2.4.0) (2020-07-07)
### Features
* full screen editor ([0d665e5](https://github.com/filebrowser/filebrowser/commit/0d665e528f880ceda0976ceed66070ac34de7969))
### Bug Fixes
* add preview bypass for .gif files ([#1012](https://github.com/filebrowser/filebrowser/issues/1012)) ([453636d](https://github.com/filebrowser/filebrowser/commit/453636dfe2bbf177c74617862eb763485d4774bf))
* prompt key shortcut conflict ([0d69fbd](https://github.com/filebrowser/filebrowser/commit/0d69fbd9a342aa2695859021df0c423e3ae4a4fa))
## [2.3.0](https://github.com/filebrowser/filebrowser/compare/v2.2.0...v2.3.0) (2020-06-26)

View File

@@ -124,6 +124,14 @@ nav > div {
color: var(--textPrimary);
}
#editor-container {
background: var(--background);
}
#editor-container .bar {
background: var(--surfacePrimary);
}
@media (max-width: 736px) {
#file-selection {
background: var(--surfaceSecondary) !important;

View File

@@ -1,5 +1,5 @@
<template>
<header>
<header v-if="!isEditor">
<div>
<button @click="openSidebar" :aria-label="$t('buttons.toggleSidebar')" :title="$t('buttons.toggleSidebar')" class="action">
<i class="material-icons">menu</i>
@@ -13,10 +13,6 @@
<i class="material-icons">search</i>
</button>
<button v-show="showSaveButton" :aria-label="$t('buttons.save')" :title="$t('buttons.save')" class="action" id="save-button">
<i class="material-icons">save</i>
</button>
<button @click="openMore" id="more" :aria-label="$t('buttons.more')" :title="$t('buttons.more')" class="action">
<i class="material-icons">more_vert</i>
</button>
@@ -129,9 +125,6 @@ export default {
showUpload () {
return this.isListing && this.user.perm.create
},
showSaveButton () {
return this.isEditor && this.user.perm.modify
},
showDownloadButton () {
return this.isFiles && this.user.perm.download
},

View File

@@ -136,12 +136,6 @@ export default {
}
},
mounted() {
window.addEventListener("keydown", event => {
if (event.keyCode === 27) {
this.closeHovers()
}
})
this.$refs.result.addEventListener('scroll', event => {
if (event.target.offsetHeight + event.target.scrollTop >= event.target.scrollHeight - 100) {
this.resultsCount += 50

View File

@@ -1,11 +1,37 @@
<template>
<form id="editor"></form>
<div id="editor-container">
<div class="bar">
<button @click="back" :title="$t('files.closePreview')" :aria-label="$t('files.closePreview')" id="close" class="action">
<i class="material-icons">close</i>
</button>
<div class="title">
<span>{{ req.name }}</span>
</div>
<button @click="save" v-show="user.perm.modify" :aria-label="$t('buttons.save')" :title="$t('buttons.save')" id="save-button" class="action">
<i class="material-icons">save</i>
</button>
</div>
<div id="breadcrumbs">
<span><i class="material-icons">home</i></span>
<span v-for="(link, index) in breadcrumbs" :key="index">
<span class="chevron"><i class="material-icons">keyboard_arrow_right</i></span>
<span>{{ link.name }}</span>
</span>
</div>
<form id="editor"></form>
</div>
</template>
<script>
import { mapState } from 'vuex'
import { files as api } from '@/api'
import buttons from '@/utils/buttons'
import url from '@/utils/url'
import ace from 'ace-builds/src-min-noconflict/ace.js'
import modelist from 'ace-builds/src-min-noconflict/ext-modelist.js'
@@ -14,27 +40,52 @@ import { theme } from '@/utils/constants'
export default {
name: 'editor',
computed: {
...mapState(['req'])
},
data: function () {
return {}
},
computed: {
...mapState(['req', 'user']),
breadcrumbs () {
let parts = this.$route.path.split('/')
if (parts[0] === '') {
parts.shift()
}
if (parts[parts.length - 1] === '') {
parts.pop()
}
let breadcrumbs = []
for (let i = 0; i < parts.length; i++) {
breadcrumbs.push({ name: decodeURIComponent(parts[i]) })
}
breadcrumbs.shift()
if (breadcrumbs.length > 3) {
while (breadcrumbs.length !== 4) {
breadcrumbs.shift()
}
breadcrumbs[0].name = '...'
}
return breadcrumbs
}
},
created () {
window.addEventListener('keydown', this.keyEvent)
document.getElementById('save-button').addEventListener('click', this.save)
},
beforeDestroy () {
window.removeEventListener('keydown', this.keyEvent)
document.getElementById('save-button').removeEventListener('click', this.save)
this.editor.destroy();
},
mounted: function () {
mounted: function () {
const fileContent = this.req.content || '';
this.editor = ace.edit('editor', {
maxLines: 80,
minLines: 20,
value: fileContent,
showPrintMargin: false,
readOnly: this.req.type === 'textImmutable',
@@ -48,6 +99,10 @@ export default {
}
},
methods: {
back () {
let uri = url.removeLastDir(this.$route.path) + '/'
this.$router.push({ path: uri })
},
keyEvent (event) {
if (!event.ctrlKey && !event.metaKey) {
return

View File

@@ -101,7 +101,7 @@ export default {
components: { Item },
data: function () {
return {
show: 50,
showLimit: 50,
uploading: {
id: 0,
count: 0,
@@ -111,7 +111,7 @@ export default {
}
},
computed: {
...mapState(['req', 'selected', 'user']),
...mapState(['req', 'selected', 'user', 'show']),
nameSorted () {
return (this.req.sorting.by === 'name')
},
@@ -139,14 +139,14 @@ export default {
return { dirs, files }
},
dirs () {
return this.items.dirs.slice(0, this.show)
return this.items.dirs.slice(0, this.showLimit)
},
files () {
let show = this.show - this.items.dirs.length
let showLimit = this.showLimit - this.items.dirs.length
if (show < 0) show = 0
if (showLimit < 0) showLimit = 0
return this.items.files.slice(0, show)
return this.items.files.slice(0, showLimit)
},
nameIcon () {
if (this.nameSorted && !this.ascOrdered) {
@@ -194,7 +194,11 @@ export default {
base64: function (name) {
return window.btoa(unescape(encodeURIComponent(name)))
},
keyEvent (event) {
keyEvent (event) {
if (this.show !== null) {
return
}
if (!event.ctrlKey && !event.metaKey) {
return
}
@@ -292,7 +296,7 @@ export default {
},
scrollEvent () {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
this.show += 50
this.showLimit += 50
}
},
dragEnter () {

View File

@@ -184,6 +184,53 @@
right: 0.5em;
}
/* EDITOR */
#editor-container {
background-color: #fafafa;
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: 9999;
overflow: hidden;
}
#editor-container .bar {
width: 100%;
text-align: right;
display: flex;
padding: 0.5em;
height: 3.7em;
background-color: #fff;
border-bottom: 1px solid rgba(0, 0, 0, 0.075);
box-shadow: 0 0 5px rgba(0, 0, 0, 0.1);
}
#editor-container .title {
margin-right: auto;
padding: 0 1em;
line-height: 2.7em;
overflow: hidden;
word-break: break-word;
}
#previewer .title span {
font-size: 1.2em;
}
#editor-container #editor {
height: calc(100vh - 8.2em);
}
#editor-container #breadcrumbs {
height: 2.3em;
padding: 0 1em;
}
#editor-container #breadcrumbs span {
font-size: 12px;
}
/* * * * * * * * * * * * * * * *
* PROMPT *

View File

@@ -1,6 +1,6 @@
<template>
<div>
<div id="breadcrumbs">
<div id="breadcrumbs" v-if="isListing || error">
<router-link to="/files/" :aria-label="$t('files.home')" :title="$t('files.home')">
<i class="material-icons">home</i>
</router-link>
@@ -61,7 +61,8 @@ export default {
'user',
'reload',
'multiple',
'loading'
'loading',
'show'
]),
isPreview () {
return !this.loading && !this.isListing && !this.isEditor
@@ -158,10 +159,17 @@ export default {
}
},
keyEvent (event) {
// Esc!
if (event.keyCode === 27) {
this.$store.commit('closeHovers')
if (this.show !== null) {
// Esc!
if (event.keyCode === 27) {
this.$store.commit('closeHovers')
}
return
}
// Esc!
if (event.keyCode === 27) {
// If we're on a listing, unselect all
// files and folders.
if (this.isListing) {

View File

@@ -59,6 +59,19 @@ func handleImagePreview(w http.ResponseWriter, r *http.Request, file *files.File
return errToStatus(err), err
}
fd, err := file.Fs.Open(file.Path)
if err != nil {
return errToStatus(err), err
}
defer fd.Close()
if format == imaging.GIF && size == sizeBig {
if _, err := rawFileHandler(w, r, file); err != nil { //nolint: govet
return errToStatus(err), err
}
return 0, nil
}
var imgProcessor imageProcessor
switch size {
case sizeBig:
@@ -73,12 +86,6 @@ func handleImagePreview(w http.ResponseWriter, r *http.Request, file *files.File
return http.StatusBadRequest, fmt.Errorf("unsupported preview size %s", size)
}
fd, err := file.Fs.Open(file.Path)
if err != nil {
return errToStatus(err), err
}
defer fd.Close()
img, err := imaging.Decode(fd, imaging.AutoOrientation(true))
if err != nil {
return errToStatus(err), err