Migrated camera.android.ipcam UI
This commit is contained in:
parent
e508d453ba
commit
ca2fd60950
16 changed files with 456 additions and 163 deletions
2
platypush/backend/http/dist/index.html
vendored
2
platypush/backend/http/dist/index.html
vendored
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>platypush</title><link href="/static/css/chunk-12dc74e9.505ac0f9.css" rel="prefetch"><link href="/static/css/chunk-13b07ca5.029dd736.css" rel="prefetch"><link href="/static/css/chunk-1653b664.5b949e24.css" rel="prefetch"><link href="/static/css/chunk-233baa62.8a0131ad.css" rel="prefetch"><link href="/static/css/chunk-23726328.7e460329.css" rel="prefetch"><link href="/static/css/chunk-2ca39dde.efa1eae8.css" rel="prefetch"><link href="/static/css/chunk-2f304dee.a8a2d99a.css" rel="prefetch"><link href="/static/css/chunk-487896e7.b7730bd4.css" rel="prefetch"><link href="/static/css/chunk-49211740.43a25f0f.css" rel="prefetch"><link href="/static/css/chunk-4dae396b.92b3713e.css" rel="prefetch"><link href="/static/css/chunk-5145872a.197de139.css" rel="prefetch"><link href="/static/css/chunk-595ffc05.678c9c97.css" rel="prefetch"><link href="/static/css/chunk-64076603.e451beea.css" rel="prefetch"><link href="/static/css/chunk-675c7703.75b51be7.css" rel="prefetch"><link href="/static/css/chunk-792fd41e.4d467174.css" rel="prefetch"><link href="/static/css/chunk-7fae0422.c233115f.css" rel="prefetch"><link href="/static/css/chunk-d22da0c0.7c71cffb.css" rel="prefetch"><link href="/static/css/chunk-d28a86c4.cdd32c08.css" rel="prefetch"><link href="/static/css/chunk-da9476ec.f1965e2d.css" rel="prefetch"><link href="/static/css/chunk-ee62c128.44bbe779.css" rel="prefetch"><link href="/static/js/chunk-12dc74e9.a7799079.js" rel="prefetch"><link href="/static/js/chunk-13b07ca5.11833bcd.js" rel="prefetch"><link href="/static/js/chunk-1653b664.4bba37ff.js" rel="prefetch"><link href="/static/js/chunk-233baa62.348949bb.js" rel="prefetch"><link href="/static/js/chunk-23726328.7a638dfb.js" rel="prefetch"><link href="/static/js/chunk-2ca39dde.bfb67629.js" rel="prefetch"><link href="/static/js/chunk-2d0aa612.2338a00b.js" rel="prefetch"><link href="/static/js/chunk-2d0b270c.82d7f897.js" rel="prefetch"><link href="/static/js/chunk-2d0c1eb0.2fc91e77.js" rel="prefetch"><link href="/static/js/chunk-2d0c229a.c6f13c92.js" rel="prefetch"><link href="/static/js/chunk-2d0cc2be.71e3fcd8.js" rel="prefetch"><link href="/static/js/chunk-2d0d5f97.57d7afa3.js" rel="prefetch"><link href="/static/js/chunk-2d0da3df.99de332b.js" rel="prefetch"><link href="/static/js/chunk-2d208116.4f67ac14.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.90a98553.js" rel="prefetch"><link href="/static/js/chunk-2d21b0dc.465e6abf.js" rel="prefetch"><link href="/static/js/chunk-2d21da1a.707bd994.js" rel="prefetch"><link href="/static/js/chunk-2d231217.5ff519da.js" rel="prefetch"><link href="/static/js/chunk-2d237d41.b4b87abb.js" rel="prefetch"><link href="/static/js/chunk-2f304dee.649e4dc7.js" rel="prefetch"><link href="/static/js/chunk-487896e7.69cdcafb.js" rel="prefetch"><link href="/static/js/chunk-49211740.e4dea096.js" rel="prefetch"><link href="/static/js/chunk-4dae396b.0ee6bb40.js" rel="prefetch"><link href="/static/js/chunk-5145872a.f0bd0577.js" rel="prefetch"><link href="/static/js/chunk-595ffc05.8affd7fe.js" rel="prefetch"><link href="/static/js/chunk-64076603.2c344ed9.js" rel="prefetch"><link href="/static/js/chunk-675c7703.7c7378cd.js" rel="prefetch"><link href="/static/js/chunk-792fd41e.aca41198.js" rel="prefetch"><link href="/static/js/chunk-7fae0422.0d9be069.js" rel="prefetch"><link href="/static/js/chunk-d22da0c0.da01e99e.js" rel="prefetch"><link href="/static/js/chunk-d28a86c4.d0c1f74e.js" rel="prefetch"><link href="/static/js/chunk-da9476ec.f8c15985.js" rel="prefetch"><link href="/static/js/chunk-ee62c128.c11fb53e.js" rel="prefetch"><link href="/static/css/app.a835db3a.css" rel="preload" as="style"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="preload" as="style"><link href="/static/js/app.9940ca10.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.948dc2e5.js" rel="preload" as="script"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="stylesheet"><link href="/static/css/app.a835db3a.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.948dc2e5.js"></script><script src="/static/js/app.9940ca10.js"></script></body></html>
|
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>platypush</title><link href="/static/css/chunk-12dc74e9.505ac0f9.css" rel="prefetch"><link href="/static/css/chunk-13b07ca5.029dd736.css" rel="prefetch"><link href="/static/css/chunk-1653b664.5b949e24.css" rel="prefetch"><link href="/static/css/chunk-23726328.7e460329.css" rel="prefetch"><link href="/static/css/chunk-2ca39dde.efa1eae8.css" rel="prefetch"><link href="/static/css/chunk-2f304dee.a8a2d99a.css" rel="prefetch"><link href="/static/css/chunk-487896e7.b7730bd4.css" rel="prefetch"><link href="/static/css/chunk-49211740.43a25f0f.css" rel="prefetch"><link href="/static/css/chunk-49531d8d.fc36911d.css" rel="prefetch"><link href="/static/css/chunk-4dae396b.92b3713e.css" rel="prefetch"><link href="/static/css/chunk-5145872a.197de139.css" rel="prefetch"><link href="/static/css/chunk-595ffc05.678c9c97.css" rel="prefetch"><link href="/static/css/chunk-64076603.e451beea.css" rel="prefetch"><link href="/static/css/chunk-675c7703.75b51be7.css" rel="prefetch"><link href="/static/css/chunk-792fd41e.4d467174.css" rel="prefetch"><link href="/static/css/chunk-7fae0422.c233115f.css" rel="prefetch"><link href="/static/css/chunk-d22da0c0.7c71cffb.css" rel="prefetch"><link href="/static/css/chunk-d28a86c4.cdd32c08.css" rel="prefetch"><link href="/static/css/chunk-da9476ec.f1965e2d.css" rel="prefetch"><link href="/static/css/chunk-ee62c128.44bbe779.css" rel="prefetch"><link href="/static/css/chunk-f8a20d76.8a0131ad.css" rel="prefetch"><link href="/static/js/chunk-12dc74e9.a7799079.js" rel="prefetch"><link href="/static/js/chunk-13b07ca5.11833bcd.js" rel="prefetch"><link href="/static/js/chunk-1653b664.4bba37ff.js" rel="prefetch"><link href="/static/js/chunk-23726328.7a638dfb.js" rel="prefetch"><link href="/static/js/chunk-2ca39dde.bfb67629.js" rel="prefetch"><link href="/static/js/chunk-2d0aa612.2338a00b.js" rel="prefetch"><link href="/static/js/chunk-2d0b270c.82d7f897.js" rel="prefetch"><link href="/static/js/chunk-2d0c1eb0.2fc91e77.js" rel="prefetch"><link href="/static/js/chunk-2d0c229a.c6f13c92.js" rel="prefetch"><link href="/static/js/chunk-2d0cc2be.71e3fcd8.js" rel="prefetch"><link href="/static/js/chunk-2d0d5f97.57d7afa3.js" rel="prefetch"><link href="/static/js/chunk-2d0da3df.99de332b.js" rel="prefetch"><link href="/static/js/chunk-2d208116.4f67ac14.js" rel="prefetch"><link href="/static/js/chunk-2d2091df.90a98553.js" rel="prefetch"><link href="/static/js/chunk-2d21b0dc.465e6abf.js" rel="prefetch"><link href="/static/js/chunk-2d21da1a.707bd994.js" rel="prefetch"><link href="/static/js/chunk-2d231217.5ff519da.js" rel="prefetch"><link href="/static/js/chunk-2d237d41.b4b87abb.js" rel="prefetch"><link href="/static/js/chunk-2f304dee.649e4dc7.js" rel="prefetch"><link href="/static/js/chunk-487896e7.69cdcafb.js" rel="prefetch"><link href="/static/js/chunk-49211740.e4dea096.js" rel="prefetch"><link href="/static/js/chunk-49531d8d.1ccab0d9.js" rel="prefetch"><link href="/static/js/chunk-4dae396b.0ee6bb40.js" rel="prefetch"><link href="/static/js/chunk-5145872a.f0bd0577.js" rel="prefetch"><link href="/static/js/chunk-595ffc05.8affd7fe.js" rel="prefetch"><link href="/static/js/chunk-64076603.2c344ed9.js" rel="prefetch"><link href="/static/js/chunk-675c7703.7c7378cd.js" rel="prefetch"><link href="/static/js/chunk-792fd41e.aca41198.js" rel="prefetch"><link href="/static/js/chunk-7fae0422.0d9be069.js" rel="prefetch"><link href="/static/js/chunk-d22da0c0.da01e99e.js" rel="prefetch"><link href="/static/js/chunk-d28a86c4.d0c1f74e.js" rel="prefetch"><link href="/static/js/chunk-da9476ec.f8c15985.js" rel="prefetch"><link href="/static/js/chunk-ee62c128.c11fb53e.js" rel="prefetch"><link href="/static/js/chunk-f8a20d76.70a12fd2.js" rel="prefetch"><link href="/static/css/app.a835db3a.css" rel="preload" as="style"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="preload" as="style"><link href="/static/js/app.fe071759.js" rel="preload" as="script"><link href="/static/js/chunk-vendors.948dc2e5.js" rel="preload" as="script"><link href="/static/css/chunk-vendors.5dad8b00.css" rel="stylesheet"><link href="/static/css/app.a835db3a.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but platypush doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/static/js/chunk-vendors.948dc2e5.js"></script><script src="/static/js/app.fe071759.js"></script></body></html>
|
1
platypush/backend/http/dist/static/css/chunk-49531d8d.fc36911d.css
vendored
Normal file
1
platypush/backend/http/dist/static/css/chunk-49531d8d.fc36911d.css
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
platypush/backend/http/dist/static/js/app.fe071759.js
vendored
Normal file
2
platypush/backend/http/dist/static/js/app.fe071759.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
platypush/backend/http/dist/static/js/app.fe071759.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/app.fe071759.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
platypush/backend/http/dist/static/js/chunk-49531d8d.1ccab0d9.js
vendored
Normal file
2
platypush/backend/http/dist/static/js/chunk-49531d8d.1ccab0d9.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
platypush/backend/http/dist/static/js/chunk-49531d8d.1ccab0d9.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/chunk-49531d8d.1ccab0d9.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
platypush/backend/http/dist/static/js/chunk-f8a20d76.70a12fd2.js.map
vendored
Normal file
1
platypush/backend/http/dist/static/js/chunk-f8a20d76.70a12fd2.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -1,5 +1,8 @@
|
||||||
{
|
{
|
||||||
"icons": {
|
"icons": {
|
||||||
|
"camera.android.ipcam": {
|
||||||
|
"class": "fab fa-android"
|
||||||
|
},
|
||||||
"camera.cv": {
|
"camera.cv": {
|
||||||
"class": "fas fa-camera"
|
"class": "fas fa-camera"
|
||||||
},
|
},
|
||||||
|
|
|
@ -129,160 +129,5 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
$camera-background: #101520;
|
@import "common";
|
||||||
|
|
||||||
.camera {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
background: $background-color;
|
|
||||||
overflow: auto;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
padding-top: 3em;
|
|
||||||
|
|
||||||
.camera-container {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
background: $camera-background;
|
|
||||||
|
|
||||||
.frame-container {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
.frame, .no-frame {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.frame {
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.no-frame {
|
|
||||||
display: flex;
|
|
||||||
color: white;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
z-index: 2;
|
|
||||||
background: black;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
border-top: 1px solid #202530;
|
|
||||||
padding: .5em .25em;
|
|
||||||
|
|
||||||
.left,.right {
|
|
||||||
width: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background: none;
|
|
||||||
color: white;
|
|
||||||
border: none;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
color: $default-hover-fg-2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.url {
|
|
||||||
@media screen and (max-width: calc(#{$tablet} - 1px)) {
|
|
||||||
width: 80%;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media screen and (min-width: $tablet) {
|
|
||||||
width: 640px;
|
|
||||||
}
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
margin: 1em;
|
|
||||||
|
|
||||||
.row {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.name {
|
|
||||||
width: 140px;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 500px;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.params {
|
|
||||||
@media screen and (min-width: $tablet) {
|
|
||||||
width: 640px;
|
|
||||||
}
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
margin: -2em;
|
|
||||||
|
|
||||||
label {
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.head {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
label {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: right;
|
|
||||||
|
|
||||||
.name {
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.row {
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0.5em 1em;
|
|
||||||
|
|
||||||
.name {
|
|
||||||
width: 30%;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
width: 70%;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:nth-child(even) {
|
|
||||||
background: $default-bg-4;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: $hover-bg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal {
|
|
||||||
.content {
|
|
||||||
@media screen and (max-width: calc(#{$tablet} - 1px)) {
|
|
||||||
width: 90% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,156 @@
|
||||||
|
$camera-background: #101520;
|
||||||
|
|
||||||
|
.camera {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: $background-color;
|
||||||
|
overflow: auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding-top: 3em;
|
||||||
|
|
||||||
|
.camera-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
background: $camera-background;
|
||||||
|
|
||||||
|
.frame-container {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frame, .no-frame {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.frame {
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-frame {
|
||||||
|
display: flex;
|
||||||
|
color: white;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 2;
|
||||||
|
background: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
border-top: 1px solid #202530;
|
||||||
|
padding: .5em .25em;
|
||||||
|
|
||||||
|
.left,.right {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: none;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $default-hover-fg-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.url {
|
||||||
|
@media screen and (max-width: calc(#{$tablet} - 1px)) {
|
||||||
|
width: 80%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: $tablet) {
|
||||||
|
width: 640px;
|
||||||
|
}
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
margin: 1em;
|
||||||
|
|
||||||
|
.row {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
width: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 500px;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.params {
|
||||||
|
@media screen and (min-width: $tablet) {
|
||||||
|
width: 640px;
|
||||||
|
}
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
margin: -2em;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
|
||||||
|
.head {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
label {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
justify-content: right;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.5em 1em;
|
||||||
|
|
||||||
|
.name {
|
||||||
|
width: 30%;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 70%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:nth-child(even) {
|
||||||
|
background: $default-bg-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background: $hover-bg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
.content {
|
||||||
|
@media screen and (max-width: calc(#{$tablet} - 1px)) {
|
||||||
|
width: 90% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,285 @@
|
||||||
|
<template>
|
||||||
|
<div class="camera">
|
||||||
|
<Loading v-if="loading" />
|
||||||
|
|
||||||
|
<div class="camera-selector">
|
||||||
|
<div class="left">
|
||||||
|
<label>
|
||||||
|
<select ref="cameraSelector" @change="onCameraSelected">
|
||||||
|
<option selected disabled v-if="!Object.keys(cameras).length">-- No cameras available</option>
|
||||||
|
<option v-for="name in Object.keys(cameras)" :key="name" :value="name" v-text="name" />
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
<button type="button" @click="updateCameraStatus" :disabled="loading">
|
||||||
|
<i class="fas fa-sync-alt" title="Refresh cameras" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="camera-container">
|
||||||
|
<div class="frame-container" ref="frameContainer">
|
||||||
|
<div class="no-frame" v-if="!streaming && !capturing && !captured">The camera is not active</div>
|
||||||
|
<img class="frame" ref="frame" alt="" src="">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
<div class="left">
|
||||||
|
<button type="button" @click="startStreaming" :disabled="capturing || loading" v-if="!streaming">
|
||||||
|
<i class="fa fa-play" title="Start video" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" @click="stopStreaming" :disabled="capturing || loading" v-else>
|
||||||
|
<i class="fa fa-stop" title="Stop video" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" @click="capture" :disabled="streaming || capturing || loading">
|
||||||
|
<i class="fas fa-camera" title="Take a picture" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="right">
|
||||||
|
<button type="button" @click="flipCamera" :disabled="loading">
|
||||||
|
<i class="fas fa-retweet" title="Flip camera" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" @click="recording = true" v-if="!recording" :disabled="loading">
|
||||||
|
<i class="fa fa-volume-up" title="Start audio" />
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button type="button" @click="recording = false" v-else :disabled="loading">
|
||||||
|
<i class="fa fa-volume-mute" title="Stop audio" />
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="sound-container">
|
||||||
|
<audio autoplay preload="none" ref="player" v-if="recording">
|
||||||
|
<source :src="cameras[selectedCamera].audio_url" type="audio/x-wav;codec=pcm">
|
||||||
|
Your browser does not support audio elements
|
||||||
|
</audio>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Utils from "@/Utils";
|
||||||
|
import Loading from "@/components/Loading";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "CameraAndroidIpcam",
|
||||||
|
components: {Loading},
|
||||||
|
mixins: [Utils],
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
loading: false,
|
||||||
|
streaming: false,
|
||||||
|
capturing: false,
|
||||||
|
recording: false,
|
||||||
|
captured: false,
|
||||||
|
cameras: {},
|
||||||
|
selectedCamera: undefined,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
computed: {
|
||||||
|
config() {
|
||||||
|
return this.$root.config['camera.android.ipcam']
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
startStreaming() {
|
||||||
|
if (this.streaming)
|
||||||
|
return
|
||||||
|
|
||||||
|
const cam = this.cameras[this.selectedCamera]
|
||||||
|
this.streaming = true
|
||||||
|
this.capturing = false
|
||||||
|
this.captured = false
|
||||||
|
this.$refs.frame.setAttribute('src', cam.stream_url)
|
||||||
|
},
|
||||||
|
|
||||||
|
stopStreaming() {
|
||||||
|
if (!this.streaming)
|
||||||
|
return
|
||||||
|
|
||||||
|
this.streaming = false
|
||||||
|
this.capturing = false
|
||||||
|
this.$refs.frame.removeAttribute('src')
|
||||||
|
},
|
||||||
|
|
||||||
|
capture() {
|
||||||
|
if (this.capturing)
|
||||||
|
return
|
||||||
|
|
||||||
|
const cam = this.cameras[this.selectedCamera]
|
||||||
|
this.streaming = false
|
||||||
|
this.capturing = true
|
||||||
|
this.captured = true
|
||||||
|
this.$refs.frame.setAttribute('src', cam.image_url + '?t=' + (new Date()).getTime())
|
||||||
|
},
|
||||||
|
|
||||||
|
onFrameLoaded() {
|
||||||
|
if (this.capturing)
|
||||||
|
this.capturing = false
|
||||||
|
},
|
||||||
|
|
||||||
|
onCameraSelected(event) {
|
||||||
|
this.selectedCamera = event.target.value
|
||||||
|
},
|
||||||
|
|
||||||
|
async flipCamera() {
|
||||||
|
const cam = this.cameras[this.selectedCamera]
|
||||||
|
this.loading = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const value = !cam.ffc
|
||||||
|
await this.request('camera.android.ipcam.set_front_facing_camera', {
|
||||||
|
activate: value, camera: cam.name
|
||||||
|
})
|
||||||
|
|
||||||
|
this.cameras[this.selectedCamera].ffc = value
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async updateCameraStatus() {
|
||||||
|
this.loading = true
|
||||||
|
|
||||||
|
try {
|
||||||
|
const cameras = await this.request('camera.android.ipcam.status')
|
||||||
|
this.cameras = cameras.reduce((cameras, cam) => {
|
||||||
|
for (const attr of ['stream_url', 'image_url', 'audio_url']) {
|
||||||
|
if (cam[attr].startsWith('https://')) {
|
||||||
|
cam[attr] = cam[attr].replace('https://', 'http://')
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cam.name in this.config.cameras && this.config.cameras[cam.name].username) {
|
||||||
|
cam[attr] = 'http://' + this.config.cameras[cam.name].username + ':' +
|
||||||
|
this.config.cameras[cam.name].password + '@' + cam[attr].substr(7)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cameras[cam.name] = cam
|
||||||
|
return cameras
|
||||||
|
}, {})
|
||||||
|
|
||||||
|
if (cameras.length)
|
||||||
|
this.selectedCamera = cameras[0].name
|
||||||
|
|
||||||
|
} finally {
|
||||||
|
this.loading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
this.$refs.frame.addEventListener('load', this.onFrameLoaded)
|
||||||
|
this.updateCameraStatus()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import "../Camera/common";
|
||||||
|
|
||||||
|
$controls-height: 3.5em;
|
||||||
|
|
||||||
|
.camera {
|
||||||
|
.camera-selector {
|
||||||
|
width: 100%;
|
||||||
|
height: $controls-height;
|
||||||
|
margin-top: -3em;
|
||||||
|
box-shadow: $border-shadow-bottom;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.left,
|
||||||
|
.right {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left {
|
||||||
|
width: 90%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right {
|
||||||
|
width: 10%;
|
||||||
|
justify-content: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
width: 100%;
|
||||||
|
padding-left: 1em;
|
||||||
|
select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
&:hover {
|
||||||
|
color: $default-hover-fg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.camera-container {
|
||||||
|
margin-top: 2em;
|
||||||
|
min-width: 640px;
|
||||||
|
min-height: calc(480px + #{$controls-height});
|
||||||
|
|
||||||
|
.frame-container {
|
||||||
|
min-width: 640px;
|
||||||
|
min-height: 480px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
height: $controls-height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//.camera {
|
||||||
|
// min-height: 90%;
|
||||||
|
// overflow: auto;
|
||||||
|
// display: flex;
|
||||||
|
// flex-direction: column;
|
||||||
|
// align-items: center;
|
||||||
|
//
|
||||||
|
// .camera-container {
|
||||||
|
// min-width: 640px;
|
||||||
|
// min-height: 480px;
|
||||||
|
// position: relative;
|
||||||
|
// background: black;
|
||||||
|
// margin-bottom: 1em;
|
||||||
|
//
|
||||||
|
// .frame, .no-frame {
|
||||||
|
// position: absolute;
|
||||||
|
// top: 0;
|
||||||
|
// width: 100%;
|
||||||
|
// height: 100%;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// .frame {
|
||||||
|
// z-index: 1;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// .no-frame {
|
||||||
|
// display: flex;
|
||||||
|
// background: rgba(0, 0, 0, 0.1);
|
||||||
|
// color: white;
|
||||||
|
// align-items: center;
|
||||||
|
// justify-content: center;
|
||||||
|
// z-index: 2;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
</style>
|
Loading…
Reference in a new issue