зеркало из https://github.com/nextcloud/viewer.git
Livephoto support (#80)
If a video have an image with the same title, use the image as a poster and static view. Test sample files [Images-test.gz](https://github.com/nextcloud/viewer/files/3120215/Images-test.gz)
This commit is contained in:
Родитель
69bc0d32a1
Коммит
c52e717d5d
22
js/viewer.js
22
js/viewer.js
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -23,7 +23,9 @@
|
|||
<template>
|
||||
<div id="emptycontent">
|
||||
<div class="icon-error" />
|
||||
<h2>{{ t('viewer', 'Error loading {name}', { name }) }}</h2>
|
||||
<h2>
|
||||
<slot>{{ t('viewer', 'Error loading {name}', { name }) }}</slot>
|
||||
</h2>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -42,6 +44,8 @@ export default {
|
|||
|
||||
<style scoped>
|
||||
#emptycontent {
|
||||
margin: 10% 5%;
|
||||
margin: 0;
|
||||
padding: 10% 5%;
|
||||
background-color: var(--color-main-background);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -41,17 +41,18 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import mime from 'Mixins/Mime'
|
||||
import axios from 'axios'
|
||||
import Vue from 'vue'
|
||||
import AsyncComputed from 'vue-async-computed'
|
||||
|
||||
import Mime from 'Mixins/Mime'
|
||||
|
||||
Vue.use(AsyncComputed)
|
||||
|
||||
export default {
|
||||
name: 'Images',
|
||||
mixins: [
|
||||
mime
|
||||
Mime
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
|
|
|
@ -22,52 +22,93 @@
|
|||
|
||||
<template>
|
||||
<video
|
||||
v-if="path"
|
||||
v-if="path && canPlay"
|
||||
:autoplay="active"
|
||||
preload
|
||||
:controls="visibleControls"
|
||||
:poster="livePhotoPath"
|
||||
:preload="true"
|
||||
:style="{
|
||||
height: height + 'px',
|
||||
width: width + 'px'
|
||||
}"
|
||||
@canplay="doneLoading"
|
||||
@click.prevent="playPause"
|
||||
@dblclick.prevent="toggleFullScreen"
|
||||
@canplay="doneLoading"
|
||||
@ended="donePlaying"
|
||||
@loadedmetadata="updateVideoSize"
|
||||
@mouseenter="showControls"
|
||||
@mouseleave="hideControls"
|
||||
@loadedmetadata="updateVideoSize">
|
||||
@mouseleave="hideControls">
|
||||
|
||||
<source :src="davPath" :type="mime">
|
||||
|
||||
{{ t('viewer', 'Your browser does not support the video tag.') }}
|
||||
</video>
|
||||
|
||||
<!-- Browser cannot play this file -->
|
||||
<Error v-else>
|
||||
{{ t('viewer', 'This video is not playable in your browser') }}
|
||||
</Error>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import mime from 'Mixins/Mime'
|
||||
import Error from 'Components/Error'
|
||||
import Mime from 'Mixins/Mime'
|
||||
import PreviewUrl from 'Mixins/PreviewUrl'
|
||||
|
||||
const liveExt = ['jpg', 'jpeg', 'png']
|
||||
|
||||
export default {
|
||||
name: 'Videos',
|
||||
mixins: [
|
||||
mime
|
||||
],
|
||||
|
||||
components: {
|
||||
Error
|
||||
},
|
||||
|
||||
mixins: [Mime, PreviewUrl],
|
||||
|
||||
data() {
|
||||
return {
|
||||
canPlay: true,
|
||||
visibleControls: false
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
livePhoto() {
|
||||
return this.fileList.find(file => {
|
||||
// if same filename and extension is allowed
|
||||
return file.name.startsWith(this.name)
|
||||
&& liveExt.indexOf(file.name.split('.')[1] > -1)
|
||||
})
|
||||
},
|
||||
livePhotoPath() {
|
||||
return this.getPreviewIfAny(this.livePhoto)
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
active: function(val, old) {
|
||||
// the item was hidden before and is now the current view
|
||||
if (val === true && old === false) {
|
||||
this.$el.play()
|
||||
// if we cannot play the file, we announce we're done loading
|
||||
this.canPlayCheck()
|
||||
if (this.canPlay) {
|
||||
this.$el.play()
|
||||
}
|
||||
|
||||
// the item was playing before and is now hidden
|
||||
} else if (val === false && old === true) {
|
||||
this.$el.pause()
|
||||
if (this.canPlay) {
|
||||
this.$el.pause()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mounted() {
|
||||
this.canPlayCheck()
|
||||
},
|
||||
|
||||
methods: {
|
||||
// Updates the dimensions of the modal
|
||||
updateVideoSize() {
|
||||
|
@ -91,6 +132,22 @@ export default {
|
|||
} else {
|
||||
this.$el.pause()
|
||||
}
|
||||
},
|
||||
|
||||
donePlaying() {
|
||||
// reset and show poster after play
|
||||
this.$el.autoplay = false
|
||||
this.$el.load()
|
||||
},
|
||||
|
||||
canPlayCheck() {
|
||||
if (this.$el.canPlayType
|
||||
&& this.$el.canPlayType(this.mime) !== '') {
|
||||
this.canPlay = true
|
||||
} else {
|
||||
this.canPlay = false
|
||||
this.doneLoading()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,15 @@ export default {
|
|||
},
|
||||
fileId: {
|
||||
type: Number,
|
||||
default: null
|
||||
required: true
|
||||
},
|
||||
fileList: {
|
||||
type: Array,
|
||||
default: []
|
||||
},
|
||||
fileName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
davPath: {
|
||||
type: String,
|
||||
|
@ -71,6 +79,15 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
name() {
|
||||
return this.fileName.split('.')[0]
|
||||
},
|
||||
ext() {
|
||||
return this.fileName.split('.')[1]
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
active: function(val, old) {
|
||||
// the item was hidden before and is now the current view
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
/**
|
||||
* @copyright Copyright (c) 2019 John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @author John Molakvoæ <skjnldsv@protonmail.com>
|
||||
*
|
||||
* @license GNU AGPL version 3 or any later version
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as
|
||||
* published by the Free Software Foundation, either version 3 of the
|
||||
* License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
import { generateUrl } from 'nextcloud-server/dist/router'
|
||||
|
||||
export default {
|
||||
methods: {
|
||||
getPreviewIfAny(fileInfo) {
|
||||
if (fileInfo.hasPreview) {
|
||||
return generateUrl(`/core/preview?fileId=${fileInfo.id}&x=${window.outerWidth}&y=${window.outerHeight}&a=true`)
|
||||
}
|
||||
return fileInfo.path
|
||||
}
|
||||
}
|
||||
}
|
|
@ -42,12 +42,14 @@
|
|||
<component
|
||||
:is="previousFile.modal"
|
||||
v-if="!previousFile.failed"
|
||||
:key="getPath(previousFile)"
|
||||
:key="getPreviewIfAny(previousFile)"
|
||||
ref="previous-content"
|
||||
:dav-path="previousFile.path"
|
||||
:file-id="previousFile.id"
|
||||
:file-list="fileList"
|
||||
:file-name="previousFile.name"
|
||||
:mime="previousFile.mime"
|
||||
:path="getPath(previousFile)"
|
||||
:path="getPreviewIfAny(previousFile)"
|
||||
class="hidden-visually file-view"
|
||||
@error="previousFailed" />
|
||||
<Error
|
||||
|
@ -58,16 +60,18 @@
|
|||
<component
|
||||
:is="currentFile.modal"
|
||||
v-if="!currentFile.failed"
|
||||
:key="getPath(currentFile)"
|
||||
:key="getPreviewIfAny(currentFile)"
|
||||
ref="content"
|
||||
:active="true"
|
||||
:can-swipe.sync="canSwipe"
|
||||
:dav-path="currentFile.path"
|
||||
:file-id="currentFile.id"
|
||||
:file-list="fileList"
|
||||
:file-name="currentFile.name"
|
||||
:is-full-screen="isFullscreen"
|
||||
:loaded.sync="currentFile.loaded"
|
||||
:mime="currentFile.mime"
|
||||
:path="getPath(currentFile)"
|
||||
:path="getPreviewIfAny(currentFile)"
|
||||
:sidebar-shown="showSidebar"
|
||||
class="file-view"
|
||||
@error="currentFailed" />
|
||||
|
@ -79,12 +83,14 @@
|
|||
<component
|
||||
:is="nextFile.modal"
|
||||
v-if="!nextFile.failed"
|
||||
:key="getPath(nextFile)"
|
||||
:key="getPreviewIfAny(nextFile)"
|
||||
ref="next-content"
|
||||
:dav-path="nextFile.path"
|
||||
:file-id="nextFile.id"
|
||||
:file-list="fileList"
|
||||
:file-name="nextFile.name"
|
||||
:mime="nextFile.mime"
|
||||
:path="getPath(nextFile)"
|
||||
:path="getPreviewIfAny(nextFile)"
|
||||
class="hidden-visually file-view"
|
||||
@error="nextFailed" />
|
||||
<Error
|
||||
|
@ -97,9 +103,10 @@
|
|||
import Vue from 'vue'
|
||||
|
||||
import isMobile from 'nextcloud-vue/dist/Mixins/isMobile'
|
||||
import { generateRemoteUrl, generateUrl } from 'nextcloud-server/dist/router'
|
||||
import { generateRemoteUrl } from 'nextcloud-server/dist/router'
|
||||
|
||||
import Error from 'Components/Error'
|
||||
import PreviewUrl from 'Mixins/PreviewUrl'
|
||||
import FileList from 'Services/FileList'
|
||||
import Modal from 'nextcloud-vue/dist/Components/Modal'
|
||||
|
||||
|
@ -111,7 +118,7 @@ export default {
|
|||
Error
|
||||
},
|
||||
|
||||
mixins: [isMobile],
|
||||
mixins: [isMobile, PreviewUrl],
|
||||
|
||||
data: () => ({
|
||||
handlers: OCA.Viewer.availableHandlers,
|
||||
|
@ -434,13 +441,6 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
getPath(fileInfo) {
|
||||
if (fileInfo.hasPreview) {
|
||||
return generateUrl(`/core/preview?fileId=${fileInfo.id}&x=${window.outerWidth}&y=${window.outerHeight}&a=true`)
|
||||
}
|
||||
return fileInfo.path
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the viewer
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче