Skip to content

Commit 7411ae7

Browse files
Fix keyboard shortcuts and add join
1 parent 80658ee commit 7411ae7

File tree

3 files changed

+85
-19
lines changed

3 files changed

+85
-19
lines changed

htdocs/fcut.html

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
<script src="FileChooser.js" type="text/javascript"></script>
1717
<script src="fcut-utils.js" type="text/javascript"></script>
1818
</head><body>
19-
<div id="app">
19+
<div id="app" tabindex="0" v-on:keyup="pages.dispatchKey($event)">
2020
<page name="home">
2121
<div class="padded">
2222
<div class="bar-flex-row">
2323
<button v-on:click="openProject().then(function() { pages.navigateTo('preview'); })" title="Select FCut Project file to open"><i class="fas fa-file"></i></button>
2424
<button v-on:click="saveProject()" title="Select FCut Project file to save as"><i class="fas fa-save"></i></button>
2525
<span class="bar-flex-row-content"></span>
26-
<button v-on:click="pages.navigateTo('about')"><i class="fas fa-question"></i></button>
26+
<button v-on:click="pages.navigateTo('help')"><i class="fas fa-question"></i></button>
2727
</div>
2828
<h2>Fast FFmpeg Cutter (Preview)</h2>
2929
<div class="flow">
@@ -53,14 +53,13 @@ <h2>Fast FFmpeg Cutter (Preview)</h2>
5353
</div>
5454
</div>
5555
</page>
56-
<page name="preview" eclass="scroll" v-on:page-show="arguments[0].$el.focus()">
57-
<div tabindex="0" v-on:keyup.e="pages.navigateTo('export')"
58-
v-on:keyup.t="bars.time = !bars.time" v-on:keyup.c="bars.cut = !bars.cut" v-on:keyup.s="bars.bsearch = !bars.bsearch" v-on:keyup.p="bars.project = !bars.project"
59-
v-on:keyup.delete="removePart(partIndex)" v-on:keyup.enter="split()"
60-
v-on:keyup.left="move(-step)" v-on:keyup.right="move(step)"
61-
v-on:keyup.up="move(-60)" v-on:keyup.down="move(60)"
62-
v-on:keyup.page-up="move(-period)" v-on:keyup.page-down="move(period)"
63-
v-on:keyup.home="navigateTo(0)" v-on:keyup.end="navigateTo(duration)">
56+
<page name="preview" eclass="scroll" v-on:page-key-e="pages.navigateTo('export')"
57+
v-on:page-key-t="bars.time = !bars.time" v-on:page-key-c="bars.cut = !bars.cut" v-on:page-key-s="bars.bsearch = !bars.bsearch" v-on:page-key-p="bars.project = !bars.project"
58+
v-on:page-key-delete="removePart(partIndex)" v-on:page-key-enter="split()"
59+
v-on:page-key-left="move(-step)" v-on:page-key-right="move(step)"
60+
v-on:page-key-up="move(-60)" v-on:page-key-down="move(60)"
61+
v-on:page-key-pageup="move(-period)" v-on:page-key-pagedown="move(period)"
62+
v-on:page-key-home="navigateTo(0)" v-on:page-key-end="navigateTo(duration)">
6463
<img v-bind:style="{ height: aspectRatio > 0 ? (Math.floor(10000 / aspectRatio) / 100) + 'vw' : undefined }" class="preview" :src="previewSrc" v-on:click="navigateOnPreviewClick" />
6564
<div class="overlay padded">
6665
<div class="bar-flex-row">
@@ -84,9 +83,9 @@ <h2>Fast FFmpeg Cutter (Preview)</h2>
8483
</div>
8584
<div v-if="bars.time" class="button-bar" title="Preview time">
8685
<a href="#" v-on:click="navigateTo(0)" class="time" title="Go to start">0:00</a>
87-
<button v-on:click="move(-period)" title="Move backard one period"><i class="fas fa-backward"></i></button>
88-
<button v-on:click="move(-60)" title="Move backard one minute"><i class="fas fa-fast-backward"></i></button>
89-
<button v-on:click="move(-step)" title="Move backard one step"><i class="fas fa-step-backward"></i></button>
86+
<button v-on:click="move(-period)" title="Move backward one period"><i class="fas fa-backward"></i></button>
87+
<button v-on:click="move(-60)" title="Move backward one minute"><i class="fas fa-fast-backward"></i></button>
88+
<button v-on:click="move(-step)" title="Move backward one step"><i class="fas fa-step-backward"></i></button>
9089
<input type="text" v-model="timeHMS" class="time" title="Preview time" />
9190
<button v-on:click="move(step)" title="Move forward one step"><i class="fas fa-step-forward"></i></button>
9291
<button v-on:click="move(60)" title="Move forward one minute"><i class="fas fa-fast-forward"></i></button>
@@ -102,11 +101,12 @@ <h2>Fast FFmpeg Cutter (Preview)</h2>
102101
<a href="#" v-on:click="navigateTo(partEndTime)" class="time" title="Go to period end">{{ formatHMS(partEndTime) }}</a>
103102
<button v-on:click="movePart(partIndex, partIndex + 1)" v-bind:disabled="partIndex === parts.length - 1" title="Move the part forward"><i class="fas fa-arrow-right"></i></button>
104103
<button v-on:click="split()" title="Cut the part in 2 at preview time"><i class="fas fa-cut"></i> Split</button>
104+
<button v-on:click="join()" v-bind:disabled="!canJoin" title="Join the 2 parts"><i class="fas fa-paperclip"></i> Join</button>
105105
</div>
106106
<div v-if="bars.bsearch" class="button-bar" title="Binary search">
107107
<input type="text" v-model="stepHMS" class="time" title="Step" />
108108
<input type="text" v-model="periodHMS" class="time" title="Period" />
109-
<button v-on:click="findNext(false)" title="Move backard"><i class="fas fa-angle-double-left"></i> Back</button>
109+
<button v-on:click="findNext(false)" title="Move backward"><i class="fas fa-angle-double-left"></i> Back</button>
110110
<button v-on:click="findNext(true)" title="Move forward"><i class="fas fa-angle-double-right"></i> Next</button>
111111
<div class="time" title="Search period" style="display: inline-block;">
112112
<i v-if="findPeriod === 0" class="fas fa-check"></i>
@@ -128,7 +128,6 @@ <h2>Fast FFmpeg Cutter (Preview)</h2>
128128
<button v-on:click="saveProject()" title="Select FCut Project file to save as"><i class="fas fa-save"></i> Save as...</button>
129129
<button v-on:click="pages.navigateTo('export')"><i class="fas fa-cogs"></i> Export...</button>
130130
</div>
131-
</div>
132131
</page>
133132
<page name="export">
134133
<div class="padded">
@@ -248,7 +247,7 @@ <h2>Export</h2>
248247
<div class="padded">
249248
<div class="bar-flex-row">
250249
<span class="bar-flex-row-content"></span>
251-
<button v-on:click="pages.navigateTo('about')"><i class="fas fa-question"></i></button>
250+
<button v-on:click="pages.navigateTo('help')"><i class="fas fa-question"></i></button>
252251
</div>
253252
<h2>Missing Configuration</h2>
254253
<p>It seems that some configuration is missing or invalid.</p>
@@ -257,9 +256,14 @@ <h2>Missing Configuration</h2>
257256
or on the <a href="https://github.com/javalikescript/fcut/releases/download/v0.3.0/ffmpeg-x86_64-windows.zip" target="_blank">FCut github</a>.</li>
258257
</div>
259258
</page>
260-
<page name="about">
259+
<page name="help">
261260
<div class="padded">
262261
<button v-on:click="pages.navigateBack()"><i class="fas fa-arrow-left"></i></button>
262+
<h2>Help</h2>
263+
<p>Fast Cut allows to visually cut and join videos then export them losslessly.</p>
264+
<p>The binary search helps you to find a cut time quickly,
265+
use the forward and backward buttons to indicate the cut location,
266+
the time shows how close you are from the cut point.</p>
263267
<h2>About</h2>
264268
<p>A <a href="https://github.com/javalikescript/luajls" target="_blank">luajls</a> application, see <a href="https://github.com/javalikescript/fcut" target="_blank">sources</a>.</p>
265269
<p>This application uses the following external software/libraries</p>

htdocs/fcut.js

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var vm = new Vue({
3636
partTime: 0,
3737
partEndTime: 0,
3838
partInfo: {},
39+
canJoin: false,
3940
time: 0,
4041
logBuffer: '',
4142
logLine: '',
@@ -258,12 +259,14 @@ var vm = new Vue({
258259
this.partTime = at.time;
259260
this.partEndTime = at.time + at.part.duration;
260261
this.partInfo = this.sources[at.part.sourceId];
262+
this.canJoin = this.getJoinFirstindex(at) >= 0;
261263
} else {
262264
this.previewSrc = 'roll.png';
263265
this.partIndex = 0;
264266
this.partTime = 0;
265267
this.partEndTime = 0;
266268
this.partInfo = {}
269+
this.canJoin = false;
267270
}
268271
},
269272
movePart: function(atIndex, toIndex) {
@@ -286,9 +289,42 @@ var vm = new Vue({
286289
}
287290
}
288291
},
292+
getJoinFirstindex: function(at) {
293+
if (at) {
294+
var firstIndex;
295+
if (at.relTime <= this.step) {
296+
firstIndex = at.index - 1;
297+
} else if (at.part.duration - at.relTime <= this.step) {
298+
firstIndex = at.index;
299+
}
300+
if ((firstIndex >= 0) && (firstIndex < this.parts.length)) {
301+
var part1 = this.parts[firstIndex];
302+
var part2 = this.parts[firstIndex + 1];
303+
if (part1 && part2 && (part1.sourceId === part2.sourceId)) {
304+
return firstIndex;
305+
}
306+
}
307+
}
308+
return -1;
309+
},
310+
join: function() {
311+
var at = this.findPartAndTime(this.time);
312+
var firstIndex = this.getJoinFirstindex(at);
313+
if (firstIndex >= 0) {
314+
var part1 = this.parts[firstIndex];
315+
var part2 = this.parts[firstIndex + 1];
316+
var part = {
317+
sourceId: part1.sourceId,
318+
duration: part1.duration + part2.duration,
319+
from: part1.from,
320+
to: part2.to
321+
};
322+
this.parts.splice(firstIndex, 2, part);
323+
}
324+
},
289325
split: function() {
290326
var at = this.findPartAndTime(this.time);
291-
if (at && (at.relTime > 0)&& (at.relTime < at.part.duration)) {
327+
if (at && (at.relTime > 0) && (at.relTime < at.part.duration)) {
292328
var part = at.part;
293329
var splitTime = part.from + at.relTime;
294330
var part1 = {

htdocs/page.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,33 @@ var pages = {
2121
page.$emit('page-show', page);
2222
}
2323
},
24-
navigateBack: function() {
24+
current: function() {
25+
return this.names[this.name];
26+
},
27+
dispatchKey: function(event) {
28+
var tagName = event.target.tagName.toUpperCase();
29+
if (tagName !== 'INPUT') {
30+
var eventName = event.key;
31+
if (eventName.length > 1) {
32+
eventName = eventName.toLowerCase();
33+
}
34+
if (eventName.substring(0, 5) === 'arrow') {
35+
eventName = eventName.substring(5);
36+
}
37+
if (event.altKey) {
38+
eventName = 'alt-' + eventName;
39+
}
40+
if (event.ctrlKey) {
41+
eventName = 'ctrl-' + eventName;
42+
}
43+
//console.log('dispatchKey(): ' + eventName, event, this);
44+
var page = this.names[this.name];
45+
if (page) {
46+
page.$emit('page-key-' + eventName, event);
47+
}
48+
}
49+
},
50+
navigateBack: function() {
2551
if (this.navigationHistory.length > 1) {
2652
this.navigationHistory.pop();
2753
this.name = this.navigationHistory[this.navigationHistory.length - 1];

0 commit comments

Comments
 (0)