diff --git a/dist/hass-aarlo.js b/dist/hass-aarlo.js index 986bb5d..bcfe310 100644 --- a/dist/hass-aarlo.js +++ b/dist/hass-aarlo.js @@ -341,6 +341,9 @@ class AarloGlance extends LitElement {
+ + @@ -393,6 +396,9 @@ class AarloGlance extends LitElement { + +
@@ -700,33 +706,51 @@ class AarloGlance extends LitElement { get gc() { return this._gc } + set gc( value ) { + this._gc = value + } get gs() { return this._gs } + set gs( value ) { + this._gs = value + } get cc() { if( !(`${this._cameraIndex}` in this._cc) ) { this._cc[`${this._cameraIndex}`] = {} } return this._cc[`${this._cameraIndex}`] } + set cc( value ) { + this._cc[`${this._cameraIndex}`] = value + } get cs() { if( !(`${this._cameraIndex}` in this._cs) ) { this._cs[`${this._cameraIndex}`] = {} } return this._cs[this._cameraIndex] } + set cs( value ) { + this._cs[this._cameraIndex] = value + } get lc() { if( !(`${this._cameraIndex}` in this._lc) ) { this._lc[`${this._cameraIndex}`] = {} } return this._lc[this._cameraIndex] } + set lc( value ) { + this._lc[this._cameraIndex] = value + } get ls() { if( !(`${this._cameraIndex}` in this._ls) ) { this._ls[`${this._cameraIndex}`] = {} } return this._ls[this._cameraIndex] } + set ls( value ) { + this._ls[this._cameraIndex] = value + } _getState(_id, default_value = '') { return this._hass !== null && _id in this._hass.states ? @@ -741,15 +765,15 @@ class AarloGlance extends LitElement { }; } - updateStatuses() { + _updateStatuses() { // CAMERA const camera = this._getState(this.cc.id,'unknown'); // Set the camera name now. We have to wait untik now to ensure `_hass` // is set and we can get to the camera state. - if ( !this.cc.name ) { - this.cc.name = this._config.name ? this._config.name : camera.attributes.friendly_name; + if ( this.cc.name === null ) { + this.cc.name = camera.attributes.friendly_name } // Image changed? See if: @@ -891,18 +915,24 @@ class AarloGlance extends LitElement { const bell = this._getState(this.cc.doorBellId, 'off'); const name = bell.attributes.friendly_name const mute = bell.attributes.chimes_silenced || bell.attributes.calls_silenced + const muteable = !!this.cc.doorBellMuteId if ( bell.state === 'on' ) { this.cs.doorBellState = 'on' this.cs.doorBellText = `${name}: ${this._i.status.doorbell_pressed}` this.cs.doorBellIcon = 'mdi:bell-ring' - } - else if ( mute ) { - this.cs.doorBellState = 'warn' - this.cs.doorBellText = `${name}: ${this._i.status.doorbell_muted}` - this.cs.doorBellIcon = 'mdi:bell-off' + } else if( muteable ) { + if ( mute ) { + this.cs.doorBellState = 'warn' + this.cs.doorBellText = `${name}: ${this._i.status.doorbell_muted}` + this.cs.doorBellIcon = 'mdi:bell-off' + } else { + this.cs.doorBellState = 'off' + this.cs.doorBellText = `${name}: ${this._i.status.doorbell_mute}` + this.cs.doorBellIcon = 'mdi:bell' + } } else { this.cs.doorBellState = 'off' - this.cs.doorBellText = `${name}: ${mute.state === 'off' ? this._i.status.doorbell_mute : this._i.status.doorbell_idle}` + this.cs.doorBellText = `${name}: ${this._i.status.doorbell_idle}` this.cs.doorBellIcon = 'mdi:bell' } } @@ -911,18 +941,24 @@ class AarloGlance extends LitElement { const bell = this._getState(this.cc.door2BellId, 'off'); const name = bell.attributes.friendly_name const mute = bell.attributes.chimes_silenced || bell.attributes.calls_silenced + const muteable = !!this.cc.door2BellMuteId if ( bell.state === 'on' ) { this.cs.door2BellState = 'on' this.cs.door2BellText = `${name}: ${this._i.status.doorbell_pressed}` this.cs.door2BellIcon = 'mdi:bell-ring' - } - else if ( mute ) { - this.cs.door2BellState = 'warn' - this.cs.door2BellText = `${name}: ${this._i.status.doorbell_muted}` - this.cs.door2BellIcon = 'mdi:bell-off' + } else if( muteable ) { + if ( mute ) { + this.cs.door2BellState = 'warn' + this.cs.door2BellText = `${name}: ${this._i.status.doorbell_muted}` + this.cs.door2BellIcon = 'mdi:bell-off' + } else { + this.cs.door2BellState = 'off' + this.cs.door2BellText = `${name}: ${this._i.status.doorbell_mute}` + this.cs.door2BellIcon = 'mdi:bell' + } } else { this.cs.door2BellState = 'off' - this.cs.door2BellText = `${name}: ${mute.state === 'off' ? this._i.status.doorbell_mute : this._i.status.doorbell_idle}` + this.cs.door2BellText = `${name}: ${this._i.status.doorbell_idle}` this.cs.door2BellIcon = 'mdi:bell' } } @@ -936,6 +972,14 @@ class AarloGlance extends LitElement { } } + updateStatuses() { + const index = this._cameraIndex + for( this._cameraIndex = 0; this._cameraIndex < this._cameraCount; this._cameraIndex++ ) { + this._updateStatuses() + } + this._cameraIndex = index + } + checkConfig() { if ( this._hass === null ) { @@ -965,20 +1009,42 @@ class AarloGlance extends LitElement { } } - getGlobalCameraConfig( config ) { - } + getGlobalConfig( config ) { - getGlobalLibraryConfig( config ) { - } + return { + // GLOBAL config + // Mobile? see here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent + isMobile: navigator.userAgent.includes("Mobi"), + + // Language override? + lang: config.lang, + + // aspect ratio + aspectRatio: config.aspect_ratio === 'square' ? '1x1' : '16x9', + aspectRatioMultiplier: config.aspect_ratio === 'square' ? 1 : 0.5625, + + // logging? + log: config.logging ? config.logging : false, - getCameraConfig( config ) { + // lovelace card size + cardSize: config.card_size ? parseInt(config.card_size) : 3, + + // swipe threshold + swipeThreshold: config.swipe_threshold ? parseInt(config.swipe_threshold) : 150, + } } - getLibraryConfig( config ) { + getGlobalLibraryConfig( config ) { } - setConfig(config) { + _merge_config( global, local ) { + let merged = Object.assign( {}, global ) + return Object.assign( merged, local ) + } + getCameraConfig( global, local ) { + const config = this._merge_config( global, local ) + // find camera let camera = "" if( config.entity ) { @@ -1006,101 +1072,55 @@ class AarloGlance extends LitElement { prefix = config.prefix; } - // save then check new config - this._config = config - this.checkConfig() - - // GLOBAL config - // Mobile? see here: https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent - this.gc.isMobile = navigator.userAgent.includes("Mobi") - - // Language override? - this.gc.lang = config.lang + let cc = {} - // aspect ratio - this.gc.aspectRatio = config.aspect_ratio === 'square' ? '1x1' : '16x9'; - this.gc.aspectRatioMultiplier = config.aspect_ratio === 'square' ? 1 : 0.5625 - - // logging? - this.gc.log = config.logging ? config.logging : false - - // lovelace card size - this.gc.cardSize = config.card_size ? parseInt(config.card_size) : 3 - - // swipe threshold - this.gc.swipeThreshold = config.swipe_threshold ? parseInt(config.swipe_threshold) : 150 - - // TODO use proxy for defaults... read defaults as though a camera... or just keep simple - // and copy the defaults and add camera specifics - - // PER-CAMERA config - // TODO save and restore index - this._cameraIndex = 0 + // Grab name if there + cc.name = config.name ? config.name : null - // library config - const library_click = config.image_click ? config.image_click : "" - this.lc.imageClickModal = library_click.includes("modal") - this.lc.imageClickSmart = library_click.includes("smart") - this.lc.imageAutoPlay = library_click.includes("autoplay") - this.lc.sizes = config.library_sizes ? config.library_sizes : [ 3 ] - this.lc.recordings = config.max_recordings ? parseInt(config.max_recordings) : 99 - this.lc.regions = config.library_regions ? config.library_regions : this.lc.sizes - this.lc.colors = { - "Animal" : config.library_animal ? config.library_animal : 'orangered', - "Vehicle" : config.library_vehicle ? config.library_vehicle : 'yellow', - "Person" : config.library_person ? config.library_person : 'lime' - } - this.ls.sizeIndex = 0 - this.ls.size = -1 - this.ls.gridCount = -1 - - // on click - // click on image + // What happens when we click on image const image_click = config.image_click ? config.image_click : "" - this.cc.imageClickStream = image_click.includes("live") || + cc.imageClickStream = image_click.includes("live") || image_click.includes("play") || image_click.includes("stream") - this.cc.imageClickModal = image_click.includes("modal") - this.cc.imageClickSmart = image_click.includes("smart") - this.cc.imageAutoPlay = image_click.includes("autoplay") + cc.imageClickModal = image_click.includes("modal") + cc.imageClickSmart = image_click.includes("smart") + cc.imageAutoPlay = image_click.includes("autoplay") // snapshot updates - this.cc.snapshotTimeouts = config.snapshot_retry ? config.snapshot_retry : [ 2, 5 ] + cc.snapshotTimeouts = config.snapshot_retry ? config.snapshot_retry : [ 2, 5 ] // modal window multiplier - this.cc.modalMultiplier = config.modal_multiplier ? parseFloat(config.modal_multiplier) : 0.8; + cc.modalMultiplier = config.modal_multiplier ? parseFloat(config.modal_multiplier) : 0.8; // stream directly from Arlo - this.cc.playDirectFromArlo = config.play_direct ? config.play_direct : false; + cc.playDirectFromArlo = config.play_direct ? config.play_direct : false; // auto play - this.cc.autoPlay = config.auto_play ? config.auto_play : false - this.cs.autoPlay = this.cc.autoPlay - this.cs.autoPlayTimer = null + cc.autoPlay = config.auto_play ? config.auto_play : false // camera and sensors - this.cc.id = config.camera_id ? config.camera_id : 'camera.' + prefix + camera; - this.cc.motionId = config.motion_id ? config.motion_id : 'binary_sensor.' + prefix + 'motion_' + camera; - this.cc.soundId = config.sound_id ? config.sound_id : 'binary_sensor.' + prefix + 'sound_' + camera; - this.cc.batteryId = config.battery_id ? config.battery_id : 'sensor.' + prefix + 'battery_level_' + camera; - this.cc.signalId = config.signal_id ? config.signal_id : 'sensor.' + prefix + 'signal_strength_' + camera; - this.cc.capturedTodayId = config.capture_id ? config.capture_id : 'sensor.' + prefix + 'captured_today_' + camera; - this.cc.lastCaptureId = config.last_id ? config.last_id : 'sensor.' + prefix + 'last_' + camera; + cc.id = config.camera_id ? config.camera_id : 'camera.' + prefix + camera; + cc.motionId = config.motion_id ? config.motion_id : 'binary_sensor.' + prefix + 'motion_' + camera; + cc.soundId = config.sound_id ? config.sound_id : 'binary_sensor.' + prefix + 'sound_' + camera; + cc.batteryId = config.battery_id ? config.battery_id : 'sensor.' + prefix + 'battery_level_' + camera; + cc.signalId = config.signal_id ? config.signal_id : 'sensor.' + prefix + 'signal_strength_' + camera; + cc.capturedTodayId = config.capture_id ? config.capture_id : 'sensor.' + prefix + 'captured_today_' + camera; + cc.lastCaptureId = config.last_id ? config.last_id : 'sensor.' + prefix + 'last_' + camera; // door definition - this.cc.doorId = config.door ? config.door: null; - this.cc.doorBellId = config.door_bell ? config.door_bell : null; - this.cc.doorBellMuteId = config.door_bell_mute ? config.door_bell_mute : null; - this.cc.doorLockId = config.door_lock ? config.door_lock : null; + cc.doorId = config.door ? config.door: null; + cc.doorBellId = config.door_bell ? config.door_bell : null; + cc.doorBellMuteId = config.door_bell_mute ? config.door_bell_mute : null; + cc.doorLockId = config.door_lock ? config.door_lock : null; // door2 definition - this.cc.door2Id = config.door2 ? config.door2: null; - this.cc.door2BellId = config.door2_bell ? config.door2_bell : null; - this.cc.door2BellMuteId = config.door2_bell_mute ? config.door2_bell_mute : null; - this.cc.door2LockId = config.door2_lock ? config.door2_lock : null; + cc.door2Id = config.door2 ? config.door2: null; + cc.door2BellId = config.door2_bell ? config.door2_bell : null; + cc.door2BellMuteId = config.door2_bell_mute ? config.door2_bell_mute : null; + cc.door2LockId = config.door2_lock ? config.door2_lock : null; // light definition - this.cc.lightId = config.light ? config.light: null; + cc.lightId = config.light ? config.light: null; // what are we hiding? const hide = this._config.hide || []; @@ -1109,41 +1129,115 @@ class AarloGlance extends LitElement { const show_status = !hide.includes('status') // ui configuration - this.cc.showTopTitle = config.top_title ? show_title : false - this.cc.showTopDate = config.top_date ? show_date : false - this.cc.showTopStatus = config.top_status ? show_status : false - this.cc.showBottomTitle = config.top_title ? false : show_title - this.cc.showBottomDate = config.top_date ? false : show_date - this.cc.showBottomStatus = config.top_status ? false : show_status + cc.showTopTitle = config.top_title ? show_title : false + cc.showTopDate = config.top_date ? show_date : false + cc.showTopStatus = config.top_status ? show_status : false + cc.showBottomTitle = config.top_title ? false : show_title + cc.showBottomDate = config.top_date ? false : show_date + cc.showBottomStatus = config.top_status ? false : show_status // what are we showing? const show = this._config.show || []; - this.cc.showPlay = show.includes('play') - this.cc.showSnapshot = show.includes('snapshot') - this.cc.showCameraOnOff = show.includes('on_off') - - this.cc.showBattery = show.includes('battery') || show.includes('battery_level') - this.cc.showSignal = show.includes('signal_strength') - this.cc.showMotion = show.includes('motion') - this.cc.showSound = show.includes('sound') - this.cc.showCaptured = show.includes('captured') || show.includes('captured_today') - this.cc.showImageDate = show.includes('image_date') - - this.cc.showDoor = !!this.cc.doorId - this.cc.showDoorLock = !!this.cc.doorLockId - this.cc.showDoorBell = !!this.cc.doorBellId - this.cc.showDoor2 = !!this.cc.door2Id - this.cc.showDoor2Lock = !!this.cc.door2LockId - this.cc.showDoor2Bell = !!this.cc.door2BellId - - this.cc.showLight = !!this.cc.lightId - this.cc.showLightLeft = config.light_left ? !!config.light_left : false; - this.cc.showLightRight = !this.cc.showLightLeft - - this.cc.showOthers = ( this.cc.showDoor || this.cc.showDoorLock || this.cc.showDoorBell || - this.cc.showDoor2 || this.cc.showDoor2Lock || this.cc.showDoor2Bell || - this.cc.showLight ) + cc.showPlay = show.includes('play') + cc.showSnapshot = show.includes('snapshot') + cc.showCameraOnOff = show.includes('on_off') + + cc.showBattery = show.includes('battery') || show.includes('battery_level') + cc.showSignal = show.includes('signal_strength') + cc.showMotion = show.includes('motion') + cc.showSound = show.includes('sound') + cc.showCaptured = show.includes('captured') || show.includes('captured_today') + cc.showImageDate = show.includes('image_date') + + cc.showDoor = !!cc.doorId + cc.showDoorLock = !!cc.doorLockId + cc.showDoorBell = !!cc.doorBellId + cc.showDoor2 = !!cc.door2Id + cc.showDoor2Lock = !!cc.door2LockId + cc.showDoor2Bell = !!cc.door2BellId + + cc.showLight = !!cc.lightId + cc.showLightLeft = config.light_left ? !!config.light_left : false; + cc.showLightRight = !cc.showLightLeft + + cc.showOthers = ( cc.showDoor || cc.showDoorLock || cc.showDoorBell || + cc.showDoor2 || cc.showDoor2Lock || cc.showDoor2Bell || + cc.showLight ) + + return cc + } + + getCameraState( config ) { + return { + autoPlay: config.autoPlay, + autoPlayTimer: null, + } + } + + getLibraryConfig( global, local ) { + + const config = this._merge_config( global, local ) + const library_click = config.image_click ? config.image_click : "" + const sizes = config.library_sizes ? config.library_sizes : [ 3 ] + + return { + // What to when video clicked + imageClickModal: library_click.includes("modal"), + imageClickSmart: library_click.includes("smart"), + imageAutoPlay: library_click.includes("autoplay"), + + // How many recordings to show + sizes: sizes, + recordings: config.max_recordings ? parseInt(config.max_recordings) : 99, + + // Highlight motion triggers? + regions: config.library_regions ? config.library_regions : sizes, + colors: { + "Animal": config.library_animal ? config.library_animal : 'orangered', + "Vehicle": config.library_vehicle ? config.library_vehicle : 'yellow', + "Person": config.library_person ? config.library_person : 'lime', + }, + } + } + + getLibraryState( _config ) { + return { + size: -1, + sizeIndex: 0, + gridCount: -1, + } + } + + setConfig(config) { + + // save then check new config + this._config = config + + this.gc = this.getGlobalConfig( config ) + + if( "entities" in this._config ) { + this._cameraIndex = 0 + this._config.entities.forEach( (local_config) => { + this.cc = this.getCameraConfig( config, local_config ) + this.cs = this.getCameraState( this.cc ) + this.lc = this.getLibraryConfig( config, local_config ) + this.ls = this.getLibraryState( this.lc ) + this._cameraIndex++ + }) + this._cameraCount = this._cameraIndex + this._cameraIndex = 0 + } else { + // Single camera. Much simpler. + this._cameraIndex = 0 + this.cc = this.getCameraConfig( config, {} ) + this.cs = this.getCameraState( this.cc ) + this.lc = this.getLibraryConfig( config, {} ) + this.ls = this.getLibraryState( this.lc ) + this._cameraCount = 1 + } + + //this.checkConfig() // web item id suffix //this.gc.idSuffix = this.cc.id.replaceAll('.','-').replaceAll('_','-') @@ -1212,9 +1306,10 @@ class AarloGlance extends LitElement { this._show('bottom-bar-title', this.cc.showBottomTitle ) this._show('bottom-bar-camera', this.cs.showCameraControls ) this._show('bottom-bar-date', this.cc.showBottomDate && this.cc.showImageDate ) - this._show('bottom-bar-externals', this.cc.showOthers ) + this._show('bottom-bar-externals', this.cc.showOthers || (!this.gc.isMobile && this._cameraCount > 1) ) this._show('bottom-bar-status', this.cc.showBottomStatus ) + this._show('camera-previous', this._cameraCount > 1 ) this._show('camera-on-off', this.cc.showCameraOnOff ) this._show('camera-captured', this.cc.showCaptured ) this._show('camera-light-left', this.cc.showLightLeft ) @@ -1226,9 +1321,37 @@ class AarloGlance extends LitElement { this._show("externals-door-lock-2", this.cc.showDoor2Lock ) this._show("externals-door-bell-2", this.cc.showDoor2Bell ) this._show("externals-light", this.cc.showLightRight ) + this._show('camera-next', !this.gc.isMobile && this._cameraCount > 1 ) this._set("top-bar-title", {text: this.cc.name}) this._set("bottom-bar-title", {text: this.cc.name}) + } + + setupImageHandlers() { + + const viewer = this._element("image-viewer") + + if( this.gc.isMobile ) { + viewer.addEventListener('touchstart', (e) => { + this.ls.xDown = e.touches[0].clientX + this.ls.xUp = null + }, { passive: true }) + + viewer.addEventListener('touchmove', (e) => { + this.ls.xUp = e.touches[0].clientX + }, { passive: true }) + + viewer.addEventListener('touchend', () => { + if( this.ls.xDown && this.ls.xUp ) { + const xDiff = this.ls.xDown - this.ls.xUp; + if( xDiff > this.gc.swipeThreshold ) { + this.nextCameraImage() + } else if( xDiff < (0 - this.gc.swipeThreshold) ) { + this.previousCameraImage() + } + } + }, { passive: true }) + } this._element("externals-door-bell").addEventListener('click', () => { if ( this.cc.doorBellMuteId ) { @@ -1276,6 +1399,7 @@ class AarloGlance extends LitElement { this._set("bottom-bar-date", {text: this.cs.imageDate}) this._set("bottom-bar-status", {text: this.cs.state}) + this._set ("camera-previous", {title: this._i.status.previous_camera, icon: "mdi:chevron-left", state: "on"}) this._set ("camera-on-off", {title: this.cs.onOffText, icon: this.cs.onOffIcon, state: this.cs.onOffState}) this._set ("camera-motion", {title: this.cs.motionText, icon: "mdi:run-fast", state: this.cs.motionState}) this._show('camera-motion', this.cc.showMotion && this.cs.showCameraControls ) @@ -1299,6 +1423,7 @@ class AarloGlance extends LitElement { this._set("externals-door-bell-2", {title: this.cs.door2BellText, icon: this.cs.door2BellIcon, state: this.cs.door2BellState}) this._set("externals-door-lock-2", {title: this.cs.door2LockText, icon: this.cs.door2LockIcon, state: this.cs.door2LockState}) this._set("externals-light", {title: this.cs.lightText, icon: this.cs.lightIcon, state: this.cs.lightState}) + this._set("camera-next", {title: this._i.status.next_camera, icon: "mdi:chevron-right", state: "on"}) } /** @@ -1355,44 +1480,51 @@ class AarloGlance extends LitElement { this._set("library-control-resize",{ state: "on"} ) this._set("library-control-close",{ state: "on"} ) + // set state + this.ls.offset = 0 + } + + setupLibraryHandlers() { // rudementary swipe support - let viewer = this._element("library-viewer") - viewer.addEventListener('touchstart', (e) => { - this.ls.xDown = e.touches[0].clientX - this.ls.xUp = null - }, { passive: true }) - viewer.addEventListener('touchmove', (e) => { - this.ls.xUp = e.touches[0].clientX - }, { passive: true }) - viewer.addEventListener('touchend', () => { - if( this.ls.xDown && this.ls.xUp ) { - const xDiff = this.ls.xDown - this.ls.xUp; - if( xDiff > this.gc.swipeThreshold ) { - this.nextLibraryPage() - } else if( xDiff < (0 - this.gc.swipeThreshold) ) { - this.previousLibraryPage() + const viewer = this._element("library-viewer") + + if( this.gc.isMobile ) { + viewer.addEventListener('touchstart', (e) => { + this.ls.xDown = e.touches[0].clientX + this.ls.xUp = null + }, { passive: true }) + + viewer.addEventListener('touchmove', (e) => { + this.ls.xUp = e.touches[0].clientX + }, { passive: true }) + + viewer.addEventListener('touchend', () => { + if( this.ls.xDown && this.ls.xUp ) { + const xDiff = this.ls.xDown - this.ls.xUp; + if( xDiff > this.gc.swipeThreshold ) { + this.nextLibraryPage() + } else if( xDiff < (0 - this.gc.swipeThreshold) ) { + this.previousLibraryPage() + } } - } - }, { passive: true }) - - // set state - this.ls.offset = -1 + }, { passive: true }) + } } _updateLibraryHTML() { // update library state to reflect the new layout - this.ls.size = this.lc.sizes[this.ls.sizeIndex] - this.ls.gridCount = this.ls.size * this.ls.size + this.gs.librarySize = this.lc.sizes[this.ls.sizeIndex] + this.ls.gridCount = this.gs.librarySize * this.gs.librarySize let grid = document.createElement("div") grid.style.display = "grid" - grid.style['grid-template-columns'] = `repeat(${this.ls.size},1fr)` - grid.style['grid-template-rows'] = `repeat(${this.ls.size},1fr)` + grid.style['grid-template-columns'] = `repeat(${this.gs.librarySize},1fr)` + grid.style['grid-template-rows'] = `repeat(${this.gs.librarySize},1fr)` grid.style['grid-gap'] = '1px' grid.style.padding= '2px' - for( let i = 0; i < this.ls.size * this.ls.size; ++i ) { + for( let i = 0; i < this.gs.librarySize * this.gs.librarySize; ++i ) { let img = document.createElement("img") img.id = this._id(`library-${i}`) @@ -1409,8 +1541,8 @@ class AarloGlance extends LitElement { box.style.top = "0" img.addEventListener("click", () => { this.playLibraryVideo(i) } ) - const column = Math.floor((i % this.ls.size) + 1) - const row = Math.floor((i / this.ls.size) + 1) + const column = Math.floor((i % this.gs.librarySize) + 1) + const row = Math.floor((i / this.gs.librarySize) + 1) let div = document.createElement("div") div.style.position= 'relative' div.style.gridColumn = `${column}` @@ -1437,7 +1569,7 @@ class AarloGlance extends LitElement { let i = 0; let j= this.ls.offset; - const show_triggers = this.lc.regions.includes(this.ls.size) + const show_triggers = this.lc.regions.includes(this.gs.librarySize) const last = Math.min(j + this.ls.gridCount, this.ls.videos.length) for( ; j < last; i++, j++ ) { const id = `library-${i}` @@ -1512,7 +1644,7 @@ class AarloGlance extends LitElement { } // Resized? Rebuild grid and force reload of images. - if ( this.ls.size !== this.lc.sizes[this.ls.sizeIndex] ) { + if ( this.gs.librarySize !== this.lc.sizes[this.ls.sizeIndex] ) { this._updateLibraryHTML() this.ls.lastOffset = -1 } @@ -1767,6 +1899,9 @@ class AarloGlance extends LitElement { this.setupVideoView() this.setupStreamView() + this.setupImageHandlers() + this.setupLibraryHandlers() + // And go... this.updateImageView() this.updateLibraryView() @@ -1989,6 +2124,20 @@ class AarloGlance extends LitElement { } } + nextCameraImage() { + this._cameraIndex = this._cameraIndex === (this._cameraCount - 1) ? 0 : (this._cameraIndex + 1) + this.setupImageView() + this.setupLibraryView() + this.updateImageView() + } + + previousCameraImage() { + this._cameraIndex = this._cameraIndex === 0 ? (this._cameraCount - 1) : (this._cameraIndex - 1) + this.setupImageView() + this.setupLibraryView() + this.updateImageView() + } + clickVideo() { if ( this._misHidden("video-controls") ) { this.showVideoControls(2) diff --git a/lang/en-gb.js b/lang/en-gb.js new file mode 120000 index 0000000..78e6f7f --- /dev/null +++ b/lang/en-gb.js @@ -0,0 +1 @@ +en.js \ No newline at end of file diff --git a/lang/en-us.js b/lang/en-us.js new file mode 120000 index 0000000..78e6f7f --- /dev/null +++ b/lang/en-us.js @@ -0,0 +1 @@ +en.js \ No newline at end of file diff --git a/lang/en.js b/lang/en.js index 6444eb1..ccaee92 100644 --- a/lang/en.js +++ b/lang/en.js @@ -58,6 +58,8 @@ export var messages = { doorbell_muted: 'muted (click to unmute)', light_on: 'on', light_off: 'off', + next_camera: 'next camera', + previous_camera: 'previous camera', }, // known triggers diff --git a/lang/fr-ca.js b/lang/fr-ca.js deleted file mode 100644 index 01558ff..0000000 --- a/lang/fr-ca.js +++ /dev/null @@ -1,66 +0,0 @@ - - -export var messages = { - - // image viewer - image: { - turn_camera_on: 'allume la caméra', - turn_camera_off: 'éteins la caméra', - take_a_snapshot: 'prends une photo', - start_stream: 'visionne le livestream', - stop_stream: 'arrête le livestream', - automatic_capture: 'capturée automatiquement à', - snapshot_capture: 'image instantanée capturée à', - }, - - // library viewer - library: { - first_page: 'première page', - previous_page: 'page précédente', - next_size: 'prochaine taille de grille', - close: 'ferme la bibliothèque', - next_page: 'prochaine page', - last_page: 'dernière page', - captured: 'capturée', - }, - - // video/stream viewer - video: { - stop: 'arrête', - play: 'joue', - pause: 'pause', - fullscreen: 'plein écran', - }, - - // device statuses - status: { - battery_strength: 'puissance batterie', - detected: 'détecté', - door_closed: 'fermée', - door_open: 'ouverte', - captured: 'capturée', - captured_nothing: 'rien aujourd’hui', - captured_something: 'clips d’aujourd’hui, capturés à', - clear: 'sans mouvement', - plugged_in: 'branchée', - signal_strength: 'intensité du signal', - motion: 'mouvement', - sound: 'son', - lock_locked: 'verrouillée. appuyez pour déverrouiller', - lock_unlocked: 'déverrouillée. appuyer pour verrouiller', - doorbell_pressed: 'Dring-dring!', - doorbell_idle: 'en attente', - doorbell_mute: 'click to mute', - doorbell_muted: 'muted, click to unmute', - light_on: 'allumé', - light_off: 'éteint', - }, - - // known triggers - trigger : { - animal: 'animal', - vehicle: 'véhicule', - person: 'personne', - parcel: 'colis', - }, -} diff --git a/lang/fr-ca.js b/lang/fr-ca.js new file mode 120000 index 0000000..b0fd9cf --- /dev/null +++ b/lang/fr-ca.js @@ -0,0 +1 @@ +fr.js \ No newline at end of file diff --git a/lang/fr.js b/lang/fr.js index 01558ff..b7e2f38 100644 --- a/lang/fr.js +++ b/lang/fr.js @@ -54,6 +54,8 @@ export var messages = { doorbell_muted: 'muted, click to unmute', light_on: 'allumé', light_off: 'éteint', + next_camera: 'prochaine caméra', + previous_camera: 'caméra précédente', }, // known triggers