You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

209 lines
7.1 KiB

/** @odoo-module **/
import { isMobileOS } from "@web/core/browser/feature_detection";
import { _lt } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
import { url } from "@web/core/utils/urls";
import { isBinarySize } from "@web/core/utils/binary";
import rpc from 'web.rpc';
import { FileUploader } from "@web/views/fields/file_handler";
import { standardFieldProps } from "@web/views/fields/standard_field_props";
import { Component, useState, onWillUpdateProps } from "@odoo/owl";
const { DateTime } = luxon;
export const fileTypeMagicWordMap = {
"/": "jpg",
R: "gif",
i: "png",
P: "svg+xml",
};
const placeholder = "/web/static/img/placeholder.png";
export function imageCacheKey(value) {
if (value instanceof DateTime) {
return value.ts;
}
return "";
}
export class ImageCapture extends Component {
setup() {
this.notification = useService("notification");
this.isMobile = isMobileOS();
this.state = useState({
isValid: true,
});
this.rawCacheKey = this.props.record.data.__last_update;
onWillUpdateProps((nextProps) => {
const { record } = this.props;
const { record: nextRecord } = nextProps;
if (record.resId !== nextRecord.resId || nextRecord.mode === "readonly") {
this.rawCacheKey = nextRecord.data.__last_update;
}
});
}
get sizeStyle() {
// For getting image style details
let style = "";
if (this.props.width) {
style += `max-width: ${this.props.width}px;`;
}
if (this.props.height) {
style += `max-height: ${this.props.height}px;`;
}
return style;
}
get hasTooltip() {
return this.props.enableZoom && this.props.readonly && this.props.value;
}
getUrl(previewFieldName) {
// getting the details and url of the image
if (this.state.isValid && this.props.value) {
if (isBinarySize(this.props.value)) {
if (!this.rawCacheKey) {
this.rawCacheKey = this.props.record.data.__last_update;
}
return url("/web/image", {
model: this.props.record.resModel,
id: this.props.record.resId,
field: previewFieldName,
unique: imageCacheKey(this.rawCacheKey),
});
} else {
// Use magic-word technique for detecting image type
const magic = fileTypeMagicWordMap[this.props.value[0]] || "png";
return `data:image/${magic};base64,${this.props.value}`;
}
}
return placeholder;
}
onFileRemove() {
// removing the images
this.state.isValid = true;
this.props.update(false);
}
onFileUploaded(info) {
// Upload the images
this.state.isValid = true;
this.rawCacheKey = null;
this.props.update(info.data);
}
onFileCaptureImage() {
// Open a window for open the image and capture it
var field = this.props.name;
var id = this.props.record.data.id;
var model = this.props.record.resModel;
}
async OnClickOpenCamera() {
// opening the camera for capture the image
var player = document.getElementById('player');
var captureButton = document.getElementById('capture');
var camera = document.getElementById('camera');
player.classList.remove('d-none');
captureButton.classList.remove('d-none');
camera.classList.add('d-none');
let stream = await navigator.mediaDevices.getUserMedia({ video: true, audio: false });
player.srcObject = stream;
}
async OnClickCaptureImage() {
// Capture the image from webcam and close the webcam
var context = snapshot.getContext('2d');
var canvas = document.getElementById('snapshot')
var save_image = document.getElementById('save_image')
var image = document.getElementById('image');
var video = document.getElementById('video')
var camera = document.getElementById('camera');
save_image.classList.remove('d-none');
context.drawImage(player, 0, 0, 320, 240);
image.value = context.canvas.toDataURL();
canvas.classList.remove('d-none');
this.url = context.canvas.toDataURL();
console.log(context.canvas.toDataURL());
console.log(context);
console.log(context.getImageData);
}
async OnClickSaveImage(){
// Saving the image to that field
var self = this;
rpc.query({
model: 'image.capture',
method: 'action_save_image',
args: [[], this.url],
}).then(function(results){
self.props.value = results
var data = {
data: results,
name : "ImageFile.png",
objectUrl: null,
size : 106252,
type: "image/png"
}
self.onFileUploaded(data)
})
var player = document.getElementById('player')
player.classList.add('d-none');
var snapshot = document.getElementById('snapshot')
snapshot.classList.add('d-none');
var capture = document.getElementById('capture')
capture.classList.add('d-none');
var save_image = document.getElementById('save_image')
save_image.classList.add('d-none');
var camera = document.getElementById('camera')
camera.classList.remove('d-none');
}
onLoadFailed() {
this.state.isValid = false;
this.notification.add(this.env._t("Could not display the selected image"), {
type: "danger",
});
}
}
ImageCapture.template = "CaptureImage";
ImageCapture.components = {
FileUploader,
};
ImageCapture.props = {
...standardFieldProps,
enableZoom: { type: Boolean, optional: true },
zoomDelay: { type: Number, optional: true },
previewImage: { type: String, optional: true },
acceptedFileExtensions: { type: String, optional: true },
width: { type: Number, optional: true },
height: { type: Number, optional: true },
};
ImageCapture.defaultProps = {
acceptedFileExtensions: "image/*",
};
ImageCapture.displayName = _lt("Image");
ImageCapture.supportedTypes = ["binary"];
ImageCapture.fieldDependencies = {
__last_update: { type: "datetime" },
};
ImageCapture.extractProps = ({ attrs }) => {
return {
enableZoom: attrs.options.zoom,
zoomDelay: attrs.options.zoom_delay,
previewImage: attrs.options.preview_image,
acceptedFileExtensions: attrs.options.accepted_file_extensions,
width:
attrs.options.size && Boolean(attrs.options.size[0])
? attrs.options.size[0]
: attrs.width,
height:
attrs.options.size && Boolean(attrs.options.size[1])
? attrs.options.size[1]
: attrs.height,
};
};
registry.category("fields").add("capture_image", ImageCapture);