UNPKG

teslacam-browser

Version:

A minimal TeslaCam Browser

227 lines (198 loc) 11.6 kB
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>TeslaCam Browser</title> <link rel="stylesheet" href="node_modules/flatpickr/dist/flatpickr.min.css"> <link rel="stylesheet" href="node_modules/bootstrap/dist/css/bootstrap.min.css" /> <link rel="stylesheet" href="node_modules/open-iconic/font/css/open-iconic-bootstrap.css" /> <link rel="stylesheet" href="app.css" /> <script type="text/javascript" src="node_modules/vue/dist/vue.js"></script> <script type="text/javascript" src="node_modules/flatpickr/dist/flatpickr.min.js"></script> <script>const $ = require("jquery");</script> <script>const bootstrap = require("bootstrap");</script> <script>const path = require("path");</script> <script>const helpers = require("./helpers");</script> <script>const ui = require("./ui");</script> </head> <body> <div id="root" class="d-flex flex-column"> <div v-cloak class="d-flex flex-column"> <div class="d-flex flex-column"> <div id="heading" class="d-flex justify-content-between"> <div class="d-flex"> <div class="p-2 align-self-center" @click="showSidebar = !showSidebar"> <button class="btn btn-primary btn-lg" style="width: 60px;" v-show="!showSidebar"> <span class="oi oi-menu" title="Folders"></span> </button> <button class="btn btn-primary btn-lg" style="width: 60px;" v-show="showSidebar"> <span class="oi oi-chevron-left" title="Collapse"></span> </button> </div> <div class="p-2 align-self-baseline text-nowrap"> <span class="heading" @click="showSidebar = !showSidebar">TeslaCam Browser</span> </div> <div class="p-2 align-self-baseline text-nowrap"> <span class="version" id="version">{{ args.version }}</span> </div> <div class="p-2 align-self-baseline text-nowrap"> <span class="credits">by Chris Cavanagh</span> </div> </div> <div class="p-2 donate mt-2"> <div class="d-flex flex-row-reverse"> <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank"> <input type="hidden" name="cmd" value="_donations" /> <input type="hidden" name="business" value="32J86B5QYPD6Y" /> <input type="hidden" name="currency_code" value="USD" /> <input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_SM.gif" border="0" name="submit" title="PayPal - The safer, easier way to pay online!" alt="Donate with PayPal button" /> <img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1" /> </form> </div> <div class="d-flex flex-row custom-control custom-switch mr-2"> <input type="checkbox" v-model="combineClips" class="custom-control-input" id="combineClips"> <label class="custom-control-label" for="combineClips">Combine clips</label> </div> </div> </div> <div id="content" class="d-flex"> <nav id="sidebar" class="d-flex flex-column align-items-start" :class="{ hidden: !showSidebar }"> <div class="navigation overflow-auto"> <div class="px-2 mb-2 overflow-auto"> <button class="btn btn-primary btn-block dropdown-toggle" type="button" @click.prevent="showFolders = !showFolders" style="word-wrap: break-word; white-space: normal; max-width: 320px;"> <span class="oi oi-folder text-warning"></span> <span>{{args.folder}}</span> </button> <div v-show="showFolders"> <div v-for="f, i in args.folderPathParts" :style="{ marginLeft: ( i * 10 ) + 'px' }"> <a href="" @click.prevent="selectedFolder = f.path"> <span class="oi oi-folder text-warning"></span> <span :style="{ fontWeight: i < args.folderPathParts.length - 1 ? 'normal' : 'bold' }">{{f.name}}</span> </a> </div> <div v-for="subfolder in args.subfolders" :style="{ marginLeft: ( args.folderPathParts.length * 10 ) + 'px' }"> <a href="" @click.prevent="selectedFolder = subfolder.path"> <span class="oi oi-folder text-warning"></span> <span>{{subfolder.name}}</span> </a> </div> </div> </div> <div class="d-flex align-items-center"> <div class="px-2 mb-2 flex-grow-1" style="font-size: small;"> <div>{{ args && args.folderInfos ? args.folderInfos.length : 0 }} event{{ args && args.folderInfos && args.folderInfos.length != 1 ? "s" : "" }}</div> <div>{{ args && args.dates ? args.dates.length : 0 }} day{{ args && args.dates && args.dates != 1 ? "s" : "" }}</div> </div> <div class="px-2 mb-2 text-nowrap"> <button id="openButton" type="button" class="btn btn-primary" @click="openFolders()">Open...</button> <button id="browseButton" type="button" class="btn btn-secondary" @click="openBrowser()">Browse</button> </div> </div> <div class="px-2 mb-2"> <input id="calendar" class="flatpickr flatpickr-input dates form-control" type="text" placeholder="Select Date..." readonly="readonly" /> </div> <div class="px-2 mb-2"> <div class="list-group list-group-flush overflow-auto times"> <a v-for="t in times" href="" class="list-group-item list-group-item-action" :class="{active: t === selectedTime}" @click.prevent="selectedTime = t" style="cursor: pointer;">{{ t.name }}</a> </div> </div> <div class="px-2 mb-2"> <button id="deleteButton" class="btn btn-danger" @click="deleteFolder( selectedPath )">Delete folder</button> <button id="copyButton" class="btn btn-info" @click="copyPath( selectedPath )">Copy path</button> </div> </div> </nav> <div id="detail" class="d-flex flex-column flex-grow-1"> <div id="videos"> <div class="timespan card mb-2 mx-2" v-if="combineClips"> <div class="d-flex align-items-center titleContainer card-header"> <div class="px-2 controls"> <button class="btn btn-success play" v-show="!controls.playing" @click="controls.playing = !controls.playing"><span class="oi oi-media-play" title="Play"></span></button> <button class="btn btn-warning pause" v-show="controls.playing" @click="controls.playing = !controls.playing"><span class="oi oi-media-pause" title="Pause"></span></button> </div> <div class="px-2 flex-grow-1 controls"> <input class="custom-range scrub" v-model="currentTime" type="range" :max="duration" @input="controls.playing = false"/> </div> <div class="px-2 controls"> <select class="form-control" v-model="controls.speed"> <option value="1">1x</option> <option value="2">2x</option> <option value="10">10x</option> </select> </div> </div> <div class="videoContainer card-body"> <div class="alert alert-info" v-if="loading != null">Loading {{ Math.round( loading ) }}%...<span v-if="selectedTime.time.recent"> (Clips from RecentFiles will take longer to load)</span></div> <video-group :controls="controls" :timespans="timespans"></video-group> <div class="text-center">{{ timespanTime( controls.timespan ) }}</div> </div> </div> <div v-if="!combineClips"> <div v-for="timespan in timespans" class="timespan card mb-2 mx-2"> <div class="d-flex align-items-center titleContainer card-header"> <div class="px-2 flex-grow-1 title" title="Show / hide" @click="timespan.visible = !timespan.visible"><a href="#">{{timespan.visible ? "↑" : "↓"}}</a> {{timespan.title}}</div> <div class="px-2 controls"> <button class="btn btn-danger delete" @click="deleteFiles( timespan )">Delete</button> <button class="btn btn-info copy" @click="copyFilePaths( timespan )">Copy paths</button> <button class="btn btn-success play" v-show="!timespan.playing" @click="playPause( timespan )"><span class="oi oi-media-play" title="Play"></span></button> <button class="btn btn-warning pause" v-show="timespan.playing" @click="playPause( timespan )"><span class="oi oi-media-pause" title="Pause"></span></button> </div> <div class="px-2 flex-grow-1 controls" v-if="timespan.visible"> <input class="custom-range scrub" v-model="timespan.currentTime" type="range" :max="timespan.duration" @input="scrubInput( timespan )"/> </div> <div class="px-2 controls"> <select class="form-control" v-model="controls.speed"> <option value="1">1x</option> <option value="2">2x</option> <option value="10">10x</option> </select> </div> </div> <div class="videoContainer card-body" v-if="timespan.visible"> <videos :controls="controls" :timespan="timespan"></videos> <div class="text-center">{{ timespanTime( timespan ) }}</div> </div> </div> </div> </div> </div> </div> </div> </div> </div> <script type="text/javascript"> (function () { const { ipcRenderer } = require("electron") const fs = require("fs") var vueApp = ui.initialize( { openFolders: success => success(ipcRenderer.sendSync("openFolders")), reopenFolders: success => success(ipcRenderer.sendSync("reopenFolders")), openFolder: (p, success) => success(ipcRenderer.sendSync("openFolder", p)), getFiles: (p, success) => success(ipcRenderer.sendSync("getFiles", p)), openBrowser: () => ipcRenderer.send("openBrowser"), deleteFiles: files => ipcRenderer.send("deleteFiles", files), deleteFolder: folder => ipcRenderer.send("deleteFolder", folder), copyFilePaths: filePaths => ipcRenderer.send("copyFilePaths", filePaths), copyPath: path => ipcRenderer.send("copyPath", path), openExternal: path => ipcRenderer.send("openExternal", path) } ) })(); </script> </body> </html>