add share link at /m/, add share dialog in view menu, fix preview for documents
This commit is contained in:
parent
17801df8de
commit
bea0d301a4
30 changed files with 2704 additions and 4 deletions
400
static/mobile/js/VideoPlayer.js
Normal file
400
static/mobile/js/VideoPlayer.js
Normal file
|
|
@ -0,0 +1,400 @@
|
|||
(function() {
|
||||
|
||||
window.VideoPlayer = function(options) {
|
||||
|
||||
var self = {}, that;
|
||||
self.options = {
|
||||
autoplay: false,
|
||||
controls: true,
|
||||
items: [],
|
||||
loop: false,
|
||||
muted: false,
|
||||
playbackRate: 1,
|
||||
position: 0,
|
||||
volume: 1
|
||||
}
|
||||
Object.assign(self.options, options);
|
||||
that = VideoElement(options);
|
||||
|
||||
self.controls = document.createElement('div')
|
||||
self.controls.classList.add('mx-controls')
|
||||
//self.controls.style.display = "none"
|
||||
if (self.options.controls) {
|
||||
var ratio = `aspect-ratio: ${self.options.aspectratio};`
|
||||
if (!self.options.aspectratio) {
|
||||
ratio = 'height: 128px;'
|
||||
}
|
||||
self.controls.innerHTML = `
|
||||
<style>
|
||||
.fullscreen video {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.mx-controls {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
${ratio}
|
||||
max-height: 100vh;
|
||||
flex-direction: column;
|
||||
background: rgba(0,0,0,0.3);
|
||||
color: white;
|
||||
z-index: 1;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.mx-controls .toggle {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
}
|
||||
.mx-controls .volume:hover,
|
||||
.mx-controls .fullscreen-btn:hover,
|
||||
.mx-controls .toggle:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
.mx-controls .toggle div {
|
||||
margin: auto;
|
||||
}
|
||||
.mx-controls .controls {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
}
|
||||
.mx-controls .controls .position {
|
||||
flex: 1;
|
||||
}
|
||||
.mx-controls .toggle svg {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
.mx-controls .toggle .loading svg {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
}
|
||||
.mx-controls .controls .volume svg,
|
||||
.mx-controls .controls .fullscreen-btn svg {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 4px;
|
||||
}
|
||||
.mx-controls .controls .volume {
|
||||
padding-left: 4px;
|
||||
}
|
||||
.mx-controls.hidden {
|
||||
display: none;
|
||||
}
|
||||
.fullscreen .mx-controls {
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
}
|
||||
.fullscreen .mx-controls video {
|
||||
width: 100%;
|
||||
max-height: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
.fullscreen .mx-controls .controls {
|
||||
height: 64px;
|
||||
}
|
||||
.fullscreen .mx-controls .fullscreen-btn {
|
||||
padding: 16px;
|
||||
}
|
||||
.fullscreen .mx-controls .volume {
|
||||
padding: 16px;
|
||||
}
|
||||
.mx-controls {
|
||||
transition: opacity 0.3s linear;
|
||||
}
|
||||
.mx-controls .controls .position {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.mx-controls .controls .position .bar {
|
||||
width: calc(100% - 16px);
|
||||
height: 4px;
|
||||
border: solid 1px #B1B1B1;
|
||||
margin: auto;
|
||||
}
|
||||
.fullscreen .mx-controls .controls .position .bar {
|
||||
}
|
||||
.mx-controls .controls .position .progress {
|
||||
width: 0;
|
||||
background: #B1B1B180;
|
||||
height: 4px;
|
||||
}
|
||||
.mx-controls .controls .time {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
.mx-controls .controls .time div {
|
||||
margin: auto;
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
<div class="toggle" title="Play">
|
||||
<div>${icon.play}</div>
|
||||
</div>
|
||||
<div class="controls">
|
||||
<div class="volume" title="Mute">
|
||||
${icon.mute}
|
||||
</div>
|
||||
<div class="position">
|
||||
<div class="bar">
|
||||
<div class="progress"></div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="time">
|
||||
<div></div>
|
||||
</div>
|
||||
<div class="fullscreen-btn" title="Fullscreen">
|
||||
${isIOS || !self.options.aspectratio ? "" : icon.enterFullscreen}
|
||||
</div>
|
||||
</div>
|
||||
`
|
||||
var toggleVideo = event => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
if (that.paused) {
|
||||
that.play()
|
||||
} else {
|
||||
that.pause()
|
||||
}
|
||||
}
|
||||
async function toggleFullscreen(event) {
|
||||
if (isIOS) {
|
||||
return
|
||||
}
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
if (!document.fullscreenElement) {
|
||||
that.classList.add('fullscreen')
|
||||
if (that.webkitRequestFullscreen) {
|
||||
await that.webkitRequestFullscreen()
|
||||
} else {
|
||||
await that.requestFullscreen()
|
||||
}
|
||||
console.log('entered fullscreen')
|
||||
var failed = false
|
||||
if (!screen.orientation.type.startsWith("landscape")) {
|
||||
await screen.orientation.lock("landscape").catch(err => {
|
||||
console.log('no luck with lock', err)
|
||||
/*
|
||||
document.querySelector('.error').innerHTML = '' + err
|
||||
that.classList.remove('fullscreen')
|
||||
document.exitFullscreen();
|
||||
screen.orientation.unlock()
|
||||
failed = true
|
||||
*/
|
||||
})
|
||||
}
|
||||
if (that.paused && !failed) {
|
||||
that.play()
|
||||
}
|
||||
} else {
|
||||
that.classList.remove('fullscreen')
|
||||
document.exitFullscreen();
|
||||
screen.orientation.unlock()
|
||||
}
|
||||
}
|
||||
var toggleSound = event => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
if (that.muted()) {
|
||||
that.muted(false)
|
||||
} else {
|
||||
that.muted(true)
|
||||
}
|
||||
}
|
||||
var showControls
|
||||
var toggleControls = event => {
|
||||
if (self.controls.style.opacity == '0') {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
self.controls.style.opacity = '1'
|
||||
showControls = setTimeout(() => {
|
||||
self.controls.style.opacity = that.paused ? '1' : '0'
|
||||
showControls = null
|
||||
}, 3000)
|
||||
} else {
|
||||
self.controls.style.opacity = '0'
|
||||
}
|
||||
}
|
||||
self.controls.addEventListener("mousemove", event => {
|
||||
if (showControls) {
|
||||
clearTimeout(showControls)
|
||||
}
|
||||
self.controls.style.opacity = '1'
|
||||
showControls = setTimeout(() => {
|
||||
self.controls.style.opacity = that.paused ? '1' : '0'
|
||||
showControls = null
|
||||
}, 3000)
|
||||
})
|
||||
self.controls.addEventListener("mouseleave", event => {
|
||||
if (showControls) {
|
||||
clearTimeout(showControls)
|
||||
}
|
||||
self.controls.style.opacity = that.paused ? '1' : '0'
|
||||
showControls = null
|
||||
})
|
||||
self.controls.addEventListener("touchstart", toggleControls)
|
||||
self.controls.querySelector('.toggle').addEventListener("click", toggleVideo)
|
||||
self.controls.querySelector('.volume').addEventListener("click", toggleSound)
|
||||
self.controls.querySelector('.fullscreen-btn').addEventListener("click", toggleFullscreen)
|
||||
document.addEventListener('fullscreenchange', event => {
|
||||
if (!document.fullscreenElement) {
|
||||
screen.orientation.unlock()
|
||||
that.classList.remove('fullscreen')
|
||||
that.querySelector('.fullscreen-btn').innerHTML = icon.enterFullscreen
|
||||
} else {
|
||||
self.controls.querySelector('.fullscreen-btn').innerHTML = icon.exitFullscreen
|
||||
}
|
||||
})
|
||||
that.append(self.controls)
|
||||
}
|
||||
|
||||
function getVideoWidth() {
|
||||
if (document.fullscreenElement) {
|
||||
return ''
|
||||
}
|
||||
var av = that.querySelector('video.active')
|
||||
return av ? av.getBoundingClientRect().width + 'px' : '100%'
|
||||
}
|
||||
|
||||
var playOnLoad = false
|
||||
var unblock = document.createElement("div")
|
||||
|
||||
that.addEventListener("requiresusergesture", event => {
|
||||
unblock.style.position = "absolute"
|
||||
unblock.style.width = '100%'
|
||||
unblock.style.height = '100%'
|
||||
unblock.style.backgroundImage = `url(${self.options.poster})`
|
||||
unblock.style.zIndex = '1000'
|
||||
unblock.style.backgroundPosition = "top left"
|
||||
unblock.style.backgroundRepeat = "no-repeat"
|
||||
unblock.style.backgroundSize = "cover"
|
||||
unblock.style.display = 'flex'
|
||||
unblock.classList.add('mx-controls')
|
||||
unblock.classList.add('poster')
|
||||
unblock.innerHTML = `
|
||||
<div class="toggle">
|
||||
<div style="margin: auto">${icon.play}</div>
|
||||
</div>
|
||||
<div class="controls" style="height: 37px;"></div>
|
||||
`
|
||||
self.controls.style.opacity = '0'
|
||||
unblock.addEventListener("click", event => {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
playOnLoad = true
|
||||
unblock.querySelector('.toggle').innerHTML = `
|
||||
<div style="margin: auto" class="loading">${icon.loading}</div>
|
||||
`
|
||||
}, {once: true})
|
||||
that.append(unblock)
|
||||
})
|
||||
var loading = true
|
||||
that.brightness(0)
|
||||
that.addEventListener("loadedmetadata", event => {
|
||||
//
|
||||
})
|
||||
that.addEventListener("seeked", event => {
|
||||
if (loading) {
|
||||
that.brightness(1)
|
||||
loading = false
|
||||
}
|
||||
if (playOnLoad) {
|
||||
playOnLoad = false
|
||||
var toggle = self.controls.querySelector('.toggle')
|
||||
toggle.title = 'Pause'
|
||||
toggle.querySelector('div').innerHTML = icon.pause
|
||||
self.controls.style.opacity = '0'
|
||||
unblock.remove()
|
||||
that.play()
|
||||
}
|
||||
})
|
||||
|
||||
var time = that.querySelector('.controls .time div'),
|
||||
progress = that.querySelector('.controls .position .progress')
|
||||
that.querySelector('.controls .position').addEventListener("click", event => {
|
||||
var bar = event.target
|
||||
while (bar && !bar.classList.contains('bar')) {
|
||||
bar = bar.parentElement
|
||||
}
|
||||
if (bar && bar.classList.contains('bar')) {
|
||||
event.preventDefault()
|
||||
event.stopPropagation()
|
||||
var rect = bar.getBoundingClientRect()
|
||||
var x = event.clientX - rect.x
|
||||
var percent = x / rect.width
|
||||
var position = percent * self.options.duration
|
||||
if (self.options.position) {
|
||||
position += self.options.position
|
||||
}
|
||||
progress.style.width = (100 * percent) + '%'
|
||||
that.currentTime(position)
|
||||
}
|
||||
})
|
||||
that.addEventListener("timeupdate", event => {
|
||||
var currentTime = that.currentTime(),
|
||||
duration = self.options.duration
|
||||
if (self.options.position) {
|
||||
currentTime -= self.options.position
|
||||
}
|
||||
progress.style.width = (100 * currentTime / duration) + '%'
|
||||
duration = formatDuration(duration)
|
||||
currentTime = formatDuration(currentTime)
|
||||
while (duration && duration.startsWith('00:')) {
|
||||
duration = duration.slice(3)
|
||||
}
|
||||
currentTime = currentTime.slice(currentTime.length - duration.length)
|
||||
time.innerText = `${currentTime} / ${duration}`
|
||||
|
||||
})
|
||||
|
||||
that.addEventListener("play", event => {
|
||||
var toggle = self.controls.querySelector('.toggle')
|
||||
toggle.title = 'Pause'
|
||||
toggle.querySelector('div').innerHTML = icon.pause
|
||||
self.controls.style.opacity = '0'
|
||||
})
|
||||
that.addEventListener("pause", event => {
|
||||
var toggle = self.controls.querySelector('.toggle')
|
||||
toggle.title = 'Play'
|
||||
toggle.querySelector('div').innerHTML = icon.play
|
||||
self.controls.style.opacity = '1'
|
||||
})
|
||||
that.addEventListener("ended", event => {
|
||||
var toggle = self.controls.querySelector('.toggle')
|
||||
toggle.title = 'Play'
|
||||
toggle.querySelector('div').innerHTML = icon.play
|
||||
self.controls.style.opacity = '1'
|
||||
})
|
||||
that.addEventListener("seeking", event => {
|
||||
//console.log("seeking")
|
||||
|
||||
})
|
||||
that.addEventListener("seeked", event => {
|
||||
//console.log("seeked")
|
||||
})
|
||||
that.addEventListener("volumechange", event => {
|
||||
var volume = self.controls.querySelector('.volume')
|
||||
if (that.muted()) {
|
||||
volume.innerHTML = icon.unmute
|
||||
volume.title = "Unmute"
|
||||
} else {
|
||||
volume.innerHTML = icon.mute
|
||||
volume.title = "Mute"
|
||||
}
|
||||
})
|
||||
window.addEventListener('resize', event => {
|
||||
//
|
||||
})
|
||||
return that
|
||||
};
|
||||
|
||||
})();
|
||||
Loading…
Add table
Add a link
Reference in a new issue