Commit 0448bd13 by Jonathan Thomas

Refactored moveClip into Vuex action, and invoke this action on both 'Move Clip'…

Refactored moveClip into Vuex action, and invoke this action on both 'Move Clip' and 'Update Clip'... to fix all clip 'positions'
parent d1d3690c
...@@ -20,8 +20,8 @@ ...@@ -20,8 +20,8 @@
<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"/>
</svg> </svg>
<ul class="dropdown-menu small-dropdown"> <ul class="dropdown-menu small-dropdown">
<li><a v-if="index > 0" class="dropdown-item" href="#" @click="moveClip('up', clip, index, index - 1)">Move Up</a></li> <li><a v-if="index > 0" class="dropdown-item" href="#" @click="moveClipBtn('up', clip, index, index - 1)">Move Up</a></li>
<li><a v-if="index < clips.length - 1" class="dropdown-item" href="#" @click="moveClip('down', clip, index, index + 1)">Move Down</a></li> <li><a v-if="index < clips.length - 1" class="dropdown-item" href="#" @click="moveClipBtn('down', clip, index, index + 1)">Move Down</a></li>
<li><hr class="dropdown-divider"></li> <li><hr class="dropdown-divider"></li>
<li><a class="dropdown-item" href="#" @click="deleteClipBtn(clip.id)">Delete</a></li> <li><a class="dropdown-item" href="#" @click="deleteClipBtn(clip.id)">Delete</a></li>
</ul> </ul>
...@@ -53,36 +53,9 @@ export default { ...@@ -53,36 +53,9 @@ export default {
deleteClipBtn(clip_id) { deleteClipBtn(clip_id) {
this.deleteClip(clip_id) this.deleteClip(clip_id)
}, },
moveClip(direction, clipObj, start_index, dest_index) { moveClipBtn(direction, clip, current, dest) {
let local_clips = [...this.thumbnailedClips] let payload = {direction, clip, current, dest }
let reordered_clips = this.reorder(local_clips, start_index, dest_index) this.moveClip(payload)
let pos = 0.0
for (let clip of reordered_clips) {
clip.position = pos
let payload = { data: clip, latest: false, thumbnail: false }
if (clip.id == clipObj.id) {
payload.latest = true
}
this.editClip(payload)
pos += (clip.end - clip.start)
}
},
reorder(array, sourceIndex, destinationIndex) {
const smallerIndex = Math.min(sourceIndex, destinationIndex)
const largerIndex = Math.max(sourceIndex, destinationIndex)
return [
...array.slice(0, smallerIndex),
...(sourceIndex < destinationIndex
? array.slice(smallerIndex + 1, largerIndex + 1)
: []),
array[sourceIndex],
...(sourceIndex > destinationIndex
? array.slice(smallerIndex, largerIndex)
: []),
...array.slice(largerIndex + 1),
]
}, },
toggleSelection(clipObj) { toggleSelection(clipObj) {
if (clipObj != this.preview.clip) { if (clipObj != this.preview.clip) {
...@@ -108,14 +81,11 @@ export default { ...@@ -108,14 +81,11 @@ export default {
this.setScrollToClip(null) this.setScrollToClip(null)
} }
}, },
...mapActions(['loadClips', 'createClip', 'deleteClip', 'editClip']), ...mapActions(['loadClips', 'createClip', 'deleteClip', 'editClip', 'moveClip']),
...mapMutations((['setPreviewClip', 'setClips', 'setScrollToClip'])) ...mapMutations((['setPreviewClip', 'setClips', 'setScrollToClip']))
}, },
computed: { computed: {
thumbnailedClips() { ...mapGetters(['totalClipDuration', 'thumbnailedClips']),
return this.clips.filter(clip => clip.thumbnail).sort((a, b) => a.position - b.position)
},
...mapGetters(['totalClipDuration']),
...mapState(['clips', 'preview', 'scrollToClip']) ...mapState(['clips', 'preview', 'scrollToClip'])
}, },
watch: { watch: {
......
...@@ -69,6 +69,7 @@ ...@@ -69,6 +69,7 @@
<script> <script>
import {mapState, mapActions, mapGetters, mapMutations} from "vuex"; import {mapState, mapActions, mapGetters, mapMutations} from "vuex";
import {fixImageDuration} from "../store/axios";
export default { export default {
name: "Preview.vue", name: "Preview.vue",
...@@ -86,21 +87,34 @@ export default { ...@@ -86,21 +87,34 @@ export default {
}, },
methods: { methods: {
async createClipBtn() { async createClipBtn() {
let data = { if (!this.preview.clip) {
"file": this.preview.file.url, // Create new clip
"position": this.totalClipDuration, let data = {
"start": this.preview.start * this.preview.file.json.duration, "file": this.preview.file.url,
"end": this.preview.end * this.preview.file.json.duration, "position": this.totalClipDuration,
"layer": 1, "start": this.preview.start * fixImageDuration(this.preview.file.json.duration),
"project": this.project.url, "end": this.preview.end * fixImageDuration(this.preview.file.json.duration),
"json": {} "layer": 1,
"project": this.project.url,
"json": {}
}
let payload = {project_id: this.project.id, project_url: this.project.url, data}
await this.createClip(payload)
} }
let payload = { else
project_id: this.project.id, {
project_url: this.project.url, // Edit existing clip
data let clipObj = this.preview.clip
clipObj.start = this.preview.start * fixImageDuration(this.preview.file.json.duration)
clipObj.end = this.preview.end * fixImageDuration(this.preview.file.json.duration)
let payload = { data: clipObj, latest: false, thumbnail: true }
await this.editClip(payload)
// Re-order clips (and fix 'position' to be valid again)
let move_payload = {direction: null, clip: clipObj, current: -1, dest: -1 }
await this.moveClip(move_payload)
} }
await this.createClip(payload) this.setPreviewFile(null)
}, },
togglePause() { togglePause() {
if (this.$refs.video) { if (this.$refs.video) {
...@@ -228,8 +242,8 @@ export default { ...@@ -228,8 +242,8 @@ 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', 'editClip', 'moveClip']),
...mapMutations(['setPreview', 'setPreviewPosition']) ...mapMutations(['setPreview', 'setPreviewPosition', 'setPreviewFile'])
}, },
computed: { computed: {
...mapState(['preview']), ...mapState(['preview']),
......
...@@ -24,4 +24,21 @@ function fixImageDuration(duration) { ...@@ -24,4 +24,21 @@ function fixImageDuration(duration) {
} }
} }
export { instance, blob_instance, fixImageDuration }; function reorderArray(array, sourceIndex, destinationIndex) {
\ No newline at end of file const smallerIndex = Math.min(sourceIndex, destinationIndex)
const largerIndex = Math.max(sourceIndex, destinationIndex)
return [
...array.slice(0, smallerIndex),
...(sourceIndex < destinationIndex
? array.slice(smallerIndex + 1, largerIndex + 1)
: []),
array[sourceIndex],
...(sourceIndex > destinationIndex
? array.slice(smallerIndex, largerIndex)
: []),
...array.slice(largerIndex + 1),
]
}
export { instance, blob_instance, fixImageDuration, reorderArray };
\ No newline at end of file
import { createStore } from 'vuex' import { createStore } from 'vuex'
import { v4 as uuidv4 } from "uuid" import { v4 as uuidv4 } from "uuid"
import { instance, blob_instance, fixImageDuration } from "./axios" import { instance, blob_instance, fixImageDuration, reorderArray } from "./axios"
export default createStore({ export default createStore({
...@@ -165,6 +165,9 @@ export default createStore({ ...@@ -165,6 +165,9 @@ export default createStore({
isAuthenticated: state => !!state.user, isAuthenticated: state => !!state.user,
totalClipDuration: state => { totalClipDuration: state => {
return state.clips.map(clip => clip.end - clip.start).reduce((prev, curr) => prev + curr, 0.0) return state.clips.map(clip => clip.end - clip.start).reduce((prev, curr) => prev + curr, 0.0)
},
thumbnailedClips: state => {
return state.clips.filter(clip => clip.thumbnail).sort((a, b) => a.position - b.position)
} }
}, },
actions: { actions: {
...@@ -276,6 +279,23 @@ export default createStore({ ...@@ -276,6 +279,23 @@ export default createStore({
commit('addError', err.response.data) commit('addError', err.response.data)
} }
}, },
async moveClip({dispatch, getters}, payload) {
let local_clips = [...getters.thumbnailedClips]
let reordered_clips = local_clips
if (payload.current != payload.dest) {
reordered_clips = reorderArray(local_clips, payload.current, payload.dest)
}
let pos = 0.0
for (let c of reordered_clips) {
c.position = pos
let edit_payload = { data: c, latest: false, thumbnail: false }
if (c.id == payload.clip.id) {
edit_payload.latest = true
}
dispatch('editClip', edit_payload)
pos += (c.end - c.start)
}
},
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