Merge pull request #1133 from ramiresviana/fixes-5
Some fixes and shared view improvements
This commit is contained in:
		
						commit
						dcbc3286e2
					
				| 
						 | 
				
			
			@ -191,10 +191,11 @@ table th {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box, .share__box__download {
 | 
			
		||||
  background: var(--surfaceSecondary) !important;
 | 
			
		||||
.share__box {
 | 
			
		||||
  background: var(--surfacePrimary) !important;
 | 
			
		||||
  color: var(--textPrimary);
 | 
			
		||||
}
 | 
			
		||||
.share__box__download {
 | 
			
		||||
  border-bottom-color: var(--divider);
 | 
			
		||||
 | 
			
		||||
.share__box__element {
 | 
			
		||||
  border-top-color: var(--divider);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -5,9 +5,7 @@
 | 
			
		|||
        <i class="material-icons">close</i>
 | 
			
		||||
      </button>
 | 
			
		||||
 | 
			
		||||
      <div class="title">
 | 
			
		||||
        <span>{{ this.name }}</span>
 | 
			
		||||
      </div>
 | 
			
		||||
      <div class="title">{{ this.name }}</div>
 | 
			
		||||
 | 
			
		||||
      <preview-size-button v-if="isResizeEnabled && this.req.type === 'image'" @change-size="toggleSize" v-bind:size="fullSize" :disabled="loading"></preview-size-button>
 | 
			
		||||
      <button @click="openMore" id="more" :aria-label="$t('buttons.more')" :title="$t('buttons.more')" class="action">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,29 +1,61 @@
 | 
			
		|||
.share__box {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  box-shadow: rgba(0, 0, 0, 0.06) 0px 1px 3px, rgba(0, 0, 0, 0.12) 0px 1px 2px;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  display: block;
 | 
			
		||||
  border-radius: 0.2em;
 | 
			
		||||
  width: 90%;
 | 
			
		||||
  max-width: 25em;
 | 
			
		||||
  margin: 6em auto;
 | 
			
		||||
.share {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-wrap: wrap;
 | 
			
		||||
  justify-content: center;
 | 
			
		||||
  align-items: flex-start;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box__download {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
@media (max-width: 736px) {
 | 
			
		||||
  .share {
 | 
			
		||||
    display: block;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box {
 | 
			
		||||
  box-shadow: rgba(0, 0, 0, 0.06) 0px 1px 3px, rgba(0, 0, 0, 0.12) 0px 1px 2px;
 | 
			
		||||
  background: #fff;
 | 
			
		||||
  border-radius: 0.2em;
 | 
			
		||||
  margin: 5px;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box__header {
 | 
			
		||||
  padding: 1em;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  background: #ffffff;
 | 
			
		||||
  color: rgba(0, 0, 0, 0.5);
 | 
			
		||||
  border-bottom: 1px solid rgba(0, 0, 0, 0.05);
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box__icon i {
 | 
			
		||||
  font-size: 10em;
 | 
			
		||||
  color: #40c4ff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box__center {
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box__info {
 | 
			
		||||
  padding: 2em 3em;
 | 
			
		||||
  flex: 1 1 auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box__title {
 | 
			
		||||
  margin-top: .2em;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
.share__box__element {
 | 
			
		||||
  padding: 1em;
 | 
			
		||||
  border-top: 1px solid rgba(0, 0, 0, 0.1);
 | 
			
		||||
  word-break: break-all;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box__items {
 | 
			
		||||
  text-align: left;
 | 
			
		||||
  flex: 10 0 25em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box__items #listing.list .item {
 | 
			
		||||
  cursor: auto;
 | 
			
		||||
  border-left: 0;
 | 
			
		||||
  border-right: 0;
 | 
			
		||||
  border-bottom: 0;
 | 
			
		||||
  border-top: 1px solid rgba(0, 0, 0, 0.1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.share__box__items #listing.list .item .name {
 | 
			
		||||
  width: auto;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -119,18 +119,23 @@
 | 
			
		|||
 | 
			
		||||
#previewer .bar {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  text-align: right;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  padding: 0.5em;
 | 
			
		||||
  height: 3.7em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#previewer .bar > * {
 | 
			
		||||
  flex: 0 0 auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#previewer .bar .title {
 | 
			
		||||
  margin-right: auto;
 | 
			
		||||
  display: block;
 | 
			
		||||
  flex: 1 1 auto;
 | 
			
		||||
  padding: 0 1em;
 | 
			
		||||
  line-height: 2.7em;
 | 
			
		||||
  line-height: 2.3em;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  word-break: break-word;
 | 
			
		||||
  text-overflow: ellipsis;
 | 
			
		||||
  font-size: 1.2em;
 | 
			
		||||
  color: #fff;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -220,10 +225,6 @@
 | 
			
		|||
  word-break: break-word;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#previewer .title span {
 | 
			
		||||
  font-size: 1.2em;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#previewer .loading {
 | 
			
		||||
  height: 100%;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,29 +1,56 @@
 | 
			
		|||
<template>
 | 
			
		||||
  <div class="share" v-if="loaded">
 | 
			
		||||
    <a target="_blank" :href="link">
 | 
			
		||||
      <div class="share__box">
 | 
			
		||||
        <div class="share__box__download" v-if="file.isDir">{{ $t('download.downloadFolder') }}</div>
 | 
			
		||||
        <div class="share__box__download" v-else>{{ $t('download.downloadFile') }}</div>
 | 
			
		||||
        <div class="share__box__info">
 | 
			
		||||
          <svg v-if="file.isDir" fill="#40c4ff" height="150" viewBox="0 0 24 24" width="150" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
            <path d="M10 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z"/>
 | 
			
		||||
            <path d="M0 0h24v24H0z" fill="none"/>
 | 
			
		||||
          </svg>
 | 
			
		||||
          <svg v-else fill="#40c4ff" height="150" viewBox="0 0 24 24" width="150" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
            <path d="M6 2c-1.1 0-1.99.9-1.99 2L4 20c0 1.1.89 2 1.99 2H18c1.1 0 2-.9 2-2V8l-6-6H6zm7 7V3.5L18.5 9H13z"/>
 | 
			
		||||
            <path d="M0 0h24v24H0z" fill="none"/>
 | 
			
		||||
          </svg>
 | 
			
		||||
          <h1 class="share__box__title">{{ file.name }}</h1>
 | 
			
		||||
    <div class="share__box share__box__info">
 | 
			
		||||
        <div class="share__box__header">
 | 
			
		||||
          {{ file.isDir ? $t('download.downloadFolder') : $t('download.downloadFile') }}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="share__box__element share__box__center share__box__icon">
 | 
			
		||||
          <i class="material-icons">{{ file.isDir ? 'folder' : 'insert_drive_file'}}</i>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="share__box__element">
 | 
			
		||||
          <strong>{{ $t('prompts.displayName') }}</strong> {{ file.name }}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="share__box__element">
 | 
			
		||||
          <strong>{{ $t('prompts.lastModified') }}:</strong> {{ humanTime }}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="share__box__element">
 | 
			
		||||
          <strong>{{ $t('prompts.size') }}:</strong> {{ humanSize }}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="share__box__element share__box__center">
 | 
			
		||||
          <a target="_blank" :href="link" class="button button--flat">{{ $t('buttons.download') }}</a>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="share__box__element share__box__center">
 | 
			
		||||
          <qrcode-vue :value="fullLink" size="200" level="M"></qrcode-vue>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-if="file.isDir" class="share__box share__box__items">
 | 
			
		||||
      <div class="share__box__header" v-if="file.isDir">
 | 
			
		||||
        {{ $t('files.files') }}
 | 
			
		||||
      </div>
 | 
			
		||||
    </a>
 | 
			
		||||
      <div id="listing" class="list">
 | 
			
		||||
        <div class="item" v-for="(item) in file.items.slice(0, this.showLimit)" :key="base64(item.name)">
 | 
			
		||||
          <div>
 | 
			
		||||
            <i class="material-icons">{{ item.isDir ? 'folder' : (item.type==='image') ? 'insert_photo' : 'insert_drive_file' }}</i>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div>
 | 
			
		||||
            <p class="name">{{ item.name }}</p>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div v-if="file.items.length > showLimit" class="item">
 | 
			
		||||
          <div>
 | 
			
		||||
            <p class="name"> + {{ file.items.length - showLimit }} </p>
 | 
			
		||||
          </div>
 | 
			
		||||
        </div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { share as api } from '@/api'
 | 
			
		||||
import { baseURL } from '@/utils/constants'
 | 
			
		||||
import filesize from 'filesize'
 | 
			
		||||
import moment from 'moment'
 | 
			
		||||
import QrcodeVue from 'qrcode.vue'
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +61,8 @@ export default {
 | 
			
		|||
  data: () => ({
 | 
			
		||||
    loaded: false,
 | 
			
		||||
    notFound: false,
 | 
			
		||||
    file: null
 | 
			
		||||
    file: null,
 | 
			
		||||
    showLimit: 500
 | 
			
		||||
  }),
 | 
			
		||||
  watch: {
 | 
			
		||||
    '$route': 'fetchData'
 | 
			
		||||
| 
						 | 
				
			
			@ -52,8 +80,21 @@ export default {
 | 
			
		|||
    fullLink: function () {
 | 
			
		||||
      return window.location.origin + this.link
 | 
			
		||||
    },
 | 
			
		||||
    humanSize: function () {
 | 
			
		||||
      if (this.file.isDir) {
 | 
			
		||||
        return this.file.items.length
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return filesize(this.file.size)
 | 
			
		||||
    },
 | 
			
		||||
    humanTime: function () {
 | 
			
		||||
      return moment(this.file.modified).fromNow()
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
  methods: {
 | 
			
		||||
    base64: function (name) {
 | 
			
		||||
      return window.btoa(unescape(encodeURIComponent(name)))
 | 
			
		||||
    },
 | 
			
		||||
    fetchData: async function () {
 | 
			
		||||
      try {
 | 
			
		||||
        this.file = await api.getHash(this.hash)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,7 @@ var withHashFile = func(fn handleFunc) handleFunc {
 | 
			
		|||
			Fs:      d.user.Fs,
 | 
			
		||||
			Path:    link.Path,
 | 
			
		||||
			Modify:  d.user.Perm.Modify,
 | 
			
		||||
			Expand:  false,
 | 
			
		||||
			Expand:  true,
 | 
			
		||||
			Checker: d,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +54,15 @@ func ifPathWithName(r *http.Request) string {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
var publicShareHandler = withHashFile(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
 | 
			
		||||
	return renderJSON(w, r, d.raw)
 | 
			
		||||
	file := d.raw.(*files.FileInfo)
 | 
			
		||||
 | 
			
		||||
	if file.IsDir {
 | 
			
		||||
		file.Listing.Sorting = files.Sorting{By: "name", Asc: false}
 | 
			
		||||
		file.Listing.ApplySort()
 | 
			
		||||
		return renderJSON(w, r, file)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return renderJSON(w, r, file)
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
var publicDlHandler = withHashFile(func(w http.ResponseWriter, r *http.Request, d *data) (int, error) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										24
									
								
								http/raw.go
								
								
								
								
							
							
						
						
									
										24
									
								
								http/raw.go
								
								
								
								
							| 
						 | 
				
			
			@ -116,17 +116,19 @@ func addFile(ar archiver.Writer, d *data, path, commonPath string) error {
 | 
			
		|||
	}
 | 
			
		||||
	defer file.Close()
 | 
			
		||||
 | 
			
		||||
	filename := strings.TrimPrefix(path, commonPath)
 | 
			
		||||
	filename = strings.TrimPrefix(filename, "/")
 | 
			
		||||
	err = ar.Write(archiver.File{
 | 
			
		||||
		FileInfo: archiver.FileInfo{
 | 
			
		||||
			FileInfo:   info,
 | 
			
		||||
			CustomName: filename,
 | 
			
		||||
		},
 | 
			
		||||
		ReadCloser: file,
 | 
			
		||||
	})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	if path != commonPath {
 | 
			
		||||
		filename := strings.TrimPrefix(path, commonPath)
 | 
			
		||||
		filename = strings.TrimPrefix(filename, "/")
 | 
			
		||||
		err = ar.Write(archiver.File{
 | 
			
		||||
			FileInfo: archiver.FileInfo{
 | 
			
		||||
				FileInfo:   info,
 | 
			
		||||
				CustomName: filename,
 | 
			
		||||
			},
 | 
			
		||||
			ReadCloser: file,
 | 
			
		||||
		})
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if info.IsDir() {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import (
 | 
			
		|||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -122,7 +123,7 @@ var resourcePostPutHandler = withUser(func(w http.ResponseWriter, r *http.Reques
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	err := d.RunHook(func() error {
 | 
			
		||||
		dir, _ := filepath.Split(r.URL.Path)
 | 
			
		||||
		dir, _ := path.Split(r.URL.Path)
 | 
			
		||||
		err := d.user.Fs.MkdirAll(dir, 0775)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +197,8 @@ var resourcePatchHandler = withUser(func(w http.ResponseWriter, r *http.Request,
 | 
			
		|||
			if !d.user.Perm.Rename {
 | 
			
		||||
				return errors.ErrPermissionDenied
 | 
			
		||||
			}
 | 
			
		||||
			dst = filepath.Clean("/" + dst)
 | 
			
		||||
			src = path.Clean("/" + src)
 | 
			
		||||
			dst = path.Clean("/" + dst)
 | 
			
		||||
 | 
			
		||||
			return d.user.Fs.Rename(src, dst)
 | 
			
		||||
		default:
 | 
			
		||||
| 
						 | 
				
			
			@ -221,20 +223,20 @@ func checkParent(src, dst string) error {
 | 
			
		|||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func addVersionSuffix(path string, fs afero.Fs) string {
 | 
			
		||||
func addVersionSuffix(source string, fs afero.Fs) string {
 | 
			
		||||
	counter := 1
 | 
			
		||||
	dir, name := filepath.Split(path)
 | 
			
		||||
	dir, name := path.Split(source)
 | 
			
		||||
	ext := filepath.Ext(name)
 | 
			
		||||
	base := strings.TrimSuffix(name, ext)
 | 
			
		||||
 | 
			
		||||
	for {
 | 
			
		||||
		if _, err := fs.Stat(path); err != nil {
 | 
			
		||||
		if _, err := fs.Stat(source); err != nil {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		renamed := fmt.Sprintf("%s(%d)%s", base, counter, ext)
 | 
			
		||||
		path = filepath.ToSlash(dir) + renamed
 | 
			
		||||
		source = path.Join(dir, renamed)
 | 
			
		||||
		counter++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return path
 | 
			
		||||
	return source
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue