one
Version:
One is a React framework for web, iOS, and Android apps.
172 lines (169 loc) • 4.52 kB
JavaScript
import { resolveCameraOptions, resolveImagePickerOptions } from "./options.mjs";
const granted = Object.freeze({
status: "granted",
granted: true,
canAskAgain: true
});
function acceptFor(mediaTypes) {
const accept = [];
if (mediaTypes.includes("images")) accept.push("image/*");
if (mediaTypes.includes("videos")) accept.push("video/*");
return accept.join(",");
}
function pickFiles(accept, multiple, capture) {
return new Promise((resolve) => {
const input = document.createElement("input");
input.type = "file";
input.accept = accept;
input.multiple = multiple;
if (capture) input.capture = capture;
input.onchange = () => resolve(input.files ? [...input.files] : []);
input.addEventListener("cancel", () => resolve(null));
input.click();
});
}
async function imageSize(file) {
try {
const bitmap = await createImageBitmap(file);
const size = {
width: bitmap.width,
height: bitmap.height
};
bitmap.close();
return size;
} catch {
return {
width: 0,
height: 0
};
}
}
function videoSize(url) {
return new Promise((resolve) => {
const video = document.createElement("video");
video.preload = "metadata";
video.muted = true;
video.onloadedmetadata = () => resolve({
width: video.videoWidth,
height: video.videoHeight
});
video.onerror = () => resolve({
width: 0,
height: 0
});
video.src = url;
});
}
function videoDuration(url) {
return new Promise((resolve) => {
const video = document.createElement("video");
video.preload = "metadata";
video.muted = true;
video.onloadedmetadata = () => resolve(Number.isFinite(video.duration) ? Math.round(video.duration * 1e3) : void 0);
video.onerror = () => resolve(void 0);
video.src = url;
});
}
async function toAsset(file, quality) {
const uri = URL.createObjectURL(file);
const isVideo = file.type.startsWith("video/");
const asset = {
uri,
width: 0,
height: 0,
mimeType: file.type || void 0,
fileName: file.name,
fileSize: file.size,
type: isVideo ? "video" : "image"
};
if (isVideo) {
const url = uri;
const size2 = await videoSize(url);
asset.width = size2.width;
asset.height = size2.height;
const duration = await videoDuration(url);
if (duration !== void 0) asset.duration = duration;
return asset;
}
if (quality < 1) {
const compressed = await compressImage(file, quality);
if (compressed) {
URL.revokeObjectURL(uri);
return compressed;
}
}
const size = await imageSize(file);
asset.width = size.width;
asset.height = size.height;
return asset;
}
async function compressImage(file, quality) {
try {
const bitmap = await createImageBitmap(file);
const canvas = document.createElement("canvas");
canvas.width = bitmap.width;
canvas.height = bitmap.height;
const context = canvas.getContext("2d");
if (!context) {
bitmap.close();
return null;
}
context.drawImage(bitmap, 0, 0);
bitmap.close();
const blob = await new Promise((resolve) => canvas.toBlob(resolve, "image/jpeg", quality));
if (!blob) return null;
const uri = URL.createObjectURL(blob);
return {
uri,
width: canvas.width,
height: canvas.height,
mimeType: "image/jpeg",
fileName: file.name,
fileSize: blob.size,
type: "image"
};
} catch {
return null;
}
}
async function pick(verb, selectionLimit, mediaTypes, quality, capture) {
if (typeof document === "undefined") {
throw new Error(`ImagePicker.${verb} needs an iOS or Android build`);
}
const files = await pickFiles(acceptFor(mediaTypes), selectionLimit !== 1, capture);
if (!files || files.length === 0) return {
canceled: true,
assets: null
};
const limited = selectionLimit > 0 ? files.slice(0, selectionLimit) : files;
const assets = [];
for (const file of limited) {
assets.push(await toAsset(file, quality));
}
return {
canceled: false,
assets
};
}
function launchLibrary(options = {}) {
const resolved = resolveImagePickerOptions(options);
return pick("launchLibrary", resolved.selectionLimit, resolved.mediaTypes, resolved.quality);
}
function launchCamera(options = {}) {
const resolved = resolveCameraOptions(options);
return pick("launchCamera", 1, resolved.mediaTypes, resolved.quality, "environment");
}
async function getCameraPermissions() {
return granted;
}
async function requestCameraPermissions() {
return granted;
}
const ImagePicker = Object.freeze({
launchLibrary,
launchCamera,
getCameraPermissions,
requestCameraPermissions
});
export { ImagePicker };
//# sourceMappingURL=index.mjs.map