Browse Source

Add Snap widget to take quick photos

Link it ti PublishBrief (Chat soon)
pull/853/head
Timothée Jaussoin 6 years ago
parent
commit
d2ce6f975e
  1. 1
      app/views/news.tpl
  2. 7
      app/widgets/PublishBrief/_publishbrief_embed_default.tpl
  3. 1
      app/widgets/PublishBrief/locales.ini
  4. 12
      app/widgets/Snap/Snap.php
  5. 78
      app/widgets/Snap/snap.css
  6. 129
      app/widgets/Snap/snap.js
  7. 24
      app/widgets/Snap/snap.tpl
  8. 12
      app/widgets/Upload/upload.js

1
app/views/news.tpl

@ -8,6 +8,7 @@
<?php $this->widget('SendTo');?>
<?php $this->widget('PostActions');?>
<?php $this->widget('Snap');?>
<nav class="color dark">
<?php $this->widget('Presence');?>

7
app/widgets/PublishBrief/_publishbrief_embed_default.tpl

@ -1,3 +1,10 @@
<a
class="button flat icon gray"
title="{$c->__('publishbrief.add_snap')}"
href="#"
onclick="Snap.init()">
<i class="material-icons">camera_alt</i>
</a>
<a
class="button flat icon gray"
title="{$c->__('publishbrief.add_link')}"

1
app/widgets/PublishBrief/locales.ini

@ -2,6 +2,7 @@
placeholder = "What’s new?"
post = Write a post
add_link = Add a link
add_snap = Take a picture
no_title = Please provide a title
preview = Preview
attach = Add a file or a picture

12
app/widgets/Snap/Snap.php

@ -0,0 +1,12 @@
<?php
use Movim\Widget\Base;
class Snap extends Base
{
public function load()
{
$this->addjs('snap.js');
$this->addcss('snap.css');
}
}

78
app/widgets/Snap/snap.css

@ -0,0 +1,78 @@
#snap {
top: 0;
left: 0;
background-color: #111;
width: 100%;
height: 100%;
z-index: 2;
display: none;
}
#snap canvas {
border: 1rem #333 solid;
box-sizing: border-box;
}
#snap canvas,
#snap video {
width: 100%;
height: 100%;
object-fit: contain;
}
#snap select#snapsource {
display: none;
}
#snap canvas {
position: absolute;
top: 0;
left: 0;
}
#snap button#snapshoot,
#snap button#snapupload {
right: calc(50% - 3.5rem);
position: absolute;
bottom: 2rem;
}
#snap button#snapswitch {
left: 2rem;
}
/* Controls */
#snap ul.controls.list {
position: absolute;
width: 100%;
top: 0;
}
#snap ul.controls.list > li {
padding: 3rem;
}
#snap ul.controls.list > li span {
padding: 2rem;
}
#snap ul.controls.list > li span.primary {
left: 0;
}
/* States */
#snap.shoot,
#snap.upload {
display: block;
}
#snap.shoot ul.controls.list > li#snapback,
#snap.shoot #snapupload,
#snap.shoot #snapclose,
#snap.shoot canvas,
#snap.upload ul.controls.list > li#snapclose,
#snap.upload #snapshoot,
#snap.upload #snapback,
#snap.upload #snapswitch {
display: none;
}

129
app/widgets/Snap/snap.js

@ -0,0 +1,129 @@
var Snap = {
snap: undefined,
video: undefined,
videoSelect: undefined,
canvas: undefined,
gotStream: function() {
const constraints = {
video: {
deviceId: Snap.videoSelect.value,
width: {ideal: 1280},
height: {ideal: 720}
}
};
if(navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia(constraints)
.then(stream => {
Snap.video.srcObject = stream;
});
}
},
gotDevices: function(deviceInfos) {
Snap.videoSelect.innerText = '';
const ids = [];
for (let i = 0; i !== deviceInfos.length; ++i) {
const deviceInfo = deviceInfos[i];
if (deviceInfo.kind === 'videoinput' && !ids.includes(deviceInfo.deviceId)) {
const option = document.createElement('option');
option.value = deviceInfo.deviceId;
option.text = deviceInfo.label;
Snap.videoSelect.add(option);
ids.push(deviceInfo.deviceId);
}
}
Snap.videoSelect.addEventListener('change', e => Snap.gotStream() );
Snap.gotStream();
snap.classList = 'shoot';
},
shoot: function() {
Snap.canvas.width = Snap.video.videoWidth;
Snap.canvas.height = Snap.video.videoHeight;
var context = Snap.canvas.getContext('2d');
context.drawImage(Snap.video, 0, 0, Snap.video.videoWidth, Snap.video.videoHeight);
Snap.video.pause();
Upload.name = 'snapshot.jpg';
Snap.canvas.toBlob(
function (blob) {
Upload.prepare(blob);
},
'image/jpeg',
0.85
);
Snap.snap.classList = 'upload';
},
clear: function() {
Snap.video.play();
var context = Snap.canvas.getContext('2d');
context.clearRect(0, 0, Snap.canvas.width, Snap.canvas.height);
},
close: function() {
let stream = Snap.video.srcObject;
if (stream) {
stream.getTracks().forEach(function(track) {
track.stop();
});
}
Snap.video.srcObject = null;
},
init : function() {
Snap.snap = document.querySelector('#snap');
Snap.video = document.querySelector('#snap video');
Snap.videoSelect = document.querySelector('#snap select#snapsource');
Snap.canvas = document.querySelector('#snap canvas');
Snap.close(); // Just in case
navigator.mediaDevices.enumerateDevices().then(devices => Snap.gotDevices(devices));
document.querySelector("#snap #snapshoot").addEventListener('click', function() {
Snap.shoot();
});
document.querySelector("#snap #snapupload").addEventListener('click', function() {
Upload.init();
});
document.querySelector("#snap #snapback").addEventListener('click', function() {
Snap.snap.classList = '';
Snap.close();
});
document.querySelector("#snap #snapclose").addEventListener('click', function() {
Snap.snap.classList = 'shoot';
Snap.video.play();
});
document.querySelector("#snap #snapswitch").addEventListener('click', function() {
Snap.videoSelect.selectedIndex++;
// No empty selection
if (Snap.videoSelect.selectedIndex == -1) {
Snap.videoSelect.selectedIndex++;
}
Snap.close();
Snap.gotStream();
});
Upload.attach(function(file) {
document.querySelector('input[name=embed]').value = file.uri;
PublishBrief.checkEmbed();
Snap.snap.classList = '';
Snap.close();
});
}
}

24
app/widgets/Snap/snap.tpl

@ -0,0 +1,24 @@
<div id="snap">
<video autoplay></video>
<canvas id="snapcanvas"></canvas>
<select id="snapsource"></select>
<button id="snapshoot" class="button action color green">
<i class="material-icons">camera</i>
</button>
<button id="snapupload" class="button action color blue">
<i class="material-icons">publish</i>
</button>
<button id="snapswitch" class="button action color">
<i class="material-icons">switch_camera</i>
</button>
<ul class="list controls">
<li>
<span id="snapback" class="primary icon color transparent active">
<i class="material-icons">arrow_back</i>
</span>
<span id="snapclose" class="control icon color transparent active">
<i class="material-icons">close</i>
</span>
</li>
</ul>
</div>

12
app/widgets/Upload/upload.js

@ -123,10 +123,14 @@ var Upload = {
Upload.file = file;
var preview = document.querySelector('#upload img.preview_picture');
if (Upload.file.type.match(/image.*/)) {
preview.src = URL.createObjectURL(Upload.file);
} else {
preview.src = '';
// If the preview system is there
if (preview) {
if (Upload.file.type.match(/image.*/)) {
preview.src = URL.createObjectURL(Upload.file);
} else {
preview.src = '';
}
}
},

Loading…
Cancel
Save