This commit is contained in:
nnduc
2026-10-24 14:03:52 +07:00
commit 4fe046de58
4790 changed files with 311146 additions and 0 deletions
+114
View File
@@ -0,0 +1,114 @@
#snap {
top: 0;
left: 0;
background-color: rgb(var(--movim-background));
width: 100%;
height: 100%;
z-index: 2;
display: none;
animation: fadeIn 0.3s;
}
#snapclose,
#snapswitch,
#snapdraw {
width: 5.5rem;
height: 5.5rem;
line-height: 5.5rem;
margin-top: 0.75rem;
font-size: 2.5rem;
backdrop-filter: blur(1rem);
background-color: rgba(0, 0, 0, 0.25);
}
#snap canvas,
#snap video {
position: absolute;
top: 50%;
left: 50%;
translate: -50% -50%;
max-width: calc(100% - 8rem);
max-height: calc(100% - 8rem);
border-radius: 2rem;
box-shadow: var(--elevation-3);
object-fit: cover;
}
#snap.upload canvas {
animation: zoomOut 0.3s;
max-height: calc(100% - 15rem);
box-shadow: var(--elevation-5);
}
#snap.draw canvas {
background-color: white;
}
#snap video {
background-image: url(../theme/img/cloud_spinner.svg);
background-repeat: no-repeat;
background-position: center center;
animation: zoom 0.3s;
}
#snap .bottom_center {
width: 100%;
position: absolute;
bottom: 2rem;
display: flex;
justify-content: center;
}
#snap .bottom_center > button {
position: relative;
margin-left: 1rem;
margin-right: 1rem;
right: 0;
}
/* States */
#snap.shoot,
#snap.upload,
#snap.wait,
#snap.draw,
#snap.init {
display: block;
}
#snap select#snapsource,
#snap.shoot #snapupload,
#snap.shoot #snapdraw,
#snap.shoot #snapclose,
#snap.shoot #snapwait,
#snap.shoot #snapswitch:not(.enabled),
#snap.shoot canvas,
#snap.upload #snapshoot,
#snap.upload #snapwait,
#snap.upload #snapswitch,
#snap.upload video,
#snap.wait #snapshoot,
#snap.wait #snapupload,
#snap.wait #snapdraw,
#snap.wait #snapback,
#snap.wait #snapclose,
#snap.wait #snapswitch,
#snap.wait video,
#snap.draw #snapshoot,
#snap.draw #snapwait,
#snap.draw #snapclose,
#snap.draw #snapswitch,
#snap.draw video,
#snap.init #snapshoot,
#snap.init #snapupload,
#snap.init #snapdraw,
#snap.init #snapclose,
#snap.init #snapswitch,
#snap.init canvas,
#snap.init video {
display: none;
}
+206
View File
@@ -0,0 +1,206 @@
var Snap = {
snap: undefined,
video: undefined,
videoSelect: undefined,
canvas: undefined,
wait: undefined,
imageCapture: null,
init: function () {
MovimTpl.pushAnchorState('snap', function () {
Snap.snap.classList = '';
Snap.close();
});
Snap.snap = document.querySelector('#snap');
Snap.canvas = document.querySelector('#snap canvas');
Snap.wait = document.querySelector("#snap #snapwait");
Snap.video = document.querySelector('#snap video');
Snap.videoSelect = document.querySelector('#snap select#snapsource');
Snap.close();
Snap.getStream().then(Snap.getDevices).then(Snap.gotDevices);
document.querySelector("#snap #snapshoot").onclick = () => Snap.shoot();
document.querySelector("#snap #snapswitch").onclick = () => {
Snap.snap.classList = 'init';
Snap.videoSelect.selectedIndex++;
// No empty selection
if (Snap.videoSelect.selectedIndex == -1) {
Snap.videoSelect.selectedIndex++;
}
Toast.send(Snap.videoSelect.options[Snap.videoSelect.selectedIndex].label);
Snap.getStream();
};
Snap.snap.classList = 'init';
document.querySelector("#snap #snapupload").onclick = () => {
Snap.snap.classList = 'wait';
Upload.init();
};
document.querySelector("#snap #snapdraw").onclick = () => {
Snap.snap.classList = '';
Snap.close();
Draw.initCanvas = Snap.canvas;
Draw_ajaxHttpGet();
};
document.querySelector("#snap #snapback").onclick = () => {
history.back();
};
document.querySelector("#snap #snapclose").onclick = () => {
Snap.snap.classList = 'shoot';
Snap.video.play();
Upload.abort();
};
},
close: function () {
if (!Snap.video) return;
let stream = Snap.video.srcObject;
if (stream) {
stream.getTracks().forEach(track => track.stop());
}
Snap.video.srcObject = null;
},
getStream: function () {
Snap.snap.classList = 'wait';
if (Snap.video.srcObject) {
Snap.video.srcObject.getTracks().forEach(track => track.stop());
}
const videoSource = Snap.videoSelect.value;
const constraints = {
video: {
deviceId: videoSource ? { exact: videoSource } : undefined,
width: { ideal: 1920 },
height: { ideal: 1920 }
}
};
return navigator.mediaDevices.getUserMedia(constraints)
.then(Snap.gotStream);
},
gotStream: function (stream) {
Snap.snap.classList = 'shoot';
Snap.videoSelect.selectedIndex = [...Snap.videoSelect.options].
findIndex(option => option.text === stream.getVideoTracks()[0].label);
Snap.video.srcObject = stream;
// We try to use ImageCapture
if (typeof (ImageCapture) != 'undefined') {
const track = stream.getVideoTracks()[0];
Snap.imageCapture = new ImageCapture(track);
}
// If we cancel after the authorization was given
if (Snap.snap.classList == '') {
Snap.close();
};
},
getDevices: function () {
return navigator.mediaDevices.enumerateDevices();
},
gotDevices: function (devicesInfo) {
Snap.videoSelect.innerHTML = '';
for (const deviceInfo of devicesInfo) {
if (deviceInfo.kind === 'videoinput') {
const option = document.createElement('option');
option.value = deviceInfo.deviceId;
option.text = deviceInfo.label || `Camera ${videoSelect.length + 1}`;
if (!Snap.videoSelect.querySelector('option[value="' + deviceInfo.deviceId + '"]')) {
Snap.videoSelect.appendChild(option);
}
}
}
if (Snap.videoSelect.options.length >= 2) {
document.querySelector("#snap #snapswitch").classList.add('enabled');
}
},
shoot: function () {
if (Snap.imageCapture) {
Snap.imageCapture.takePhoto()
.then(blob => createImageBitmap(blob))
.then(image => {
Snap.canvas.width = image.width;
Snap.canvas.height = image.height;
var context = Snap.canvas.getContext('2d');
context.drawImage(image, 0, 0, image.width, image.height);
Snap.compress();
})
.catch(error => console.log(error));
} else {
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();
Snap.compress();
}
},
compress: function () {
Snap.canvas.toBlob(
function (blob) {
Upload.prepare(blob);
},
'image/jpeg',
0.85
);
Upload.name = 'snapshot.jpg';
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);
},
end: function () {
Snap.snap.classList = '';
Snap.wait.style.backgroundImage = '';
Snap.close();
}
}
MovimEvents.registerWindow('loaded', 'snap', () => {
Upload.attach((file) => {
if (Snap.snap) Snap.end();
});
Upload.progress((percent) => {
if (Snap.wait) {
Snap.wait.style.backgroundImage = 'linear-gradient(to top, rgba(0, 0, 0, 0.5) ' + percent + '%, transparent ' + percent + '%)';
}
});
Upload.fail(() => {
if (Snap.snap) {
Snap.snap.classList = 'upload'; Snap.wait.style.backgroundImage = '';
}
});
});