Commit 21d1ad5c by Jonathan Thomas

Refactored preview data to live in Vuex. Made clip seconds label react different…

Refactored preview data to live in Vuex. Made clip seconds label react different when it's too small. Added drop-shadow style to context menu buttons. Added editClip action, but not connected yet.
parent f9452bb5
<template> <template>
<div class="row mb-3 p-2 scrolling-container"> <div class="row mb-3 gx-2 p-2 scrolling-container">
<h3>Clips</h3> <h3>Clips <button v-if="clips" type="button" class="btn btn-danger export-btn">Export</button></h3>
<div class="col-12"> <div class="col-12">
<div class="row gy-2 gx-2 mb-2" v-for="clip in thumbnailedClips" :key="clip.id"> <div class="row gy-2 gx-2 mb-2" v-for="(clip, index) in thumbnailedClips" :key="clip.id">
<div class="col-12 text-center img-parent"> <div class="col-12 text-center img-parent">
<span class="clip-badge badge">{{ index + 1 }}</span>
<div class="btn-group dropstart context-menu"> <div class="btn-group dropstart context-menu">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="dropdown-toggle bi bi-three-dots-vertical" data-bs-toggle="dropdown" aria-expanded="false" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="dropdown-toggle bi bi-three-dots-vertical" data-bs-toggle="dropdown" aria-expanded="false" viewBox="0 0 16 16">
<path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/> <path d="M9.5 13a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0zm0-5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>
...@@ -18,7 +20,7 @@ ...@@ -18,7 +20,7 @@
</ul> </ul>
</div> </div>
<div class="clip-label"> <div ref="clip" class="clip-label">
{{ (clip.end - clip.start).toFixed(1) }} Seconds {{ (clip.end - clip.start).toFixed(1) }} Seconds
</div> </div>
...@@ -45,14 +47,14 @@ export default { ...@@ -45,14 +47,14 @@ export default {
this.deleteClip(clip_id) this.deleteClip(clip_id)
}, },
toggleSelection(clipObj) { toggleSelection(clipObj) {
if (clipObj.fileObj != this.previewFile) { if (clipObj.fileObj != this.preview.file) {
this.setPreviewFile(clipObj.fileObj) this.setPreviewFile(clipObj.fileObj)
} else { } else {
this.setPreviewFile(null) this.setPreviewFile(null)
} }
}, },
getSelectedClass(clipObj) { getSelectedClass(clipObj) {
if (this.previewFile && clipObj.fileObj.id == this.previewFile.id) { if (this.preview.file && clipObj.fileObj.id == this.preview.file.id) {
return 'selected' return 'selected'
} else { } else {
return '' return ''
...@@ -65,10 +67,10 @@ export default { ...@@ -65,10 +67,10 @@ export default {
thumbnailedClips() { thumbnailedClips() {
return this.clips.filter(clip => clip.thumbnail) return this.clips.filter(clip => clip.thumbnail)
}, },
...mapState(['clips', 'previewFile', 'latestClip']) ...mapState(['clips', 'preview', 'scrollToClip'])
}, },
watch: { watch: {
latestClip() { scrollToClip() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs.bottom.scrollIntoView({behavior: 'smooth', block: 'end'}) this.$refs.bottom.scrollIntoView({behavior: 'smooth', block: 'end'})
}) })
...@@ -116,9 +118,28 @@ export default { ...@@ -116,9 +118,28 @@ export default {
.clip-label { .clip-label {
color: #ffffff; color: #ffffff;
position: absolute; position: absolute;
top: 88%; bottom: 5%;
z-index: 999; z-index: 999;
right: 5%; right: 5%;
font-size: .8em; font-size: .8em;
background-color: #000000;
border-radius: 4px;
padding: 3px;
opacity: 75%;
}
.export-btn {
float: right;
}
.dropdown-toggle {
filter: drop-shadow(0px 0px 2px #000000);
}
.clip-badge {
position: absolute;
bottom: 5%;
left: 5%;
padding: 8px;
opacity: 75%;
background-color: #000000;
border-radius: 4px;
} }
</style> </style>
\ No newline at end of file
<template> <template>
<div class="row mb-3 gy-2 gx-2 p-2 scrolling-container"> <div class="row mb-3 gx-2 p-2 scrolling-container">
<h3>Files <button type="button" class="btn btn-primary upload-btn" @click="chooseFiles">Upload</button></h3> <h3>Files <button type="button" class="btn btn-primary upload-btn" @click="chooseFiles">Upload</button></h3>
<div class="col-sm-12"> <div class="col-sm-12">
<div class="form-floating mb-3"> <div class="form-floating mb-3">
...@@ -75,14 +75,14 @@ export default { ...@@ -75,14 +75,14 @@ export default {
await this.deleteFile(file.id) await this.deleteFile(file.id)
}, },
toggleSelection(fileObject) { toggleSelection(fileObject) {
if (fileObject != this.previewFile) { if (fileObject != this.preview.file) {
this.setPreviewFile(fileObject) this.setPreviewFile(fileObject)
} else { } else {
this.setPreviewFile(null) this.setPreviewFile(null)
} }
}, },
getSelectedClass(fileObject) { getSelectedClass(fileObject) {
if (this.previewFile && fileObject.id == this.previewFile.id) { if (this.preview.file && fileObject.id == this.preview.file.id) {
return 'selected' return 'selected'
} else { } else {
return '' return ''
...@@ -103,7 +103,7 @@ export default { ...@@ -103,7 +103,7 @@ export default {
searchedFiles() { searchedFiles() {
return this.files.filter(file => path.basename(file.media).toLowerCase().includes(this.search.toLowerCase()) && file.thumbnail) return this.files.filter(file => path.basename(file.media).toLowerCase().includes(this.search.toLowerCase()) && file.thumbnail)
}, },
...mapState(['files', 'previewFile', 'uploads']) ...mapState(['files', 'preview', 'uploads'])
}, },
mounted() { mounted() {
this.setFiles([]) this.setFiles([])
...@@ -145,4 +145,7 @@ export default { ...@@ -145,4 +145,7 @@ export default {
min-width: 5em; min-width: 5em;
opacity: 80%; opacity: 80%;
} }
.dropdown-toggle {
filter: drop-shadow(0px 0px 2px #000000);
}
</style> </style>
\ No newline at end of file
<template> <template>
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<h3 class="p-2">Preview <button v-if="hasPreviewFile" type="button" class="btn btn-danger export-btn">Export</button></h3> <h3 class="p-2">Preview</h3>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div class="col-sm-12"> <div class="col-sm-12">
<video ref="video" v-if="!isImage && hasPreviewFile" @timeupdate="videoTimeUpdate" @pause="togglePause" @play="togglePause" preload="" poster="" class="video-responsive"> <video ref="video" v-if="!isImage && hasPreviewFile" @timeupdate="videoTimeUpdate" @pause="togglePause" @play="togglePause" preload="" poster="" class="video-responsive">
<source :type="previewFormat" :src="previewFile.media"> <source :type="previewFormat" :src="preview.file.media">
</video> </video>
<img v-if="isImage && hasPreviewFile" :src="previewFile.media" class="img-fluid img-thumbnail" /> <img v-if="isImage && hasPreviewFile" :src="preview.file.media" class="img-fluid img-thumbnail" />
</div> </div>
</div> </div>
...@@ -27,19 +27,19 @@ ...@@ -27,19 +27,19 @@
</div> </div>
<div class="col-sm-10 d-flex flex-column p-1"> <div class="col-sm-10 d-flex flex-column p-1">
<div class="timeline" ref="timeline" @mousedown="seekToCursor($event)" @mousemove="drag($event)" @touchmove="drag($event)" @mouseup="endDrag" @touchend="endDrag" @mouseleave="endDrag"> <div class="timeline" ref="timeline" @mousedown="seekToCursor($event)" @mousemove="drag($event)" @touchmove="drag($event)" @mouseup="endDrag" @touchend="endDrag" @mouseleave="endDrag">
<div title="Drag Playback Position" ref="playhead" class="playhead" @mousedown="startDrag($event, 'playhead')" @touchstart="startDrag($event, 'playhead')" :style="{left: position * 100.0 + '%'}"></div> <div title="Drag Playback Position" ref="playhead" class="playhead" @mousedown="startDrag($event, 'playhead')" @touchstart="startDrag($event, 'playhead')" :style="{left: preview.position * 100.0 + '%'}"></div>
<div title="Drag to Trim Start" ref="start" class="marker marker_left" @click="seekToMarker('start')" @mousedown="startDrag($event, 'start')" @touchstart="startDrag($event, 'start')" :style="{left: markers.start * 100.0 + '%'}"> <div title="Drag to Trim Start" ref="start" class="marker marker_left" @click="seekToMarker('start')" @mousedown="startDrag($event, 'start')" @touchstart="startDrag($event, 'start')" :style="{left: preview.start * 100.0 + '%'}">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="48" fill="currentColor" class="bi bi-grip-vertical" viewBox="0 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="48" fill="currentColor" class="bi bi-grip-vertical" viewBox="0 0 16 16">
<path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/> <path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
</svg> </svg>
</div> </div>
<div title="Drag to Trim End" ref="end" class="marker marker_right" @click="seekToMarker('end')" @mousedown="startDrag($event, 'end')" @touchstart="startDrag($event, 'end')" :style="{left: (markers.end - marker_width_percent) * 100.0 + '%'}"> <div title="Drag to Trim End" ref="end" class="marker marker_right" @click="seekToMarker('end')" @mousedown="startDrag($event, 'end')" @touchstart="startDrag($event, 'end')" :style="{left: (preview.end - marker_width_percent) * 100.0 + '%'}">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="48" fill="currentColor" class="bi bi-grip-vertical" viewBox="3 0 16 16"> <svg xmlns="http://www.w3.org/2000/svg" width="16" height="48" fill="currentColor" class="bi bi-grip-vertical" viewBox="3 0 16 16">
<path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/> <path d="M7 2a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 5a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zM7 8a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm-3 3a1 1 0 1 1-2 0 1 1 0 0 1 2 0zm3 0a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
</svg> </svg>
</div> </div>
<div class="clip" :style="{left: markers.start * 100.0 + '%', width: `calc(${(markers.end - markers.start) * 100.0}%)`}"> <div ref="clip" class="clip" :class="clipSizeClass" :style="{left: preview.start * 100.0 + '%', width: `calc(${(preview.end - preview.start) * 100.0}%)`}">
{{ ((markers.end - markers.start) * previewFile.json.duration).toFixed(1) }} Sec {{ ((preview.end - preview.start) * preview.file.json.duration).toFixed(1) }} Seconds
</div> </div>
</div> </div>
</div> </div>
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
</div> </div>
</div> </div>
<div v-if="!previewFile" class="mb-5 text-center" style="margin-top: 7em;"> <div v-if="!hasPreviewFile" class="mb-5 text-center" style="margin-top: 7em;">
<div class="col-lg-6 mx-auto"> <div class="col-lg-6 mx-auto">
<p class="lead">Upload or select a video to begin!</p> <p class="lead">Upload or select a video to begin!</p>
</div> </div>
...@@ -61,7 +61,7 @@ ...@@ -61,7 +61,7 @@
</template> </template>
<script> <script>
import {mapState, mapActions} from "vuex"; import {mapState, mapActions, mapMutations} from "vuex";
export default { export default {
name: "Preview.vue", name: "Preview.vue",
...@@ -70,22 +70,18 @@ export default { ...@@ -70,22 +70,18 @@ export default {
return { return {
dragging_marker: null, dragging_marker: null,
is_paused: true, is_paused: true,
position: 0.0,
markers: {
start: 0.0,
end: 1.0
},
marker_width: 12, marker_width: 12,
marker_width_percent: 0.0 marker_width_percent: 0.0,
clipSizeClass: ""
} }
}, },
methods: { methods: {
async createClipBtn() { async createClipBtn() {
let data = { let data = {
"file": this.previewFile.url, "file": this.preview.file.url,
"position": 0.0, "position": 0.0,
"start": this.markers.start * this.previewFile.json.duration, "start": this.preview.start * this.preview.file.json.duration,
"end": this.markers.end * this.previewFile.json.duration, "end": this.preview.end * this.preview.file.json.duration,
"layer": 1, "layer": 1,
"project": this.project.url, "project": this.project.url,
"json": {} "json": {}
...@@ -114,7 +110,7 @@ export default { ...@@ -114,7 +110,7 @@ export default {
videoTimeUpdate() { videoTimeUpdate() {
if (this.$refs.video) { if (this.$refs.video) {
let playback_percent = (this.$refs.video.currentTime / this.$refs.video.duration) let playback_percent = (this.$refs.video.currentTime / this.$refs.video.duration)
this.position = playback_percent this.setPreviewPosition(playback_percent)
} }
}, },
startDrag(e, marker) { startDrag(e, marker) {
...@@ -130,9 +126,8 @@ export default { ...@@ -130,9 +126,8 @@ export default {
seekToCursor(e) { seekToCursor(e) {
if (!this.dragging_marker) { if (!this.dragging_marker) {
let percent_x = this.getCursorPosition(e) let percent_x = this.getCursorPosition(e)
this.position = percent_x
if (this.$refs.video) { if (this.$refs.video) {
this.$refs.video.currentTime = this.position * this.$refs.video.duration this.$refs.video.currentTime = percent_x * this.$refs.video.duration
} }
return false return false
} }
...@@ -140,27 +135,35 @@ export default { ...@@ -140,27 +135,35 @@ export default {
seekToMarker(marker) { seekToMarker(marker) {
if (this.$refs.video) { if (this.$refs.video) {
if (marker == 'start') { if (marker == 'start') {
this.$refs.video.currentTime = this.markers.start * this.$refs.video.duration this.$refs.video.currentTime = this.preview.start * this.$refs.video.duration
} else if (marker == 'end') { } else if (marker == 'end') {
this.$refs.video.currentTime = this.markers.end * this.$refs.video.duration this.$refs.video.currentTime = this.preview.end * this.$refs.video.duration
} }
} }
}, },
drag(e) { drag(e) {
if (this.$refs.clip.clientWidth < 80) {
this.clipSizeClass = "clip-too-small"
} else {
this.clipSizeClass = ""
}
if (this.dragging_marker == 'start') { if (this.dragging_marker == 'start') {
this.markers.start = Math.min(this.getCursorPosition(e), this.markers.end) this.setPreview({start: Math.min(this.getCursorPosition(e), this.preview.end),
if (this.$refs.video && isFinite(this.markers.start * this.$refs.video.duration)) { end: this.preview.end})
this.$refs.video.currentTime = this.markers.start * this.$refs.video.duration if (this.$refs.video && isFinite(this.preview.start * this.$refs.video.duration)) {
this.$refs.video.currentTime = this.preview.start * this.$refs.video.duration
} }
} else if (this.dragging_marker == 'end') { } else if (this.dragging_marker == 'end') {
this.markers.end = Math.max(this.getCursorPosition(e, 12), this.markers.start) this.setPreview({start: this.preview.start,
if (this.$refs.video && isFinite(this.markers.start * this.$refs.video.duration)) { end: Math.max(this.getCursorPosition(e, 12), this.preview.start)})
this.$refs.video.currentTime = this.markers.end * this.$refs.video.duration if (this.$refs.video && isFinite(this.preview.start * this.$refs.video.duration)) {
this.$refs.video.currentTime = this.preview.end * this.$refs.video.duration
} }
} else if (this.dragging_marker == 'playhead') { } else if (this.dragging_marker == 'playhead') {
let percent_x = this.getCursorPosition(e) let percent_x = this.getCursorPosition(e)
this.$refs.playhead.style.left = `${percent_x * 100}%` this.$refs.playhead.style.left = `${percent_x * 100}%`
if (this.$refs.video && isFinite(this.markers.start * this.$refs.video.duration)) { if (this.$refs.video && isFinite(this.preview.start * this.$refs.video.duration)) {
this.$refs.video.currentTime = percent_x * this.$refs.video.duration this.$refs.video.currentTime = percent_x * this.$refs.video.duration
} }
} }
...@@ -196,38 +199,38 @@ export default { ...@@ -196,38 +199,38 @@ export default {
let percent_x = (relative_x / timeline_bounds.width) let percent_x = (relative_x / timeline_bounds.width)
return percent_x return percent_x
}, },
...mapActions(['createClip']) ...mapActions(['createClip']),
...mapMutations(['setPreview', 'setPreviewPosition'])
}, },
computed: { computed: {
...mapState(['previewFile']), ...mapState(['preview']),
hasPreviewFile() { hasPreviewFile() {
if (this.previewFile) { if (this.preview.file) {
return true return true
} else { } else {
return false return false
} }
}, },
isImage() { isImage() {
return (this.previewFile && this.previewFile.json.vcodec == "QImage") return (this.preview.file && this.preview.file.json.vcodec == "QImage")
}, },
previewFormat() { previewFormat() {
if (this.previewFile && this.previewFile.json.acodec == "mp3") { if (this.preview.file && this.preview.file.json.acodec == "mp3") {
return 'audio/mpeg' return 'audio/mpeg'
} else { } else {
return `video/${this.previewFile.media.split('.').pop()}` return `video/${this.preview.file.media.split('.').pop()}`
} }
} }
}, },
watch: { watch: {
previewFile() { 'preview.file': function() {
if (this.$refs.video) { if (this.$refs.video) {
this.is_paused = true this.is_paused = true
this.$refs.video.pause() this.$refs.video.pause()
this.$refs.video.load() this.$refs.video.load()
} }
this.position = 0.0 this.setPreview({start: 0.0, end: 1.0})
this.markers.start = 0.0 this.setPreviewPosition(0.0)
this.markers.end = 1.0
}, },
}, },
updated() { updated() {
...@@ -241,9 +244,6 @@ video { ...@@ -241,9 +244,6 @@ video {
background-color: #000000; background-color: #000000;
width: 100%; width: 100%;
} }
.export-btn {
float: right;
}
.timeline { .timeline {
background-color: #000000; background-color: #000000;
height: 48px; height: 48px;
...@@ -271,6 +271,10 @@ video { ...@@ -271,6 +271,10 @@ video {
text-align: center; text-align: center;
padding-top: 15px; padding-top: 15px;
} }
.clip-too-small {
color: #0d6efd!important;
padding-top: 47px!important;
}
.marker_left { .marker_left {
border-left: rgba(255, 255, 255, 0.5) solid 1px; border-left: rgba(255, 255, 255, 0.5) solid 1px;
} }
......
...@@ -12,8 +12,14 @@ export default createStore({ ...@@ -12,8 +12,14 @@ export default createStore({
uploads: [], uploads: [],
project: null, project: null,
user: null, user: null,
previewFile: null, preview: {
latestClip: null, file: null,
clip: null,
start: 0.0,
end: 1.0,
position: 0.0
},
scrollToClip: null,
}, },
mutations: { mutations: {
...@@ -69,9 +75,15 @@ export default createStore({ ...@@ -69,9 +75,15 @@ export default createStore({
state.clips = clips state.clips = clips
if (!clips) { if (!clips) {
// clear latest clip if no clips // clear latest clip if no clips
state.latestClip = null state.scrollToClip = null
} }
}, },
setClip(state, clipObj) {
state.clips = [
...state.clips = state.clips.filter(clip => clip.id != clipObj.id),
clipObj
]
},
deleteClip(state, clip_id) { deleteClip(state, clip_id) {
state.clips = state.clips.filter(clip => clip.id != clip_id) state.clips = state.clips.filter(clip => clip.id != clip_id)
}, },
...@@ -82,12 +94,27 @@ export default createStore({ ...@@ -82,12 +94,27 @@ export default createStore({
payload.obj payload.obj
] ]
if (payload.latest) { if (payload.latest) {
state.latestClip = payload.obj state.scrollToClip = payload.obj
} }
} }
}, },
setPreview(state, payload) {
state.preview.start = payload.start
state.preview.end = payload.end
},
setPreviewPosition(state, position) {
state.preview.position = position
},
setPreviewFile(state, file) { setPreviewFile(state, file) {
state.previewFile = file state.preview.file = file
state.preview.start = 0.0
state.preview.end = 1.0
},
setPreviewClip(state, clipObj) {
state.preview.clip = clipObj
state.preview.start = clipObj.start
state.preview.end = clipObj.end
state.preview.position = clipObj.start
}, },
addUpload(state, upload) { addUpload(state, upload) {
state.uploads.push(upload) state.uploads.push(upload)
...@@ -203,6 +230,21 @@ export default createStore({ ...@@ -203,6 +230,21 @@ export default createStore({
commit('addError', err.response.data) commit('addError', err.response.data)
} }
}, },
async editClip({dispatch, commit}, payload) {
try {
const response = await instance.post(`${payload.project_url}clips/`, payload.data)
let clipObj = response.data
const file_response = await instance.get(clipObj.file)
clipObj.fileObj = file_response.data
commit('addClip', clipObj)
let fps = clipObj.json.reader.fps.num / clipObj.json.reader.fps.den
let thumbnail_payload = { obj: clipObj, frame: clipObj.start * fps, latest: true }
dispatch('attachThumbnail', thumbnail_payload)
} catch(err) {
commit('addError', err.response.data)
}
},
async deleteClip({commit}, clip_id) { async deleteClip({commit}, clip_id) {
try { try {
await instance.delete(`clips/${clip_id}/`) await instance.delete(`clips/${clip_id}/`)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment