init
This commit is contained in:
BIN
dist/assets/favicon-UvKAN7pv.ico
vendored
Normal file
BIN
dist/assets/favicon-UvKAN7pv.ico
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 99 KiB |
959
dist/assets/index-CTla4gm7.js
vendored
Normal file
959
dist/assets/index-CTla4gm7.js
vendored
Normal file
@@ -0,0 +1,959 @@
|
||||
(function polyfill() {
|
||||
const relList = document.createElement("link").relList;
|
||||
if (relList && relList.supports && relList.supports("modulepreload")) {
|
||||
return;
|
||||
}
|
||||
for (const link of document.querySelectorAll('link[rel="modulepreload"]')) {
|
||||
processPreload(link);
|
||||
}
|
||||
new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type !== "childList") {
|
||||
continue;
|
||||
}
|
||||
for (const node of mutation.addedNodes) {
|
||||
if (node.tagName === "LINK" && node.rel === "modulepreload")
|
||||
processPreload(node);
|
||||
}
|
||||
}
|
||||
}).observe(document, { childList: true, subtree: true });
|
||||
function getFetchOpts(link) {
|
||||
const fetchOpts = {};
|
||||
if (link.integrity) fetchOpts.integrity = link.integrity;
|
||||
if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy;
|
||||
if (link.crossOrigin === "use-credentials")
|
||||
fetchOpts.credentials = "include";
|
||||
else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit";
|
||||
else fetchOpts.credentials = "same-origin";
|
||||
return fetchOpts;
|
||||
}
|
||||
function processPreload(link) {
|
||||
if (link.ep)
|
||||
return;
|
||||
link.ep = true;
|
||||
const fetchOpts = getFetchOpts(link);
|
||||
fetch(link.href, fetchOpts);
|
||||
}
|
||||
})();
|
||||
const scriptRel = "modulepreload";
|
||||
const assetsURL = function(dep) {
|
||||
return "/" + dep;
|
||||
};
|
||||
const seen = {};
|
||||
const __vitePreload = function preload(baseModule, deps, importerUrl) {
|
||||
let promise = Promise.resolve();
|
||||
if (deps && deps.length > 0) {
|
||||
document.getElementsByTagName("link");
|
||||
const cspNonceMeta = document.querySelector(
|
||||
"meta[property=csp-nonce]"
|
||||
);
|
||||
const cspNonce = (cspNonceMeta == null ? void 0 : cspNonceMeta.nonce) || (cspNonceMeta == null ? void 0 : cspNonceMeta.getAttribute("nonce"));
|
||||
promise = Promise.allSettled(
|
||||
deps.map((dep) => {
|
||||
dep = assetsURL(dep);
|
||||
if (dep in seen) return;
|
||||
seen[dep] = true;
|
||||
const isCss = dep.endsWith(".css");
|
||||
const cssSelector = isCss ? '[rel="stylesheet"]' : "";
|
||||
if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) {
|
||||
return;
|
||||
}
|
||||
const link = document.createElement("link");
|
||||
link.rel = isCss ? "stylesheet" : scriptRel;
|
||||
if (!isCss) {
|
||||
link.as = "script";
|
||||
}
|
||||
link.crossOrigin = "";
|
||||
link.href = dep;
|
||||
if (cspNonce) {
|
||||
link.setAttribute("nonce", cspNonce);
|
||||
}
|
||||
document.head.appendChild(link);
|
||||
if (isCss) {
|
||||
return new Promise((res, rej) => {
|
||||
link.addEventListener("load", res);
|
||||
link.addEventListener(
|
||||
"error",
|
||||
() => rej(new Error(`Unable to preload CSS for ${dep}`))
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
function handlePreloadError(err) {
|
||||
const e = new Event("vite:preloadError", {
|
||||
cancelable: true
|
||||
});
|
||||
e.payload = err;
|
||||
window.dispatchEvent(e);
|
||||
if (!e.defaultPrevented) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
return promise.then((res) => {
|
||||
for (const item of res || []) {
|
||||
if (item.status !== "rejected") continue;
|
||||
handlePreloadError(item.reason);
|
||||
}
|
||||
return baseModule().catch(handlePreloadError);
|
||||
});
|
||||
};
|
||||
/*! Capacitor: https://capacitorjs.com/ - MIT License */
|
||||
var ExceptionCode;
|
||||
(function(ExceptionCode2) {
|
||||
ExceptionCode2["Unimplemented"] = "UNIMPLEMENTED";
|
||||
ExceptionCode2["Unavailable"] = "UNAVAILABLE";
|
||||
})(ExceptionCode || (ExceptionCode = {}));
|
||||
class CapacitorException extends Error {
|
||||
constructor(message, code, data) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
const getPlatformId = (win) => {
|
||||
var _a, _b;
|
||||
if (win === null || win === void 0 ? void 0 : win.androidBridge) {
|
||||
return "android";
|
||||
} else if ((_b = (_a = win === null || win === void 0 ? void 0 : win.webkit) === null || _a === void 0 ? void 0 : _a.messageHandlers) === null || _b === void 0 ? void 0 : _b.bridge) {
|
||||
return "ios";
|
||||
} else {
|
||||
return "web";
|
||||
}
|
||||
};
|
||||
const createCapacitor = (win) => {
|
||||
const capCustomPlatform = win.CapacitorCustomPlatform || null;
|
||||
const cap = win.Capacitor || {};
|
||||
const Plugins = cap.Plugins = cap.Plugins || {};
|
||||
const getPlatform = () => {
|
||||
return capCustomPlatform !== null ? capCustomPlatform.name : getPlatformId(win);
|
||||
};
|
||||
const isNativePlatform = () => getPlatform() !== "web";
|
||||
const isPluginAvailable = (pluginName) => {
|
||||
const plugin = registeredPlugins.get(pluginName);
|
||||
if (plugin === null || plugin === void 0 ? void 0 : plugin.platforms.has(getPlatform())) {
|
||||
return true;
|
||||
}
|
||||
if (getPluginHeader(pluginName)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const getPluginHeader = (pluginName) => {
|
||||
var _a;
|
||||
return (_a = cap.PluginHeaders) === null || _a === void 0 ? void 0 : _a.find((h) => h.name === pluginName);
|
||||
};
|
||||
const handleError = (err) => win.console.error(err);
|
||||
const registeredPlugins = /* @__PURE__ */ new Map();
|
||||
const registerPlugin2 = (pluginName, jsImplementations = {}) => {
|
||||
const registeredPlugin = registeredPlugins.get(pluginName);
|
||||
if (registeredPlugin) {
|
||||
console.warn(`Capacitor plugin "${pluginName}" already registered. Cannot register plugins twice.`);
|
||||
return registeredPlugin.proxy;
|
||||
}
|
||||
const platform = getPlatform();
|
||||
const pluginHeader = getPluginHeader(pluginName);
|
||||
let jsImplementation;
|
||||
const loadPluginImplementation = async () => {
|
||||
if (!jsImplementation && platform in jsImplementations) {
|
||||
jsImplementation = typeof jsImplementations[platform] === "function" ? jsImplementation = await jsImplementations[platform]() : jsImplementation = jsImplementations[platform];
|
||||
} else if (capCustomPlatform !== null && !jsImplementation && "web" in jsImplementations) {
|
||||
jsImplementation = typeof jsImplementations["web"] === "function" ? jsImplementation = await jsImplementations["web"]() : jsImplementation = jsImplementations["web"];
|
||||
}
|
||||
return jsImplementation;
|
||||
};
|
||||
const createPluginMethod = (impl, prop) => {
|
||||
var _a, _b;
|
||||
if (pluginHeader) {
|
||||
const methodHeader = pluginHeader === null || pluginHeader === void 0 ? void 0 : pluginHeader.methods.find((m) => prop === m.name);
|
||||
if (methodHeader) {
|
||||
if (methodHeader.rtype === "promise") {
|
||||
return (options) => cap.nativePromise(pluginName, prop.toString(), options);
|
||||
} else {
|
||||
return (options, callback) => cap.nativeCallback(pluginName, prop.toString(), options, callback);
|
||||
}
|
||||
} else if (impl) {
|
||||
return (_a = impl[prop]) === null || _a === void 0 ? void 0 : _a.bind(impl);
|
||||
}
|
||||
} else if (impl) {
|
||||
return (_b = impl[prop]) === null || _b === void 0 ? void 0 : _b.bind(impl);
|
||||
} else {
|
||||
throw new CapacitorException(`"${pluginName}" plugin is not implemented on ${platform}`, ExceptionCode.Unimplemented);
|
||||
}
|
||||
};
|
||||
const createPluginMethodWrapper = (prop) => {
|
||||
let remove;
|
||||
const wrapper = (...args) => {
|
||||
const p = loadPluginImplementation().then((impl) => {
|
||||
const fn = createPluginMethod(impl, prop);
|
||||
if (fn) {
|
||||
const p2 = fn(...args);
|
||||
remove = p2 === null || p2 === void 0 ? void 0 : p2.remove;
|
||||
return p2;
|
||||
} else {
|
||||
throw new CapacitorException(`"${pluginName}.${prop}()" is not implemented on ${platform}`, ExceptionCode.Unimplemented);
|
||||
}
|
||||
});
|
||||
if (prop === "addListener") {
|
||||
p.remove = async () => remove();
|
||||
}
|
||||
return p;
|
||||
};
|
||||
wrapper.toString = () => `${prop.toString()}() { [capacitor code] }`;
|
||||
Object.defineProperty(wrapper, "name", {
|
||||
value: prop,
|
||||
writable: false,
|
||||
configurable: false
|
||||
});
|
||||
return wrapper;
|
||||
};
|
||||
const addListener = createPluginMethodWrapper("addListener");
|
||||
const removeListener = createPluginMethodWrapper("removeListener");
|
||||
const addListenerNative = (eventName, callback) => {
|
||||
const call = addListener({ eventName }, callback);
|
||||
const remove = async () => {
|
||||
const callbackId = await call;
|
||||
removeListener({
|
||||
eventName,
|
||||
callbackId
|
||||
}, callback);
|
||||
};
|
||||
const p = new Promise((resolve) => call.then(() => resolve({ remove })));
|
||||
p.remove = async () => {
|
||||
console.warn(`Using addListener() without 'await' is deprecated.`);
|
||||
await remove();
|
||||
};
|
||||
return p;
|
||||
};
|
||||
const proxy = new Proxy({}, {
|
||||
get(_, prop) {
|
||||
switch (prop) {
|
||||
case "$$typeof":
|
||||
return void 0;
|
||||
case "toJSON":
|
||||
return () => ({});
|
||||
case "addListener":
|
||||
return pluginHeader ? addListenerNative : addListener;
|
||||
case "removeListener":
|
||||
return removeListener;
|
||||
default:
|
||||
return createPluginMethodWrapper(prop);
|
||||
}
|
||||
}
|
||||
});
|
||||
Plugins[pluginName] = proxy;
|
||||
registeredPlugins.set(pluginName, {
|
||||
name: pluginName,
|
||||
proxy,
|
||||
platforms: /* @__PURE__ */ new Set([...Object.keys(jsImplementations), ...pluginHeader ? [platform] : []])
|
||||
});
|
||||
return proxy;
|
||||
};
|
||||
if (!cap.convertFileSrc) {
|
||||
cap.convertFileSrc = (filePath) => filePath;
|
||||
}
|
||||
cap.getPlatform = getPlatform;
|
||||
cap.handleError = handleError;
|
||||
cap.isNativePlatform = isNativePlatform;
|
||||
cap.isPluginAvailable = isPluginAvailable;
|
||||
cap.registerPlugin = registerPlugin2;
|
||||
cap.Exception = CapacitorException;
|
||||
cap.DEBUG = !!cap.DEBUG;
|
||||
cap.isLoggingEnabled = !!cap.isLoggingEnabled;
|
||||
return cap;
|
||||
};
|
||||
const initCapacitorGlobal = (win) => win.Capacitor = createCapacitor(win);
|
||||
const Capacitor = /* @__PURE__ */ initCapacitorGlobal(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {});
|
||||
const registerPlugin = Capacitor.registerPlugin;
|
||||
class WebPlugin {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
this.retainedEventArguments = {};
|
||||
this.windowListeners = {};
|
||||
}
|
||||
addListener(eventName, listenerFunc) {
|
||||
let firstListener = false;
|
||||
const listeners = this.listeners[eventName];
|
||||
if (!listeners) {
|
||||
this.listeners[eventName] = [];
|
||||
firstListener = true;
|
||||
}
|
||||
this.listeners[eventName].push(listenerFunc);
|
||||
const windowListener = this.windowListeners[eventName];
|
||||
if (windowListener && !windowListener.registered) {
|
||||
this.addWindowListener(windowListener);
|
||||
}
|
||||
if (firstListener) {
|
||||
this.sendRetainedArgumentsForEvent(eventName);
|
||||
}
|
||||
const remove = async () => this.removeListener(eventName, listenerFunc);
|
||||
const p = Promise.resolve({ remove });
|
||||
return p;
|
||||
}
|
||||
async removeAllListeners() {
|
||||
this.listeners = {};
|
||||
for (const listener in this.windowListeners) {
|
||||
this.removeWindowListener(this.windowListeners[listener]);
|
||||
}
|
||||
this.windowListeners = {};
|
||||
}
|
||||
notifyListeners(eventName, data, retainUntilConsumed) {
|
||||
const listeners = this.listeners[eventName];
|
||||
if (!listeners) {
|
||||
if (retainUntilConsumed) {
|
||||
let args = this.retainedEventArguments[eventName];
|
||||
if (!args) {
|
||||
args = [];
|
||||
}
|
||||
args.push(data);
|
||||
this.retainedEventArguments[eventName] = args;
|
||||
}
|
||||
return;
|
||||
}
|
||||
listeners.forEach((listener) => listener(data));
|
||||
}
|
||||
hasListeners(eventName) {
|
||||
var _a;
|
||||
return !!((_a = this.listeners[eventName]) === null || _a === void 0 ? void 0 : _a.length);
|
||||
}
|
||||
registerWindowListener(windowEventName, pluginEventName) {
|
||||
this.windowListeners[pluginEventName] = {
|
||||
registered: false,
|
||||
windowEventName,
|
||||
pluginEventName,
|
||||
handler: (event) => {
|
||||
this.notifyListeners(pluginEventName, event);
|
||||
}
|
||||
};
|
||||
}
|
||||
unimplemented(msg = "not implemented") {
|
||||
return new Capacitor.Exception(msg, ExceptionCode.Unimplemented);
|
||||
}
|
||||
unavailable(msg = "not available") {
|
||||
return new Capacitor.Exception(msg, ExceptionCode.Unavailable);
|
||||
}
|
||||
async removeListener(eventName, listenerFunc) {
|
||||
const listeners = this.listeners[eventName];
|
||||
if (!listeners) {
|
||||
return;
|
||||
}
|
||||
const index = listeners.indexOf(listenerFunc);
|
||||
this.listeners[eventName].splice(index, 1);
|
||||
if (!this.listeners[eventName].length) {
|
||||
this.removeWindowListener(this.windowListeners[eventName]);
|
||||
}
|
||||
}
|
||||
addWindowListener(handle) {
|
||||
window.addEventListener(handle.windowEventName, handle.handler);
|
||||
handle.registered = true;
|
||||
}
|
||||
removeWindowListener(handle) {
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
window.removeEventListener(handle.windowEventName, handle.handler);
|
||||
handle.registered = false;
|
||||
}
|
||||
sendRetainedArgumentsForEvent(eventName) {
|
||||
const args = this.retainedEventArguments[eventName];
|
||||
if (!args) {
|
||||
return;
|
||||
}
|
||||
delete this.retainedEventArguments[eventName];
|
||||
args.forEach((arg) => {
|
||||
this.notifyListeners(eventName, arg);
|
||||
});
|
||||
}
|
||||
}
|
||||
const encode = (str) => encodeURIComponent(str).replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent).replace(/[()]/g, escape);
|
||||
const decode = (str) => str.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
|
||||
class CapacitorCookiesPluginWeb extends WebPlugin {
|
||||
async getCookies() {
|
||||
const cookies = document.cookie;
|
||||
const cookieMap = {};
|
||||
cookies.split(";").forEach((cookie) => {
|
||||
if (cookie.length <= 0)
|
||||
return;
|
||||
let [key, value] = cookie.replace(/=/, "CAP_COOKIE").split("CAP_COOKIE");
|
||||
key = decode(key).trim();
|
||||
value = decode(value).trim();
|
||||
cookieMap[key] = value;
|
||||
});
|
||||
return cookieMap;
|
||||
}
|
||||
async setCookie(options) {
|
||||
try {
|
||||
const encodedKey = encode(options.key);
|
||||
const encodedValue = encode(options.value);
|
||||
const expires = `; expires=${(options.expires || "").replace("expires=", "")}`;
|
||||
const path = (options.path || "/").replace("path=", "");
|
||||
const domain = options.url != null && options.url.length > 0 ? `domain=${options.url}` : "";
|
||||
document.cookie = `${encodedKey}=${encodedValue || ""}${expires}; path=${path}; ${domain};`;
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
async deleteCookie(options) {
|
||||
try {
|
||||
document.cookie = `${options.key}=; Max-Age=0`;
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
async clearCookies() {
|
||||
try {
|
||||
const cookies = document.cookie.split(";") || [];
|
||||
for (const cookie of cookies) {
|
||||
document.cookie = cookie.replace(/^ +/, "").replace(/=.*/, `=;expires=${(/* @__PURE__ */ new Date()).toUTCString()};path=/`);
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
async clearAllCookies() {
|
||||
try {
|
||||
await this.clearCookies();
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
registerPlugin("CapacitorCookies", {
|
||||
web: () => new CapacitorCookiesPluginWeb()
|
||||
});
|
||||
const readBlobAsBase64 = async (blob) => new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
const base64String = reader.result;
|
||||
resolve(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
|
||||
};
|
||||
reader.onerror = (error) => reject(error);
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
const normalizeHttpHeaders = (headers = {}) => {
|
||||
const originalKeys = Object.keys(headers);
|
||||
const loweredKeys = Object.keys(headers).map((k) => k.toLocaleLowerCase());
|
||||
const normalized = loweredKeys.reduce((acc, key, index) => {
|
||||
acc[key] = headers[originalKeys[index]];
|
||||
return acc;
|
||||
}, {});
|
||||
return normalized;
|
||||
};
|
||||
const buildUrlParams = (params, shouldEncode = true) => {
|
||||
if (!params)
|
||||
return null;
|
||||
const output = Object.entries(params).reduce((accumulator, entry) => {
|
||||
const [key, value] = entry;
|
||||
let encodedValue;
|
||||
let item;
|
||||
if (Array.isArray(value)) {
|
||||
item = "";
|
||||
value.forEach((str) => {
|
||||
encodedValue = shouldEncode ? encodeURIComponent(str) : str;
|
||||
item += `${key}=${encodedValue}&`;
|
||||
});
|
||||
item.slice(0, -1);
|
||||
} else {
|
||||
encodedValue = shouldEncode ? encodeURIComponent(value) : value;
|
||||
item = `${key}=${encodedValue}`;
|
||||
}
|
||||
return `${accumulator}&${item}`;
|
||||
}, "");
|
||||
return output.substr(1);
|
||||
};
|
||||
const buildRequestInit = (options, extra = {}) => {
|
||||
const output = Object.assign({ method: options.method || "GET", headers: options.headers }, extra);
|
||||
const headers = normalizeHttpHeaders(options.headers);
|
||||
const type = headers["content-type"] || "";
|
||||
if (typeof options.data === "string") {
|
||||
output.body = options.data;
|
||||
} else if (type.includes("application/x-www-form-urlencoded")) {
|
||||
const params = new URLSearchParams();
|
||||
for (const [key, value] of Object.entries(options.data || {})) {
|
||||
params.set(key, value);
|
||||
}
|
||||
output.body = params.toString();
|
||||
} else if (type.includes("multipart/form-data") || options.data instanceof FormData) {
|
||||
const form = new FormData();
|
||||
if (options.data instanceof FormData) {
|
||||
options.data.forEach((value, key) => {
|
||||
form.append(key, value);
|
||||
});
|
||||
} else {
|
||||
for (const key of Object.keys(options.data)) {
|
||||
form.append(key, options.data[key]);
|
||||
}
|
||||
}
|
||||
output.body = form;
|
||||
const headers2 = new Headers(output.headers);
|
||||
headers2.delete("content-type");
|
||||
output.headers = headers2;
|
||||
} else if (type.includes("application/json") || typeof options.data === "object") {
|
||||
output.body = JSON.stringify(options.data);
|
||||
}
|
||||
return output;
|
||||
};
|
||||
class CapacitorHttpPluginWeb extends WebPlugin {
|
||||
/**
|
||||
* Perform an Http request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async request(options) {
|
||||
const requestInit = buildRequestInit(options, options.webFetchExtra);
|
||||
const urlParams = buildUrlParams(options.params, options.shouldEncodeUrlParams);
|
||||
const url = urlParams ? `${options.url}?${urlParams}` : options.url;
|
||||
const response = await fetch(url, requestInit);
|
||||
const contentType = response.headers.get("content-type") || "";
|
||||
let { responseType = "text" } = response.ok ? options : {};
|
||||
if (contentType.includes("application/json")) {
|
||||
responseType = "json";
|
||||
}
|
||||
let data;
|
||||
let blob;
|
||||
switch (responseType) {
|
||||
case "arraybuffer":
|
||||
case "blob":
|
||||
blob = await response.blob();
|
||||
data = await readBlobAsBase64(blob);
|
||||
break;
|
||||
case "json":
|
||||
data = await response.json();
|
||||
break;
|
||||
case "document":
|
||||
case "text":
|
||||
default:
|
||||
data = await response.text();
|
||||
}
|
||||
const headers = {};
|
||||
response.headers.forEach((value, key) => {
|
||||
headers[key] = value;
|
||||
});
|
||||
return {
|
||||
data,
|
||||
headers,
|
||||
status: response.status,
|
||||
url: response.url
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Perform an Http GET request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async get(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "GET" }));
|
||||
}
|
||||
/**
|
||||
* Perform an Http POST request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async post(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "POST" }));
|
||||
}
|
||||
/**
|
||||
* Perform an Http PUT request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async put(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "PUT" }));
|
||||
}
|
||||
/**
|
||||
* Perform an Http PATCH request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async patch(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "PATCH" }));
|
||||
}
|
||||
/**
|
||||
* Perform an Http DELETE request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async delete(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "DELETE" }));
|
||||
}
|
||||
}
|
||||
registerPlugin("CapacitorHttp", {
|
||||
web: () => new CapacitorHttpPluginWeb()
|
||||
});
|
||||
const SplashScreen = registerPlugin("SplashScreen", {
|
||||
web: () => __vitePreload(() => import("./web-Ce2qnWf_.js"), true ? [] : void 0).then((m) => new m.SplashScreenWeb())
|
||||
});
|
||||
var CameraSource;
|
||||
(function(CameraSource2) {
|
||||
CameraSource2["Prompt"] = "PROMPT";
|
||||
CameraSource2["Camera"] = "CAMERA";
|
||||
CameraSource2["Photos"] = "PHOTOS";
|
||||
})(CameraSource || (CameraSource = {}));
|
||||
var CameraDirection;
|
||||
(function(CameraDirection2) {
|
||||
CameraDirection2["Rear"] = "REAR";
|
||||
CameraDirection2["Front"] = "FRONT";
|
||||
})(CameraDirection || (CameraDirection = {}));
|
||||
var CameraResultType;
|
||||
(function(CameraResultType2) {
|
||||
CameraResultType2["Uri"] = "uri";
|
||||
CameraResultType2["Base64"] = "base64";
|
||||
CameraResultType2["DataUrl"] = "dataUrl";
|
||||
})(CameraResultType || (CameraResultType = {}));
|
||||
class CameraWeb extends WebPlugin {
|
||||
async getPhoto(options) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (options.webUseInput || options.source === CameraSource.Photos) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
} else if (options.source === CameraSource.Prompt) {
|
||||
let actionSheet = document.querySelector("pwa-action-sheet");
|
||||
if (!actionSheet) {
|
||||
actionSheet = document.createElement("pwa-action-sheet");
|
||||
document.body.appendChild(actionSheet);
|
||||
}
|
||||
actionSheet.header = options.promptLabelHeader || "Photo";
|
||||
actionSheet.cancelable = false;
|
||||
actionSheet.options = [
|
||||
{ title: options.promptLabelPhoto || "From Photos" },
|
||||
{ title: options.promptLabelPicture || "Take Picture" }
|
||||
];
|
||||
actionSheet.addEventListener("onSelection", async (e) => {
|
||||
const selection = e.detail;
|
||||
if (selection === 0) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
} else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
async pickImages(_options) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
this.multipleFileInputExperience(resolve, reject);
|
||||
});
|
||||
}
|
||||
async cameraExperience(options, resolve, reject) {
|
||||
if (customElements.get("pwa-camera-modal")) {
|
||||
const cameraModal = document.createElement("pwa-camera-modal");
|
||||
cameraModal.facingMode = options.direction === CameraDirection.Front ? "user" : "environment";
|
||||
document.body.appendChild(cameraModal);
|
||||
try {
|
||||
await cameraModal.componentOnReady();
|
||||
cameraModal.addEventListener("onPhoto", async (e) => {
|
||||
const photo = e.detail;
|
||||
if (photo === null) {
|
||||
reject(new CapacitorException("User cancelled photos app"));
|
||||
} else if (photo instanceof Error) {
|
||||
reject(photo);
|
||||
} else {
|
||||
resolve(await this._getCameraPhoto(photo, options));
|
||||
}
|
||||
cameraModal.dismiss();
|
||||
document.body.removeChild(cameraModal);
|
||||
});
|
||||
cameraModal.present();
|
||||
} catch (e) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
} else {
|
||||
console.error(`Unable to load PWA Element 'pwa-camera-modal'. See the docs: https://capacitorjs.com/docs/web/pwa-elements.`);
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
}
|
||||
fileInputExperience(options, resolve, reject) {
|
||||
let input = document.querySelector("#_capacitor-camera-input");
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement("input");
|
||||
input.id = "_capacitor-camera-input";
|
||||
input.type = "file";
|
||||
input.hidden = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener("change", (_e) => {
|
||||
const file = input.files[0];
|
||||
let format = "jpeg";
|
||||
if (file.type === "image/png") {
|
||||
format = "png";
|
||||
} else if (file.type === "image/gif") {
|
||||
format = "gif";
|
||||
}
|
||||
if (options.resultType === "dataUrl" || options.resultType === "base64") {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener("load", () => {
|
||||
if (options.resultType === "dataUrl") {
|
||||
resolve({
|
||||
dataUrl: reader.result,
|
||||
format
|
||||
});
|
||||
} else if (options.resultType === "base64") {
|
||||
const b64 = reader.result.split(",")[1];
|
||||
resolve({
|
||||
base64String: b64,
|
||||
format
|
||||
});
|
||||
}
|
||||
cleanup();
|
||||
});
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format
|
||||
});
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
input.addEventListener("cancel", (_e) => {
|
||||
reject(new CapacitorException("User cancelled photos app"));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = "image/*";
|
||||
input.capture = true;
|
||||
if (options.source === CameraSource.Photos || options.source === CameraSource.Prompt) {
|
||||
input.removeAttribute("capture");
|
||||
} else if (options.direction === CameraDirection.Front) {
|
||||
input.capture = "user";
|
||||
} else if (options.direction === CameraDirection.Rear) {
|
||||
input.capture = "environment";
|
||||
}
|
||||
input.click();
|
||||
}
|
||||
multipleFileInputExperience(resolve, reject) {
|
||||
let input = document.querySelector("#_capacitor-camera-input-multiple");
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement("input");
|
||||
input.id = "_capacitor-camera-input-multiple";
|
||||
input.type = "file";
|
||||
input.hidden = true;
|
||||
input.multiple = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener("change", (_e) => {
|
||||
const photos = [];
|
||||
for (let i = 0; i < input.files.length; i++) {
|
||||
const file = input.files[i];
|
||||
let format = "jpeg";
|
||||
if (file.type === "image/png") {
|
||||
format = "png";
|
||||
} else if (file.type === "image/gif") {
|
||||
format = "gif";
|
||||
}
|
||||
photos.push({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format
|
||||
});
|
||||
}
|
||||
resolve({ photos });
|
||||
cleanup();
|
||||
});
|
||||
input.addEventListener("cancel", (_e) => {
|
||||
reject(new CapacitorException("User cancelled photos app"));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = "image/*";
|
||||
input.click();
|
||||
}
|
||||
_getCameraPhoto(photo, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
const format = photo.type.split("/")[1];
|
||||
if (options.resultType === "uri") {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(photo),
|
||||
format,
|
||||
saved: false
|
||||
});
|
||||
} else {
|
||||
reader.readAsDataURL(photo);
|
||||
reader.onloadend = () => {
|
||||
const r = reader.result;
|
||||
if (options.resultType === "dataUrl") {
|
||||
resolve({
|
||||
dataUrl: r,
|
||||
format,
|
||||
saved: false
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
base64String: r.split(",")[1],
|
||||
format,
|
||||
saved: false
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.onerror = (e) => {
|
||||
reject(e);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
async checkPermissions() {
|
||||
if (typeof navigator === "undefined" || !navigator.permissions) {
|
||||
throw this.unavailable("Permissions API not available in this browser");
|
||||
}
|
||||
try {
|
||||
const permission = await window.navigator.permissions.query({
|
||||
name: "camera"
|
||||
});
|
||||
return {
|
||||
camera: permission.state,
|
||||
photos: "granted"
|
||||
};
|
||||
} catch (_a) {
|
||||
throw this.unavailable("Camera permissions are not available in this browser");
|
||||
}
|
||||
}
|
||||
async requestPermissions() {
|
||||
throw this.unimplemented("Not implemented on web.");
|
||||
}
|
||||
async pickLimitedLibraryPhotos() {
|
||||
throw this.unavailable("Not implemented on web.");
|
||||
}
|
||||
async getLimitedLibraryPhotos() {
|
||||
throw this.unavailable("Not implemented on web.");
|
||||
}
|
||||
}
|
||||
const Camera = registerPlugin("Camera", {
|
||||
web: () => new CameraWeb()
|
||||
});
|
||||
window.customElements.define(
|
||||
"capacitor-welcome",
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
SplashScreen.hide();
|
||||
const root = this.attachShadow({ mode: "open" });
|
||||
root.innerHTML = `
|
||||
<style>
|
||||
:host {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding: 10px;
|
||||
background-color: #b71b1bff;
|
||||
color: #fff;
|
||||
font-size: 0.9em;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
main {
|
||||
padding: 15px;
|
||||
}
|
||||
main hr { height: 1px; background-color: #eee; border: 0; }
|
||||
main h1 {
|
||||
font-size: 1.4em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
main h2 {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
main h3 {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
main p {
|
||||
color: #333;
|
||||
}
|
||||
main pre {
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<capacitor-welcome-titlebar>
|
||||
<h1>Capacitor</h1>
|
||||
</capacitor-welcome-titlebar>
|
||||
<main>
|
||||
<p>
|
||||
Capacitor makes it easy to build powerful apps for the app stores, mobile web (Progressive Web Apps), and desktop, all
|
||||
with a single code base.
|
||||
</p>
|
||||
<h2>Getting Started</h2>
|
||||
<p>
|
||||
You'll probably need a UI framework to build a full-featured app. Might we recommend
|
||||
<a target="_blank" href="http://ionicframework.com/">Ionic</a>?
|
||||
</p>
|
||||
<p>
|
||||
Visit <a href="https://capacitorjs.com">capacitorjs.com</a> for information
|
||||
on using native features, building plugins, and more.
|
||||
</p>
|
||||
<a href="https://capacitorjs.com" target="_blank" class="button">Read more</a>
|
||||
<h2>Tiny Demo</h2>
|
||||
<p>
|
||||
This demo shows how to call Capacitor plugins. Say cheese!
|
||||
</p>
|
||||
<p>
|
||||
<button class="button" id="take-photo">Take Photo</button>
|
||||
</p>
|
||||
<p>
|
||||
<img id="image" style="max-width: 100%">
|
||||
</p>
|
||||
</main>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
connectedCallback() {
|
||||
const self2 = this;
|
||||
self2.shadowRoot.querySelector("#take-photo").addEventListener("click", async function(e) {
|
||||
try {
|
||||
const photo = await Camera.getPhoto({
|
||||
resultType: "uri"
|
||||
});
|
||||
const image = self2.shadowRoot.querySelector("#image");
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
image.src = photo.webPath;
|
||||
} catch (e2) {
|
||||
console.warn("User cancelled", e2);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
window.customElements.define(
|
||||
"capacitor-welcome-titlebar",
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
const root = this.attachShadow({ mode: "open" });
|
||||
root.innerHTML = `
|
||||
<style>
|
||||
:host {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 15px 15px 15px 15px;
|
||||
text-align: center;
|
||||
background-color: #73B5F6;
|
||||
}
|
||||
::slotted(h1) {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
font-size: 0.9em;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
<slot></slot>
|
||||
`;
|
||||
}
|
||||
}
|
||||
);
|
||||
export {
|
||||
WebPlugin as W
|
||||
};
|
||||
12
dist/assets/index-XN189Hic.css
vendored
Normal file
12
dist/assets/index-XN189Hic.css
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: env(safe-area-inset-top);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
padding-left: env(safe-area-inset-left);
|
||||
padding-right: env(safe-area-inset-right);
|
||||
}
|
||||
13
dist/assets/manifest-RD-sWVQA.json
vendored
Normal file
13
dist/assets/manifest-RD-sWVQA.json
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "App",
|
||||
"short_name": "App",
|
||||
"start_url": "index.html",
|
||||
"display": "standalone",
|
||||
"icons": [{
|
||||
"src": "assets/imgs/logo.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}],
|
||||
"background_color": "#31d53d",
|
||||
"theme_color": "#31d53d"
|
||||
}
|
||||
12
dist/assets/web-Ce2qnWf_.js
vendored
Normal file
12
dist/assets/web-Ce2qnWf_.js
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import { W as WebPlugin } from "./index-CTla4gm7.js";
|
||||
class SplashScreenWeb extends WebPlugin {
|
||||
async show(_options) {
|
||||
return void 0;
|
||||
}
|
||||
async hide(_options) {
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
export {
|
||||
SplashScreenWeb
|
||||
};
|
||||
32
dist/index.html
vendored
Normal file
32
dist/index.html
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
<!doctype html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Awesome Capacitor App</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta name="msapplication-tap-highlight" content="no" />
|
||||
|
||||
<script
|
||||
type="module"
|
||||
src="https://unpkg.com/@ionic/pwa-elements@latest/dist/ionicpwaelements/ionicpwaelements.esm.js"
|
||||
></script>
|
||||
<script
|
||||
nomodule
|
||||
src="https://unpkg.com/@ionic/pwa-elements@latest/dist/ionicpwaelements/ionicpwaelements.js"
|
||||
></script>
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="/assets/favicon-UvKAN7pv.ico" />
|
||||
<link rel="manifest" href="/assets/manifest-RD-sWVQA.json" />
|
||||
<meta name="theme-color" content="#31d53d" />
|
||||
<script type="module" crossorigin src="/assets/index-CTla4gm7.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-XN189Hic.css">
|
||||
</head>
|
||||
<body>
|
||||
<capacitor-welcome></capacitor-welcome>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
16
ios/App/App/capacitor.config.json
Normal file
16
ios/App/App/capacitor.config.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"appId": "so.blockcatcher.app",
|
||||
"appName": "Blockcatcher",
|
||||
"webDir": "dist",
|
||||
"plugins": {
|
||||
"SplashScreen": {
|
||||
"launchAutoHide": false
|
||||
}
|
||||
},
|
||||
"packageClassList": [
|
||||
"CAPCameraPlugin",
|
||||
"GeolocationPlugin",
|
||||
"CapacitorGoogleMapsPlugin",
|
||||
"SplashScreenPlugin"
|
||||
]
|
||||
}
|
||||
6
ios/App/App/config.xml
Normal file
6
ios/App/App/config.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<widget version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||
<access origin="*" />
|
||||
|
||||
|
||||
</widget>
|
||||
BIN
ios/App/App/public/assets/favicon-UvKAN7pv.ico
Normal file
BIN
ios/App/App/public/assets/favicon-UvKAN7pv.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 99 KiB |
959
ios/App/App/public/assets/index-CTla4gm7.js
Normal file
959
ios/App/App/public/assets/index-CTla4gm7.js
Normal file
@@ -0,0 +1,959 @@
|
||||
(function polyfill() {
|
||||
const relList = document.createElement("link").relList;
|
||||
if (relList && relList.supports && relList.supports("modulepreload")) {
|
||||
return;
|
||||
}
|
||||
for (const link of document.querySelectorAll('link[rel="modulepreload"]')) {
|
||||
processPreload(link);
|
||||
}
|
||||
new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type !== "childList") {
|
||||
continue;
|
||||
}
|
||||
for (const node of mutation.addedNodes) {
|
||||
if (node.tagName === "LINK" && node.rel === "modulepreload")
|
||||
processPreload(node);
|
||||
}
|
||||
}
|
||||
}).observe(document, { childList: true, subtree: true });
|
||||
function getFetchOpts(link) {
|
||||
const fetchOpts = {};
|
||||
if (link.integrity) fetchOpts.integrity = link.integrity;
|
||||
if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy;
|
||||
if (link.crossOrigin === "use-credentials")
|
||||
fetchOpts.credentials = "include";
|
||||
else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit";
|
||||
else fetchOpts.credentials = "same-origin";
|
||||
return fetchOpts;
|
||||
}
|
||||
function processPreload(link) {
|
||||
if (link.ep)
|
||||
return;
|
||||
link.ep = true;
|
||||
const fetchOpts = getFetchOpts(link);
|
||||
fetch(link.href, fetchOpts);
|
||||
}
|
||||
})();
|
||||
const scriptRel = "modulepreload";
|
||||
const assetsURL = function(dep) {
|
||||
return "/" + dep;
|
||||
};
|
||||
const seen = {};
|
||||
const __vitePreload = function preload(baseModule, deps, importerUrl) {
|
||||
let promise = Promise.resolve();
|
||||
if (deps && deps.length > 0) {
|
||||
document.getElementsByTagName("link");
|
||||
const cspNonceMeta = document.querySelector(
|
||||
"meta[property=csp-nonce]"
|
||||
);
|
||||
const cspNonce = (cspNonceMeta == null ? void 0 : cspNonceMeta.nonce) || (cspNonceMeta == null ? void 0 : cspNonceMeta.getAttribute("nonce"));
|
||||
promise = Promise.allSettled(
|
||||
deps.map((dep) => {
|
||||
dep = assetsURL(dep);
|
||||
if (dep in seen) return;
|
||||
seen[dep] = true;
|
||||
const isCss = dep.endsWith(".css");
|
||||
const cssSelector = isCss ? '[rel="stylesheet"]' : "";
|
||||
if (document.querySelector(`link[href="${dep}"]${cssSelector}`)) {
|
||||
return;
|
||||
}
|
||||
const link = document.createElement("link");
|
||||
link.rel = isCss ? "stylesheet" : scriptRel;
|
||||
if (!isCss) {
|
||||
link.as = "script";
|
||||
}
|
||||
link.crossOrigin = "";
|
||||
link.href = dep;
|
||||
if (cspNonce) {
|
||||
link.setAttribute("nonce", cspNonce);
|
||||
}
|
||||
document.head.appendChild(link);
|
||||
if (isCss) {
|
||||
return new Promise((res, rej) => {
|
||||
link.addEventListener("load", res);
|
||||
link.addEventListener(
|
||||
"error",
|
||||
() => rej(new Error(`Unable to preload CSS for ${dep}`))
|
||||
);
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
function handlePreloadError(err) {
|
||||
const e = new Event("vite:preloadError", {
|
||||
cancelable: true
|
||||
});
|
||||
e.payload = err;
|
||||
window.dispatchEvent(e);
|
||||
if (!e.defaultPrevented) {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
return promise.then((res) => {
|
||||
for (const item of res || []) {
|
||||
if (item.status !== "rejected") continue;
|
||||
handlePreloadError(item.reason);
|
||||
}
|
||||
return baseModule().catch(handlePreloadError);
|
||||
});
|
||||
};
|
||||
/*! Capacitor: https://capacitorjs.com/ - MIT License */
|
||||
var ExceptionCode;
|
||||
(function(ExceptionCode2) {
|
||||
ExceptionCode2["Unimplemented"] = "UNIMPLEMENTED";
|
||||
ExceptionCode2["Unavailable"] = "UNAVAILABLE";
|
||||
})(ExceptionCode || (ExceptionCode = {}));
|
||||
class CapacitorException extends Error {
|
||||
constructor(message, code, data) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
this.data = data;
|
||||
}
|
||||
}
|
||||
const getPlatformId = (win) => {
|
||||
var _a, _b;
|
||||
if (win === null || win === void 0 ? void 0 : win.androidBridge) {
|
||||
return "android";
|
||||
} else if ((_b = (_a = win === null || win === void 0 ? void 0 : win.webkit) === null || _a === void 0 ? void 0 : _a.messageHandlers) === null || _b === void 0 ? void 0 : _b.bridge) {
|
||||
return "ios";
|
||||
} else {
|
||||
return "web";
|
||||
}
|
||||
};
|
||||
const createCapacitor = (win) => {
|
||||
const capCustomPlatform = win.CapacitorCustomPlatform || null;
|
||||
const cap = win.Capacitor || {};
|
||||
const Plugins = cap.Plugins = cap.Plugins || {};
|
||||
const getPlatform = () => {
|
||||
return capCustomPlatform !== null ? capCustomPlatform.name : getPlatformId(win);
|
||||
};
|
||||
const isNativePlatform = () => getPlatform() !== "web";
|
||||
const isPluginAvailable = (pluginName) => {
|
||||
const plugin = registeredPlugins.get(pluginName);
|
||||
if (plugin === null || plugin === void 0 ? void 0 : plugin.platforms.has(getPlatform())) {
|
||||
return true;
|
||||
}
|
||||
if (getPluginHeader(pluginName)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const getPluginHeader = (pluginName) => {
|
||||
var _a;
|
||||
return (_a = cap.PluginHeaders) === null || _a === void 0 ? void 0 : _a.find((h) => h.name === pluginName);
|
||||
};
|
||||
const handleError = (err) => win.console.error(err);
|
||||
const registeredPlugins = /* @__PURE__ */ new Map();
|
||||
const registerPlugin2 = (pluginName, jsImplementations = {}) => {
|
||||
const registeredPlugin = registeredPlugins.get(pluginName);
|
||||
if (registeredPlugin) {
|
||||
console.warn(`Capacitor plugin "${pluginName}" already registered. Cannot register plugins twice.`);
|
||||
return registeredPlugin.proxy;
|
||||
}
|
||||
const platform = getPlatform();
|
||||
const pluginHeader = getPluginHeader(pluginName);
|
||||
let jsImplementation;
|
||||
const loadPluginImplementation = async () => {
|
||||
if (!jsImplementation && platform in jsImplementations) {
|
||||
jsImplementation = typeof jsImplementations[platform] === "function" ? jsImplementation = await jsImplementations[platform]() : jsImplementation = jsImplementations[platform];
|
||||
} else if (capCustomPlatform !== null && !jsImplementation && "web" in jsImplementations) {
|
||||
jsImplementation = typeof jsImplementations["web"] === "function" ? jsImplementation = await jsImplementations["web"]() : jsImplementation = jsImplementations["web"];
|
||||
}
|
||||
return jsImplementation;
|
||||
};
|
||||
const createPluginMethod = (impl, prop) => {
|
||||
var _a, _b;
|
||||
if (pluginHeader) {
|
||||
const methodHeader = pluginHeader === null || pluginHeader === void 0 ? void 0 : pluginHeader.methods.find((m) => prop === m.name);
|
||||
if (methodHeader) {
|
||||
if (methodHeader.rtype === "promise") {
|
||||
return (options) => cap.nativePromise(pluginName, prop.toString(), options);
|
||||
} else {
|
||||
return (options, callback) => cap.nativeCallback(pluginName, prop.toString(), options, callback);
|
||||
}
|
||||
} else if (impl) {
|
||||
return (_a = impl[prop]) === null || _a === void 0 ? void 0 : _a.bind(impl);
|
||||
}
|
||||
} else if (impl) {
|
||||
return (_b = impl[prop]) === null || _b === void 0 ? void 0 : _b.bind(impl);
|
||||
} else {
|
||||
throw new CapacitorException(`"${pluginName}" plugin is not implemented on ${platform}`, ExceptionCode.Unimplemented);
|
||||
}
|
||||
};
|
||||
const createPluginMethodWrapper = (prop) => {
|
||||
let remove;
|
||||
const wrapper = (...args) => {
|
||||
const p = loadPluginImplementation().then((impl) => {
|
||||
const fn = createPluginMethod(impl, prop);
|
||||
if (fn) {
|
||||
const p2 = fn(...args);
|
||||
remove = p2 === null || p2 === void 0 ? void 0 : p2.remove;
|
||||
return p2;
|
||||
} else {
|
||||
throw new CapacitorException(`"${pluginName}.${prop}()" is not implemented on ${platform}`, ExceptionCode.Unimplemented);
|
||||
}
|
||||
});
|
||||
if (prop === "addListener") {
|
||||
p.remove = async () => remove();
|
||||
}
|
||||
return p;
|
||||
};
|
||||
wrapper.toString = () => `${prop.toString()}() { [capacitor code] }`;
|
||||
Object.defineProperty(wrapper, "name", {
|
||||
value: prop,
|
||||
writable: false,
|
||||
configurable: false
|
||||
});
|
||||
return wrapper;
|
||||
};
|
||||
const addListener = createPluginMethodWrapper("addListener");
|
||||
const removeListener = createPluginMethodWrapper("removeListener");
|
||||
const addListenerNative = (eventName, callback) => {
|
||||
const call = addListener({ eventName }, callback);
|
||||
const remove = async () => {
|
||||
const callbackId = await call;
|
||||
removeListener({
|
||||
eventName,
|
||||
callbackId
|
||||
}, callback);
|
||||
};
|
||||
const p = new Promise((resolve) => call.then(() => resolve({ remove })));
|
||||
p.remove = async () => {
|
||||
console.warn(`Using addListener() without 'await' is deprecated.`);
|
||||
await remove();
|
||||
};
|
||||
return p;
|
||||
};
|
||||
const proxy = new Proxy({}, {
|
||||
get(_, prop) {
|
||||
switch (prop) {
|
||||
case "$$typeof":
|
||||
return void 0;
|
||||
case "toJSON":
|
||||
return () => ({});
|
||||
case "addListener":
|
||||
return pluginHeader ? addListenerNative : addListener;
|
||||
case "removeListener":
|
||||
return removeListener;
|
||||
default:
|
||||
return createPluginMethodWrapper(prop);
|
||||
}
|
||||
}
|
||||
});
|
||||
Plugins[pluginName] = proxy;
|
||||
registeredPlugins.set(pluginName, {
|
||||
name: pluginName,
|
||||
proxy,
|
||||
platforms: /* @__PURE__ */ new Set([...Object.keys(jsImplementations), ...pluginHeader ? [platform] : []])
|
||||
});
|
||||
return proxy;
|
||||
};
|
||||
if (!cap.convertFileSrc) {
|
||||
cap.convertFileSrc = (filePath) => filePath;
|
||||
}
|
||||
cap.getPlatform = getPlatform;
|
||||
cap.handleError = handleError;
|
||||
cap.isNativePlatform = isNativePlatform;
|
||||
cap.isPluginAvailable = isPluginAvailable;
|
||||
cap.registerPlugin = registerPlugin2;
|
||||
cap.Exception = CapacitorException;
|
||||
cap.DEBUG = !!cap.DEBUG;
|
||||
cap.isLoggingEnabled = !!cap.isLoggingEnabled;
|
||||
return cap;
|
||||
};
|
||||
const initCapacitorGlobal = (win) => win.Capacitor = createCapacitor(win);
|
||||
const Capacitor = /* @__PURE__ */ initCapacitorGlobal(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : {});
|
||||
const registerPlugin = Capacitor.registerPlugin;
|
||||
class WebPlugin {
|
||||
constructor() {
|
||||
this.listeners = {};
|
||||
this.retainedEventArguments = {};
|
||||
this.windowListeners = {};
|
||||
}
|
||||
addListener(eventName, listenerFunc) {
|
||||
let firstListener = false;
|
||||
const listeners = this.listeners[eventName];
|
||||
if (!listeners) {
|
||||
this.listeners[eventName] = [];
|
||||
firstListener = true;
|
||||
}
|
||||
this.listeners[eventName].push(listenerFunc);
|
||||
const windowListener = this.windowListeners[eventName];
|
||||
if (windowListener && !windowListener.registered) {
|
||||
this.addWindowListener(windowListener);
|
||||
}
|
||||
if (firstListener) {
|
||||
this.sendRetainedArgumentsForEvent(eventName);
|
||||
}
|
||||
const remove = async () => this.removeListener(eventName, listenerFunc);
|
||||
const p = Promise.resolve({ remove });
|
||||
return p;
|
||||
}
|
||||
async removeAllListeners() {
|
||||
this.listeners = {};
|
||||
for (const listener in this.windowListeners) {
|
||||
this.removeWindowListener(this.windowListeners[listener]);
|
||||
}
|
||||
this.windowListeners = {};
|
||||
}
|
||||
notifyListeners(eventName, data, retainUntilConsumed) {
|
||||
const listeners = this.listeners[eventName];
|
||||
if (!listeners) {
|
||||
if (retainUntilConsumed) {
|
||||
let args = this.retainedEventArguments[eventName];
|
||||
if (!args) {
|
||||
args = [];
|
||||
}
|
||||
args.push(data);
|
||||
this.retainedEventArguments[eventName] = args;
|
||||
}
|
||||
return;
|
||||
}
|
||||
listeners.forEach((listener) => listener(data));
|
||||
}
|
||||
hasListeners(eventName) {
|
||||
var _a;
|
||||
return !!((_a = this.listeners[eventName]) === null || _a === void 0 ? void 0 : _a.length);
|
||||
}
|
||||
registerWindowListener(windowEventName, pluginEventName) {
|
||||
this.windowListeners[pluginEventName] = {
|
||||
registered: false,
|
||||
windowEventName,
|
||||
pluginEventName,
|
||||
handler: (event) => {
|
||||
this.notifyListeners(pluginEventName, event);
|
||||
}
|
||||
};
|
||||
}
|
||||
unimplemented(msg = "not implemented") {
|
||||
return new Capacitor.Exception(msg, ExceptionCode.Unimplemented);
|
||||
}
|
||||
unavailable(msg = "not available") {
|
||||
return new Capacitor.Exception(msg, ExceptionCode.Unavailable);
|
||||
}
|
||||
async removeListener(eventName, listenerFunc) {
|
||||
const listeners = this.listeners[eventName];
|
||||
if (!listeners) {
|
||||
return;
|
||||
}
|
||||
const index = listeners.indexOf(listenerFunc);
|
||||
this.listeners[eventName].splice(index, 1);
|
||||
if (!this.listeners[eventName].length) {
|
||||
this.removeWindowListener(this.windowListeners[eventName]);
|
||||
}
|
||||
}
|
||||
addWindowListener(handle) {
|
||||
window.addEventListener(handle.windowEventName, handle.handler);
|
||||
handle.registered = true;
|
||||
}
|
||||
removeWindowListener(handle) {
|
||||
if (!handle) {
|
||||
return;
|
||||
}
|
||||
window.removeEventListener(handle.windowEventName, handle.handler);
|
||||
handle.registered = false;
|
||||
}
|
||||
sendRetainedArgumentsForEvent(eventName) {
|
||||
const args = this.retainedEventArguments[eventName];
|
||||
if (!args) {
|
||||
return;
|
||||
}
|
||||
delete this.retainedEventArguments[eventName];
|
||||
args.forEach((arg) => {
|
||||
this.notifyListeners(eventName, arg);
|
||||
});
|
||||
}
|
||||
}
|
||||
const encode = (str) => encodeURIComponent(str).replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent).replace(/[()]/g, escape);
|
||||
const decode = (str) => str.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent);
|
||||
class CapacitorCookiesPluginWeb extends WebPlugin {
|
||||
async getCookies() {
|
||||
const cookies = document.cookie;
|
||||
const cookieMap = {};
|
||||
cookies.split(";").forEach((cookie) => {
|
||||
if (cookie.length <= 0)
|
||||
return;
|
||||
let [key, value] = cookie.replace(/=/, "CAP_COOKIE").split("CAP_COOKIE");
|
||||
key = decode(key).trim();
|
||||
value = decode(value).trim();
|
||||
cookieMap[key] = value;
|
||||
});
|
||||
return cookieMap;
|
||||
}
|
||||
async setCookie(options) {
|
||||
try {
|
||||
const encodedKey = encode(options.key);
|
||||
const encodedValue = encode(options.value);
|
||||
const expires = `; expires=${(options.expires || "").replace("expires=", "")}`;
|
||||
const path = (options.path || "/").replace("path=", "");
|
||||
const domain = options.url != null && options.url.length > 0 ? `domain=${options.url}` : "";
|
||||
document.cookie = `${encodedKey}=${encodedValue || ""}${expires}; path=${path}; ${domain};`;
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
async deleteCookie(options) {
|
||||
try {
|
||||
document.cookie = `${options.key}=; Max-Age=0`;
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
async clearCookies() {
|
||||
try {
|
||||
const cookies = document.cookie.split(";") || [];
|
||||
for (const cookie of cookies) {
|
||||
document.cookie = cookie.replace(/^ +/, "").replace(/=.*/, `=;expires=${(/* @__PURE__ */ new Date()).toUTCString()};path=/`);
|
||||
}
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
async clearAllCookies() {
|
||||
try {
|
||||
await this.clearCookies();
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
registerPlugin("CapacitorCookies", {
|
||||
web: () => new CapacitorCookiesPluginWeb()
|
||||
});
|
||||
const readBlobAsBase64 = async (blob) => new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
reader.onload = () => {
|
||||
const base64String = reader.result;
|
||||
resolve(base64String.indexOf(",") >= 0 ? base64String.split(",")[1] : base64String);
|
||||
};
|
||||
reader.onerror = (error) => reject(error);
|
||||
reader.readAsDataURL(blob);
|
||||
});
|
||||
const normalizeHttpHeaders = (headers = {}) => {
|
||||
const originalKeys = Object.keys(headers);
|
||||
const loweredKeys = Object.keys(headers).map((k) => k.toLocaleLowerCase());
|
||||
const normalized = loweredKeys.reduce((acc, key, index) => {
|
||||
acc[key] = headers[originalKeys[index]];
|
||||
return acc;
|
||||
}, {});
|
||||
return normalized;
|
||||
};
|
||||
const buildUrlParams = (params, shouldEncode = true) => {
|
||||
if (!params)
|
||||
return null;
|
||||
const output = Object.entries(params).reduce((accumulator, entry) => {
|
||||
const [key, value] = entry;
|
||||
let encodedValue;
|
||||
let item;
|
||||
if (Array.isArray(value)) {
|
||||
item = "";
|
||||
value.forEach((str) => {
|
||||
encodedValue = shouldEncode ? encodeURIComponent(str) : str;
|
||||
item += `${key}=${encodedValue}&`;
|
||||
});
|
||||
item.slice(0, -1);
|
||||
} else {
|
||||
encodedValue = shouldEncode ? encodeURIComponent(value) : value;
|
||||
item = `${key}=${encodedValue}`;
|
||||
}
|
||||
return `${accumulator}&${item}`;
|
||||
}, "");
|
||||
return output.substr(1);
|
||||
};
|
||||
const buildRequestInit = (options, extra = {}) => {
|
||||
const output = Object.assign({ method: options.method || "GET", headers: options.headers }, extra);
|
||||
const headers = normalizeHttpHeaders(options.headers);
|
||||
const type = headers["content-type"] || "";
|
||||
if (typeof options.data === "string") {
|
||||
output.body = options.data;
|
||||
} else if (type.includes("application/x-www-form-urlencoded")) {
|
||||
const params = new URLSearchParams();
|
||||
for (const [key, value] of Object.entries(options.data || {})) {
|
||||
params.set(key, value);
|
||||
}
|
||||
output.body = params.toString();
|
||||
} else if (type.includes("multipart/form-data") || options.data instanceof FormData) {
|
||||
const form = new FormData();
|
||||
if (options.data instanceof FormData) {
|
||||
options.data.forEach((value, key) => {
|
||||
form.append(key, value);
|
||||
});
|
||||
} else {
|
||||
for (const key of Object.keys(options.data)) {
|
||||
form.append(key, options.data[key]);
|
||||
}
|
||||
}
|
||||
output.body = form;
|
||||
const headers2 = new Headers(output.headers);
|
||||
headers2.delete("content-type");
|
||||
output.headers = headers2;
|
||||
} else if (type.includes("application/json") || typeof options.data === "object") {
|
||||
output.body = JSON.stringify(options.data);
|
||||
}
|
||||
return output;
|
||||
};
|
||||
class CapacitorHttpPluginWeb extends WebPlugin {
|
||||
/**
|
||||
* Perform an Http request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async request(options) {
|
||||
const requestInit = buildRequestInit(options, options.webFetchExtra);
|
||||
const urlParams = buildUrlParams(options.params, options.shouldEncodeUrlParams);
|
||||
const url = urlParams ? `${options.url}?${urlParams}` : options.url;
|
||||
const response = await fetch(url, requestInit);
|
||||
const contentType = response.headers.get("content-type") || "";
|
||||
let { responseType = "text" } = response.ok ? options : {};
|
||||
if (contentType.includes("application/json")) {
|
||||
responseType = "json";
|
||||
}
|
||||
let data;
|
||||
let blob;
|
||||
switch (responseType) {
|
||||
case "arraybuffer":
|
||||
case "blob":
|
||||
blob = await response.blob();
|
||||
data = await readBlobAsBase64(blob);
|
||||
break;
|
||||
case "json":
|
||||
data = await response.json();
|
||||
break;
|
||||
case "document":
|
||||
case "text":
|
||||
default:
|
||||
data = await response.text();
|
||||
}
|
||||
const headers = {};
|
||||
response.headers.forEach((value, key) => {
|
||||
headers[key] = value;
|
||||
});
|
||||
return {
|
||||
data,
|
||||
headers,
|
||||
status: response.status,
|
||||
url: response.url
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Perform an Http GET request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async get(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "GET" }));
|
||||
}
|
||||
/**
|
||||
* Perform an Http POST request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async post(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "POST" }));
|
||||
}
|
||||
/**
|
||||
* Perform an Http PUT request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async put(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "PUT" }));
|
||||
}
|
||||
/**
|
||||
* Perform an Http PATCH request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async patch(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "PATCH" }));
|
||||
}
|
||||
/**
|
||||
* Perform an Http DELETE request given a set of options
|
||||
* @param options Options to build the HTTP request
|
||||
*/
|
||||
async delete(options) {
|
||||
return this.request(Object.assign(Object.assign({}, options), { method: "DELETE" }));
|
||||
}
|
||||
}
|
||||
registerPlugin("CapacitorHttp", {
|
||||
web: () => new CapacitorHttpPluginWeb()
|
||||
});
|
||||
const SplashScreen = registerPlugin("SplashScreen", {
|
||||
web: () => __vitePreload(() => import("./web-Ce2qnWf_.js"), true ? [] : void 0).then((m) => new m.SplashScreenWeb())
|
||||
});
|
||||
var CameraSource;
|
||||
(function(CameraSource2) {
|
||||
CameraSource2["Prompt"] = "PROMPT";
|
||||
CameraSource2["Camera"] = "CAMERA";
|
||||
CameraSource2["Photos"] = "PHOTOS";
|
||||
})(CameraSource || (CameraSource = {}));
|
||||
var CameraDirection;
|
||||
(function(CameraDirection2) {
|
||||
CameraDirection2["Rear"] = "REAR";
|
||||
CameraDirection2["Front"] = "FRONT";
|
||||
})(CameraDirection || (CameraDirection = {}));
|
||||
var CameraResultType;
|
||||
(function(CameraResultType2) {
|
||||
CameraResultType2["Uri"] = "uri";
|
||||
CameraResultType2["Base64"] = "base64";
|
||||
CameraResultType2["DataUrl"] = "dataUrl";
|
||||
})(CameraResultType || (CameraResultType = {}));
|
||||
class CameraWeb extends WebPlugin {
|
||||
async getPhoto(options) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (options.webUseInput || options.source === CameraSource.Photos) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
} else if (options.source === CameraSource.Prompt) {
|
||||
let actionSheet = document.querySelector("pwa-action-sheet");
|
||||
if (!actionSheet) {
|
||||
actionSheet = document.createElement("pwa-action-sheet");
|
||||
document.body.appendChild(actionSheet);
|
||||
}
|
||||
actionSheet.header = options.promptLabelHeader || "Photo";
|
||||
actionSheet.cancelable = false;
|
||||
actionSheet.options = [
|
||||
{ title: options.promptLabelPhoto || "From Photos" },
|
||||
{ title: options.promptLabelPicture || "Take Picture" }
|
||||
];
|
||||
actionSheet.addEventListener("onSelection", async (e) => {
|
||||
const selection = e.detail;
|
||||
if (selection === 0) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
} else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
async pickImages(_options) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
this.multipleFileInputExperience(resolve, reject);
|
||||
});
|
||||
}
|
||||
async cameraExperience(options, resolve, reject) {
|
||||
if (customElements.get("pwa-camera-modal")) {
|
||||
const cameraModal = document.createElement("pwa-camera-modal");
|
||||
cameraModal.facingMode = options.direction === CameraDirection.Front ? "user" : "environment";
|
||||
document.body.appendChild(cameraModal);
|
||||
try {
|
||||
await cameraModal.componentOnReady();
|
||||
cameraModal.addEventListener("onPhoto", async (e) => {
|
||||
const photo = e.detail;
|
||||
if (photo === null) {
|
||||
reject(new CapacitorException("User cancelled photos app"));
|
||||
} else if (photo instanceof Error) {
|
||||
reject(photo);
|
||||
} else {
|
||||
resolve(await this._getCameraPhoto(photo, options));
|
||||
}
|
||||
cameraModal.dismiss();
|
||||
document.body.removeChild(cameraModal);
|
||||
});
|
||||
cameraModal.present();
|
||||
} catch (e) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
} else {
|
||||
console.error(`Unable to load PWA Element 'pwa-camera-modal'. See the docs: https://capacitorjs.com/docs/web/pwa-elements.`);
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
}
|
||||
fileInputExperience(options, resolve, reject) {
|
||||
let input = document.querySelector("#_capacitor-camera-input");
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement("input");
|
||||
input.id = "_capacitor-camera-input";
|
||||
input.type = "file";
|
||||
input.hidden = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener("change", (_e) => {
|
||||
const file = input.files[0];
|
||||
let format = "jpeg";
|
||||
if (file.type === "image/png") {
|
||||
format = "png";
|
||||
} else if (file.type === "image/gif") {
|
||||
format = "gif";
|
||||
}
|
||||
if (options.resultType === "dataUrl" || options.resultType === "base64") {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener("load", () => {
|
||||
if (options.resultType === "dataUrl") {
|
||||
resolve({
|
||||
dataUrl: reader.result,
|
||||
format
|
||||
});
|
||||
} else if (options.resultType === "base64") {
|
||||
const b64 = reader.result.split(",")[1];
|
||||
resolve({
|
||||
base64String: b64,
|
||||
format
|
||||
});
|
||||
}
|
||||
cleanup();
|
||||
});
|
||||
reader.readAsDataURL(file);
|
||||
} else {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format
|
||||
});
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
input.addEventListener("cancel", (_e) => {
|
||||
reject(new CapacitorException("User cancelled photos app"));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = "image/*";
|
||||
input.capture = true;
|
||||
if (options.source === CameraSource.Photos || options.source === CameraSource.Prompt) {
|
||||
input.removeAttribute("capture");
|
||||
} else if (options.direction === CameraDirection.Front) {
|
||||
input.capture = "user";
|
||||
} else if (options.direction === CameraDirection.Rear) {
|
||||
input.capture = "environment";
|
||||
}
|
||||
input.click();
|
||||
}
|
||||
multipleFileInputExperience(resolve, reject) {
|
||||
let input = document.querySelector("#_capacitor-camera-input-multiple");
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement("input");
|
||||
input.id = "_capacitor-camera-input-multiple";
|
||||
input.type = "file";
|
||||
input.hidden = true;
|
||||
input.multiple = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener("change", (_e) => {
|
||||
const photos = [];
|
||||
for (let i = 0; i < input.files.length; i++) {
|
||||
const file = input.files[i];
|
||||
let format = "jpeg";
|
||||
if (file.type === "image/png") {
|
||||
format = "png";
|
||||
} else if (file.type === "image/gif") {
|
||||
format = "gif";
|
||||
}
|
||||
photos.push({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format
|
||||
});
|
||||
}
|
||||
resolve({ photos });
|
||||
cleanup();
|
||||
});
|
||||
input.addEventListener("cancel", (_e) => {
|
||||
reject(new CapacitorException("User cancelled photos app"));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = "image/*";
|
||||
input.click();
|
||||
}
|
||||
_getCameraPhoto(photo, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
const format = photo.type.split("/")[1];
|
||||
if (options.resultType === "uri") {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(photo),
|
||||
format,
|
||||
saved: false
|
||||
});
|
||||
} else {
|
||||
reader.readAsDataURL(photo);
|
||||
reader.onloadend = () => {
|
||||
const r = reader.result;
|
||||
if (options.resultType === "dataUrl") {
|
||||
resolve({
|
||||
dataUrl: r,
|
||||
format,
|
||||
saved: false
|
||||
});
|
||||
} else {
|
||||
resolve({
|
||||
base64String: r.split(",")[1],
|
||||
format,
|
||||
saved: false
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.onerror = (e) => {
|
||||
reject(e);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
async checkPermissions() {
|
||||
if (typeof navigator === "undefined" || !navigator.permissions) {
|
||||
throw this.unavailable("Permissions API not available in this browser");
|
||||
}
|
||||
try {
|
||||
const permission = await window.navigator.permissions.query({
|
||||
name: "camera"
|
||||
});
|
||||
return {
|
||||
camera: permission.state,
|
||||
photos: "granted"
|
||||
};
|
||||
} catch (_a) {
|
||||
throw this.unavailable("Camera permissions are not available in this browser");
|
||||
}
|
||||
}
|
||||
async requestPermissions() {
|
||||
throw this.unimplemented("Not implemented on web.");
|
||||
}
|
||||
async pickLimitedLibraryPhotos() {
|
||||
throw this.unavailable("Not implemented on web.");
|
||||
}
|
||||
async getLimitedLibraryPhotos() {
|
||||
throw this.unavailable("Not implemented on web.");
|
||||
}
|
||||
}
|
||||
const Camera = registerPlugin("Camera", {
|
||||
web: () => new CameraWeb()
|
||||
});
|
||||
window.customElements.define(
|
||||
"capacitor-welcome",
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
SplashScreen.hide();
|
||||
const root = this.attachShadow({ mode: "open" });
|
||||
root.innerHTML = `
|
||||
<style>
|
||||
:host {
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5 {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.button {
|
||||
display: inline-block;
|
||||
padding: 10px;
|
||||
background-color: #b71b1bff;
|
||||
color: #fff;
|
||||
font-size: 0.9em;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
text-decoration: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
main {
|
||||
padding: 15px;
|
||||
}
|
||||
main hr { height: 1px; background-color: #eee; border: 0; }
|
||||
main h1 {
|
||||
font-size: 1.4em;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
main h2 {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
main h3 {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
main p {
|
||||
color: #333;
|
||||
}
|
||||
main pre {
|
||||
white-space: pre-line;
|
||||
}
|
||||
</style>
|
||||
<div>
|
||||
<capacitor-welcome-titlebar>
|
||||
<h1>Capacitor</h1>
|
||||
</capacitor-welcome-titlebar>
|
||||
<main>
|
||||
<p>
|
||||
Capacitor makes it easy to build powerful apps for the app stores, mobile web (Progressive Web Apps), and desktop, all
|
||||
with a single code base.
|
||||
</p>
|
||||
<h2>Getting Started</h2>
|
||||
<p>
|
||||
You'll probably need a UI framework to build a full-featured app. Might we recommend
|
||||
<a target="_blank" href="http://ionicframework.com/">Ionic</a>?
|
||||
</p>
|
||||
<p>
|
||||
Visit <a href="https://capacitorjs.com">capacitorjs.com</a> for information
|
||||
on using native features, building plugins, and more.
|
||||
</p>
|
||||
<a href="https://capacitorjs.com" target="_blank" class="button">Read more</a>
|
||||
<h2>Tiny Demo</h2>
|
||||
<p>
|
||||
This demo shows how to call Capacitor plugins. Say cheese!
|
||||
</p>
|
||||
<p>
|
||||
<button class="button" id="take-photo">Take Photo</button>
|
||||
</p>
|
||||
<p>
|
||||
<img id="image" style="max-width: 100%">
|
||||
</p>
|
||||
</main>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
connectedCallback() {
|
||||
const self2 = this;
|
||||
self2.shadowRoot.querySelector("#take-photo").addEventListener("click", async function(e) {
|
||||
try {
|
||||
const photo = await Camera.getPhoto({
|
||||
resultType: "uri"
|
||||
});
|
||||
const image = self2.shadowRoot.querySelector("#image");
|
||||
if (!image) {
|
||||
return;
|
||||
}
|
||||
image.src = photo.webPath;
|
||||
} catch (e2) {
|
||||
console.warn("User cancelled", e2);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
);
|
||||
window.customElements.define(
|
||||
"capacitor-welcome-titlebar",
|
||||
class extends HTMLElement {
|
||||
constructor() {
|
||||
super();
|
||||
const root = this.attachShadow({ mode: "open" });
|
||||
root.innerHTML = `
|
||||
<style>
|
||||
:host {
|
||||
position: relative;
|
||||
display: block;
|
||||
padding: 15px 15px 15px 15px;
|
||||
text-align: center;
|
||||
background-color: #73B5F6;
|
||||
}
|
||||
::slotted(h1) {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||
font-size: 0.9em;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
||||
<slot></slot>
|
||||
`;
|
||||
}
|
||||
}
|
||||
);
|
||||
export {
|
||||
WebPlugin as W
|
||||
};
|
||||
12
ios/App/App/public/assets/index-XN189Hic.css
Normal file
12
ios/App/App/public/assets/index-XN189Hic.css
Normal file
@@ -0,0 +1,12 @@
|
||||
html,
|
||||
body {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
body {
|
||||
padding-top: env(safe-area-inset-top);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
padding-left: env(safe-area-inset-left);
|
||||
padding-right: env(safe-area-inset-right);
|
||||
}
|
||||
13
ios/App/App/public/assets/manifest-RD-sWVQA.json
Normal file
13
ios/App/App/public/assets/manifest-RD-sWVQA.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"name": "App",
|
||||
"short_name": "App",
|
||||
"start_url": "index.html",
|
||||
"display": "standalone",
|
||||
"icons": [{
|
||||
"src": "assets/imgs/logo.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}],
|
||||
"background_color": "#31d53d",
|
||||
"theme_color": "#31d53d"
|
||||
}
|
||||
12
ios/App/App/public/assets/web-Ce2qnWf_.js
Normal file
12
ios/App/App/public/assets/web-Ce2qnWf_.js
Normal file
@@ -0,0 +1,12 @@
|
||||
import { W as WebPlugin } from "./index-CTla4gm7.js";
|
||||
class SplashScreenWeb extends WebPlugin {
|
||||
async show(_options) {
|
||||
return void 0;
|
||||
}
|
||||
async hide(_options) {
|
||||
return void 0;
|
||||
}
|
||||
}
|
||||
export {
|
||||
SplashScreenWeb
|
||||
};
|
||||
0
ios/App/App/public/cordova.js
vendored
Normal file
0
ios/App/App/public/cordova.js
vendored
Normal file
0
ios/App/App/public/cordova_plugins.js
vendored
Normal file
0
ios/App/App/public/cordova_plugins.js
vendored
Normal file
32
ios/App/App/public/index.html
Normal file
32
ios/App/App/public/index.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!doctype html>
|
||||
<html lang="en" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Awesome Capacitor App</title>
|
||||
<meta
|
||||
name="viewport"
|
||||
content="viewport-fit=cover, width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||
/>
|
||||
<meta name="format-detection" content="telephone=no" />
|
||||
<meta name="msapplication-tap-highlight" content="no" />
|
||||
|
||||
<script
|
||||
type="module"
|
||||
src="https://unpkg.com/@ionic/pwa-elements@latest/dist/ionicpwaelements/ionicpwaelements.esm.js"
|
||||
></script>
|
||||
<script
|
||||
nomodule
|
||||
src="https://unpkg.com/@ionic/pwa-elements@latest/dist/ionicpwaelements/ionicpwaelements.js"
|
||||
></script>
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="/assets/favicon-UvKAN7pv.ico" />
|
||||
<link rel="manifest" href="/assets/manifest-RD-sWVQA.json" />
|
||||
<meta name="theme-color" content="#31d53d" />
|
||||
<script type="module" crossorigin src="/assets/index-CTla4gm7.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-XN189Hic.css">
|
||||
</head>
|
||||
<body>
|
||||
<capacitor-welcome></capacitor-welcome>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
16
ios/capacitor-cordova-ios-plugins/CordovaPlugins.podspec
Normal file
16
ios/capacitor-cordova-ios-plugins/CordovaPlugins.podspec
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'CordovaPlugins'
|
||||
s.version = '7.4.4'
|
||||
s.summary = 'Autogenerated spec'
|
||||
s.license = 'Unknown'
|
||||
s.homepage = 'https://example.com'
|
||||
s.authors = { 'Capacitor Generator' => 'hi@example.com' }
|
||||
s.source = { :git => 'https://github.com/ionic-team/does-not-exist.git', :tag => '7.4.4' }
|
||||
s.source_files = 'sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
||||
s.ios.deployment_target = '14.0'
|
||||
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1 WK_WEB_VIEW_ONLY=1' }
|
||||
s.dependency 'CapacitorCordova'
|
||||
s.swift_version = '5.1'
|
||||
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'CordovaPluginsResources'
|
||||
s.version = '0.0.105'
|
||||
s.summary = 'Resources for Cordova plugins'
|
||||
s.license = 'MIT'
|
||||
s.homepage = 'https://capacitorjs.com/'
|
||||
s.authors = { 'Ionic Team' => 'hi@ionicframework.com' }
|
||||
s.source = { :git => 'https://github.com/ionic-team/capacitor.git', :tag => s.version.to_s }
|
||||
s.resources = ['resources/*']
|
||||
end
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'CordovaPluginsStatic'
|
||||
s.version = '7.4.4'
|
||||
s.summary = 'Autogenerated spec'
|
||||
s.license = 'Unknown'
|
||||
s.homepage = 'https://example.com'
|
||||
s.authors = { 'Capacitor Generator' => 'hi@example.com' }
|
||||
s.source = { :git => 'https://github.com/ionic-team/does-not-exist.git', :tag => '7.4.4' }
|
||||
s.source_files = 'sourcesstatic/**/*.{swift,h,m,c,cc,mm,cpp}'
|
||||
s.ios.deployment_target = '14.0'
|
||||
s.xcconfig = {'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1 WK_WEB_VIEW_ONLY=1' }
|
||||
s.dependency 'CapacitorCordova'
|
||||
s.swift_version = '5.1'
|
||||
s.static_framework = true
|
||||
end
|
||||
1
ios/capacitor-cordova-ios-plugins/resources/.gitkeep
Normal file
1
ios/capacitor-cordova-ios-plugins/resources/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
1
ios/capacitor-cordova-ios-plugins/sources/.gitkeep
Normal file
1
ios/capacitor-cordova-ios-plugins/sources/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
1
node_modules/.bin/cap
generated
vendored
Symbolic link
1
node_modules/.bin/cap
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../@capacitor/cli/bin/capacitor
|
||||
1
node_modules/.bin/capacitor
generated
vendored
Symbolic link
1
node_modules/.bin/capacitor
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../@capacitor/cli/bin/capacitor
|
||||
1
node_modules/.bin/esbuild
generated
vendored
Symbolic link
1
node_modules/.bin/esbuild
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../esbuild/bin/esbuild
|
||||
1
node_modules/.bin/glob
generated
vendored
Symbolic link
1
node_modules/.bin/glob
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../glob/dist/esm/bin.mjs
|
||||
1
node_modules/.bin/is-docker
generated
vendored
Symbolic link
1
node_modules/.bin/is-docker
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../is-docker/cli.js
|
||||
1
node_modules/.bin/mkdirp
generated
vendored
Symbolic link
1
node_modules/.bin/mkdirp
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../mkdirp/bin/cmd.js
|
||||
1
node_modules/.bin/nanoid
generated
vendored
Symbolic link
1
node_modules/.bin/nanoid
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../nanoid/bin/nanoid.cjs
|
||||
1
node_modules/.bin/native-run
generated
vendored
Symbolic link
1
node_modules/.bin/native-run
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../native-run/bin/native-run
|
||||
1
node_modules/.bin/node-which
generated
vendored
Symbolic link
1
node_modules/.bin/node-which
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../which/bin/node-which
|
||||
1
node_modules/.bin/rimraf
generated
vendored
Symbolic link
1
node_modules/.bin/rimraf
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../rimraf/dist/esm/bin.mjs
|
||||
1
node_modules/.bin/rollup
generated
vendored
Symbolic link
1
node_modules/.bin/rollup
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../rollup/dist/bin/rollup
|
||||
1
node_modules/.bin/semver
generated
vendored
Symbolic link
1
node_modules/.bin/semver
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../semver/bin/semver.js
|
||||
1
node_modules/.bin/tree-kill
generated
vendored
Symbolic link
1
node_modules/.bin/tree-kill
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../tree-kill/cli.js
|
||||
1
node_modules/.bin/vite
generated
vendored
Symbolic link
1
node_modules/.bin/vite
generated
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../vite/bin/vite.js
|
||||
1633
node_modules/.package-lock.json
generated
vendored
Normal file
1633
node_modules/.package-lock.json
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
node_modules/.vite/deps/_metadata.json
generated
vendored
Normal file
8
node_modules/.vite/deps/_metadata.json
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"hash": "f83f3e32",
|
||||
"configHash": "26c357e2",
|
||||
"lockfileHash": "b09a1382",
|
||||
"browserHash": "049b0783",
|
||||
"optimized": {},
|
||||
"chunks": {}
|
||||
}
|
||||
3
node_modules/.vite/deps/package.json
generated
vendored
Normal file
3
node_modules/.vite/deps/package.json
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"type": "module"
|
||||
}
|
||||
17
node_modules/@capacitor/camera/CapacitorCamera.podspec
generated
vendored
Normal file
17
node_modules/@capacitor/camera/CapacitorCamera.podspec
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
require 'json'
|
||||
|
||||
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
||||
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'CapacitorCamera'
|
||||
s.version = package['version']
|
||||
s.summary = package['description']
|
||||
s.license = package['license']
|
||||
s.homepage = 'https://capacitorjs.com'
|
||||
s.author = package['author']
|
||||
s.source = { :git => 'https://github.com/ionic-team/capacitor-plugins.git', :tag => package['name'] + '@' + package['version'] }
|
||||
s.source_files = 'ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}', 'camera/ios/Sources/**/*.{swift,h,m,c,cc,mm,cpp}'
|
||||
s.ios.deployment_target = '14.0'
|
||||
s.dependency 'Capacitor'
|
||||
s.swift_version = '5.1'
|
||||
end
|
||||
23
node_modules/@capacitor/camera/LICENSE
generated
vendored
Normal file
23
node_modules/@capacitor/camera/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
Copyright 2020-present Ionic
|
||||
https://ionic.io
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
28
node_modules/@capacitor/camera/Package.swift
generated
vendored
Normal file
28
node_modules/@capacitor/camera/Package.swift
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
// swift-tools-version: 5.9
|
||||
import PackageDescription
|
||||
|
||||
let package = Package(
|
||||
name: "CapacitorCamera",
|
||||
platforms: [.iOS(.v14)],
|
||||
products: [
|
||||
.library(
|
||||
name: "CapacitorCamera",
|
||||
targets: ["CameraPlugin"])
|
||||
],
|
||||
dependencies: [
|
||||
.package(url: "https://github.com/ionic-team/capacitor-swift-pm.git", from: "7.0.0")
|
||||
],
|
||||
targets: [
|
||||
.target(
|
||||
name: "CameraPlugin",
|
||||
dependencies: [
|
||||
.product(name: "Capacitor", package: "capacitor-swift-pm"),
|
||||
.product(name: "Cordova", package: "capacitor-swift-pm")
|
||||
],
|
||||
path: "ios/Sources/CameraPlugin"),
|
||||
.testTarget(
|
||||
name: "CameraPluginTests",
|
||||
dependencies: ["CameraPlugin"],
|
||||
path: "ios/Tests/CameraPluginTests")
|
||||
]
|
||||
)
|
||||
353
node_modules/@capacitor/camera/README.md
generated
vendored
Normal file
353
node_modules/@capacitor/camera/README.md
generated
vendored
Normal file
@@ -0,0 +1,353 @@
|
||||
# @capacitor/camera
|
||||
|
||||
The Camera API provides the ability to take a photo with the camera or choose an existing one from the photo album.
|
||||
|
||||
## Install
|
||||
|
||||
```bash
|
||||
npm install @capacitor/camera
|
||||
npx cap sync
|
||||
```
|
||||
|
||||
## iOS
|
||||
|
||||
iOS requires the following usage description be added and filled out for your app in `Info.plist`:
|
||||
|
||||
- `NSCameraUsageDescription` (`Privacy - Camera Usage Description`)
|
||||
- `NSPhotoLibraryAddUsageDescription` (`Privacy - Photo Library Additions Usage Description`)
|
||||
- `NSPhotoLibraryUsageDescription` (`Privacy - Photo Library Usage Description`)
|
||||
|
||||
Read about [Configuring `Info.plist`](https://capacitorjs.com/docs/ios/configuration#configuring-infoplist) in the [iOS Guide](https://capacitorjs.com/docs/ios) for more information on setting iOS permissions in Xcode
|
||||
|
||||
## Android
|
||||
|
||||
When picking existing images from the device gallery, the Android Photo Picker component is now used. The Photo Picker is available on devices that meet the following criteria:
|
||||
|
||||
- Run Android 11 (API level 30) or higher
|
||||
- Receive changes to Modular System Components through Google System Updates
|
||||
|
||||
Older devices and Android Go devices running Android 11 or 12 that support Google Play services can install a backported version of the photo picker. To enable the automatic installation of the backported photo picker module through Google Play services, add the following entry to the `<application>` tag in your `AndroidManifest.xml` file:
|
||||
|
||||
```xml
|
||||
<!-- Trigger Google Play services to install the backported photo picker module. -->
|
||||
<!--suppress AndroidDomInspection -->
|
||||
<service android:name="com.google.android.gms.metadata.ModuleDependencies"
|
||||
android:enabled="false"
|
||||
android:exported="false"
|
||||
tools:ignore="MissingClass">
|
||||
<intent-filter>
|
||||
<action android:name="com.google.android.gms.metadata.MODULE_DEPENDENCIES" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="photopicker_activity:0:required" android:value="" />
|
||||
</service>
|
||||
```
|
||||
|
||||
If that entry is not added, the devices that don't support the Photo Picker, the Photo Picker component fallbacks to `Intent.ACTION_OPEN_DOCUMENT`.
|
||||
|
||||
The Camera plugin requires no permissions, unless using `saveToGallery: true`, in that case the following permissions should be added to your `AndroidManifest.xml`:
|
||||
|
||||
```xml
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
```
|
||||
|
||||
You can also specify those permissions only for the Android versions where they will be requested:
|
||||
|
||||
```xml
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29"/>
|
||||
```
|
||||
|
||||
The storage permissions are for reading/saving photo files.
|
||||
|
||||
Read about [Setting Permissions](https://capacitorjs.com/docs/android/configuration#setting-permissions) in the [Android Guide](https://capacitorjs.com/docs/android) for more information on setting Android permissions.
|
||||
|
||||
Additionally, because the Camera API launches a separate Activity to handle taking the photo, you should listen for `appRestoredResult` in the `App` plugin to handle any camera data that was sent in the case your app was terminated by the operating system while the Activity was running.
|
||||
|
||||
### Variables
|
||||
|
||||
This plugin will use the following project variables (defined in your app's `variables.gradle` file):
|
||||
|
||||
- `androidxExifInterfaceVersion`: version of `androidx.exifinterface:exifinterface` (default: `1.3.7`)
|
||||
- `androidxMaterialVersion`: version of `com.google.android.material:material` (default: `1.12.0`)
|
||||
|
||||
## PWA Notes
|
||||
|
||||
[PWA Elements](https://capacitorjs.com/docs/web/pwa-elements) are required for Camera plugin to work.
|
||||
|
||||
## Example
|
||||
|
||||
```typescript
|
||||
import { Camera, CameraResultType } from '@capacitor/camera';
|
||||
|
||||
const takePicture = async () => {
|
||||
const image = await Camera.getPhoto({
|
||||
quality: 90,
|
||||
allowEditing: true,
|
||||
resultType: CameraResultType.Uri
|
||||
});
|
||||
|
||||
// image.webPath will contain a path that can be set as an image src.
|
||||
// You can access the original file using image.path, which can be
|
||||
// passed to the Filesystem API to read the raw data of the image,
|
||||
// if desired (or pass resultType: CameraResultType.Base64 to getPhoto)
|
||||
var imageUrl = image.webPath;
|
||||
|
||||
// Can be set to the src of an image now
|
||||
imageElement.src = imageUrl;
|
||||
};
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
<docgen-index>
|
||||
|
||||
* [`getPhoto(...)`](#getphoto)
|
||||
* [`pickImages(...)`](#pickimages)
|
||||
* [`pickLimitedLibraryPhotos()`](#picklimitedlibraryphotos)
|
||||
* [`getLimitedLibraryPhotos()`](#getlimitedlibraryphotos)
|
||||
* [`checkPermissions()`](#checkpermissions)
|
||||
* [`requestPermissions(...)`](#requestpermissions)
|
||||
* [Interfaces](#interfaces)
|
||||
* [Type Aliases](#type-aliases)
|
||||
* [Enums](#enums)
|
||||
|
||||
</docgen-index>
|
||||
|
||||
<docgen-api>
|
||||
<!--Update the source file JSDoc comments and rerun docgen to update the docs below-->
|
||||
|
||||
### getPhoto(...)
|
||||
|
||||
```typescript
|
||||
getPhoto(options: ImageOptions) => Promise<Photo>
|
||||
```
|
||||
|
||||
Prompt the user to pick a photo from an album, or take a new photo
|
||||
with the camera.
|
||||
|
||||
| Param | Type |
|
||||
| ------------- | ----------------------------------------------------- |
|
||||
| **`options`** | <code><a href="#imageoptions">ImageOptions</a></code> |
|
||||
|
||||
**Returns:** <code>Promise<<a href="#photo">Photo</a>></code>
|
||||
|
||||
**Since:** 1.0.0
|
||||
|
||||
--------------------
|
||||
|
||||
|
||||
### pickImages(...)
|
||||
|
||||
```typescript
|
||||
pickImages(options: GalleryImageOptions) => Promise<GalleryPhotos>
|
||||
```
|
||||
|
||||
Allows the user to pick multiple pictures from the photo gallery.
|
||||
On iOS 13 and older it only allows to pick one picture.
|
||||
|
||||
| Param | Type |
|
||||
| ------------- | ------------------------------------------------------------------- |
|
||||
| **`options`** | <code><a href="#galleryimageoptions">GalleryImageOptions</a></code> |
|
||||
|
||||
**Returns:** <code>Promise<<a href="#galleryphotos">GalleryPhotos</a>></code>
|
||||
|
||||
**Since:** 1.2.0
|
||||
|
||||
--------------------
|
||||
|
||||
|
||||
### pickLimitedLibraryPhotos()
|
||||
|
||||
```typescript
|
||||
pickLimitedLibraryPhotos() => Promise<GalleryPhotos>
|
||||
```
|
||||
|
||||
iOS 14+ Only: Allows the user to update their limited photo library selection.
|
||||
On iOS 15+ returns all the limited photos after the picker dismissal.
|
||||
On iOS 14 or if the user gave full access to the photos it returns an empty array.
|
||||
|
||||
**Returns:** <code>Promise<<a href="#galleryphotos">GalleryPhotos</a>></code>
|
||||
|
||||
**Since:** 4.1.0
|
||||
|
||||
--------------------
|
||||
|
||||
|
||||
### getLimitedLibraryPhotos()
|
||||
|
||||
```typescript
|
||||
getLimitedLibraryPhotos() => Promise<GalleryPhotos>
|
||||
```
|
||||
|
||||
iOS 14+ Only: Return an array of photos selected from the limited photo library.
|
||||
|
||||
**Returns:** <code>Promise<<a href="#galleryphotos">GalleryPhotos</a>></code>
|
||||
|
||||
**Since:** 4.1.0
|
||||
|
||||
--------------------
|
||||
|
||||
|
||||
### checkPermissions()
|
||||
|
||||
```typescript
|
||||
checkPermissions() => Promise<PermissionStatus>
|
||||
```
|
||||
|
||||
Check camera and photo album permissions
|
||||
|
||||
**Returns:** <code>Promise<<a href="#permissionstatus">PermissionStatus</a>></code>
|
||||
|
||||
**Since:** 1.0.0
|
||||
|
||||
--------------------
|
||||
|
||||
|
||||
### requestPermissions(...)
|
||||
|
||||
```typescript
|
||||
requestPermissions(permissions?: CameraPluginPermissions | undefined) => Promise<PermissionStatus>
|
||||
```
|
||||
|
||||
Request camera and photo album permissions
|
||||
|
||||
| Param | Type |
|
||||
| ----------------- | --------------------------------------------------------------------------- |
|
||||
| **`permissions`** | <code><a href="#camerapluginpermissions">CameraPluginPermissions</a></code> |
|
||||
|
||||
**Returns:** <code>Promise<<a href="#permissionstatus">PermissionStatus</a>></code>
|
||||
|
||||
**Since:** 1.0.0
|
||||
|
||||
--------------------
|
||||
|
||||
|
||||
### Interfaces
|
||||
|
||||
|
||||
#### Photo
|
||||
|
||||
| Prop | Type | Description | Since |
|
||||
| ------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----- |
|
||||
| **`base64String`** | <code>string</code> | The base64 encoded string representation of the image, if using <a href="#cameraresulttype">CameraResultType.Base64</a>. | 1.0.0 |
|
||||
| **`dataUrl`** | <code>string</code> | The url starting with 'data:image/jpeg;base64,' and the base64 encoded string representation of the image, if using <a href="#cameraresulttype">CameraResultType.DataUrl</a>. Note: On web, the file format could change depending on the browser. | 1.0.0 |
|
||||
| **`path`** | <code>string</code> | If using <a href="#cameraresulttype">CameraResultType.Uri</a>, the path will contain a full, platform-specific file URL that can be read later using the Filesystem API. | 1.0.0 |
|
||||
| **`webPath`** | <code>string</code> | webPath returns a path that can be used to set the src attribute of an image for efficient loading and rendering. | 1.0.0 |
|
||||
| **`exif`** | <code>any</code> | Exif data, if any, retrieved from the image | 1.0.0 |
|
||||
| **`format`** | <code>string</code> | The format of the image, ex: jpeg, png, gif. iOS and Android only support jpeg. Web supports jpeg, png and gif, but the exact availability may vary depending on the browser. gif is only supported if `webUseInput` is set to `true` or if `source` is set to `Photos`. | 1.0.0 |
|
||||
| **`saved`** | <code>boolean</code> | Whether if the image was saved to the gallery or not. On Android and iOS, saving to the gallery can fail if the user didn't grant the required permissions. On Web there is no gallery, so always returns false. | 1.1.0 |
|
||||
|
||||
|
||||
#### ImageOptions
|
||||
|
||||
| Prop | Type | Description | Default | Since |
|
||||
| ------------------------ | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | ----- |
|
||||
| **`quality`** | <code>number</code> | The quality of image to return as JPEG, from 0-100 Note: This option is only supported on Android and iOS | | 1.0.0 |
|
||||
| **`allowEditing`** | <code>boolean</code> | Whether to allow the user to crop or make small edits (platform specific). On iOS 14+ it's only supported for <a href="#camerasource">CameraSource.Camera</a>, but not for <a href="#camerasource">CameraSource.Photos</a>. | | 1.0.0 |
|
||||
| **`resultType`** | <code><a href="#cameraresulttype">CameraResultType</a></code> | How the data should be returned. Currently, only 'Base64', 'DataUrl' or 'Uri' is supported | | 1.0.0 |
|
||||
| **`saveToGallery`** | <code>boolean</code> | Whether to save the photo to the gallery. If the photo was picked from the gallery, it will only be saved if edited. | <code>: false</code> | 1.0.0 |
|
||||
| **`width`** | <code>number</code> | The desired maximum width of the saved image. The aspect ratio is respected. | | 1.0.0 |
|
||||
| **`height`** | <code>number</code> | The desired maximum height of the saved image. The aspect ratio is respected. | | 1.0.0 |
|
||||
| **`correctOrientation`** | <code>boolean</code> | Whether to automatically rotate the image "up" to correct for orientation in portrait mode | <code>: true</code> | 1.0.0 |
|
||||
| **`source`** | <code><a href="#camerasource">CameraSource</a></code> | The source to get the photo from. By default this prompts the user to select either the photo album or take a photo. | <code>: CameraSource.Prompt</code> | 1.0.0 |
|
||||
| **`direction`** | <code><a href="#cameradirection">CameraDirection</a></code> | iOS and Web only: The camera direction. | <code>: CameraDirection.Rear</code> | 1.0.0 |
|
||||
| **`presentationStyle`** | <code>'fullscreen' \| 'popover'</code> | iOS only: The presentation style of the Camera. | <code>: 'fullscreen'</code> | 1.0.0 |
|
||||
| **`webUseInput`** | <code>boolean</code> | Web only: Whether to use the PWA Element experience or file input. The default is to use PWA Elements if installed and fall back to file input. To always use file input, set this to `true`. Learn more about PWA Elements: https://capacitorjs.com/docs/web/pwa-elements | | 1.0.0 |
|
||||
| **`promptLabelHeader`** | <code>string</code> | Text value to use when displaying the prompt. | <code>: 'Photo'</code> | 1.0.0 |
|
||||
| **`promptLabelCancel`** | <code>string</code> | Text value to use when displaying the prompt. iOS only: The label of the 'cancel' button. | <code>: 'Cancel'</code> | 1.0.0 |
|
||||
| **`promptLabelPhoto`** | <code>string</code> | Text value to use when displaying the prompt. The label of the button to select a saved image. | <code>: 'From Photos'</code> | 1.0.0 |
|
||||
| **`promptLabelPicture`** | <code>string</code> | Text value to use when displaying the prompt. The label of the button to open the camera. | <code>: 'Take Picture'</code> | 1.0.0 |
|
||||
|
||||
|
||||
#### GalleryPhotos
|
||||
|
||||
| Prop | Type | Description | Since |
|
||||
| ------------ | --------------------------- | ------------------------------- | ----- |
|
||||
| **`photos`** | <code>GalleryPhoto[]</code> | Array of all the picked photos. | 1.2.0 |
|
||||
|
||||
|
||||
#### GalleryPhoto
|
||||
|
||||
| Prop | Type | Description | Since |
|
||||
| ------------- | ------------------- | ----------------------------------------------------------------------------------------------------------------- | ----- |
|
||||
| **`path`** | <code>string</code> | Full, platform-specific file URL that can be read later using the Filesystem API. | 1.2.0 |
|
||||
| **`webPath`** | <code>string</code> | webPath returns a path that can be used to set the src attribute of an image for efficient loading and rendering. | 1.2.0 |
|
||||
| **`exif`** | <code>any</code> | Exif data, if any, retrieved from the image | 1.2.0 |
|
||||
| **`format`** | <code>string</code> | The format of the image, ex: jpeg, png, gif. iOS and Android only support jpeg. Web supports jpeg, png and gif. | 1.2.0 |
|
||||
|
||||
|
||||
#### GalleryImageOptions
|
||||
|
||||
| Prop | Type | Description | Default | Since |
|
||||
| ------------------------ | -------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------- | ----- |
|
||||
| **`quality`** | <code>number</code> | The quality of image to return as JPEG, from 0-100 Note: This option is only supported on Android and iOS. | | 1.2.0 |
|
||||
| **`width`** | <code>number</code> | The desired maximum width of the saved image. The aspect ratio is respected. | | 1.2.0 |
|
||||
| **`height`** | <code>number</code> | The desired maximum height of the saved image. The aspect ratio is respected. | | 1.2.0 |
|
||||
| **`correctOrientation`** | <code>boolean</code> | Whether to automatically rotate the image "up" to correct for orientation in portrait mode | <code>: true</code> | 1.2.0 |
|
||||
| **`presentationStyle`** | <code>'fullscreen' \| 'popover'</code> | iOS only: The presentation style of the Camera. | <code>: 'fullscreen'</code> | 1.2.0 |
|
||||
| **`limit`** | <code>number</code> | Maximum number of pictures the user will be able to choose. Note: This option is only supported on Android 13+ and iOS. | <code>0 (unlimited)</code> | 1.2.0 |
|
||||
|
||||
|
||||
#### PermissionStatus
|
||||
|
||||
| Prop | Type |
|
||||
| ------------ | ----------------------------------------------------------------------- |
|
||||
| **`camera`** | <code><a href="#camerapermissionstate">CameraPermissionState</a></code> |
|
||||
| **`photos`** | <code><a href="#camerapermissionstate">CameraPermissionState</a></code> |
|
||||
|
||||
|
||||
#### CameraPluginPermissions
|
||||
|
||||
| Prop | Type |
|
||||
| ----------------- | ----------------------------------- |
|
||||
| **`permissions`** | <code>CameraPermissionType[]</code> |
|
||||
|
||||
|
||||
### Type Aliases
|
||||
|
||||
|
||||
#### CameraPermissionState
|
||||
|
||||
<code><a href="#permissionstate">PermissionState</a> | 'limited'</code>
|
||||
|
||||
|
||||
#### PermissionState
|
||||
|
||||
<code>'prompt' | 'prompt-with-rationale' | 'granted' | 'denied'</code>
|
||||
|
||||
|
||||
#### CameraPermissionType
|
||||
|
||||
<code>'camera' | 'photos'</code>
|
||||
|
||||
|
||||
### Enums
|
||||
|
||||
|
||||
#### CameraResultType
|
||||
|
||||
| Members | Value |
|
||||
| ------------- | ---------------------- |
|
||||
| **`Uri`** | <code>'uri'</code> |
|
||||
| **`Base64`** | <code>'base64'</code> |
|
||||
| **`DataUrl`** | <code>'dataUrl'</code> |
|
||||
|
||||
|
||||
#### CameraSource
|
||||
|
||||
| Members | Value | Description |
|
||||
| ------------ | --------------------- | ------------------------------------------------------------------ |
|
||||
| **`Prompt`** | <code>'PROMPT'</code> | Prompts the user to select either the photo album or take a photo. |
|
||||
| **`Camera`** | <code>'CAMERA'</code> | Take a new photo using the camera. |
|
||||
| **`Photos`** | <code>'PHOTOS'</code> | Pick an existing photo from the gallery or photo album. |
|
||||
|
||||
|
||||
#### CameraDirection
|
||||
|
||||
| Members | Value |
|
||||
| ----------- | -------------------- |
|
||||
| **`Rear`** | <code>'REAR'</code> |
|
||||
| **`Front`** | <code>'FRONT'</code> |
|
||||
|
||||
</docgen-api>
|
||||
83
node_modules/@capacitor/camera/android/build.gradle
generated
vendored
Normal file
83
node_modules/@capacitor/camera/android/build.gradle
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
ext {
|
||||
capacitorVersion = System.getenv('CAPACITOR_VERSION')
|
||||
junitVersion = project.hasProperty('junitVersion') ? rootProject.ext.junitVersion : '4.13.2'
|
||||
androidxAppCompatVersion = project.hasProperty('androidxAppCompatVersion') ? rootProject.ext.androidxAppCompatVersion : '1.7.0'
|
||||
androidxEspressoCoreVersion = project.hasProperty('androidxEspressoCoreVersion') ? rootProject.ext.androidxEspressoCoreVersion : '3.6.1'
|
||||
androidxExifInterfaceVersion = project.hasProperty('androidxExifInterfaceVersion') ? rootProject.ext.androidxExifInterfaceVersion : '1.3.7'
|
||||
androidxJunitVersion = project.hasProperty('androidxJunitVersion') ? rootProject.ext.androidxJunitVersion : '1.2.1'
|
||||
androidxMaterialVersion = project.hasProperty('androidxMaterialVersion') ? rootProject.ext.androidxMaterialVersion : '1.12.0'
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
maven {
|
||||
url "https://plugins.gradle.org/m2/"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:8.7.2'
|
||||
if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
|
||||
classpath 'io.github.gradle-nexus:publish-plugin:1.3.0'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.android.library'
|
||||
if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
|
||||
apply plugin: 'io.github.gradle-nexus.publish-plugin'
|
||||
apply from: file('../../scripts/android/publish-root.gradle')
|
||||
apply from: file('../../scripts/android/publish-module.gradle')
|
||||
}
|
||||
|
||||
android {
|
||||
namespace "com.capacitorjs.plugins.camera"
|
||||
compileSdk project.hasProperty('compileSdkVersion') ? rootProject.ext.compileSdkVersion : 35
|
||||
defaultConfig {
|
||||
minSdkVersion project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : 23
|
||||
targetSdkVersion project.hasProperty('targetSdkVersion') ? rootProject.ext.targetSdkVersion : 35
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
}
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_21
|
||||
targetCompatibility JavaVersion.VERSION_21
|
||||
}
|
||||
publishing {
|
||||
singleVariant("release")
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
|
||||
if (System.getenv("CAP_PLUGIN_PUBLISH") == "true") {
|
||||
implementation "com.capacitorjs:core:$capacitorVersion"
|
||||
} else {
|
||||
implementation project(':capacitor-android')
|
||||
}
|
||||
|
||||
implementation "androidx.exifinterface:exifinterface:$androidxExifInterfaceVersion"
|
||||
implementation "androidx.appcompat:appcompat:$androidxAppCompatVersion"
|
||||
implementation "com.google.android.material:material:$androidxMaterialVersion"
|
||||
testImplementation "junit:junit:$junitVersion"
|
||||
androidTestImplementation "androidx.test.ext:junit:$androidxJunitVersion"
|
||||
androidTestImplementation "androidx.test.espresso:espresso-core:$androidxEspressoCoreVersion"
|
||||
}
|
||||
7
node_modules/@capacitor/camera/android/src/main/AndroidManifest.xml
generated
vendored
Normal file
7
node_modules/@capacitor/camera/android/src/main/AndroidManifest.xml
generated
vendored
Normal file
@@ -0,0 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<queries>
|
||||
<intent>
|
||||
<action android:name="android.media.action.IMAGE_CAPTURE" />
|
||||
</intent>
|
||||
</queries>
|
||||
</manifest>
|
||||
124
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraBottomSheetDialogFragment.java
generated
vendored
Normal file
124
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraBottomSheetDialogFragment.java
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
package com.capacitorjs.plugins.camera;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.graphics.Color;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.coordinatorlayout.widget.CoordinatorLayout;
|
||||
import com.google.android.material.bottomsheet.BottomSheetBehavior;
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
|
||||
import java.util.List;
|
||||
|
||||
public class CameraBottomSheetDialogFragment extends BottomSheetDialogFragment {
|
||||
|
||||
interface BottomSheetOnSelectedListener {
|
||||
void onSelected(int index);
|
||||
}
|
||||
|
||||
interface BottomSheetOnCanceledListener {
|
||||
void onCanceled();
|
||||
}
|
||||
|
||||
private BottomSheetOnSelectedListener selectedListener;
|
||||
private BottomSheetOnCanceledListener canceledListener;
|
||||
private List<String> options;
|
||||
private String title;
|
||||
|
||||
void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
void setOptions(List<String> options, BottomSheetOnSelectedListener selectedListener, BottomSheetOnCanceledListener canceledListener) {
|
||||
this.options = options;
|
||||
this.selectedListener = selectedListener;
|
||||
this.canceledListener = canceledListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
super.onCancel(dialog);
|
||||
if (canceledListener != null) {
|
||||
this.canceledListener.onCanceled();
|
||||
}
|
||||
}
|
||||
|
||||
private BottomSheetBehavior.BottomSheetCallback mBottomSheetBehaviorCallback = new BottomSheetBehavior.BottomSheetCallback() {
|
||||
@Override
|
||||
public void onStateChanged(@NonNull View bottomSheet, int newState) {
|
||||
if (newState == BottomSheetBehavior.STATE_HIDDEN) {
|
||||
dismiss();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSlide(@NonNull View bottomSheet, float slideOffset) {}
|
||||
};
|
||||
|
||||
@Override
|
||||
@SuppressLint("RestrictedApi")
|
||||
public void setupDialog(Dialog dialog, int style) {
|
||||
super.setupDialog(dialog, style);
|
||||
|
||||
if (options == null || options.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Window w = dialog.getWindow();
|
||||
|
||||
final float scale = getResources().getDisplayMetrics().density;
|
||||
|
||||
float layoutPaddingDp16 = 16.0f;
|
||||
float layoutPaddingDp12 = 12.0f;
|
||||
float layoutPaddingDp8 = 8.0f;
|
||||
int layoutPaddingPx16 = (int) (layoutPaddingDp16 * scale + 0.5f);
|
||||
int layoutPaddingPx12 = (int) (layoutPaddingDp12 * scale + 0.5f);
|
||||
int layoutPaddingPx8 = (int) (layoutPaddingDp8 * scale + 0.5f);
|
||||
|
||||
CoordinatorLayout parentLayout = new CoordinatorLayout(getContext());
|
||||
|
||||
LinearLayout layout = new LinearLayout(getContext());
|
||||
layout.setOrientation(LinearLayout.VERTICAL);
|
||||
layout.setPadding(layoutPaddingPx16, layoutPaddingPx16, layoutPaddingPx16, layoutPaddingPx16);
|
||||
TextView ttv = new TextView(getContext());
|
||||
ttv.setTextColor(Color.parseColor("#757575"));
|
||||
ttv.setPadding(layoutPaddingPx8, layoutPaddingPx8, layoutPaddingPx8, layoutPaddingPx8);
|
||||
ttv.setText(title);
|
||||
layout.addView(ttv);
|
||||
|
||||
for (int i = 0; i < options.size(); i++) {
|
||||
final int optionIndex = i;
|
||||
|
||||
TextView tv = new TextView(getContext());
|
||||
tv.setTextColor(Color.parseColor("#000000"));
|
||||
tv.setPadding(layoutPaddingPx12, layoutPaddingPx12, layoutPaddingPx12, layoutPaddingPx12);
|
||||
tv.setText(options.get(i));
|
||||
tv.setOnClickListener(
|
||||
view -> {
|
||||
if (selectedListener != null) {
|
||||
selectedListener.onSelected(optionIndex);
|
||||
}
|
||||
dismiss();
|
||||
}
|
||||
);
|
||||
layout.addView(tv);
|
||||
}
|
||||
|
||||
parentLayout.addView(layout.getRootView());
|
||||
|
||||
dialog.setContentView(parentLayout.getRootView());
|
||||
|
||||
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) ((View) parentLayout.getParent()).getLayoutParams();
|
||||
CoordinatorLayout.Behavior<View> behavior = params.getBehavior();
|
||||
|
||||
if (behavior instanceof BottomSheetBehavior) {
|
||||
BottomSheetBehavior<View> bottomSheetBehavior = (BottomSheetBehavior<View>) behavior;
|
||||
bottomSheetBehavior.addBottomSheetCallback(mBottomSheetBehaviorCallback);
|
||||
bottomSheetBehavior.setState(BottomSheetBehavior.STATE_EXPANDED);
|
||||
}
|
||||
}
|
||||
}
|
||||
923
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.java
generated
vendored
Normal file
923
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraPlugin.java
generated
vendored
Normal file
@@ -0,0 +1,923 @@
|
||||
package com.capacitorjs.plugins.camera;
|
||||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Parcelable;
|
||||
import android.provider.MediaStore;
|
||||
import android.util.Base64;
|
||||
import androidx.activity.result.ActivityResult;
|
||||
import androidx.activity.result.ActivityResultCallback;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.ActivityResultRegistryOwner;
|
||||
import androidx.activity.result.PickVisualMediaRequest;
|
||||
import androidx.activity.result.contract.ActivityResultContract;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.core.content.FileProvider;
|
||||
import com.getcapacitor.FileUtils;
|
||||
import com.getcapacitor.JSArray;
|
||||
import com.getcapacitor.JSObject;
|
||||
import com.getcapacitor.Logger;
|
||||
import com.getcapacitor.PermissionState;
|
||||
import com.getcapacitor.Plugin;
|
||||
import com.getcapacitor.PluginCall;
|
||||
import com.getcapacitor.PluginMethod;
|
||||
import com.getcapacitor.annotation.ActivityCallback;
|
||||
import com.getcapacitor.annotation.CapacitorPlugin;
|
||||
import com.getcapacitor.annotation.Permission;
|
||||
import com.getcapacitor.annotation.PermissionCallback;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import org.json.JSONException;
|
||||
|
||||
/**
|
||||
* The Camera plugin makes it easy to take a photo or have the user select a photo
|
||||
* from their albums.
|
||||
*
|
||||
* On Android, this plugin sends an intent that opens the stock Camera app.
|
||||
*
|
||||
* Adapted from https://developer.android.com/training/camera/photobasics.html
|
||||
*/
|
||||
@SuppressLint("InlinedApi")
|
||||
@CapacitorPlugin(
|
||||
name = "Camera",
|
||||
permissions = {
|
||||
@Permission(strings = { Manifest.permission.CAMERA }, alias = CameraPlugin.CAMERA),
|
||||
@Permission(strings = {}, alias = CameraPlugin.PHOTOS),
|
||||
// SDK VERSIONS 29 AND BELOW
|
||||
@Permission(
|
||||
strings = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE },
|
||||
alias = CameraPlugin.SAVE_GALLERY
|
||||
),
|
||||
/*
|
||||
SDK VERSIONS 30-32
|
||||
This alias is a placeholder and the SAVE_GALLERY alias will be updated to use this permission
|
||||
so that the end user does not need to explicitly use separate aliases depending
|
||||
on the SDK version.
|
||||
*/
|
||||
@Permission(strings = { Manifest.permission.READ_EXTERNAL_STORAGE }, alias = CameraPlugin.READ_EXTERNAL_STORAGE)
|
||||
}
|
||||
)
|
||||
public class CameraPlugin extends Plugin {
|
||||
|
||||
// Permission alias constants
|
||||
static final String CAMERA = "camera";
|
||||
static final String PHOTOS = "photos";
|
||||
static final String SAVE_GALLERY = "saveGallery";
|
||||
static final String READ_EXTERNAL_STORAGE = "readExternalStorage";
|
||||
|
||||
// Message constants
|
||||
private static final String INVALID_RESULT_TYPE_ERROR = "Invalid resultType option";
|
||||
private static final String PERMISSION_DENIED_ERROR_CAMERA = "User denied access to camera";
|
||||
private static final String NO_CAMERA_ERROR = "Device doesn't have a camera available";
|
||||
private static final String NO_CAMERA_ACTIVITY_ERROR = "Unable to resolve camera activity";
|
||||
private static final String NO_PHOTO_ACTIVITY_ERROR = "Unable to resolve photo activity";
|
||||
private static final String IMAGE_FILE_SAVE_ERROR = "Unable to create photo on disk";
|
||||
private static final String IMAGE_PROCESS_NO_FILE_ERROR = "Unable to process image, file not found on disk";
|
||||
private static final String UNABLE_TO_PROCESS_IMAGE = "Unable to process image";
|
||||
private static final String IMAGE_EDIT_ERROR = "Unable to edit image";
|
||||
private static final String IMAGE_GALLERY_SAVE_ERROR = "Unable to save the image in the gallery";
|
||||
private static final String USER_CANCELLED = "User cancelled photos app";
|
||||
|
||||
private String imageFileSavePath;
|
||||
private String imageEditedFileSavePath;
|
||||
private Uri imageFileUri;
|
||||
private Uri imagePickedContentUri;
|
||||
private boolean isEdited = false;
|
||||
private boolean isFirstRequest = true;
|
||||
private boolean isSaved = false;
|
||||
private ActivityResultLauncher<PickVisualMediaRequest> pickMultipleMedia = null;
|
||||
private ActivityResultLauncher<PickVisualMediaRequest> pickMedia = null;
|
||||
|
||||
private final AtomicInteger mNextLocalRequestCode = new AtomicInteger();
|
||||
|
||||
private CameraSettings settings = new CameraSettings();
|
||||
|
||||
@Override
|
||||
public void load() {
|
||||
super.load();
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void getPhoto(PluginCall call) {
|
||||
isEdited = false;
|
||||
settings = getSettings(call);
|
||||
doShow(call);
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void pickImages(PluginCall call) {
|
||||
settings = getSettings(call);
|
||||
openPhotos(call, true);
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void pickLimitedLibraryPhotos(PluginCall call) {
|
||||
call.unimplemented("not supported on android");
|
||||
}
|
||||
|
||||
@PluginMethod
|
||||
public void getLimitedLibraryPhotos(PluginCall call) {
|
||||
call.unimplemented("not supported on android");
|
||||
}
|
||||
|
||||
private void doShow(PluginCall call) {
|
||||
switch (settings.getSource()) {
|
||||
case CAMERA:
|
||||
showCamera(call);
|
||||
break;
|
||||
case PHOTOS:
|
||||
showPhotos(call);
|
||||
break;
|
||||
default:
|
||||
showPrompt(call);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void showPrompt(final PluginCall call) {
|
||||
// We have all necessary permissions, open the camera
|
||||
List<String> options = new ArrayList<>();
|
||||
options.add(call.getString("promptLabelPhoto", "From Photos"));
|
||||
options.add(call.getString("promptLabelPicture", "Take Picture"));
|
||||
|
||||
final CameraBottomSheetDialogFragment fragment = new CameraBottomSheetDialogFragment();
|
||||
fragment.setTitle(call.getString("promptLabelHeader", "Photo"));
|
||||
fragment.setOptions(
|
||||
options,
|
||||
index -> {
|
||||
if (index == 0) {
|
||||
settings.setSource(CameraSource.PHOTOS);
|
||||
openPhotos(call);
|
||||
} else if (index == 1) {
|
||||
settings.setSource(CameraSource.CAMERA);
|
||||
openCamera(call);
|
||||
}
|
||||
},
|
||||
() -> call.reject(USER_CANCELLED)
|
||||
);
|
||||
fragment.show(getActivity().getSupportFragmentManager(), "capacitorModalsActionSheet");
|
||||
}
|
||||
|
||||
private void showCamera(final PluginCall call) {
|
||||
if (!getContext().getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_ANY)) {
|
||||
call.reject(NO_CAMERA_ERROR);
|
||||
return;
|
||||
}
|
||||
openCamera(call);
|
||||
}
|
||||
|
||||
private void showPhotos(final PluginCall call) {
|
||||
openPhotos(call);
|
||||
}
|
||||
|
||||
private boolean checkCameraPermissions(PluginCall call) {
|
||||
// if the manifest does not contain the camera permissions key, we don't need to ask the user
|
||||
boolean needCameraPerms = isPermissionDeclared(CAMERA);
|
||||
boolean hasCameraPerms = !needCameraPerms || getPermissionState(CAMERA) == PermissionState.GRANTED;
|
||||
boolean hasGalleryPerms = getPermissionState(SAVE_GALLERY) == PermissionState.GRANTED;
|
||||
|
||||
// If we want to save to the gallery, we need two permissions
|
||||
// actually we only need permissions to save to gallery for Android <= 9 (API 28)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
// we might still need to request permission for the camera
|
||||
if (!hasCameraPerms) {
|
||||
requestPermissionForAlias(CAMERA, call, "cameraPermissionsCallback");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// we need to request permissions to save to gallery for Android <= 9
|
||||
if (settings.isSaveToGallery() && !(hasCameraPerms && hasGalleryPerms) && isFirstRequest) {
|
||||
isFirstRequest = false;
|
||||
String[] aliases;
|
||||
if (needCameraPerms) {
|
||||
aliases = new String[] { CAMERA, SAVE_GALLERY };
|
||||
} else {
|
||||
aliases = new String[] { SAVE_GALLERY };
|
||||
}
|
||||
requestPermissionForAliases(aliases, call, "cameraPermissionsCallback");
|
||||
return false;
|
||||
}
|
||||
// If we don't need to save to the gallery, we can just ask for camera permissions
|
||||
else if (!hasCameraPerms) {
|
||||
requestPermissionForAlias(CAMERA, call, "cameraPermissionsCallback");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes the plugin call after a camera permission request
|
||||
*
|
||||
* @see #getPhoto(PluginCall)
|
||||
* @param call the plugin call
|
||||
*/
|
||||
@PermissionCallback
|
||||
private void cameraPermissionsCallback(PluginCall call) {
|
||||
if (call.getMethodName().equals("pickImages")) {
|
||||
openPhotos(call, true);
|
||||
} else {
|
||||
if (settings.getSource() == CameraSource.CAMERA && getPermissionState(CAMERA) != PermissionState.GRANTED) {
|
||||
Logger.debug(getLogTag(), "User denied camera permission: " + getPermissionState(CAMERA).toString());
|
||||
call.reject(PERMISSION_DENIED_ERROR_CAMERA);
|
||||
return;
|
||||
}
|
||||
doShow(call);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void requestPermissionForAliases(@NonNull String[] aliases, @NonNull PluginCall call, @NonNull String callbackName) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
for (int i = 0; i < aliases.length; i++) {
|
||||
if (aliases[i].equals(SAVE_GALLERY)) {
|
||||
aliases[i] = READ_EXTERNAL_STORAGE;
|
||||
}
|
||||
}
|
||||
}
|
||||
super.requestPermissionForAliases(aliases, call, callbackName);
|
||||
}
|
||||
|
||||
private CameraSettings getSettings(PluginCall call) {
|
||||
CameraSettings settings = new CameraSettings();
|
||||
settings.setResultType(getResultType(call.getString("resultType")));
|
||||
settings.setSaveToGallery(call.getBoolean("saveToGallery", CameraSettings.DEFAULT_SAVE_IMAGE_TO_GALLERY));
|
||||
settings.setAllowEditing(call.getBoolean("allowEditing", false));
|
||||
settings.setQuality(call.getInt("quality", CameraSettings.DEFAULT_QUALITY));
|
||||
settings.setWidth(call.getInt("width", 0));
|
||||
settings.setHeight(call.getInt("height", 0));
|
||||
settings.setShouldResize(settings.getWidth() > 0 || settings.getHeight() > 0);
|
||||
settings.setShouldCorrectOrientation(call.getBoolean("correctOrientation", CameraSettings.DEFAULT_CORRECT_ORIENTATION));
|
||||
try {
|
||||
settings.setSource(CameraSource.valueOf(call.getString("source", CameraSource.PROMPT.getSource())));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
settings.setSource(CameraSource.PROMPT);
|
||||
}
|
||||
return settings;
|
||||
}
|
||||
|
||||
private CameraResultType getResultType(String resultType) {
|
||||
if (resultType == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return CameraResultType.valueOf(resultType.toUpperCase(Locale.ROOT));
|
||||
} catch (IllegalArgumentException ex) {
|
||||
Logger.debug(getLogTag(), "Invalid result type \"" + resultType + "\", defaulting to base64");
|
||||
return CameraResultType.BASE64;
|
||||
}
|
||||
}
|
||||
|
||||
public void openCamera(final PluginCall call) {
|
||||
if (checkCameraPermissions(call)) {
|
||||
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
|
||||
if (takePictureIntent.resolveActivity(getContext().getPackageManager()) != null) {
|
||||
// If we will be saving the photo, send the target file along
|
||||
try {
|
||||
String appId = getAppId();
|
||||
File photoFile = CameraUtils.createImageFile(getActivity());
|
||||
imageFileSavePath = photoFile.getAbsolutePath();
|
||||
// TODO: Verify provider config exists
|
||||
imageFileUri = FileProvider.getUriForFile(getActivity(), appId + ".fileprovider", photoFile);
|
||||
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageFileUri);
|
||||
} catch (Exception ex) {
|
||||
call.reject(IMAGE_FILE_SAVE_ERROR, ex);
|
||||
return;
|
||||
}
|
||||
|
||||
startActivityForResult(call, takePictureIntent, "processCameraImage");
|
||||
} else {
|
||||
call.reject(NO_CAMERA_ACTIVITY_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void openPhotos(final PluginCall call) {
|
||||
openPhotos(call, false);
|
||||
}
|
||||
|
||||
private <I, O> ActivityResultLauncher<I> registerActivityResultLauncher(
|
||||
ActivityResultContract<I, O> contract,
|
||||
ActivityResultCallback<O> callback
|
||||
) {
|
||||
String key = "cap_activity_rq#" + mNextLocalRequestCode.getAndIncrement();
|
||||
if (bridge.getFragment() != null) {
|
||||
Object host = bridge.getFragment().getHost();
|
||||
if (host instanceof ActivityResultRegistryOwner) {
|
||||
return ((ActivityResultRegistryOwner) host).getActivityResultRegistry().register(key, contract, callback);
|
||||
}
|
||||
return bridge.getFragment().requireActivity().getActivityResultRegistry().register(key, contract, callback);
|
||||
}
|
||||
return bridge.getActivity().getActivityResultRegistry().register(key, contract, callback);
|
||||
}
|
||||
|
||||
private ActivityResultContract<PickVisualMediaRequest, List<Uri>> getContractForCall(final PluginCall call) {
|
||||
int limit = call.getInt("limit", 0);
|
||||
if (limit > 1) {
|
||||
return new ActivityResultContracts.PickMultipleVisualMedia(limit);
|
||||
} else {
|
||||
return new ActivityResultContracts.PickMultipleVisualMedia();
|
||||
}
|
||||
}
|
||||
|
||||
private void openPhotos(final PluginCall call, boolean multiple) {
|
||||
try {
|
||||
if (multiple) {
|
||||
pickMultipleMedia =
|
||||
registerActivityResultLauncher(
|
||||
getContractForCall(call),
|
||||
uris -> {
|
||||
if (!uris.isEmpty()) {
|
||||
Executor executor = Executors.newSingleThreadExecutor();
|
||||
executor.execute(
|
||||
() -> {
|
||||
JSObject ret = new JSObject();
|
||||
JSArray photos = new JSArray();
|
||||
for (Uri imageUri : uris) {
|
||||
try {
|
||||
JSObject processResult = processPickedImages(imageUri);
|
||||
if (
|
||||
processResult.getString("error") != null && !processResult.getString("error").isEmpty()
|
||||
) {
|
||||
call.reject(processResult.getString("error"));
|
||||
return;
|
||||
} else {
|
||||
photos.put(processResult);
|
||||
}
|
||||
} catch (SecurityException ex) {
|
||||
call.reject("SecurityException");
|
||||
}
|
||||
}
|
||||
ret.put("photos", photos);
|
||||
call.resolve(ret);
|
||||
}
|
||||
);
|
||||
} else {
|
||||
call.reject(USER_CANCELLED);
|
||||
}
|
||||
pickMultipleMedia.unregister();
|
||||
}
|
||||
);
|
||||
pickMultipleMedia.launch(
|
||||
new PickVisualMediaRequest.Builder().setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE).build()
|
||||
);
|
||||
} else {
|
||||
pickMedia =
|
||||
registerActivityResultLauncher(
|
||||
new ActivityResultContracts.PickVisualMedia(),
|
||||
uri -> {
|
||||
if (uri != null) {
|
||||
imagePickedContentUri = uri;
|
||||
processPickedImage(uri, call);
|
||||
} else {
|
||||
call.reject(USER_CANCELLED);
|
||||
}
|
||||
pickMedia.unregister();
|
||||
}
|
||||
);
|
||||
pickMedia.launch(
|
||||
new PickVisualMediaRequest.Builder().setMediaType(ActivityResultContracts.PickVisualMedia.ImageOnly.INSTANCE).build()
|
||||
);
|
||||
}
|
||||
} catch (ActivityNotFoundException ex) {
|
||||
call.reject(NO_PHOTO_ACTIVITY_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@ActivityCallback
|
||||
public void processCameraImage(PluginCall call, ActivityResult result) {
|
||||
settings = getSettings(call);
|
||||
if (imageFileSavePath == null) {
|
||||
call.reject(IMAGE_PROCESS_NO_FILE_ERROR);
|
||||
return;
|
||||
}
|
||||
// Load the image as a Bitmap
|
||||
File f = new File(imageFileSavePath);
|
||||
BitmapFactory.Options bmOptions = new BitmapFactory.Options();
|
||||
Uri contentUri = Uri.fromFile(f);
|
||||
Bitmap bitmap = BitmapFactory.decodeFile(imageFileSavePath, bmOptions);
|
||||
|
||||
if (bitmap == null) {
|
||||
call.reject(USER_CANCELLED);
|
||||
return;
|
||||
}
|
||||
|
||||
returnResult(call, bitmap, contentUri);
|
||||
}
|
||||
|
||||
public void processPickedImage(PluginCall call, ActivityResult result) {
|
||||
settings = getSettings(call);
|
||||
Intent data = result.getData();
|
||||
if (data == null) {
|
||||
call.reject(USER_CANCELLED);
|
||||
return;
|
||||
}
|
||||
|
||||
Uri u = data.getData();
|
||||
|
||||
imagePickedContentUri = u;
|
||||
|
||||
processPickedImage(u, call);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private ArrayList<Parcelable> getLegacyParcelableArrayList(Bundle bundle, String key) {
|
||||
return bundle.getParcelableArrayList(key);
|
||||
}
|
||||
|
||||
private void processPickedImage(Uri imageUri, PluginCall call) {
|
||||
InputStream imageStream = null;
|
||||
|
||||
try {
|
||||
imageStream = getContext().getContentResolver().openInputStream(imageUri);
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
|
||||
|
||||
if (bitmap == null) {
|
||||
call.reject("Unable to process bitmap");
|
||||
return;
|
||||
}
|
||||
|
||||
returnResult(call, bitmap, imageUri);
|
||||
} catch (OutOfMemoryError err) {
|
||||
call.reject("Out of memory");
|
||||
} catch (FileNotFoundException ex) {
|
||||
call.reject("No such image found", ex);
|
||||
} finally {
|
||||
if (imageStream != null) {
|
||||
try {
|
||||
imageStream.close();
|
||||
} catch (IOException e) {
|
||||
Logger.error(getLogTag(), UNABLE_TO_PROCESS_IMAGE, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JSObject processPickedImages(Uri imageUri) {
|
||||
InputStream imageStream = null;
|
||||
JSObject ret = new JSObject();
|
||||
try {
|
||||
imageStream = getContext().getContentResolver().openInputStream(imageUri);
|
||||
Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
|
||||
|
||||
if (bitmap == null) {
|
||||
ret.put("error", "Unable to process bitmap");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ExifWrapper exif = ImageUtils.getExifData(getContext(), bitmap, imageUri);
|
||||
try {
|
||||
bitmap = prepareBitmap(bitmap, imageUri, exif);
|
||||
} catch (IOException e) {
|
||||
ret.put("error", UNABLE_TO_PROCESS_IMAGE);
|
||||
return ret;
|
||||
}
|
||||
// Compress the final image and prepare for output to client
|
||||
ByteArrayOutputStream bitmapOutputStream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, settings.getQuality(), bitmapOutputStream);
|
||||
|
||||
Uri newUri = getTempImage(imageUri, bitmapOutputStream);
|
||||
exif.copyExif(newUri.getPath());
|
||||
if (newUri != null) {
|
||||
ret.put("format", "jpeg");
|
||||
ret.put("exif", exif.toJson());
|
||||
ret.put("path", newUri.toString());
|
||||
ret.put("webPath", FileUtils.getPortablePath(getContext(), bridge.getLocalUrl(), newUri));
|
||||
} else {
|
||||
ret.put("error", UNABLE_TO_PROCESS_IMAGE);
|
||||
}
|
||||
return ret;
|
||||
} catch (OutOfMemoryError err) {
|
||||
ret.put("error", "Out of memory");
|
||||
} catch (FileNotFoundException ex) {
|
||||
ret.put("error", "No such image found");
|
||||
Logger.error(getLogTag(), "No such image found", ex);
|
||||
} finally {
|
||||
if (imageStream != null) {
|
||||
try {
|
||||
imageStream.close();
|
||||
} catch (IOException e) {
|
||||
Logger.error(getLogTag(), UNABLE_TO_PROCESS_IMAGE, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ActivityCallback
|
||||
private void processEditedImage(PluginCall call, ActivityResult result) {
|
||||
isEdited = true;
|
||||
settings = getSettings(call);
|
||||
if (result.getResultCode() == Activity.RESULT_CANCELED) {
|
||||
// User cancelled the edit operation, if this file was picked from photos,
|
||||
// process the original picked image, otherwise process it as a camera photo
|
||||
if (imagePickedContentUri != null) {
|
||||
processPickedImage(imagePickedContentUri, call);
|
||||
} else {
|
||||
processCameraImage(call, result);
|
||||
}
|
||||
} else {
|
||||
processPickedImage(call, result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the modified image on the same path,
|
||||
* or on a temporary location if it's a content url
|
||||
* @param uri
|
||||
* @param is
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private Uri saveImage(Uri uri, InputStream is) throws IOException {
|
||||
File outFile = null;
|
||||
if (uri.getScheme().equals("content")) {
|
||||
outFile = getTempFile(uri);
|
||||
} else {
|
||||
outFile = new File(uri.getPath());
|
||||
}
|
||||
try {
|
||||
writePhoto(outFile, is);
|
||||
} catch (FileNotFoundException ex) {
|
||||
// Some gallery apps return read only file url, create a temporary file for modifications
|
||||
outFile = getTempFile(uri);
|
||||
writePhoto(outFile, is);
|
||||
}
|
||||
return Uri.fromFile(outFile);
|
||||
}
|
||||
|
||||
private void writePhoto(File outFile, InputStream is) throws IOException {
|
||||
FileOutputStream fos = new FileOutputStream(outFile);
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
fos.close();
|
||||
}
|
||||
|
||||
private File getTempFile(Uri uri) {
|
||||
String filename = Uri.parse(Uri.decode(uri.toString())).getLastPathSegment();
|
||||
if (!filename.contains(".jpg") && !filename.contains(".jpeg")) {
|
||||
filename += "." + (new java.util.Date()).getTime() + ".jpeg";
|
||||
}
|
||||
File cacheDir = getContext().getCacheDir();
|
||||
return new File(cacheDir, filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* After processing the image, return the final result back to the caller.
|
||||
* @param call
|
||||
* @param bitmap
|
||||
* @param u
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
private void returnResult(PluginCall call, Bitmap bitmap, Uri u) {
|
||||
ExifWrapper exif = ImageUtils.getExifData(getContext(), bitmap, u);
|
||||
try {
|
||||
bitmap = prepareBitmap(bitmap, u, exif);
|
||||
} catch (IOException e) {
|
||||
call.reject(UNABLE_TO_PROCESS_IMAGE);
|
||||
return;
|
||||
}
|
||||
// Compress the final image and prepare for output to client
|
||||
ByteArrayOutputStream bitmapOutputStream = new ByteArrayOutputStream();
|
||||
bitmap.compress(Bitmap.CompressFormat.JPEG, settings.getQuality(), bitmapOutputStream);
|
||||
|
||||
if (settings.isAllowEditing() && !isEdited) {
|
||||
editImage(call, u, bitmapOutputStream);
|
||||
return;
|
||||
}
|
||||
|
||||
boolean saveToGallery = call.getBoolean("saveToGallery", CameraSettings.DEFAULT_SAVE_IMAGE_TO_GALLERY);
|
||||
if (saveToGallery && (imageEditedFileSavePath != null || imageFileSavePath != null)) {
|
||||
isSaved = true;
|
||||
try {
|
||||
String fileToSavePath = imageEditedFileSavePath != null ? imageEditedFileSavePath : imageFileSavePath;
|
||||
File fileToSave = new File(fileToSavePath);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||
ContentResolver resolver = getContext().getContentResolver();
|
||||
ContentValues values = new ContentValues();
|
||||
values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileToSave.getName());
|
||||
values.put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg");
|
||||
values.put(MediaStore.MediaColumns.RELATIVE_PATH, Environment.DIRECTORY_DCIM);
|
||||
|
||||
final Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
|
||||
Uri uri = resolver.insert(contentUri, values);
|
||||
|
||||
if (uri == null) {
|
||||
throw new IOException("Failed to create new MediaStore record.");
|
||||
}
|
||||
|
||||
OutputStream stream = resolver.openOutputStream(uri);
|
||||
if (stream == null) {
|
||||
throw new IOException("Failed to open output stream.");
|
||||
}
|
||||
|
||||
Boolean inserted = bitmap.compress(Bitmap.CompressFormat.JPEG, settings.getQuality(), stream);
|
||||
|
||||
if (!inserted) {
|
||||
isSaved = false;
|
||||
}
|
||||
} else {
|
||||
String inserted = MediaStore.Images.Media.insertImage(
|
||||
getContext().getContentResolver(),
|
||||
fileToSavePath,
|
||||
fileToSave.getName(),
|
||||
""
|
||||
);
|
||||
|
||||
if (inserted == null) {
|
||||
isSaved = false;
|
||||
}
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
isSaved = false;
|
||||
Logger.error(getLogTag(), IMAGE_GALLERY_SAVE_ERROR, e);
|
||||
} catch (IOException e) {
|
||||
isSaved = false;
|
||||
Logger.error(getLogTag(), IMAGE_GALLERY_SAVE_ERROR, e);
|
||||
}
|
||||
}
|
||||
|
||||
if (settings.getResultType() == CameraResultType.BASE64) {
|
||||
returnBase64(call, exif, bitmapOutputStream);
|
||||
} else if (settings.getResultType() == CameraResultType.URI) {
|
||||
returnFileURI(call, exif, bitmap, u, bitmapOutputStream);
|
||||
} else if (settings.getResultType() == CameraResultType.DATAURL) {
|
||||
returnDataUrl(call, exif, bitmapOutputStream);
|
||||
} else {
|
||||
call.reject(INVALID_RESULT_TYPE_ERROR);
|
||||
}
|
||||
// Result returned, clear stored paths and images
|
||||
if (settings.getResultType() != CameraResultType.URI) {
|
||||
deleteImageFile();
|
||||
}
|
||||
imageFileSavePath = null;
|
||||
imageFileUri = null;
|
||||
imagePickedContentUri = null;
|
||||
imageEditedFileSavePath = null;
|
||||
}
|
||||
|
||||
private void deleteImageFile() {
|
||||
if (imageFileSavePath != null && !settings.isSaveToGallery()) {
|
||||
File photoFile = new File(imageFileSavePath);
|
||||
if (photoFile.exists()) {
|
||||
photoFile.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void returnFileURI(PluginCall call, ExifWrapper exif, Bitmap bitmap, Uri u, ByteArrayOutputStream bitmapOutputStream) {
|
||||
Uri newUri = getTempImage(u, bitmapOutputStream);
|
||||
exif.copyExif(newUri.getPath());
|
||||
if (newUri != null) {
|
||||
JSObject ret = new JSObject();
|
||||
ret.put("format", "jpeg");
|
||||
ret.put("exif", exif.toJson());
|
||||
ret.put("path", newUri.toString());
|
||||
ret.put("webPath", FileUtils.getPortablePath(getContext(), bridge.getLocalUrl(), newUri));
|
||||
ret.put("saved", isSaved);
|
||||
call.resolve(ret);
|
||||
} else {
|
||||
call.reject(UNABLE_TO_PROCESS_IMAGE);
|
||||
}
|
||||
}
|
||||
|
||||
private Uri getTempImage(Uri u, ByteArrayOutputStream bitmapOutputStream) {
|
||||
ByteArrayInputStream bis = null;
|
||||
Uri newUri = null;
|
||||
try {
|
||||
bis = new ByteArrayInputStream(bitmapOutputStream.toByteArray());
|
||||
newUri = saveImage(u, bis);
|
||||
} catch (IOException ex) {} finally {
|
||||
if (bis != null) {
|
||||
try {
|
||||
bis.close();
|
||||
} catch (IOException e) {
|
||||
Logger.error(getLogTag(), UNABLE_TO_PROCESS_IMAGE, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return newUri;
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply our standard processing of the bitmap, returning a new one and
|
||||
* recycling the old one in the process
|
||||
* @param bitmap
|
||||
* @param imageUri
|
||||
* @param exif
|
||||
* @return
|
||||
*/
|
||||
private Bitmap prepareBitmap(Bitmap bitmap, Uri imageUri, ExifWrapper exif) throws IOException {
|
||||
if (settings.isShouldCorrectOrientation()) {
|
||||
final Bitmap newBitmap = ImageUtils.correctOrientation(getContext(), bitmap, imageUri, exif);
|
||||
bitmap = replaceBitmap(bitmap, newBitmap);
|
||||
}
|
||||
|
||||
if (settings.isShouldResize()) {
|
||||
final Bitmap newBitmap = ImageUtils.resize(bitmap, settings.getWidth(), settings.getHeight());
|
||||
bitmap = replaceBitmap(bitmap, newBitmap);
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private Bitmap replaceBitmap(Bitmap bitmap, final Bitmap newBitmap) {
|
||||
if (bitmap != newBitmap) {
|
||||
bitmap.recycle();
|
||||
}
|
||||
bitmap = newBitmap;
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
private void returnDataUrl(PluginCall call, ExifWrapper exif, ByteArrayOutputStream bitmapOutputStream) {
|
||||
byte[] byteArray = bitmapOutputStream.toByteArray();
|
||||
String encoded = Base64.encodeToString(byteArray, Base64.NO_WRAP);
|
||||
|
||||
JSObject data = new JSObject();
|
||||
data.put("format", "jpeg");
|
||||
data.put("dataUrl", "data:image/jpeg;base64," + encoded);
|
||||
data.put("exif", exif.toJson());
|
||||
call.resolve(data);
|
||||
}
|
||||
|
||||
private void returnBase64(PluginCall call, ExifWrapper exif, ByteArrayOutputStream bitmapOutputStream) {
|
||||
byte[] byteArray = bitmapOutputStream.toByteArray();
|
||||
String encoded = Base64.encodeToString(byteArray, Base64.NO_WRAP);
|
||||
|
||||
JSObject data = new JSObject();
|
||||
data.put("format", "jpeg");
|
||||
data.put("base64String", encoded);
|
||||
data.put("exif", exif.toJson());
|
||||
call.resolve(data);
|
||||
}
|
||||
|
||||
@Override
|
||||
@PluginMethod
|
||||
public void requestPermissions(PluginCall call) {
|
||||
// If the camera permission is defined in the manifest, then we have to prompt the user
|
||||
// or else we will get a security exception when trying to present the camera. If, however,
|
||||
// it is not defined in the manifest then we don't need to prompt and it will just work.
|
||||
if (isPermissionDeclared(CAMERA)) {
|
||||
// just request normally
|
||||
super.requestPermissions(call);
|
||||
} else {
|
||||
// the manifest does not define camera permissions, so we need to decide what to do
|
||||
// first, extract the permissions being requested
|
||||
JSArray providedPerms = call.getArray("permissions");
|
||||
List<String> permsList = null;
|
||||
if (providedPerms != null) {
|
||||
try {
|
||||
permsList = providedPerms.toList();
|
||||
} catch (JSONException e) {}
|
||||
}
|
||||
|
||||
if (
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU ||
|
||||
(permsList != null && permsList.size() == 1 && (permsList.contains(CAMERA) || permsList.contains(PHOTOS)))
|
||||
) {
|
||||
// either we're on Android 13+ (storage permissions do not apply)
|
||||
// or the only thing being asked for was the camera so we can just return the current state
|
||||
checkPermissions(call);
|
||||
} else {
|
||||
requestPermissionForAlias(SAVE_GALLERY, call, "checkPermissions");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, PermissionState> getPermissionStates() {
|
||||
Map<String, PermissionState> permissionStates = super.getPermissionStates();
|
||||
|
||||
// If Camera is not in the manifest and therefore not required, say the permission is granted
|
||||
if (!isPermissionDeclared(CAMERA)) {
|
||||
permissionStates.put(CAMERA, PermissionState.GRANTED);
|
||||
}
|
||||
|
||||
if (permissionStates.containsKey(PHOTOS)) {
|
||||
permissionStates.put(PHOTOS, PermissionState.GRANTED);
|
||||
}
|
||||
|
||||
// If the SDK version is 30 or higher, update the SAVE_GALLERY state to match the READ_EXTERNAL_STORAGE state.
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
String alias = READ_EXTERNAL_STORAGE;
|
||||
if (permissionStates.containsKey(alias)) {
|
||||
permissionStates.put(SAVE_GALLERY, permissionStates.get(alias));
|
||||
}
|
||||
}
|
||||
|
||||
return permissionStates;
|
||||
}
|
||||
|
||||
private void editImage(PluginCall call, Uri uri, ByteArrayOutputStream bitmapOutputStream) {
|
||||
try {
|
||||
Uri tempImage = getTempImage(uri, bitmapOutputStream);
|
||||
Intent editIntent = createEditIntent(tempImage);
|
||||
if (editIntent != null) {
|
||||
startActivityForResult(call, editIntent, "processEditedImage");
|
||||
} else {
|
||||
call.reject(IMAGE_EDIT_ERROR);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
call.reject(IMAGE_EDIT_ERROR, ex);
|
||||
}
|
||||
}
|
||||
|
||||
private Intent createEditIntent(Uri origPhotoUri) {
|
||||
try {
|
||||
File editFile = new File(origPhotoUri.getPath());
|
||||
Uri editUri = FileProvider.getUriForFile(getActivity(), getContext().getPackageName() + ".fileprovider", editFile);
|
||||
Intent editIntent = new Intent(Intent.ACTION_EDIT);
|
||||
editIntent.setDataAndType(editUri, "image/*");
|
||||
imageEditedFileSavePath = editFile.getAbsolutePath();
|
||||
int flags = Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
|
||||
editIntent.addFlags(flags);
|
||||
editIntent.putExtra(MediaStore.EXTRA_OUTPUT, editUri);
|
||||
|
||||
List<ResolveInfo> resInfoList;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
resInfoList =
|
||||
getContext()
|
||||
.getPackageManager()
|
||||
.queryIntentActivities(editIntent, PackageManager.ResolveInfoFlags.of(PackageManager.MATCH_DEFAULT_ONLY));
|
||||
} else {
|
||||
resInfoList = legacyQueryIntentActivities(editIntent);
|
||||
}
|
||||
|
||||
for (ResolveInfo resolveInfo : resInfoList) {
|
||||
String packageName = resolveInfo.activityInfo.packageName;
|
||||
getContext().grantUriPermission(packageName, editUri, flags);
|
||||
}
|
||||
return editIntent;
|
||||
} catch (Exception ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private List<ResolveInfo> legacyQueryIntentActivities(Intent intent) {
|
||||
return getContext().getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bundle saveInstanceState() {
|
||||
Bundle bundle = super.saveInstanceState();
|
||||
if (bundle != null) {
|
||||
bundle.putString("cameraImageFileSavePath", imageFileSavePath);
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void restoreState(Bundle state) {
|
||||
String storedImageFileSavePath = state.getString("cameraImageFileSavePath");
|
||||
if (storedImageFileSavePath != null) {
|
||||
imageFileSavePath = storedImageFileSavePath;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregister activity result launches to prevent leaks.
|
||||
*/
|
||||
@Override
|
||||
protected void handleOnDestroy() {
|
||||
if (pickMedia != null) {
|
||||
pickMedia.unregister();
|
||||
}
|
||||
if (pickMultipleMedia != null) {
|
||||
pickMultipleMedia.unregister();
|
||||
}
|
||||
}
|
||||
}
|
||||
17
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraResultType.java
generated
vendored
Normal file
17
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraResultType.java
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.capacitorjs.plugins.camera;
|
||||
|
||||
public enum CameraResultType {
|
||||
BASE64("base64"),
|
||||
URI("uri"),
|
||||
DATAURL("dataUrl");
|
||||
|
||||
private String type;
|
||||
|
||||
CameraResultType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
90
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraSettings.java
generated
vendored
Normal file
90
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraSettings.java
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
package com.capacitorjs.plugins.camera;
|
||||
|
||||
public class CameraSettings {
|
||||
|
||||
public static final int DEFAULT_QUALITY = 90;
|
||||
public static final boolean DEFAULT_SAVE_IMAGE_TO_GALLERY = false;
|
||||
public static final boolean DEFAULT_CORRECT_ORIENTATION = true;
|
||||
|
||||
private CameraResultType resultType = CameraResultType.BASE64;
|
||||
private int quality = DEFAULT_QUALITY;
|
||||
private boolean shouldResize = false;
|
||||
private boolean shouldCorrectOrientation = DEFAULT_CORRECT_ORIENTATION;
|
||||
private boolean saveToGallery = DEFAULT_SAVE_IMAGE_TO_GALLERY;
|
||||
private boolean allowEditing = false;
|
||||
private int width = 0;
|
||||
private int height = 0;
|
||||
private CameraSource source = CameraSource.PROMPT;
|
||||
|
||||
public CameraResultType getResultType() {
|
||||
return resultType;
|
||||
}
|
||||
|
||||
public void setResultType(CameraResultType resultType) {
|
||||
this.resultType = resultType;
|
||||
}
|
||||
|
||||
public int getQuality() {
|
||||
return quality;
|
||||
}
|
||||
|
||||
public void setQuality(int quality) {
|
||||
this.quality = quality;
|
||||
}
|
||||
|
||||
public boolean isShouldResize() {
|
||||
return shouldResize;
|
||||
}
|
||||
|
||||
public void setShouldResize(boolean shouldResize) {
|
||||
this.shouldResize = shouldResize;
|
||||
}
|
||||
|
||||
public boolean isShouldCorrectOrientation() {
|
||||
return shouldCorrectOrientation;
|
||||
}
|
||||
|
||||
public void setShouldCorrectOrientation(boolean shouldCorrectOrientation) {
|
||||
this.shouldCorrectOrientation = shouldCorrectOrientation;
|
||||
}
|
||||
|
||||
public boolean isSaveToGallery() {
|
||||
return saveToGallery;
|
||||
}
|
||||
|
||||
public void setSaveToGallery(boolean saveToGallery) {
|
||||
this.saveToGallery = saveToGallery;
|
||||
}
|
||||
|
||||
public boolean isAllowEditing() {
|
||||
return allowEditing;
|
||||
}
|
||||
|
||||
public void setAllowEditing(boolean allowEditing) {
|
||||
this.allowEditing = allowEditing;
|
||||
}
|
||||
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setWidth(int width) {
|
||||
this.width = width;
|
||||
}
|
||||
|
||||
public int getHeight() {
|
||||
return height;
|
||||
}
|
||||
|
||||
public void setHeight(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
public CameraSource getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public void setSource(CameraSource source) {
|
||||
this.source = source;
|
||||
}
|
||||
}
|
||||
17
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraSource.java
generated
vendored
Normal file
17
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraSource.java
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
package com.capacitorjs.plugins.camera;
|
||||
|
||||
public enum CameraSource {
|
||||
PROMPT("PROMPT"),
|
||||
CAMERA("CAMERA"),
|
||||
PHOTOS("PHOTOS");
|
||||
|
||||
private String source;
|
||||
|
||||
CameraSource(String source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
return this.source;
|
||||
}
|
||||
}
|
||||
34
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraUtils.java
generated
vendored
Normal file
34
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/CameraUtils.java
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
package com.capacitorjs.plugins.camera;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.net.Uri;
|
||||
import android.os.Environment;
|
||||
import androidx.core.content.FileProvider;
|
||||
import com.getcapacitor.Logger;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
public class CameraUtils {
|
||||
|
||||
public static Uri createImageFileUri(Activity activity, String appId) throws IOException {
|
||||
File photoFile = CameraUtils.createImageFile(activity);
|
||||
return FileProvider.getUriForFile(activity, appId + ".fileprovider", photoFile);
|
||||
}
|
||||
|
||||
public static File createImageFile(Activity activity) throws IOException {
|
||||
// Create an image file name
|
||||
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
|
||||
String imageFileName = "JPEG_" + timeStamp + "_";
|
||||
File storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
|
||||
|
||||
File image = File.createTempFile(imageFileName, /* prefix */".jpg", /* suffix */storageDir/* directory */);
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
protected static String getLogTag() {
|
||||
return Logger.tags("CameraUtils");
|
||||
}
|
||||
}
|
||||
205
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/ExifWrapper.java
generated
vendored
Normal file
205
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/ExifWrapper.java
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
package com.capacitorjs.plugins.camera;
|
||||
|
||||
import static androidx.exifinterface.media.ExifInterface.*;
|
||||
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import com.getcapacitor.JSObject;
|
||||
|
||||
public class ExifWrapper {
|
||||
|
||||
private final ExifInterface exif;
|
||||
private final String[] attributes = new String[] {
|
||||
TAG_APERTURE_VALUE,
|
||||
TAG_ARTIST,
|
||||
TAG_BITS_PER_SAMPLE,
|
||||
TAG_BODY_SERIAL_NUMBER,
|
||||
TAG_BRIGHTNESS_VALUE,
|
||||
TAG_CAMERA_OWNER_NAME,
|
||||
TAG_CFA_PATTERN,
|
||||
TAG_COLOR_SPACE,
|
||||
TAG_COMPONENTS_CONFIGURATION,
|
||||
TAG_COMPRESSED_BITS_PER_PIXEL,
|
||||
TAG_COMPRESSION,
|
||||
TAG_CONTRAST,
|
||||
TAG_COPYRIGHT,
|
||||
TAG_CUSTOM_RENDERED,
|
||||
TAG_DATETIME,
|
||||
TAG_DATETIME_DIGITIZED,
|
||||
TAG_DATETIME_ORIGINAL,
|
||||
TAG_DEFAULT_CROP_SIZE,
|
||||
TAG_DEVICE_SETTING_DESCRIPTION,
|
||||
TAG_DIGITAL_ZOOM_RATIO,
|
||||
TAG_DNG_VERSION,
|
||||
TAG_EXIF_VERSION,
|
||||
TAG_EXPOSURE_BIAS_VALUE,
|
||||
TAG_EXPOSURE_INDEX,
|
||||
TAG_EXPOSURE_MODE,
|
||||
TAG_EXPOSURE_PROGRAM,
|
||||
TAG_EXPOSURE_TIME,
|
||||
TAG_FILE_SOURCE,
|
||||
TAG_FLASH,
|
||||
TAG_FLASHPIX_VERSION,
|
||||
TAG_FLASH_ENERGY,
|
||||
TAG_FOCAL_LENGTH,
|
||||
TAG_FOCAL_LENGTH_IN_35MM_FILM,
|
||||
TAG_FOCAL_PLANE_RESOLUTION_UNIT,
|
||||
TAG_FOCAL_PLANE_X_RESOLUTION,
|
||||
TAG_FOCAL_PLANE_Y_RESOLUTION,
|
||||
TAG_F_NUMBER,
|
||||
TAG_GAIN_CONTROL,
|
||||
TAG_GAMMA,
|
||||
TAG_GPS_ALTITUDE,
|
||||
TAG_GPS_ALTITUDE_REF,
|
||||
TAG_GPS_AREA_INFORMATION,
|
||||
TAG_GPS_DATESTAMP,
|
||||
TAG_GPS_DEST_BEARING,
|
||||
TAG_GPS_DEST_BEARING_REF,
|
||||
TAG_GPS_DEST_DISTANCE,
|
||||
TAG_GPS_DEST_DISTANCE_REF,
|
||||
TAG_GPS_DEST_LATITUDE,
|
||||
TAG_GPS_DEST_LATITUDE_REF,
|
||||
TAG_GPS_DEST_LONGITUDE,
|
||||
TAG_GPS_DEST_LONGITUDE_REF,
|
||||
TAG_GPS_DIFFERENTIAL,
|
||||
TAG_GPS_DOP,
|
||||
TAG_GPS_H_POSITIONING_ERROR,
|
||||
TAG_GPS_IMG_DIRECTION,
|
||||
TAG_GPS_IMG_DIRECTION_REF,
|
||||
TAG_GPS_LATITUDE,
|
||||
TAG_GPS_LATITUDE_REF,
|
||||
TAG_GPS_LONGITUDE,
|
||||
TAG_GPS_LONGITUDE_REF,
|
||||
TAG_GPS_MAP_DATUM,
|
||||
TAG_GPS_MEASURE_MODE,
|
||||
TAG_GPS_PROCESSING_METHOD,
|
||||
TAG_GPS_SATELLITES,
|
||||
TAG_GPS_SPEED,
|
||||
TAG_GPS_SPEED_REF,
|
||||
TAG_GPS_STATUS,
|
||||
TAG_GPS_TIMESTAMP,
|
||||
TAG_GPS_TRACK,
|
||||
TAG_GPS_TRACK_REF,
|
||||
TAG_GPS_VERSION_ID,
|
||||
TAG_IMAGE_DESCRIPTION,
|
||||
TAG_IMAGE_LENGTH,
|
||||
TAG_IMAGE_UNIQUE_ID,
|
||||
TAG_IMAGE_WIDTH,
|
||||
TAG_INTEROPERABILITY_INDEX,
|
||||
TAG_ISO_SPEED,
|
||||
TAG_ISO_SPEED_LATITUDE_YYY,
|
||||
TAG_ISO_SPEED_LATITUDE_ZZZ,
|
||||
TAG_JPEG_INTERCHANGE_FORMAT,
|
||||
TAG_JPEG_INTERCHANGE_FORMAT_LENGTH,
|
||||
TAG_LENS_MAKE,
|
||||
TAG_LENS_MODEL,
|
||||
TAG_LENS_SERIAL_NUMBER,
|
||||
TAG_LENS_SPECIFICATION,
|
||||
TAG_LIGHT_SOURCE,
|
||||
TAG_MAKE,
|
||||
TAG_MAKER_NOTE,
|
||||
TAG_MAX_APERTURE_VALUE,
|
||||
TAG_METERING_MODE,
|
||||
TAG_MODEL,
|
||||
TAG_NEW_SUBFILE_TYPE,
|
||||
TAG_OECF,
|
||||
TAG_OFFSET_TIME,
|
||||
TAG_OFFSET_TIME_DIGITIZED,
|
||||
TAG_OFFSET_TIME_ORIGINAL,
|
||||
TAG_ORF_ASPECT_FRAME,
|
||||
TAG_ORF_PREVIEW_IMAGE_LENGTH,
|
||||
TAG_ORF_PREVIEW_IMAGE_START,
|
||||
TAG_ORF_THUMBNAIL_IMAGE,
|
||||
TAG_ORIENTATION,
|
||||
TAG_PHOTOGRAPHIC_SENSITIVITY,
|
||||
TAG_PHOTOMETRIC_INTERPRETATION,
|
||||
TAG_PIXEL_X_DIMENSION,
|
||||
TAG_PIXEL_Y_DIMENSION,
|
||||
TAG_PLANAR_CONFIGURATION,
|
||||
TAG_PRIMARY_CHROMATICITIES,
|
||||
TAG_RECOMMENDED_EXPOSURE_INDEX,
|
||||
TAG_REFERENCE_BLACK_WHITE,
|
||||
TAG_RELATED_SOUND_FILE,
|
||||
TAG_RESOLUTION_UNIT,
|
||||
TAG_ROWS_PER_STRIP,
|
||||
TAG_RW2_ISO,
|
||||
TAG_RW2_JPG_FROM_RAW,
|
||||
TAG_RW2_SENSOR_BOTTOM_BORDER,
|
||||
TAG_RW2_SENSOR_LEFT_BORDER,
|
||||
TAG_RW2_SENSOR_RIGHT_BORDER,
|
||||
TAG_RW2_SENSOR_TOP_BORDER,
|
||||
TAG_SAMPLES_PER_PIXEL,
|
||||
TAG_SATURATION,
|
||||
TAG_SCENE_CAPTURE_TYPE,
|
||||
TAG_SCENE_TYPE,
|
||||
TAG_SENSING_METHOD,
|
||||
TAG_SENSITIVITY_TYPE,
|
||||
TAG_SHARPNESS,
|
||||
TAG_SHUTTER_SPEED_VALUE,
|
||||
TAG_SOFTWARE,
|
||||
TAG_SPATIAL_FREQUENCY_RESPONSE,
|
||||
TAG_SPECTRAL_SENSITIVITY,
|
||||
TAG_STANDARD_OUTPUT_SENSITIVITY,
|
||||
TAG_STRIP_BYTE_COUNTS,
|
||||
TAG_STRIP_OFFSETS,
|
||||
TAG_SUBFILE_TYPE,
|
||||
TAG_SUBJECT_AREA,
|
||||
TAG_SUBJECT_DISTANCE,
|
||||
TAG_SUBJECT_DISTANCE_RANGE,
|
||||
TAG_SUBJECT_LOCATION,
|
||||
TAG_SUBSEC_TIME,
|
||||
TAG_SUBSEC_TIME_DIGITIZED,
|
||||
TAG_SUBSEC_TIME_ORIGINAL,
|
||||
TAG_THUMBNAIL_IMAGE_LENGTH,
|
||||
TAG_THUMBNAIL_IMAGE_WIDTH,
|
||||
TAG_TRANSFER_FUNCTION,
|
||||
TAG_USER_COMMENT,
|
||||
TAG_WHITE_BALANCE,
|
||||
TAG_WHITE_POINT,
|
||||
TAG_XMP,
|
||||
TAG_X_RESOLUTION,
|
||||
TAG_Y_CB_CR_COEFFICIENTS,
|
||||
TAG_Y_CB_CR_POSITIONING,
|
||||
TAG_Y_CB_CR_SUB_SAMPLING,
|
||||
TAG_Y_RESOLUTION
|
||||
};
|
||||
|
||||
public ExifWrapper(ExifInterface exif) {
|
||||
this.exif = exif;
|
||||
}
|
||||
|
||||
public JSObject toJson() {
|
||||
JSObject ret = new JSObject();
|
||||
|
||||
if (this.exif == null) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
p(ret, attributes[i]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void p(JSObject o, String tag) {
|
||||
String val = exif.getAttribute(tag);
|
||||
o.put(tag, val);
|
||||
}
|
||||
|
||||
public void copyExif(String destFile) {
|
||||
try {
|
||||
ExifInterface destExif = new ExifInterface(destFile);
|
||||
for (int i = 0; i < attributes.length; i++) {
|
||||
String value = exif.getAttribute(attributes[i]);
|
||||
if (value != null) {
|
||||
destExif.setAttribute(attributes[i], value);
|
||||
}
|
||||
}
|
||||
destExif.saveAttributes();
|
||||
} catch (Exception ex) {}
|
||||
}
|
||||
|
||||
public void resetOrientation() {
|
||||
exif.resetOrientation();
|
||||
}
|
||||
}
|
||||
124
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/ImageUtils.java
generated
vendored
Normal file
124
node_modules/@capacitor/camera/android/src/main/java/com/capacitorjs/plugins/camera/ImageUtils.java
generated
vendored
Normal file
@@ -0,0 +1,124 @@
|
||||
package com.capacitorjs.plugins.camera;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.provider.MediaStore;
|
||||
import androidx.exifinterface.media.ExifInterface;
|
||||
import com.getcapacitor.Logger;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ImageUtils {
|
||||
|
||||
/**
|
||||
* Resize an image to the given max width and max height. Constraint can be put
|
||||
* on one dimension, or both. Resize will always preserve aspect ratio.
|
||||
* @param bitmap
|
||||
* @param desiredMaxWidth
|
||||
* @param desiredMaxHeight
|
||||
* @return a new, scaled Bitmap
|
||||
*/
|
||||
public static Bitmap resize(Bitmap bitmap, final int desiredMaxWidth, final int desiredMaxHeight) {
|
||||
return ImageUtils.resizePreservingAspectRatio(bitmap, desiredMaxWidth, desiredMaxHeight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize an image to the given max width and max height. Constraint can be put
|
||||
* on one dimension, or both. Resize will always preserve aspect ratio.
|
||||
* @param bitmap
|
||||
* @param desiredMaxWidth
|
||||
* @param desiredMaxHeight
|
||||
* @return a new, scaled Bitmap
|
||||
*/
|
||||
private static Bitmap resizePreservingAspectRatio(Bitmap bitmap, final int desiredMaxWidth, final int desiredMaxHeight) {
|
||||
int width = bitmap.getWidth();
|
||||
int height = bitmap.getHeight();
|
||||
|
||||
// 0 is treated as 'no restriction'
|
||||
int maxHeight = desiredMaxHeight == 0 ? height : desiredMaxHeight;
|
||||
int maxWidth = desiredMaxWidth == 0 ? width : desiredMaxWidth;
|
||||
|
||||
// resize with preserved aspect ratio
|
||||
float newWidth = Math.min(width, maxWidth);
|
||||
float newHeight = (height * newWidth) / width;
|
||||
|
||||
if (newHeight > maxHeight) {
|
||||
newWidth = (width * maxHeight) / height;
|
||||
newHeight = maxHeight;
|
||||
}
|
||||
return Bitmap.createScaledBitmap(bitmap, Math.round(newWidth), Math.round(newHeight), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform an image with the given matrix
|
||||
* @param bitmap
|
||||
* @param matrix
|
||||
* @return
|
||||
*/
|
||||
private static Bitmap transform(final Bitmap bitmap, final Matrix matrix) {
|
||||
return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Correct the orientation of an image by reading its exif information and rotating
|
||||
* the appropriate amount for portrait mode
|
||||
* @param bitmap
|
||||
* @param imageUri
|
||||
* @param exif
|
||||
* @return
|
||||
*/
|
||||
public static Bitmap correctOrientation(final Context c, final Bitmap bitmap, final Uri imageUri, ExifWrapper exif) throws IOException {
|
||||
final int orientation = getOrientation(c, imageUri);
|
||||
if (orientation != 0) {
|
||||
Matrix matrix = new Matrix();
|
||||
matrix.postRotate(orientation);
|
||||
exif.resetOrientation();
|
||||
return transform(bitmap, matrix);
|
||||
} else {
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
|
||||
private static int getOrientation(final Context c, final Uri imageUri) throws IOException {
|
||||
int result = 0;
|
||||
|
||||
try (InputStream iStream = c.getContentResolver().openInputStream(imageUri)) {
|
||||
final ExifInterface exifInterface = new ExifInterface(iStream);
|
||||
|
||||
final int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
|
||||
|
||||
if (orientation == ExifInterface.ORIENTATION_ROTATE_90) {
|
||||
result = 90;
|
||||
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_180) {
|
||||
result = 180;
|
||||
} else if (orientation == ExifInterface.ORIENTATION_ROTATE_270) {
|
||||
result = 270;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static ExifWrapper getExifData(final Context c, final Bitmap bitmap, final Uri imageUri) {
|
||||
InputStream stream = null;
|
||||
try {
|
||||
stream = c.getContentResolver().openInputStream(imageUri);
|
||||
final ExifInterface exifInterface = new ExifInterface(stream);
|
||||
|
||||
return new ExifWrapper(exifInterface);
|
||||
} catch (IOException ex) {
|
||||
Logger.error("Error loading exif data from image", ex);
|
||||
} finally {
|
||||
if (stream != null) {
|
||||
try {
|
||||
stream.close();
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
return new ExifWrapper(null);
|
||||
}
|
||||
}
|
||||
804
node_modules/@capacitor/camera/dist/docs.json
generated
vendored
Normal file
804
node_modules/@capacitor/camera/dist/docs.json
generated
vendored
Normal file
@@ -0,0 +1,804 @@
|
||||
{
|
||||
"api": {
|
||||
"name": "CameraPlugin",
|
||||
"slug": "cameraplugin",
|
||||
"docs": "",
|
||||
"tags": [],
|
||||
"methods": [
|
||||
{
|
||||
"name": "getPhoto",
|
||||
"signature": "(options: ImageOptions) => Promise<Photo>",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "options",
|
||||
"docs": "",
|
||||
"type": "ImageOptions"
|
||||
}
|
||||
],
|
||||
"returns": "Promise<Photo>",
|
||||
"tags": [
|
||||
{
|
||||
"name": "since",
|
||||
"text": "1.0.0"
|
||||
}
|
||||
],
|
||||
"docs": "Prompt the user to pick a photo from an album, or take a new photo\nwith the camera.",
|
||||
"complexTypes": [
|
||||
"Photo",
|
||||
"ImageOptions"
|
||||
],
|
||||
"slug": "getphoto"
|
||||
},
|
||||
{
|
||||
"name": "pickImages",
|
||||
"signature": "(options: GalleryImageOptions) => Promise<GalleryPhotos>",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "options",
|
||||
"docs": "",
|
||||
"type": "GalleryImageOptions"
|
||||
}
|
||||
],
|
||||
"returns": "Promise<GalleryPhotos>",
|
||||
"tags": [
|
||||
{
|
||||
"name": "since",
|
||||
"text": "1.2.0"
|
||||
}
|
||||
],
|
||||
"docs": "Allows the user to pick multiple pictures from the photo gallery.\nOn iOS 13 and older it only allows to pick one picture.",
|
||||
"complexTypes": [
|
||||
"GalleryPhotos",
|
||||
"GalleryImageOptions"
|
||||
],
|
||||
"slug": "pickimages"
|
||||
},
|
||||
{
|
||||
"name": "pickLimitedLibraryPhotos",
|
||||
"signature": "() => Promise<GalleryPhotos>",
|
||||
"parameters": [],
|
||||
"returns": "Promise<GalleryPhotos>",
|
||||
"tags": [
|
||||
{
|
||||
"name": "since",
|
||||
"text": "4.1.0"
|
||||
}
|
||||
],
|
||||
"docs": "iOS 14+ Only: Allows the user to update their limited photo library selection.\nOn iOS 15+ returns all the limited photos after the picker dismissal.\nOn iOS 14 or if the user gave full access to the photos it returns an empty array.",
|
||||
"complexTypes": [
|
||||
"GalleryPhotos"
|
||||
],
|
||||
"slug": "picklimitedlibraryphotos"
|
||||
},
|
||||
{
|
||||
"name": "getLimitedLibraryPhotos",
|
||||
"signature": "() => Promise<GalleryPhotos>",
|
||||
"parameters": [],
|
||||
"returns": "Promise<GalleryPhotos>",
|
||||
"tags": [
|
||||
{
|
||||
"name": "since",
|
||||
"text": "4.1.0"
|
||||
}
|
||||
],
|
||||
"docs": "iOS 14+ Only: Return an array of photos selected from the limited photo library.",
|
||||
"complexTypes": [
|
||||
"GalleryPhotos"
|
||||
],
|
||||
"slug": "getlimitedlibraryphotos"
|
||||
},
|
||||
{
|
||||
"name": "checkPermissions",
|
||||
"signature": "() => Promise<PermissionStatus>",
|
||||
"parameters": [],
|
||||
"returns": "Promise<PermissionStatus>",
|
||||
"tags": [
|
||||
{
|
||||
"name": "since",
|
||||
"text": "1.0.0"
|
||||
}
|
||||
],
|
||||
"docs": "Check camera and photo album permissions",
|
||||
"complexTypes": [
|
||||
"PermissionStatus"
|
||||
],
|
||||
"slug": "checkpermissions"
|
||||
},
|
||||
{
|
||||
"name": "requestPermissions",
|
||||
"signature": "(permissions?: CameraPluginPermissions | undefined) => Promise<PermissionStatus>",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "permissions",
|
||||
"docs": "",
|
||||
"type": "CameraPluginPermissions | undefined"
|
||||
}
|
||||
],
|
||||
"returns": "Promise<PermissionStatus>",
|
||||
"tags": [
|
||||
{
|
||||
"name": "since",
|
||||
"text": "1.0.0"
|
||||
}
|
||||
],
|
||||
"docs": "Request camera and photo album permissions",
|
||||
"complexTypes": [
|
||||
"PermissionStatus",
|
||||
"CameraPluginPermissions"
|
||||
],
|
||||
"slug": "requestpermissions"
|
||||
}
|
||||
],
|
||||
"properties": []
|
||||
},
|
||||
"interfaces": [
|
||||
{
|
||||
"name": "Photo",
|
||||
"slug": "photo",
|
||||
"docs": "",
|
||||
"tags": [],
|
||||
"methods": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "base64String",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The base64 encoded string representation of the image, if using CameraResultType.Base64.",
|
||||
"complexTypes": [],
|
||||
"type": "string | undefined"
|
||||
},
|
||||
{
|
||||
"name": "dataUrl",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The url starting with 'data:image/jpeg;base64,' and the base64 encoded string representation of the image, if using CameraResultType.DataUrl.\n\nNote: On web, the file format could change depending on the browser.",
|
||||
"complexTypes": [],
|
||||
"type": "string | undefined"
|
||||
},
|
||||
{
|
||||
"name": "path",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "If using CameraResultType.Uri, the path will contain a full,\nplatform-specific file URL that can be read later using the Filesystem API.",
|
||||
"complexTypes": [],
|
||||
"type": "string | undefined"
|
||||
},
|
||||
{
|
||||
"name": "webPath",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "webPath returns a path that can be used to set the src attribute of an image for efficient\nloading and rendering.",
|
||||
"complexTypes": [],
|
||||
"type": "string | undefined"
|
||||
},
|
||||
{
|
||||
"name": "exif",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Exif data, if any, retrieved from the image",
|
||||
"complexTypes": [],
|
||||
"type": "any"
|
||||
},
|
||||
{
|
||||
"name": "format",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The format of the image, ex: jpeg, png, gif.\n\niOS and Android only support jpeg.\nWeb supports jpeg, png and gif, but the exact availability may vary depending on the browser.\ngif is only supported if `webUseInput` is set to `true` or if `source` is set to `Photos`.",
|
||||
"complexTypes": [],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "saved",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.1.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Whether if the image was saved to the gallery or not.\n\nOn Android and iOS, saving to the gallery can fail if the user didn't\ngrant the required permissions.\nOn Web there is no gallery, so always returns false.",
|
||||
"complexTypes": [],
|
||||
"type": "boolean"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "ImageOptions",
|
||||
"slug": "imageoptions",
|
||||
"docs": "",
|
||||
"tags": [],
|
||||
"methods": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "quality",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The quality of image to return as JPEG, from 0-100\nNote: This option is only supported on Android and iOS",
|
||||
"complexTypes": [],
|
||||
"type": "number | undefined"
|
||||
},
|
||||
{
|
||||
"name": "allowEditing",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Whether to allow the user to crop or make small edits (platform specific).\nOn iOS 14+ it's only supported for CameraSource.Camera, but not for CameraSource.Photos.",
|
||||
"complexTypes": [],
|
||||
"type": "boolean | undefined"
|
||||
},
|
||||
{
|
||||
"name": "resultType",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "How the data should be returned. Currently, only 'Base64', 'DataUrl' or 'Uri' is supported",
|
||||
"complexTypes": [
|
||||
"CameraResultType"
|
||||
],
|
||||
"type": "CameraResultType"
|
||||
},
|
||||
{
|
||||
"name": "saveToGallery",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": false",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Whether to save the photo to the gallery.\nIf the photo was picked from the gallery, it will only be saved if edited.",
|
||||
"complexTypes": [],
|
||||
"type": "boolean | undefined"
|
||||
},
|
||||
{
|
||||
"name": "width",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The desired maximum width of the saved image. The aspect ratio is respected.",
|
||||
"complexTypes": [],
|
||||
"type": "number | undefined"
|
||||
},
|
||||
{
|
||||
"name": "height",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The desired maximum height of the saved image. The aspect ratio is respected.",
|
||||
"complexTypes": [],
|
||||
"type": "number | undefined"
|
||||
},
|
||||
{
|
||||
"name": "correctOrientation",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": true",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Whether to automatically rotate the image \"up\" to correct for orientation\nin portrait mode",
|
||||
"complexTypes": [],
|
||||
"type": "boolean | undefined"
|
||||
},
|
||||
{
|
||||
"name": "source",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": CameraSource.Prompt",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The source to get the photo from. By default this prompts the user to select\neither the photo album or take a photo.",
|
||||
"complexTypes": [
|
||||
"CameraSource"
|
||||
],
|
||||
"type": "CameraSource"
|
||||
},
|
||||
{
|
||||
"name": "direction",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": CameraDirection.Rear",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "iOS and Web only: The camera direction.",
|
||||
"complexTypes": [
|
||||
"CameraDirection"
|
||||
],
|
||||
"type": "CameraDirection"
|
||||
},
|
||||
{
|
||||
"name": "presentationStyle",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": 'fullscreen'",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "iOS only: The presentation style of the Camera.",
|
||||
"complexTypes": [],
|
||||
"type": "'fullscreen' | 'popover' | undefined"
|
||||
},
|
||||
{
|
||||
"name": "webUseInput",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Web only: Whether to use the PWA Element experience or file input. The\ndefault is to use PWA Elements if installed and fall back to file input.\nTo always use file input, set this to `true`.\n\nLearn more about PWA Elements: https://capacitorjs.com/docs/web/pwa-elements",
|
||||
"complexTypes": [],
|
||||
"type": "boolean | undefined"
|
||||
},
|
||||
{
|
||||
"name": "promptLabelHeader",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": 'Photo'",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Text value to use when displaying the prompt.",
|
||||
"complexTypes": [],
|
||||
"type": "string | undefined"
|
||||
},
|
||||
{
|
||||
"name": "promptLabelCancel",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": 'Cancel'",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Text value to use when displaying the prompt.\niOS only: The label of the 'cancel' button.",
|
||||
"complexTypes": [],
|
||||
"type": "string | undefined"
|
||||
},
|
||||
{
|
||||
"name": "promptLabelPhoto",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": 'From Photos'",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Text value to use when displaying the prompt.\nThe label of the button to select a saved image.",
|
||||
"complexTypes": [],
|
||||
"type": "string | undefined"
|
||||
},
|
||||
{
|
||||
"name": "promptLabelPicture",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": 'Take Picture'",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.0.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Text value to use when displaying the prompt.\nThe label of the button to open the camera.",
|
||||
"complexTypes": [],
|
||||
"type": "string | undefined"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "GalleryPhotos",
|
||||
"slug": "galleryphotos",
|
||||
"docs": "",
|
||||
"tags": [],
|
||||
"methods": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "photos",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Array of all the picked photos.",
|
||||
"complexTypes": [
|
||||
"GalleryPhoto"
|
||||
],
|
||||
"type": "GalleryPhoto[]"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "GalleryPhoto",
|
||||
"slug": "galleryphoto",
|
||||
"docs": "",
|
||||
"tags": [],
|
||||
"methods": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "path",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Full, platform-specific file URL that can be read later using the Filesystem API.",
|
||||
"complexTypes": [],
|
||||
"type": "string | undefined"
|
||||
},
|
||||
{
|
||||
"name": "webPath",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "webPath returns a path that can be used to set the src attribute of an image for efficient\nloading and rendering.",
|
||||
"complexTypes": [],
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "exif",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Exif data, if any, retrieved from the image",
|
||||
"complexTypes": [],
|
||||
"type": "any"
|
||||
},
|
||||
{
|
||||
"name": "format",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The format of the image, ex: jpeg, png, gif.\n\niOS and Android only support jpeg.\nWeb supports jpeg, png and gif.",
|
||||
"complexTypes": [],
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "GalleryImageOptions",
|
||||
"slug": "galleryimageoptions",
|
||||
"docs": "",
|
||||
"tags": [],
|
||||
"methods": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "quality",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The quality of image to return as JPEG, from 0-100\nNote: This option is only supported on Android and iOS.",
|
||||
"complexTypes": [],
|
||||
"type": "number | undefined"
|
||||
},
|
||||
{
|
||||
"name": "width",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The desired maximum width of the saved image. The aspect ratio is respected.",
|
||||
"complexTypes": [],
|
||||
"type": "number | undefined"
|
||||
},
|
||||
{
|
||||
"name": "height",
|
||||
"tags": [
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "The desired maximum height of the saved image. The aspect ratio is respected.",
|
||||
"complexTypes": [],
|
||||
"type": "number | undefined"
|
||||
},
|
||||
{
|
||||
"name": "correctOrientation",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": true",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Whether to automatically rotate the image \"up\" to correct for orientation\nin portrait mode",
|
||||
"complexTypes": [],
|
||||
"type": "boolean | undefined"
|
||||
},
|
||||
{
|
||||
"name": "presentationStyle",
|
||||
"tags": [
|
||||
{
|
||||
"text": ": 'fullscreen'",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "iOS only: The presentation style of the Camera.",
|
||||
"complexTypes": [],
|
||||
"type": "'fullscreen' | 'popover' | undefined"
|
||||
},
|
||||
{
|
||||
"name": "limit",
|
||||
"tags": [
|
||||
{
|
||||
"text": "0 (unlimited)",
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"text": "1.2.0",
|
||||
"name": "since"
|
||||
}
|
||||
],
|
||||
"docs": "Maximum number of pictures the user will be able to choose.\nNote: This option is only supported on Android 13+ and iOS.",
|
||||
"complexTypes": [],
|
||||
"type": "number | undefined"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PermissionStatus",
|
||||
"slug": "permissionstatus",
|
||||
"docs": "",
|
||||
"tags": [],
|
||||
"methods": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "camera",
|
||||
"tags": [],
|
||||
"docs": "",
|
||||
"complexTypes": [
|
||||
"CameraPermissionState"
|
||||
],
|
||||
"type": "CameraPermissionState"
|
||||
},
|
||||
{
|
||||
"name": "photos",
|
||||
"tags": [],
|
||||
"docs": "",
|
||||
"complexTypes": [
|
||||
"CameraPermissionState"
|
||||
],
|
||||
"type": "CameraPermissionState"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "CameraPluginPermissions",
|
||||
"slug": "camerapluginpermissions",
|
||||
"docs": "",
|
||||
"tags": [],
|
||||
"methods": [],
|
||||
"properties": [
|
||||
{
|
||||
"name": "permissions",
|
||||
"tags": [],
|
||||
"docs": "",
|
||||
"complexTypes": [
|
||||
"CameraPermissionType"
|
||||
],
|
||||
"type": "CameraPermissionType[]"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"enums": [
|
||||
{
|
||||
"name": "CameraResultType",
|
||||
"slug": "cameraresulttype",
|
||||
"members": [
|
||||
{
|
||||
"name": "Uri",
|
||||
"value": "'uri'",
|
||||
"tags": [],
|
||||
"docs": ""
|
||||
},
|
||||
{
|
||||
"name": "Base64",
|
||||
"value": "'base64'",
|
||||
"tags": [],
|
||||
"docs": ""
|
||||
},
|
||||
{
|
||||
"name": "DataUrl",
|
||||
"value": "'dataUrl'",
|
||||
"tags": [],
|
||||
"docs": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "CameraSource",
|
||||
"slug": "camerasource",
|
||||
"members": [
|
||||
{
|
||||
"name": "Prompt",
|
||||
"value": "'PROMPT'",
|
||||
"tags": [],
|
||||
"docs": "Prompts the user to select either the photo album or take a photo."
|
||||
},
|
||||
{
|
||||
"name": "Camera",
|
||||
"value": "'CAMERA'",
|
||||
"tags": [],
|
||||
"docs": "Take a new photo using the camera."
|
||||
},
|
||||
{
|
||||
"name": "Photos",
|
||||
"value": "'PHOTOS'",
|
||||
"tags": [],
|
||||
"docs": "Pick an existing photo from the gallery or photo album."
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "CameraDirection",
|
||||
"slug": "cameradirection",
|
||||
"members": [
|
||||
{
|
||||
"name": "Rear",
|
||||
"value": "'REAR'",
|
||||
"tags": [],
|
||||
"docs": ""
|
||||
},
|
||||
{
|
||||
"name": "Front",
|
||||
"value": "'FRONT'",
|
||||
"tags": [],
|
||||
"docs": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"typeAliases": [
|
||||
{
|
||||
"name": "CameraPermissionState",
|
||||
"slug": "camerapermissionstate",
|
||||
"docs": "",
|
||||
"types": [
|
||||
{
|
||||
"text": "PermissionState",
|
||||
"complexTypes": [
|
||||
"PermissionState"
|
||||
]
|
||||
},
|
||||
{
|
||||
"text": "'limited'",
|
||||
"complexTypes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "PermissionState",
|
||||
"slug": "permissionstate",
|
||||
"docs": "",
|
||||
"types": [
|
||||
{
|
||||
"text": "'prompt'",
|
||||
"complexTypes": []
|
||||
},
|
||||
{
|
||||
"text": "'prompt-with-rationale'",
|
||||
"complexTypes": []
|
||||
},
|
||||
{
|
||||
"text": "'granted'",
|
||||
"complexTypes": []
|
||||
},
|
||||
{
|
||||
"text": "'denied'",
|
||||
"complexTypes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "CameraPermissionType",
|
||||
"slug": "camerapermissiontype",
|
||||
"docs": "",
|
||||
"types": [
|
||||
{
|
||||
"text": "'camera'",
|
||||
"complexTypes": []
|
||||
},
|
||||
{
|
||||
"text": "'photos'",
|
||||
"complexTypes": []
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"pluginConfigs": []
|
||||
}
|
||||
337
node_modules/@capacitor/camera/dist/esm/definitions.d.ts
generated
vendored
Normal file
337
node_modules/@capacitor/camera/dist/esm/definitions.d.ts
generated
vendored
Normal file
@@ -0,0 +1,337 @@
|
||||
import type { PermissionState } from '@capacitor/core';
|
||||
export declare type CameraPermissionState = PermissionState | 'limited';
|
||||
export declare type CameraPermissionType = 'camera' | 'photos';
|
||||
export interface PermissionStatus {
|
||||
camera: CameraPermissionState;
|
||||
photos: CameraPermissionState;
|
||||
}
|
||||
export interface CameraPluginPermissions {
|
||||
permissions: CameraPermissionType[];
|
||||
}
|
||||
export interface CameraPlugin {
|
||||
/**
|
||||
* Prompt the user to pick a photo from an album, or take a new photo
|
||||
* with the camera.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
getPhoto(options: ImageOptions): Promise<Photo>;
|
||||
/**
|
||||
* Allows the user to pick multiple pictures from the photo gallery.
|
||||
* On iOS 13 and older it only allows to pick one picture.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
pickImages(options: GalleryImageOptions): Promise<GalleryPhotos>;
|
||||
/**
|
||||
* iOS 14+ Only: Allows the user to update their limited photo library selection.
|
||||
* On iOS 15+ returns all the limited photos after the picker dismissal.
|
||||
* On iOS 14 or if the user gave full access to the photos it returns an empty array.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
pickLimitedLibraryPhotos(): Promise<GalleryPhotos>;
|
||||
/**
|
||||
* iOS 14+ Only: Return an array of photos selected from the limited photo library.
|
||||
*
|
||||
* @since 4.1.0
|
||||
*/
|
||||
getLimitedLibraryPhotos(): Promise<GalleryPhotos>;
|
||||
/**
|
||||
* Check camera and photo album permissions
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
checkPermissions(): Promise<PermissionStatus>;
|
||||
/**
|
||||
* Request camera and photo album permissions
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
requestPermissions(permissions?: CameraPluginPermissions): Promise<PermissionStatus>;
|
||||
}
|
||||
export interface ImageOptions {
|
||||
/**
|
||||
* The quality of image to return as JPEG, from 0-100
|
||||
* Note: This option is only supported on Android and iOS
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
quality?: number;
|
||||
/**
|
||||
* Whether to allow the user to crop or make small edits (platform specific).
|
||||
* On iOS 14+ it's only supported for CameraSource.Camera, but not for CameraSource.Photos.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
allowEditing?: boolean;
|
||||
/**
|
||||
* How the data should be returned. Currently, only 'Base64', 'DataUrl' or 'Uri' is supported
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
resultType: CameraResultType;
|
||||
/**
|
||||
* Whether to save the photo to the gallery.
|
||||
* If the photo was picked from the gallery, it will only be saved if edited.
|
||||
* @default: false
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
saveToGallery?: boolean;
|
||||
/**
|
||||
* The desired maximum width of the saved image. The aspect ratio is respected.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
width?: number;
|
||||
/**
|
||||
* The desired maximum height of the saved image. The aspect ratio is respected.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
height?: number;
|
||||
/**
|
||||
* Whether to automatically rotate the image "up" to correct for orientation
|
||||
* in portrait mode
|
||||
* @default: true
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
correctOrientation?: boolean;
|
||||
/**
|
||||
* The source to get the photo from. By default this prompts the user to select
|
||||
* either the photo album or take a photo.
|
||||
* @default: CameraSource.Prompt
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
source?: CameraSource;
|
||||
/**
|
||||
* iOS and Web only: The camera direction.
|
||||
* @default: CameraDirection.Rear
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
direction?: CameraDirection;
|
||||
/**
|
||||
* iOS only: The presentation style of the Camera.
|
||||
* @default: 'fullscreen'
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
presentationStyle?: 'fullscreen' | 'popover';
|
||||
/**
|
||||
* Web only: Whether to use the PWA Element experience or file input. The
|
||||
* default is to use PWA Elements if installed and fall back to file input.
|
||||
* To always use file input, set this to `true`.
|
||||
*
|
||||
* Learn more about PWA Elements: https://capacitorjs.com/docs/web/pwa-elements
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
webUseInput?: boolean;
|
||||
/**
|
||||
* Text value to use when displaying the prompt.
|
||||
* @default: 'Photo'
|
||||
*
|
||||
* @since 1.0.0
|
||||
*
|
||||
*/
|
||||
promptLabelHeader?: string;
|
||||
/**
|
||||
* Text value to use when displaying the prompt.
|
||||
* iOS only: The label of the 'cancel' button.
|
||||
* @default: 'Cancel'
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
promptLabelCancel?: string;
|
||||
/**
|
||||
* Text value to use when displaying the prompt.
|
||||
* The label of the button to select a saved image.
|
||||
* @default: 'From Photos'
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
promptLabelPhoto?: string;
|
||||
/**
|
||||
* Text value to use when displaying the prompt.
|
||||
* The label of the button to open the camera.
|
||||
* @default: 'Take Picture'
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
promptLabelPicture?: string;
|
||||
}
|
||||
export interface Photo {
|
||||
/**
|
||||
* The base64 encoded string representation of the image, if using CameraResultType.Base64.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
base64String?: string;
|
||||
/**
|
||||
* The url starting with 'data:image/jpeg;base64,' and the base64 encoded string representation of the image, if using CameraResultType.DataUrl.
|
||||
*
|
||||
* Note: On web, the file format could change depending on the browser.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
dataUrl?: string;
|
||||
/**
|
||||
* If using CameraResultType.Uri, the path will contain a full,
|
||||
* platform-specific file URL that can be read later using the Filesystem API.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* webPath returns a path that can be used to set the src attribute of an image for efficient
|
||||
* loading and rendering.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
webPath?: string;
|
||||
/**
|
||||
* Exif data, if any, retrieved from the image
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
exif?: any;
|
||||
/**
|
||||
* The format of the image, ex: jpeg, png, gif.
|
||||
*
|
||||
* iOS and Android only support jpeg.
|
||||
* Web supports jpeg, png and gif, but the exact availability may vary depending on the browser.
|
||||
* gif is only supported if `webUseInput` is set to `true` or if `source` is set to `Photos`.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
format: string;
|
||||
/**
|
||||
* Whether if the image was saved to the gallery or not.
|
||||
*
|
||||
* On Android and iOS, saving to the gallery can fail if the user didn't
|
||||
* grant the required permissions.
|
||||
* On Web there is no gallery, so always returns false.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
saved: boolean;
|
||||
}
|
||||
export interface GalleryPhotos {
|
||||
/**
|
||||
* Array of all the picked photos.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
photos: GalleryPhoto[];
|
||||
}
|
||||
export interface GalleryPhoto {
|
||||
/**
|
||||
* Full, platform-specific file URL that can be read later using the Filesystem API.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* webPath returns a path that can be used to set the src attribute of an image for efficient
|
||||
* loading and rendering.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
webPath: string;
|
||||
/**
|
||||
* Exif data, if any, retrieved from the image
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
exif?: any;
|
||||
/**
|
||||
* The format of the image, ex: jpeg, png, gif.
|
||||
*
|
||||
* iOS and Android only support jpeg.
|
||||
* Web supports jpeg, png and gif.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
format: string;
|
||||
}
|
||||
export interface GalleryImageOptions {
|
||||
/**
|
||||
* The quality of image to return as JPEG, from 0-100
|
||||
* Note: This option is only supported on Android and iOS.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
quality?: number;
|
||||
/**
|
||||
* The desired maximum width of the saved image. The aspect ratio is respected.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
width?: number;
|
||||
/**
|
||||
* The desired maximum height of the saved image. The aspect ratio is respected.
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
height?: number;
|
||||
/**
|
||||
* Whether to automatically rotate the image "up" to correct for orientation
|
||||
* in portrait mode
|
||||
* @default: true
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
correctOrientation?: boolean;
|
||||
/**
|
||||
* iOS only: The presentation style of the Camera.
|
||||
* @default: 'fullscreen'
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
presentationStyle?: 'fullscreen' | 'popover';
|
||||
/**
|
||||
* Maximum number of pictures the user will be able to choose.
|
||||
* Note: This option is only supported on Android 13+ and iOS.
|
||||
*
|
||||
* @default 0 (unlimited)
|
||||
*
|
||||
* @since 1.2.0
|
||||
*/
|
||||
limit?: number;
|
||||
}
|
||||
export declare enum CameraSource {
|
||||
/**
|
||||
* Prompts the user to select either the photo album or take a photo.
|
||||
*/
|
||||
Prompt = "PROMPT",
|
||||
/**
|
||||
* Take a new photo using the camera.
|
||||
*/
|
||||
Camera = "CAMERA",
|
||||
/**
|
||||
* Pick an existing photo from the gallery or photo album.
|
||||
*/
|
||||
Photos = "PHOTOS"
|
||||
}
|
||||
export declare enum CameraDirection {
|
||||
Rear = "REAR",
|
||||
Front = "FRONT"
|
||||
}
|
||||
export declare enum CameraResultType {
|
||||
Uri = "uri",
|
||||
Base64 = "base64",
|
||||
DataUrl = "dataUrl"
|
||||
}
|
||||
/**
|
||||
* @deprecated Use `Photo`.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
export declare type CameraPhoto = Photo;
|
||||
/**
|
||||
* @deprecated Use `ImageOptions`.
|
||||
* @since 1.0.0
|
||||
*/
|
||||
export declare type CameraOptions = ImageOptions;
|
||||
27
node_modules/@capacitor/camera/dist/esm/definitions.js
generated
vendored
Normal file
27
node_modules/@capacitor/camera/dist/esm/definitions.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
export var CameraSource;
|
||||
(function (CameraSource) {
|
||||
/**
|
||||
* Prompts the user to select either the photo album or take a photo.
|
||||
*/
|
||||
CameraSource["Prompt"] = "PROMPT";
|
||||
/**
|
||||
* Take a new photo using the camera.
|
||||
*/
|
||||
CameraSource["Camera"] = "CAMERA";
|
||||
/**
|
||||
* Pick an existing photo from the gallery or photo album.
|
||||
*/
|
||||
CameraSource["Photos"] = "PHOTOS";
|
||||
})(CameraSource || (CameraSource = {}));
|
||||
export var CameraDirection;
|
||||
(function (CameraDirection) {
|
||||
CameraDirection["Rear"] = "REAR";
|
||||
CameraDirection["Front"] = "FRONT";
|
||||
})(CameraDirection || (CameraDirection = {}));
|
||||
export var CameraResultType;
|
||||
(function (CameraResultType) {
|
||||
CameraResultType["Uri"] = "uri";
|
||||
CameraResultType["Base64"] = "base64";
|
||||
CameraResultType["DataUrl"] = "dataUrl";
|
||||
})(CameraResultType || (CameraResultType = {}));
|
||||
//# sourceMappingURL=definitions.js.map
|
||||
1
node_modules/@capacitor/camera/dist/esm/definitions.js.map
generated
vendored
Normal file
1
node_modules/@capacitor/camera/dist/esm/definitions.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
4
node_modules/@capacitor/camera/dist/esm/index.d.ts
generated
vendored
Normal file
4
node_modules/@capacitor/camera/dist/esm/index.d.ts
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
import type { CameraPlugin } from './definitions';
|
||||
declare const Camera: CameraPlugin;
|
||||
export * from './definitions';
|
||||
export { Camera };
|
||||
8
node_modules/@capacitor/camera/dist/esm/index.js
generated
vendored
Normal file
8
node_modules/@capacitor/camera/dist/esm/index.js
generated
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
import { registerPlugin } from '@capacitor/core';
|
||||
import { CameraWeb } from './web';
|
||||
const Camera = registerPlugin('Camera', {
|
||||
web: () => new CameraWeb(),
|
||||
});
|
||||
export * from './definitions';
|
||||
export { Camera };
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@capacitor/camera/dist/esm/index.js.map
generated
vendored
Normal file
1
node_modules/@capacitor/camera/dist/esm/index.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGjD,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAElC,MAAM,MAAM,GAAG,cAAc,CAAe,QAAQ,EAAE;IACpD,GAAG,EAAE,GAAG,EAAE,CAAC,IAAI,SAAS,EAAE;CAC3B,CAAC,CAAC;AAEH,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,CAAC","sourcesContent":["import { registerPlugin } from '@capacitor/core';\n\nimport type { CameraPlugin } from './definitions';\nimport { CameraWeb } from './web';\n\nconst Camera = registerPlugin<CameraPlugin>('Camera', {\n web: () => new CameraWeb(),\n});\n\nexport * from './definitions';\nexport { Camera };\n"]}
|
||||
16
node_modules/@capacitor/camera/dist/esm/web.d.ts
generated
vendored
Normal file
16
node_modules/@capacitor/camera/dist/esm/web.d.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { WebPlugin } from '@capacitor/core';
|
||||
import type { CameraPlugin, GalleryImageOptions, GalleryPhotos, ImageOptions, PermissionStatus, Photo } from './definitions';
|
||||
export declare class CameraWeb extends WebPlugin implements CameraPlugin {
|
||||
getPhoto(options: ImageOptions): Promise<Photo>;
|
||||
pickImages(_options: GalleryImageOptions): Promise<GalleryPhotos>;
|
||||
private cameraExperience;
|
||||
private fileInputExperience;
|
||||
private multipleFileInputExperience;
|
||||
private _getCameraPhoto;
|
||||
checkPermissions(): Promise<PermissionStatus>;
|
||||
requestPermissions(): Promise<PermissionStatus>;
|
||||
pickLimitedLibraryPhotos(): Promise<GalleryPhotos>;
|
||||
getLimitedLibraryPhotos(): Promise<GalleryPhotos>;
|
||||
}
|
||||
declare const Camera: CameraWeb;
|
||||
export { Camera };
|
||||
254
node_modules/@capacitor/camera/dist/esm/web.js
generated
vendored
Normal file
254
node_modules/@capacitor/camera/dist/esm/web.js
generated
vendored
Normal file
@@ -0,0 +1,254 @@
|
||||
import { WebPlugin, CapacitorException } from '@capacitor/core';
|
||||
import { CameraSource, CameraDirection } from './definitions';
|
||||
export class CameraWeb extends WebPlugin {
|
||||
async getPhoto(options) {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (options.webUseInput || options.source === CameraSource.Photos) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
else if (options.source === CameraSource.Prompt) {
|
||||
let actionSheet = document.querySelector('pwa-action-sheet');
|
||||
if (!actionSheet) {
|
||||
actionSheet = document.createElement('pwa-action-sheet');
|
||||
document.body.appendChild(actionSheet);
|
||||
}
|
||||
actionSheet.header = options.promptLabelHeader || 'Photo';
|
||||
actionSheet.cancelable = false;
|
||||
actionSheet.options = [
|
||||
{ title: options.promptLabelPhoto || 'From Photos' },
|
||||
{ title: options.promptLabelPicture || 'Take Picture' },
|
||||
];
|
||||
actionSheet.addEventListener('onSelection', async (e) => {
|
||||
const selection = e.detail;
|
||||
if (selection === 0) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
async pickImages(_options) {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve, reject) => {
|
||||
this.multipleFileInputExperience(resolve, reject);
|
||||
});
|
||||
}
|
||||
async cameraExperience(options, resolve, reject) {
|
||||
if (customElements.get('pwa-camera-modal')) {
|
||||
const cameraModal = document.createElement('pwa-camera-modal');
|
||||
cameraModal.facingMode =
|
||||
options.direction === CameraDirection.Front ? 'user' : 'environment';
|
||||
document.body.appendChild(cameraModal);
|
||||
try {
|
||||
await cameraModal.componentOnReady();
|
||||
cameraModal.addEventListener('onPhoto', async (e) => {
|
||||
const photo = e.detail;
|
||||
if (photo === null) {
|
||||
reject(new CapacitorException('User cancelled photos app'));
|
||||
}
|
||||
else if (photo instanceof Error) {
|
||||
reject(photo);
|
||||
}
|
||||
else {
|
||||
resolve(await this._getCameraPhoto(photo, options));
|
||||
}
|
||||
cameraModal.dismiss();
|
||||
document.body.removeChild(cameraModal);
|
||||
});
|
||||
cameraModal.present();
|
||||
}
|
||||
catch (e) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error(`Unable to load PWA Element 'pwa-camera-modal'. See the docs: https://capacitorjs.com/docs/web/pwa-elements.`);
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
}
|
||||
fileInputExperience(options, resolve, reject) {
|
||||
let input = document.querySelector('#_capacitor-camera-input');
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement('input');
|
||||
input.id = '_capacitor-camera-input';
|
||||
input.type = 'file';
|
||||
input.hidden = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener('change', (_e) => {
|
||||
const file = input.files[0];
|
||||
let format = 'jpeg';
|
||||
if (file.type === 'image/png') {
|
||||
format = 'png';
|
||||
}
|
||||
else if (file.type === 'image/gif') {
|
||||
format = 'gif';
|
||||
}
|
||||
if (options.resultType === 'dataUrl' ||
|
||||
options.resultType === 'base64') {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener('load', () => {
|
||||
if (options.resultType === 'dataUrl') {
|
||||
resolve({
|
||||
dataUrl: reader.result,
|
||||
format,
|
||||
});
|
||||
}
|
||||
else if (options.resultType === 'base64') {
|
||||
const b64 = reader.result.split(',')[1];
|
||||
resolve({
|
||||
base64String: b64,
|
||||
format,
|
||||
});
|
||||
}
|
||||
cleanup();
|
||||
});
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
else {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format: format,
|
||||
});
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
input.addEventListener('cancel', (_e) => {
|
||||
reject(new CapacitorException('User cancelled photos app'));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = 'image/*';
|
||||
input.capture = true;
|
||||
if (options.source === CameraSource.Photos ||
|
||||
options.source === CameraSource.Prompt) {
|
||||
input.removeAttribute('capture');
|
||||
}
|
||||
else if (options.direction === CameraDirection.Front) {
|
||||
input.capture = 'user';
|
||||
}
|
||||
else if (options.direction === CameraDirection.Rear) {
|
||||
input.capture = 'environment';
|
||||
}
|
||||
input.click();
|
||||
}
|
||||
multipleFileInputExperience(resolve, reject) {
|
||||
let input = document.querySelector('#_capacitor-camera-input-multiple');
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement('input');
|
||||
input.id = '_capacitor-camera-input-multiple';
|
||||
input.type = 'file';
|
||||
input.hidden = true;
|
||||
input.multiple = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener('change', (_e) => {
|
||||
const photos = [];
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
||||
for (let i = 0; i < input.files.length; i++) {
|
||||
const file = input.files[i];
|
||||
let format = 'jpeg';
|
||||
if (file.type === 'image/png') {
|
||||
format = 'png';
|
||||
}
|
||||
else if (file.type === 'image/gif') {
|
||||
format = 'gif';
|
||||
}
|
||||
photos.push({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format: format,
|
||||
});
|
||||
}
|
||||
resolve({ photos });
|
||||
cleanup();
|
||||
});
|
||||
input.addEventListener('cancel', (_e) => {
|
||||
reject(new CapacitorException('User cancelled photos app'));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = 'image/*';
|
||||
input.click();
|
||||
}
|
||||
_getCameraPhoto(photo, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
const format = photo.type.split('/')[1];
|
||||
if (options.resultType === 'uri') {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(photo),
|
||||
format: format,
|
||||
saved: false,
|
||||
});
|
||||
}
|
||||
else {
|
||||
reader.readAsDataURL(photo);
|
||||
reader.onloadend = () => {
|
||||
const r = reader.result;
|
||||
if (options.resultType === 'dataUrl') {
|
||||
resolve({
|
||||
dataUrl: r,
|
||||
format: format,
|
||||
saved: false,
|
||||
});
|
||||
}
|
||||
else {
|
||||
resolve({
|
||||
base64String: r.split(',')[1],
|
||||
format: format,
|
||||
saved: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.onerror = e => {
|
||||
reject(e);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
async checkPermissions() {
|
||||
if (typeof navigator === 'undefined' || !navigator.permissions) {
|
||||
throw this.unavailable('Permissions API not available in this browser');
|
||||
}
|
||||
try {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Permissions/query
|
||||
// the specific permissions that are supported varies among browsers that implement the
|
||||
// permissions API, so we need a try/catch in case 'camera' is invalid
|
||||
const permission = await window.navigator.permissions.query({
|
||||
name: 'camera',
|
||||
});
|
||||
return {
|
||||
camera: permission.state,
|
||||
photos: 'granted',
|
||||
};
|
||||
}
|
||||
catch (_a) {
|
||||
throw this.unavailable('Camera permissions are not available in this browser');
|
||||
}
|
||||
}
|
||||
async requestPermissions() {
|
||||
throw this.unimplemented('Not implemented on web.');
|
||||
}
|
||||
async pickLimitedLibraryPhotos() {
|
||||
throw this.unavailable('Not implemented on web.');
|
||||
}
|
||||
async getLimitedLibraryPhotos() {
|
||||
throw this.unavailable('Not implemented on web.');
|
||||
}
|
||||
}
|
||||
const Camera = new CameraWeb();
|
||||
export { Camera };
|
||||
//# sourceMappingURL=web.js.map
|
||||
1
node_modules/@capacitor/camera/dist/esm/web.js.map
generated
vendored
Normal file
1
node_modules/@capacitor/camera/dist/esm/web.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
288
node_modules/@capacitor/camera/dist/plugin.cjs.js
generated
vendored
Normal file
288
node_modules/@capacitor/camera/dist/plugin.cjs.js
generated
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
'use strict';
|
||||
|
||||
var core = require('@capacitor/core');
|
||||
|
||||
exports.CameraSource = void 0;
|
||||
(function (CameraSource) {
|
||||
/**
|
||||
* Prompts the user to select either the photo album or take a photo.
|
||||
*/
|
||||
CameraSource["Prompt"] = "PROMPT";
|
||||
/**
|
||||
* Take a new photo using the camera.
|
||||
*/
|
||||
CameraSource["Camera"] = "CAMERA";
|
||||
/**
|
||||
* Pick an existing photo from the gallery or photo album.
|
||||
*/
|
||||
CameraSource["Photos"] = "PHOTOS";
|
||||
})(exports.CameraSource || (exports.CameraSource = {}));
|
||||
exports.CameraDirection = void 0;
|
||||
(function (CameraDirection) {
|
||||
CameraDirection["Rear"] = "REAR";
|
||||
CameraDirection["Front"] = "FRONT";
|
||||
})(exports.CameraDirection || (exports.CameraDirection = {}));
|
||||
exports.CameraResultType = void 0;
|
||||
(function (CameraResultType) {
|
||||
CameraResultType["Uri"] = "uri";
|
||||
CameraResultType["Base64"] = "base64";
|
||||
CameraResultType["DataUrl"] = "dataUrl";
|
||||
})(exports.CameraResultType || (exports.CameraResultType = {}));
|
||||
|
||||
class CameraWeb extends core.WebPlugin {
|
||||
async getPhoto(options) {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (options.webUseInput || options.source === exports.CameraSource.Photos) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
else if (options.source === exports.CameraSource.Prompt) {
|
||||
let actionSheet = document.querySelector('pwa-action-sheet');
|
||||
if (!actionSheet) {
|
||||
actionSheet = document.createElement('pwa-action-sheet');
|
||||
document.body.appendChild(actionSheet);
|
||||
}
|
||||
actionSheet.header = options.promptLabelHeader || 'Photo';
|
||||
actionSheet.cancelable = false;
|
||||
actionSheet.options = [
|
||||
{ title: options.promptLabelPhoto || 'From Photos' },
|
||||
{ title: options.promptLabelPicture || 'Take Picture' },
|
||||
];
|
||||
actionSheet.addEventListener('onSelection', async (e) => {
|
||||
const selection = e.detail;
|
||||
if (selection === 0) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
async pickImages(_options) {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve, reject) => {
|
||||
this.multipleFileInputExperience(resolve, reject);
|
||||
});
|
||||
}
|
||||
async cameraExperience(options, resolve, reject) {
|
||||
if (customElements.get('pwa-camera-modal')) {
|
||||
const cameraModal = document.createElement('pwa-camera-modal');
|
||||
cameraModal.facingMode =
|
||||
options.direction === exports.CameraDirection.Front ? 'user' : 'environment';
|
||||
document.body.appendChild(cameraModal);
|
||||
try {
|
||||
await cameraModal.componentOnReady();
|
||||
cameraModal.addEventListener('onPhoto', async (e) => {
|
||||
const photo = e.detail;
|
||||
if (photo === null) {
|
||||
reject(new core.CapacitorException('User cancelled photos app'));
|
||||
}
|
||||
else if (photo instanceof Error) {
|
||||
reject(photo);
|
||||
}
|
||||
else {
|
||||
resolve(await this._getCameraPhoto(photo, options));
|
||||
}
|
||||
cameraModal.dismiss();
|
||||
document.body.removeChild(cameraModal);
|
||||
});
|
||||
cameraModal.present();
|
||||
}
|
||||
catch (e) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error(`Unable to load PWA Element 'pwa-camera-modal'. See the docs: https://capacitorjs.com/docs/web/pwa-elements.`);
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
}
|
||||
fileInputExperience(options, resolve, reject) {
|
||||
let input = document.querySelector('#_capacitor-camera-input');
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement('input');
|
||||
input.id = '_capacitor-camera-input';
|
||||
input.type = 'file';
|
||||
input.hidden = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener('change', (_e) => {
|
||||
const file = input.files[0];
|
||||
let format = 'jpeg';
|
||||
if (file.type === 'image/png') {
|
||||
format = 'png';
|
||||
}
|
||||
else if (file.type === 'image/gif') {
|
||||
format = 'gif';
|
||||
}
|
||||
if (options.resultType === 'dataUrl' ||
|
||||
options.resultType === 'base64') {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener('load', () => {
|
||||
if (options.resultType === 'dataUrl') {
|
||||
resolve({
|
||||
dataUrl: reader.result,
|
||||
format,
|
||||
});
|
||||
}
|
||||
else if (options.resultType === 'base64') {
|
||||
const b64 = reader.result.split(',')[1];
|
||||
resolve({
|
||||
base64String: b64,
|
||||
format,
|
||||
});
|
||||
}
|
||||
cleanup();
|
||||
});
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
else {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format: format,
|
||||
});
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
input.addEventListener('cancel', (_e) => {
|
||||
reject(new core.CapacitorException('User cancelled photos app'));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = 'image/*';
|
||||
input.capture = true;
|
||||
if (options.source === exports.CameraSource.Photos ||
|
||||
options.source === exports.CameraSource.Prompt) {
|
||||
input.removeAttribute('capture');
|
||||
}
|
||||
else if (options.direction === exports.CameraDirection.Front) {
|
||||
input.capture = 'user';
|
||||
}
|
||||
else if (options.direction === exports.CameraDirection.Rear) {
|
||||
input.capture = 'environment';
|
||||
}
|
||||
input.click();
|
||||
}
|
||||
multipleFileInputExperience(resolve, reject) {
|
||||
let input = document.querySelector('#_capacitor-camera-input-multiple');
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement('input');
|
||||
input.id = '_capacitor-camera-input-multiple';
|
||||
input.type = 'file';
|
||||
input.hidden = true;
|
||||
input.multiple = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener('change', (_e) => {
|
||||
const photos = [];
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
||||
for (let i = 0; i < input.files.length; i++) {
|
||||
const file = input.files[i];
|
||||
let format = 'jpeg';
|
||||
if (file.type === 'image/png') {
|
||||
format = 'png';
|
||||
}
|
||||
else if (file.type === 'image/gif') {
|
||||
format = 'gif';
|
||||
}
|
||||
photos.push({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format: format,
|
||||
});
|
||||
}
|
||||
resolve({ photos });
|
||||
cleanup();
|
||||
});
|
||||
input.addEventListener('cancel', (_e) => {
|
||||
reject(new core.CapacitorException('User cancelled photos app'));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = 'image/*';
|
||||
input.click();
|
||||
}
|
||||
_getCameraPhoto(photo, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
const format = photo.type.split('/')[1];
|
||||
if (options.resultType === 'uri') {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(photo),
|
||||
format: format,
|
||||
saved: false,
|
||||
});
|
||||
}
|
||||
else {
|
||||
reader.readAsDataURL(photo);
|
||||
reader.onloadend = () => {
|
||||
const r = reader.result;
|
||||
if (options.resultType === 'dataUrl') {
|
||||
resolve({
|
||||
dataUrl: r,
|
||||
format: format,
|
||||
saved: false,
|
||||
});
|
||||
}
|
||||
else {
|
||||
resolve({
|
||||
base64String: r.split(',')[1],
|
||||
format: format,
|
||||
saved: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.onerror = e => {
|
||||
reject(e);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
async checkPermissions() {
|
||||
if (typeof navigator === 'undefined' || !navigator.permissions) {
|
||||
throw this.unavailable('Permissions API not available in this browser');
|
||||
}
|
||||
try {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Permissions/query
|
||||
// the specific permissions that are supported varies among browsers that implement the
|
||||
// permissions API, so we need a try/catch in case 'camera' is invalid
|
||||
const permission = await window.navigator.permissions.query({
|
||||
name: 'camera',
|
||||
});
|
||||
return {
|
||||
camera: permission.state,
|
||||
photos: 'granted',
|
||||
};
|
||||
}
|
||||
catch (_a) {
|
||||
throw this.unavailable('Camera permissions are not available in this browser');
|
||||
}
|
||||
}
|
||||
async requestPermissions() {
|
||||
throw this.unimplemented('Not implemented on web.');
|
||||
}
|
||||
async pickLimitedLibraryPhotos() {
|
||||
throw this.unavailable('Not implemented on web.');
|
||||
}
|
||||
async getLimitedLibraryPhotos() {
|
||||
throw this.unavailable('Not implemented on web.');
|
||||
}
|
||||
}
|
||||
new CameraWeb();
|
||||
|
||||
const Camera = core.registerPlugin('Camera', {
|
||||
web: () => new CameraWeb(),
|
||||
});
|
||||
|
||||
exports.Camera = Camera;
|
||||
//# sourceMappingURL=plugin.cjs.js.map
|
||||
1
node_modules/@capacitor/camera/dist/plugin.cjs.js.map
generated
vendored
Normal file
1
node_modules/@capacitor/camera/dist/plugin.cjs.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
291
node_modules/@capacitor/camera/dist/plugin.js
generated
vendored
Normal file
291
node_modules/@capacitor/camera/dist/plugin.js
generated
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
var capacitorCamera = (function (exports, core) {
|
||||
'use strict';
|
||||
|
||||
exports.CameraSource = void 0;
|
||||
(function (CameraSource) {
|
||||
/**
|
||||
* Prompts the user to select either the photo album or take a photo.
|
||||
*/
|
||||
CameraSource["Prompt"] = "PROMPT";
|
||||
/**
|
||||
* Take a new photo using the camera.
|
||||
*/
|
||||
CameraSource["Camera"] = "CAMERA";
|
||||
/**
|
||||
* Pick an existing photo from the gallery or photo album.
|
||||
*/
|
||||
CameraSource["Photos"] = "PHOTOS";
|
||||
})(exports.CameraSource || (exports.CameraSource = {}));
|
||||
exports.CameraDirection = void 0;
|
||||
(function (CameraDirection) {
|
||||
CameraDirection["Rear"] = "REAR";
|
||||
CameraDirection["Front"] = "FRONT";
|
||||
})(exports.CameraDirection || (exports.CameraDirection = {}));
|
||||
exports.CameraResultType = void 0;
|
||||
(function (CameraResultType) {
|
||||
CameraResultType["Uri"] = "uri";
|
||||
CameraResultType["Base64"] = "base64";
|
||||
CameraResultType["DataUrl"] = "dataUrl";
|
||||
})(exports.CameraResultType || (exports.CameraResultType = {}));
|
||||
|
||||
class CameraWeb extends core.WebPlugin {
|
||||
async getPhoto(options) {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve, reject) => {
|
||||
if (options.webUseInput || options.source === exports.CameraSource.Photos) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
else if (options.source === exports.CameraSource.Prompt) {
|
||||
let actionSheet = document.querySelector('pwa-action-sheet');
|
||||
if (!actionSheet) {
|
||||
actionSheet = document.createElement('pwa-action-sheet');
|
||||
document.body.appendChild(actionSheet);
|
||||
}
|
||||
actionSheet.header = options.promptLabelHeader || 'Photo';
|
||||
actionSheet.cancelable = false;
|
||||
actionSheet.options = [
|
||||
{ title: options.promptLabelPhoto || 'From Photos' },
|
||||
{ title: options.promptLabelPicture || 'Take Picture' },
|
||||
];
|
||||
actionSheet.addEventListener('onSelection', async (e) => {
|
||||
const selection = e.detail;
|
||||
if (selection === 0) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.cameraExperience(options, resolve, reject);
|
||||
}
|
||||
});
|
||||
}
|
||||
async pickImages(_options) {
|
||||
// eslint-disable-next-line no-async-promise-executor
|
||||
return new Promise(async (resolve, reject) => {
|
||||
this.multipleFileInputExperience(resolve, reject);
|
||||
});
|
||||
}
|
||||
async cameraExperience(options, resolve, reject) {
|
||||
if (customElements.get('pwa-camera-modal')) {
|
||||
const cameraModal = document.createElement('pwa-camera-modal');
|
||||
cameraModal.facingMode =
|
||||
options.direction === exports.CameraDirection.Front ? 'user' : 'environment';
|
||||
document.body.appendChild(cameraModal);
|
||||
try {
|
||||
await cameraModal.componentOnReady();
|
||||
cameraModal.addEventListener('onPhoto', async (e) => {
|
||||
const photo = e.detail;
|
||||
if (photo === null) {
|
||||
reject(new core.CapacitorException('User cancelled photos app'));
|
||||
}
|
||||
else if (photo instanceof Error) {
|
||||
reject(photo);
|
||||
}
|
||||
else {
|
||||
resolve(await this._getCameraPhoto(photo, options));
|
||||
}
|
||||
cameraModal.dismiss();
|
||||
document.body.removeChild(cameraModal);
|
||||
});
|
||||
cameraModal.present();
|
||||
}
|
||||
catch (e) {
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.error(`Unable to load PWA Element 'pwa-camera-modal'. See the docs: https://capacitorjs.com/docs/web/pwa-elements.`);
|
||||
this.fileInputExperience(options, resolve, reject);
|
||||
}
|
||||
}
|
||||
fileInputExperience(options, resolve, reject) {
|
||||
let input = document.querySelector('#_capacitor-camera-input');
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement('input');
|
||||
input.id = '_capacitor-camera-input';
|
||||
input.type = 'file';
|
||||
input.hidden = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener('change', (_e) => {
|
||||
const file = input.files[0];
|
||||
let format = 'jpeg';
|
||||
if (file.type === 'image/png') {
|
||||
format = 'png';
|
||||
}
|
||||
else if (file.type === 'image/gif') {
|
||||
format = 'gif';
|
||||
}
|
||||
if (options.resultType === 'dataUrl' ||
|
||||
options.resultType === 'base64') {
|
||||
const reader = new FileReader();
|
||||
reader.addEventListener('load', () => {
|
||||
if (options.resultType === 'dataUrl') {
|
||||
resolve({
|
||||
dataUrl: reader.result,
|
||||
format,
|
||||
});
|
||||
}
|
||||
else if (options.resultType === 'base64') {
|
||||
const b64 = reader.result.split(',')[1];
|
||||
resolve({
|
||||
base64String: b64,
|
||||
format,
|
||||
});
|
||||
}
|
||||
cleanup();
|
||||
});
|
||||
reader.readAsDataURL(file);
|
||||
}
|
||||
else {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format: format,
|
||||
});
|
||||
cleanup();
|
||||
}
|
||||
});
|
||||
input.addEventListener('cancel', (_e) => {
|
||||
reject(new core.CapacitorException('User cancelled photos app'));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = 'image/*';
|
||||
input.capture = true;
|
||||
if (options.source === exports.CameraSource.Photos ||
|
||||
options.source === exports.CameraSource.Prompt) {
|
||||
input.removeAttribute('capture');
|
||||
}
|
||||
else if (options.direction === exports.CameraDirection.Front) {
|
||||
input.capture = 'user';
|
||||
}
|
||||
else if (options.direction === exports.CameraDirection.Rear) {
|
||||
input.capture = 'environment';
|
||||
}
|
||||
input.click();
|
||||
}
|
||||
multipleFileInputExperience(resolve, reject) {
|
||||
let input = document.querySelector('#_capacitor-camera-input-multiple');
|
||||
const cleanup = () => {
|
||||
var _a;
|
||||
(_a = input.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(input);
|
||||
};
|
||||
if (!input) {
|
||||
input = document.createElement('input');
|
||||
input.id = '_capacitor-camera-input-multiple';
|
||||
input.type = 'file';
|
||||
input.hidden = true;
|
||||
input.multiple = true;
|
||||
document.body.appendChild(input);
|
||||
input.addEventListener('change', (_e) => {
|
||||
const photos = [];
|
||||
// eslint-disable-next-line @typescript-eslint/prefer-for-of
|
||||
for (let i = 0; i < input.files.length; i++) {
|
||||
const file = input.files[i];
|
||||
let format = 'jpeg';
|
||||
if (file.type === 'image/png') {
|
||||
format = 'png';
|
||||
}
|
||||
else if (file.type === 'image/gif') {
|
||||
format = 'gif';
|
||||
}
|
||||
photos.push({
|
||||
webPath: URL.createObjectURL(file),
|
||||
format: format,
|
||||
});
|
||||
}
|
||||
resolve({ photos });
|
||||
cleanup();
|
||||
});
|
||||
input.addEventListener('cancel', (_e) => {
|
||||
reject(new core.CapacitorException('User cancelled photos app'));
|
||||
cleanup();
|
||||
});
|
||||
}
|
||||
input.accept = 'image/*';
|
||||
input.click();
|
||||
}
|
||||
_getCameraPhoto(photo, options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const reader = new FileReader();
|
||||
const format = photo.type.split('/')[1];
|
||||
if (options.resultType === 'uri') {
|
||||
resolve({
|
||||
webPath: URL.createObjectURL(photo),
|
||||
format: format,
|
||||
saved: false,
|
||||
});
|
||||
}
|
||||
else {
|
||||
reader.readAsDataURL(photo);
|
||||
reader.onloadend = () => {
|
||||
const r = reader.result;
|
||||
if (options.resultType === 'dataUrl') {
|
||||
resolve({
|
||||
dataUrl: r,
|
||||
format: format,
|
||||
saved: false,
|
||||
});
|
||||
}
|
||||
else {
|
||||
resolve({
|
||||
base64String: r.split(',')[1],
|
||||
format: format,
|
||||
saved: false,
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.onerror = e => {
|
||||
reject(e);
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
async checkPermissions() {
|
||||
if (typeof navigator === 'undefined' || !navigator.permissions) {
|
||||
throw this.unavailable('Permissions API not available in this browser');
|
||||
}
|
||||
try {
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/Permissions/query
|
||||
// the specific permissions that are supported varies among browsers that implement the
|
||||
// permissions API, so we need a try/catch in case 'camera' is invalid
|
||||
const permission = await window.navigator.permissions.query({
|
||||
name: 'camera',
|
||||
});
|
||||
return {
|
||||
camera: permission.state,
|
||||
photos: 'granted',
|
||||
};
|
||||
}
|
||||
catch (_a) {
|
||||
throw this.unavailable('Camera permissions are not available in this browser');
|
||||
}
|
||||
}
|
||||
async requestPermissions() {
|
||||
throw this.unimplemented('Not implemented on web.');
|
||||
}
|
||||
async pickLimitedLibraryPhotos() {
|
||||
throw this.unavailable('Not implemented on web.');
|
||||
}
|
||||
async getLimitedLibraryPhotos() {
|
||||
throw this.unavailable('Not implemented on web.');
|
||||
}
|
||||
}
|
||||
new CameraWeb();
|
||||
|
||||
const Camera = core.registerPlugin('Camera', {
|
||||
web: () => new CameraWeb(),
|
||||
});
|
||||
|
||||
exports.Camera = Camera;
|
||||
|
||||
return exports;
|
||||
|
||||
})({}, capacitorExports);
|
||||
//# sourceMappingURL=plugin.js.map
|
||||
1
node_modules/@capacitor/camera/dist/plugin.js.map
generated
vendored
Normal file
1
node_modules/@capacitor/camera/dist/plugin.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
100
node_modules/@capacitor/camera/ios/Sources/CameraPlugin/CameraExtensions.swift
generated
vendored
Normal file
100
node_modules/@capacitor/camera/ios/Sources/CameraPlugin/CameraExtensions.swift
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
import UIKit
|
||||
import Photos
|
||||
|
||||
internal protocol CameraAuthorizationState {
|
||||
var authorizationState: String { get }
|
||||
}
|
||||
|
||||
extension AVAuthorizationStatus: CameraAuthorizationState {
|
||||
var authorizationState: String {
|
||||
switch self {
|
||||
case .denied, .restricted:
|
||||
return "denied"
|
||||
case .authorized:
|
||||
return "granted"
|
||||
case .notDetermined:
|
||||
fallthrough
|
||||
@unknown default:
|
||||
return "prompt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension PHAuthorizationStatus: CameraAuthorizationState {
|
||||
var authorizationState: String {
|
||||
switch self {
|
||||
case .denied, .restricted:
|
||||
return "denied"
|
||||
case .authorized:
|
||||
return "granted"
|
||||
case .limited:
|
||||
return "limited"
|
||||
case .notDetermined:
|
||||
fallthrough
|
||||
@unknown default:
|
||||
return "prompt"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal extension PHAsset {
|
||||
/**
|
||||
Retrieves the image metadata for the asset.
|
||||
*/
|
||||
var imageData: [String: Any] {
|
||||
let options = PHImageRequestOptions()
|
||||
options.isSynchronous = true
|
||||
options.resizeMode = .none
|
||||
options.isNetworkAccessAllowed = false
|
||||
options.version = .current
|
||||
|
||||
var result: [String: Any] = [:]
|
||||
_ = PHCachingImageManager().requestImageDataAndOrientation(for: self, options: options) { (data, _, _, _) in
|
||||
if let data = data as NSData? {
|
||||
let options = [kCGImageSourceShouldCache as String: kCFBooleanFalse] as CFDictionary
|
||||
if let imgSrc = CGImageSourceCreateWithData(data, options),
|
||||
let metadata = CGImageSourceCopyPropertiesAtIndex(imgSrc, 0, options) as? [String: Any] {
|
||||
result = metadata
|
||||
}
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
internal extension UIImage {
|
||||
/**
|
||||
Generates a new image from the existing one, implicitly resetting any orientation.
|
||||
Dimensions greater than 0 will resize the image while preserving the aspect ratio.
|
||||
*/
|
||||
func reformat(to size: CGSize? = nil) -> UIImage {
|
||||
let imageHeight = self.size.height
|
||||
let imageWidth = self.size.width
|
||||
// determine the max dimensions, 0 is treated as 'no restriction'
|
||||
var maxWidth: CGFloat
|
||||
if let size = size, size.width > 0 {
|
||||
maxWidth = size.width
|
||||
} else {
|
||||
maxWidth = imageWidth
|
||||
}
|
||||
let maxHeight: CGFloat
|
||||
if let size = size, size.height > 0 {
|
||||
maxHeight = size.height
|
||||
} else {
|
||||
maxHeight = imageHeight
|
||||
}
|
||||
// adjust to preserve aspect ratio
|
||||
var targetWidth = min(imageWidth, maxWidth)
|
||||
var targetHeight = (imageHeight * targetWidth) / imageWidth
|
||||
if targetHeight > maxHeight {
|
||||
targetWidth = (imageWidth * maxHeight) / imageHeight
|
||||
targetHeight = maxHeight
|
||||
}
|
||||
// generate the new image and return
|
||||
UIGraphicsBeginImageContextWithOptions(.init(width: targetWidth, height: targetHeight), false, 1.0) // size, opaque and scale
|
||||
self.draw(in: .init(origin: .zero, size: .init(width: targetWidth, height: targetHeight)))
|
||||
let resizedImage = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return resizedImage ?? self
|
||||
}
|
||||
}
|
||||
584
node_modules/@capacitor/camera/ios/Sources/CameraPlugin/CameraPlugin.swift
generated
vendored
Normal file
584
node_modules/@capacitor/camera/ios/Sources/CameraPlugin/CameraPlugin.swift
generated
vendored
Normal file
@@ -0,0 +1,584 @@
|
||||
import Foundation
|
||||
import Capacitor
|
||||
import Photos
|
||||
import PhotosUI
|
||||
|
||||
@objc(CAPCameraPlugin)
|
||||
public class CameraPlugin: CAPPlugin, CAPBridgedPlugin {
|
||||
public let identifier = "CAPCameraPlugin"
|
||||
public let jsName = "Camera"
|
||||
public let pluginMethods: [CAPPluginMethod] = [
|
||||
CAPPluginMethod(name: "getPhoto", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "pickImages", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "checkPermissions", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "requestPermissions", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "pickLimitedLibraryPhotos", returnType: CAPPluginReturnPromise),
|
||||
CAPPluginMethod(name: "getLimitedLibraryPhotos", returnType: CAPPluginReturnPromise)
|
||||
]
|
||||
private var call: CAPPluginCall?
|
||||
private var settings = CameraSettings()
|
||||
private let defaultSource = CameraSource.prompt
|
||||
private let defaultDirection = CameraDirection.rear
|
||||
private var multiple = false
|
||||
|
||||
private var imageCounter = 0
|
||||
|
||||
@objc override public func checkPermissions(_ call: CAPPluginCall) {
|
||||
var result: [String: Any] = [:]
|
||||
for permission in CameraPermissionType.allCases {
|
||||
let state: String
|
||||
switch permission {
|
||||
case .camera:
|
||||
state = AVCaptureDevice.authorizationStatus(for: .video).authorizationState
|
||||
case .photos:
|
||||
if #available(iOS 14, *) {
|
||||
state = PHPhotoLibrary.authorizationStatus(for: .readWrite).authorizationState
|
||||
} else {
|
||||
state = PHPhotoLibrary.authorizationStatus().authorizationState
|
||||
}
|
||||
}
|
||||
result[permission.rawValue] = state
|
||||
}
|
||||
call.resolve(result)
|
||||
}
|
||||
|
||||
@objc override public func requestPermissions(_ call: CAPPluginCall) {
|
||||
// get the list of desired types, if passed
|
||||
let typeList = call.getArray("permissions", String.self)?.compactMap({ (type) -> CameraPermissionType? in
|
||||
return CameraPermissionType(rawValue: type)
|
||||
}) ?? []
|
||||
// otherwise check everything
|
||||
let permissions: [CameraPermissionType] = (typeList.count > 0) ? typeList : CameraPermissionType.allCases
|
||||
// request the permissions
|
||||
let group = DispatchGroup()
|
||||
for permission in permissions {
|
||||
switch permission {
|
||||
case .camera:
|
||||
group.enter()
|
||||
AVCaptureDevice.requestAccess(for: .video) { _ in
|
||||
group.leave()
|
||||
}
|
||||
case .photos:
|
||||
group.enter()
|
||||
if #available(iOS 14, *) {
|
||||
PHPhotoLibrary.requestAuthorization(for: .readWrite) { (_) in
|
||||
group.leave()
|
||||
}
|
||||
} else {
|
||||
PHPhotoLibrary.requestAuthorization({ (_) in
|
||||
group.leave()
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
group.notify(queue: DispatchQueue.main) { [weak self] in
|
||||
self?.checkPermissions(call)
|
||||
}
|
||||
}
|
||||
|
||||
@objc func pickLimitedLibraryPhotos(_ call: CAPPluginCall) {
|
||||
if #available(iOS 14, *) {
|
||||
PHPhotoLibrary.requestAuthorization(for: .readWrite) { (granted) in
|
||||
if granted == .limited {
|
||||
if let viewController = self.bridge?.viewController {
|
||||
if #available(iOS 15, *) {
|
||||
PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: viewController) { _ in
|
||||
self.getLimitedLibraryPhotos(call)
|
||||
}
|
||||
} else {
|
||||
PHPhotoLibrary.shared().presentLimitedLibraryPicker(from: viewController)
|
||||
call.resolve([
|
||||
"photos": []
|
||||
])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
call.resolve([
|
||||
"photos": []
|
||||
])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
call.unavailable("Not available on iOS 13")
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getLimitedLibraryPhotos(_ call: CAPPluginCall) {
|
||||
if #available(iOS 14, *) {
|
||||
PHPhotoLibrary.requestAuthorization(for: .readWrite) { (granted) in
|
||||
if granted == .limited {
|
||||
|
||||
self.call = call
|
||||
|
||||
DispatchQueue.global(qos: .utility).async {
|
||||
let assets = PHAsset.fetchAssets(with: .image, options: nil)
|
||||
var processedImages: [ProcessedImage] = []
|
||||
|
||||
let imageManager = PHImageManager.default()
|
||||
let options = PHImageRequestOptions()
|
||||
options.deliveryMode = .highQualityFormat
|
||||
|
||||
let group = DispatchGroup()
|
||||
if assets.count > 0 {
|
||||
for index in 0...(assets.count - 1) {
|
||||
let asset = assets.object(at: index)
|
||||
let fullSize = CGSize(width: asset.pixelWidth, height: asset.pixelHeight)
|
||||
|
||||
group.enter()
|
||||
imageManager.requestImage(for: asset, targetSize: fullSize, contentMode: .default, options: options) { image, _ in
|
||||
guard let image = image else {
|
||||
group.leave()
|
||||
return
|
||||
}
|
||||
processedImages.append(self.processedImage(from: image, with: asset.imageData))
|
||||
group.leave()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
group.notify(queue: .global(qos: .utility)) { [weak self] in
|
||||
self?.returnImages(processedImages)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
call.resolve([
|
||||
"photos": []
|
||||
])
|
||||
}
|
||||
}
|
||||
} else {
|
||||
call.unavailable("Not available on iOS 13")
|
||||
}
|
||||
}
|
||||
|
||||
@objc func getPhoto(_ call: CAPPluginCall) {
|
||||
self.multiple = false
|
||||
self.call = call
|
||||
self.settings = cameraSettings(from: call)
|
||||
|
||||
// Make sure they have all the necessary info.plist settings
|
||||
if let missingUsageDescription = checkUsageDescriptions() {
|
||||
CAPLog.print("⚡️ ", self.pluginId, "-", missingUsageDescription)
|
||||
call.reject(missingUsageDescription)
|
||||
return
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
switch self.settings.source {
|
||||
case .prompt:
|
||||
self.showPrompt()
|
||||
case .camera:
|
||||
self.showCamera()
|
||||
case .photos:
|
||||
self.showPhotos()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc func pickImages(_ call: CAPPluginCall) {
|
||||
self.multiple = true
|
||||
self.call = call
|
||||
self.settings = cameraSettings(from: call)
|
||||
DispatchQueue.main.async {
|
||||
self.showPhotos()
|
||||
}
|
||||
}
|
||||
|
||||
private func checkUsageDescriptions() -> String? {
|
||||
if let dict = Bundle.main.infoDictionary {
|
||||
for key in CameraPropertyListKeys.allCases where dict[key.rawValue] == nil {
|
||||
return key.missingMessage
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
private func cameraSettings(from call: CAPPluginCall) -> CameraSettings {
|
||||
var settings = CameraSettings()
|
||||
settings.jpegQuality = min(abs(CGFloat(call.getFloat("quality") ?? 100.0)) / 100.0, 1.0)
|
||||
settings.allowEditing = call.getBool("allowEditing") ?? false
|
||||
settings.source = CameraSource(rawValue: call.getString("source") ?? defaultSource.rawValue) ?? defaultSource
|
||||
settings.direction = CameraDirection(rawValue: call.getString("direction") ?? defaultDirection.rawValue) ?? defaultDirection
|
||||
if let typeString = call.getString("resultType"), let type = CameraResultType(rawValue: typeString) {
|
||||
settings.resultType = type
|
||||
}
|
||||
settings.saveToGallery = call.getBool("saveToGallery") ?? false
|
||||
|
||||
// Get the new image dimensions if provided
|
||||
settings.width = CGFloat(call.getInt("width") ?? 0)
|
||||
settings.height = CGFloat(call.getInt("height") ?? 0)
|
||||
if settings.width > 0 || settings.height > 0 {
|
||||
// We resize only if a dimension was provided
|
||||
settings.shouldResize = true
|
||||
}
|
||||
settings.shouldCorrectOrientation = call.getBool("correctOrientation") ?? true
|
||||
settings.userPromptText = CameraPromptText(title: call.getString("promptLabelHeader"),
|
||||
photoAction: call.getString("promptLabelPhoto"),
|
||||
cameraAction: call.getString("promptLabelPicture"),
|
||||
cancelAction: call.getString("promptLabelCancel"))
|
||||
if let styleString = call.getString("presentationStyle"), styleString == "popover" {
|
||||
settings.presentationStyle = .popover
|
||||
} else {
|
||||
settings.presentationStyle = .fullScreen
|
||||
}
|
||||
|
||||
return settings
|
||||
}
|
||||
}
|
||||
|
||||
// public delegate methods
|
||||
extension CameraPlugin: UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIPopoverPresentationControllerDelegate {
|
||||
public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
|
||||
picker.dismiss(animated: true)
|
||||
self.call?.reject("User cancelled photos app")
|
||||
}
|
||||
|
||||
public func popoverPresentationControllerDidDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) {
|
||||
self.call?.reject("User cancelled photos app")
|
||||
}
|
||||
|
||||
public func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
|
||||
self.call?.reject("User cancelled photos app")
|
||||
}
|
||||
|
||||
public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
|
||||
picker.dismiss(animated: true) {
|
||||
if let processedImage = self.processImage(from: info) {
|
||||
self.returnProcessedImage(processedImage)
|
||||
} else {
|
||||
self.call?.reject("Error processing image")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@available(iOS 14, *)
|
||||
extension CameraPlugin: PHPickerViewControllerDelegate {
|
||||
public func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
|
||||
picker.dismiss(animated: true, completion: nil)
|
||||
|
||||
guard !results.isEmpty else {
|
||||
self.call?.reject("User cancelled photos app")
|
||||
return
|
||||
}
|
||||
|
||||
self.fetchProcessedImages(from: results) { [weak self] processedImageArray in
|
||||
guard let processedImageArray else {
|
||||
self?.call?.reject("Error loading image")
|
||||
return
|
||||
}
|
||||
|
||||
if self?.multiple == true {
|
||||
self?.returnImages(processedImageArray)
|
||||
} else if var processedImage = processedImageArray.first {
|
||||
processedImage.flags = .gallery
|
||||
self?.returnProcessedImage(processedImage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func fetchProcessedImages(from pickerResultArray: [PHPickerResult], accumulating: [ProcessedImage] = [], _ completionHandler: @escaping ([ProcessedImage]?) -> Void) {
|
||||
func loadImage(from pickerResult: PHPickerResult, _ completionHandler: @escaping (UIImage?) -> Void) {
|
||||
let itemProvider = pickerResult.itemProvider
|
||||
if itemProvider.canLoadObject(ofClass: UIImage.self) {
|
||||
// extract the image
|
||||
itemProvider.loadObject(ofClass: UIImage.self) { itemProviderReading, _ in
|
||||
completionHandler(itemProviderReading as? UIImage)
|
||||
}
|
||||
} else {
|
||||
// extract the image's data representation
|
||||
itemProvider.loadDataRepresentation(forTypeIdentifier: UTType.image.identifier) { data, _ in
|
||||
guard let data else {
|
||||
return completionHandler(nil)
|
||||
}
|
||||
completionHandler(UIImage(data: data))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
guard let currentPickerResult = pickerResultArray.first else { return completionHandler(accumulating) }
|
||||
|
||||
loadImage(from: currentPickerResult) { [weak self] loadedImage in
|
||||
guard let self, let loadedImage else { return completionHandler(nil) }
|
||||
var asset: PHAsset?
|
||||
if let assetId = currentPickerResult.assetIdentifier {
|
||||
asset = PHAsset.fetchAssets(withLocalIdentifiers: [assetId], options: nil).firstObject
|
||||
}
|
||||
let newElement = self.processedImage(from: loadedImage, with: asset?.imageData)
|
||||
self.fetchProcessedImages(
|
||||
from: Array(pickerResultArray.dropFirst()),
|
||||
accumulating: accumulating + [newElement],
|
||||
completionHandler
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension CameraPlugin {
|
||||
func returnImage(_ processedImage: ProcessedImage, isSaved: Bool) {
|
||||
guard let jpeg = processedImage.generateJPEG(with: settings.jpegQuality) else {
|
||||
self.call?.reject("Unable to convert image to jpeg")
|
||||
return
|
||||
}
|
||||
|
||||
if settings.resultType == CameraResultType.uri || multiple {
|
||||
guard let fileURL = try? saveTemporaryImage(jpeg),
|
||||
let webURL = bridge?.portablePath(fromLocalURL: fileURL) else {
|
||||
call?.reject("Unable to get portable path to file")
|
||||
return
|
||||
}
|
||||
if self.multiple {
|
||||
call?.resolve([
|
||||
"photos": [[
|
||||
"path": fileURL.absoluteString,
|
||||
"exif": processedImage.exifData,
|
||||
"webPath": webURL.absoluteString,
|
||||
"format": "jpeg"
|
||||
]]
|
||||
])
|
||||
return
|
||||
}
|
||||
call?.resolve([
|
||||
"path": fileURL.absoluteString,
|
||||
"exif": processedImage.exifData,
|
||||
"webPath": webURL.absoluteString,
|
||||
"format": "jpeg",
|
||||
"saved": isSaved
|
||||
])
|
||||
} else if settings.resultType == CameraResultType.base64 {
|
||||
self.call?.resolve([
|
||||
"base64String": jpeg.base64EncodedString(),
|
||||
"exif": processedImage.exifData,
|
||||
"format": "jpeg",
|
||||
"saved": isSaved
|
||||
])
|
||||
} else if settings.resultType == CameraResultType.dataURL {
|
||||
call?.resolve([
|
||||
"dataUrl": "data:image/jpeg;base64," + jpeg.base64EncodedString(),
|
||||
"exif": processedImage.exifData,
|
||||
"format": "jpeg",
|
||||
"saved": isSaved
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
func returnImages(_ processedImages: [ProcessedImage]) {
|
||||
var photos: [PluginCallResultData] = []
|
||||
for processedImage in processedImages {
|
||||
guard let jpeg = processedImage.generateJPEG(with: settings.jpegQuality) else {
|
||||
self.call?.reject("Unable to convert image to jpeg")
|
||||
return
|
||||
}
|
||||
|
||||
guard let fileURL = try? saveTemporaryImage(jpeg),
|
||||
let webURL = bridge?.portablePath(fromLocalURL: fileURL) else {
|
||||
call?.reject("Unable to get portable path to file")
|
||||
return
|
||||
}
|
||||
|
||||
photos.append([
|
||||
"path": fileURL.absoluteString,
|
||||
"exif": processedImage.exifData,
|
||||
"webPath": webURL.absoluteString,
|
||||
"format": "jpeg"
|
||||
])
|
||||
}
|
||||
call?.resolve([
|
||||
"photos": photos
|
||||
])
|
||||
}
|
||||
|
||||
func returnProcessedImage(_ processedImage: ProcessedImage) {
|
||||
// conditionally save the image
|
||||
if settings.saveToGallery && (processedImage.flags.contains(.edited) == true || processedImage.flags.contains(.gallery) == false) {
|
||||
_ = ImageSaver(image: processedImage.image) { error in
|
||||
var isSaved = false
|
||||
if error == nil {
|
||||
isSaved = true
|
||||
}
|
||||
self.returnImage(processedImage, isSaved: isSaved)
|
||||
}
|
||||
} else {
|
||||
self.returnImage(processedImage, isSaved: false)
|
||||
}
|
||||
}
|
||||
|
||||
func showPrompt() {
|
||||
// Build the action sheet
|
||||
let alert = UIAlertController(title: settings.userPromptText.title, message: nil, preferredStyle: UIAlertController.Style.actionSheet)
|
||||
alert.addAction(UIAlertAction(title: settings.userPromptText.photoAction, style: .default, handler: { [weak self] (_: UIAlertAction) in
|
||||
self?.showPhotos()
|
||||
}))
|
||||
|
||||
alert.addAction(UIAlertAction(title: settings.userPromptText.cameraAction, style: .default, handler: { [weak self] (_: UIAlertAction) in
|
||||
self?.showCamera()
|
||||
}))
|
||||
|
||||
alert.addAction(UIAlertAction(title: settings.userPromptText.cancelAction, style: .cancel, handler: { [weak self] (_: UIAlertAction) in
|
||||
self?.call?.reject("User cancelled photos app")
|
||||
}))
|
||||
self.setCenteredPopover(alert)
|
||||
self.bridge?.viewController?.present(alert, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func showCamera() {
|
||||
// check if we have a camera
|
||||
if (bridge?.isSimEnvironment ?? false) || !UIImagePickerController.isSourceTypeAvailable(UIImagePickerController.SourceType.camera) {
|
||||
CAPLog.print("⚡️ ", self.pluginId, "-", "Camera not available in simulator")
|
||||
call?.reject("Camera not available while running in Simulator")
|
||||
return
|
||||
}
|
||||
// check for permission
|
||||
let authStatus = AVCaptureDevice.authorizationStatus(for: .video)
|
||||
if authStatus == .restricted || authStatus == .denied {
|
||||
call?.reject("User denied access to camera")
|
||||
return
|
||||
}
|
||||
// we either already have permission or can prompt
|
||||
AVCaptureDevice.requestAccess(for: .video) { [weak self] granted in
|
||||
if granted {
|
||||
DispatchQueue.main.async {
|
||||
self?.presentCameraPicker()
|
||||
}
|
||||
} else {
|
||||
self?.call?.reject("User denied access to camera")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func showPhotos() {
|
||||
// check for permission
|
||||
let authStatus = PHPhotoLibrary.authorizationStatus()
|
||||
if authStatus == .restricted || authStatus == .denied {
|
||||
call?.reject("User denied access to photos")
|
||||
return
|
||||
}
|
||||
// we either already have permission or can prompt
|
||||
if authStatus == .authorized {
|
||||
presentSystemAppropriateImagePicker()
|
||||
} else {
|
||||
PHPhotoLibrary.requestAuthorization({ [weak self] (status) in
|
||||
if status == PHAuthorizationStatus.authorized {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.presentSystemAppropriateImagePicker()
|
||||
}
|
||||
} else {
|
||||
self?.call?.reject("User denied access to photos")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func presentCameraPicker() {
|
||||
let picker = UIImagePickerController()
|
||||
picker.delegate = self
|
||||
picker.allowsEditing = self.settings.allowEditing
|
||||
// select the input
|
||||
picker.sourceType = .camera
|
||||
if settings.direction == .rear, UIImagePickerController.isCameraDeviceAvailable(.rear) {
|
||||
picker.cameraDevice = .rear
|
||||
} else if settings.direction == .front, UIImagePickerController.isCameraDeviceAvailable(.front) {
|
||||
picker.cameraDevice = .front
|
||||
}
|
||||
// present
|
||||
picker.modalPresentationStyle = settings.presentationStyle
|
||||
if settings.presentationStyle == .popover {
|
||||
picker.popoverPresentationController?.delegate = self
|
||||
setCenteredPopover(picker)
|
||||
}
|
||||
bridge?.viewController?.present(picker, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func presentSystemAppropriateImagePicker() {
|
||||
if #available(iOS 14, *) {
|
||||
presentPhotoPicker()
|
||||
} else {
|
||||
presentImagePicker()
|
||||
}
|
||||
}
|
||||
|
||||
func presentImagePicker() {
|
||||
let picker = UIImagePickerController()
|
||||
picker.delegate = self
|
||||
picker.allowsEditing = self.settings.allowEditing
|
||||
// select the input
|
||||
picker.sourceType = .photoLibrary
|
||||
// present
|
||||
picker.modalPresentationStyle = settings.presentationStyle
|
||||
if settings.presentationStyle == .popover {
|
||||
picker.popoverPresentationController?.delegate = self
|
||||
setCenteredPopover(picker)
|
||||
}
|
||||
bridge?.viewController?.present(picker, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@available(iOS 14, *)
|
||||
func presentPhotoPicker() {
|
||||
var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
|
||||
configuration.selectionLimit = self.multiple ? (self.call?.getInt("limit") ?? 0) : 1
|
||||
configuration.filter = .images
|
||||
let picker = PHPickerViewController(configuration: configuration)
|
||||
picker.delegate = self
|
||||
// present
|
||||
picker.modalPresentationStyle = settings.presentationStyle
|
||||
if settings.presentationStyle == .popover {
|
||||
picker.popoverPresentationController?.delegate = self
|
||||
setCenteredPopover(picker)
|
||||
}
|
||||
bridge?.viewController?.present(picker, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
func saveTemporaryImage(_ data: Data) throws -> URL {
|
||||
var url: URL
|
||||
repeat {
|
||||
imageCounter += 1
|
||||
url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("photo-\(imageCounter).jpg")
|
||||
} while FileManager.default.fileExists(atPath: url.path)
|
||||
|
||||
try data.write(to: url, options: .atomic)
|
||||
return url
|
||||
}
|
||||
|
||||
func processImage(from info: [UIImagePickerController.InfoKey: Any]) -> ProcessedImage? {
|
||||
var selectedImage: UIImage?
|
||||
var flags: PhotoFlags = []
|
||||
// get the image
|
||||
if let edited = info[UIImagePickerController.InfoKey.editedImage] as? UIImage {
|
||||
selectedImage = edited // use the edited version
|
||||
flags = flags.union([.edited])
|
||||
} else if let original = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
|
||||
selectedImage = original // use the original version
|
||||
}
|
||||
guard let image = selectedImage else {
|
||||
return nil
|
||||
}
|
||||
var metadata: [String: Any] = [:]
|
||||
// get the image's metadata from the picker or from the photo album
|
||||
if let photoMetadata = info[UIImagePickerController.InfoKey.mediaMetadata] as? [String: Any] {
|
||||
metadata = photoMetadata
|
||||
} else {
|
||||
flags = flags.union([.gallery])
|
||||
}
|
||||
if let asset = info[UIImagePickerController.InfoKey.phAsset] as? PHAsset {
|
||||
metadata = asset.imageData
|
||||
}
|
||||
// get the result
|
||||
var result = processedImage(from: image, with: metadata)
|
||||
result.flags = flags
|
||||
return result
|
||||
}
|
||||
|
||||
func processedImage(from image: UIImage, with metadata: [String: Any]?) -> ProcessedImage {
|
||||
var result = ProcessedImage(image: image, metadata: metadata ?? [:])
|
||||
// resizing the image only makes sense if we have real values to which to constrain it
|
||||
if settings.shouldResize, settings.width > 0 || settings.height > 0 {
|
||||
result.image = result.image.reformat(to: CGSize(width: settings.width, height: settings.height))
|
||||
result.overwriteMetadataOrientation(to: 1)
|
||||
} else if settings.shouldCorrectOrientation {
|
||||
// resizing implicitly reformats the image so this is only needed if we aren't resizing
|
||||
result.image = result.image.reformat()
|
||||
result.overwriteMetadataOrientation(to: 1)
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
142
node_modules/@capacitor/camera/ios/Sources/CameraPlugin/CameraTypes.swift
generated
vendored
Normal file
142
node_modules/@capacitor/camera/ios/Sources/CameraPlugin/CameraTypes.swift
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
import UIKit
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
public enum CameraSource: String {
|
||||
case prompt = "PROMPT"
|
||||
case camera = "CAMERA"
|
||||
case photos = "PHOTOS"
|
||||
}
|
||||
|
||||
public enum CameraDirection: String {
|
||||
case rear = "REAR"
|
||||
case front = "FRONT"
|
||||
}
|
||||
|
||||
public enum CameraResultType: String {
|
||||
case base64
|
||||
case uri
|
||||
case dataURL = "dataUrl"
|
||||
}
|
||||
|
||||
struct CameraPromptText {
|
||||
let title: String
|
||||
let photoAction: String
|
||||
let cameraAction: String
|
||||
let cancelAction: String
|
||||
|
||||
init(title: String? = nil, photoAction: String? = nil, cameraAction: String? = nil, cancelAction: String? = nil) {
|
||||
self.title = title ?? "Photo"
|
||||
self.photoAction = photoAction ?? "From Photos"
|
||||
self.cameraAction = cameraAction ?? "Take Picture"
|
||||
self.cancelAction = cancelAction ?? "Cancel"
|
||||
}
|
||||
}
|
||||
|
||||
public struct CameraSettings {
|
||||
var source: CameraSource = CameraSource.prompt
|
||||
var direction: CameraDirection = CameraDirection.rear
|
||||
var resultType = CameraResultType.base64
|
||||
var userPromptText = CameraPromptText()
|
||||
var jpegQuality: CGFloat = 1.0
|
||||
var width: CGFloat = 0
|
||||
var height: CGFloat = 0
|
||||
var allowEditing = false
|
||||
var shouldResize = false
|
||||
var shouldCorrectOrientation = true
|
||||
var saveToGallery = false
|
||||
var presentationStyle = UIModalPresentationStyle.fullScreen
|
||||
}
|
||||
|
||||
public struct CameraResult {
|
||||
let image: UIImage?
|
||||
let metadata: [AnyHashable: Any]
|
||||
}
|
||||
|
||||
// MARK: - Internal
|
||||
|
||||
internal enum CameraPermissionType: String, CaseIterable {
|
||||
case camera
|
||||
case photos
|
||||
}
|
||||
|
||||
internal enum CameraPropertyListKeys: String, CaseIterable {
|
||||
case photoLibraryAddUsage = "NSPhotoLibraryAddUsageDescription"
|
||||
case photoLibraryUsage = "NSPhotoLibraryUsageDescription"
|
||||
case cameraUsage = "NSCameraUsageDescription"
|
||||
|
||||
var link: String {
|
||||
switch self {
|
||||
case .photoLibraryAddUsage:
|
||||
return "https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW73"
|
||||
case .photoLibraryUsage:
|
||||
return "https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW17"
|
||||
case .cameraUsage:
|
||||
return "https://developer.apple.com/library/content/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW24"
|
||||
}
|
||||
}
|
||||
|
||||
var missingMessage: String {
|
||||
return "You are missing \(self.rawValue) in your Info.plist file." +
|
||||
" Camera will not function without it. Learn more: \(self.link)"
|
||||
}
|
||||
}
|
||||
|
||||
internal struct PhotoFlags: OptionSet {
|
||||
let rawValue: Int
|
||||
|
||||
static let edited = PhotoFlags(rawValue: 1 << 0)
|
||||
static let gallery = PhotoFlags(rawValue: 1 << 1)
|
||||
|
||||
static let all: PhotoFlags = [.edited, .gallery]
|
||||
}
|
||||
|
||||
internal struct ProcessedImage {
|
||||
var image: UIImage
|
||||
var metadata: [String: Any]
|
||||
var flags: PhotoFlags = []
|
||||
|
||||
var exifData: [String: Any] {
|
||||
var exifData = metadata["{Exif}"] as? [String: Any]
|
||||
exifData?["Orientation"] = metadata["Orientation"]
|
||||
exifData?["GPS"] = metadata["{GPS}"]
|
||||
return exifData ?? [:]
|
||||
}
|
||||
|
||||
mutating func overwriteMetadataOrientation(to orientation: Int) {
|
||||
replaceDictionaryOrientation(atNode: &metadata, to: orientation)
|
||||
}
|
||||
|
||||
func replaceDictionaryOrientation(atNode node: inout [String: Any], to orientation: Int) {
|
||||
for key in node.keys {
|
||||
if key == "Orientation", (node[key] as? Int) != nil {
|
||||
node[key] = orientation
|
||||
} else if var child = node[key] as? [String: Any] {
|
||||
replaceDictionaryOrientation(atNode: &child, to: orientation)
|
||||
node[key] = child
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func generateJPEG(with quality: CGFloat) -> Data? {
|
||||
// convert the UIImage to a jpeg
|
||||
guard let data = self.image.jpegData(compressionQuality: quality) else {
|
||||
return nil
|
||||
}
|
||||
// define our jpeg data as an image source and get its type
|
||||
guard let source = CGImageSourceCreateWithData(data as CFData, nil), let type = CGImageSourceGetType(source) else {
|
||||
return data
|
||||
}
|
||||
// allocate an output buffer and create the destination to receive the new data
|
||||
guard let output = NSMutableData(capacity: data.count), let destination = CGImageDestinationCreateWithData(output, type, 1, nil) else {
|
||||
return data
|
||||
}
|
||||
// pipe the source into the destination while overwriting the metadata, this encodes the metadata information into the image
|
||||
CGImageDestinationAddImageFromSource(destination, source, 0, self.metadata as CFDictionary)
|
||||
// finish
|
||||
guard CGImageDestinationFinalize(destination) else {
|
||||
return data
|
||||
}
|
||||
return output as Data
|
||||
}
|
||||
}
|
||||
20
node_modules/@capacitor/camera/ios/Sources/CameraPlugin/ImageSaver.swift
generated
vendored
Normal file
20
node_modules/@capacitor/camera/ios/Sources/CameraPlugin/ImageSaver.swift
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
import UIKit
|
||||
|
||||
class ImageSaver: NSObject {
|
||||
|
||||
var onResult: ((Error?) -> Void) = {_ in }
|
||||
|
||||
init(image: UIImage, onResult: @escaping ((Error?) -> Void)) {
|
||||
self.onResult = onResult
|
||||
super.init()
|
||||
UIImageWriteToSavedPhotosAlbum(image, self, #selector(saveResult), nil)
|
||||
}
|
||||
|
||||
@objc func saveResult(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
|
||||
if let error = error {
|
||||
onResult(error)
|
||||
} else {
|
||||
onResult(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
12
node_modules/@capacitor/camera/ios/Tests/CameraPluginTests/CameraPluginTests.swift
generated
vendored
Normal file
12
node_modules/@capacitor/camera/ios/Tests/CameraPluginTests/CameraPluginTests.swift
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
import XCTest
|
||||
@testable import CameraPlugin
|
||||
|
||||
final class CameraPluginTests: XCTestCase {
|
||||
func testExample() throws {
|
||||
// XCTest Documentation
|
||||
// https://developer.apple.com/documentation/xctest
|
||||
|
||||
// Defining Test Cases and Test Methods
|
||||
// https://developer.apple.com/documentation/xctest/defining_test_cases_and_test_methods
|
||||
}
|
||||
}
|
||||
85
node_modules/@capacitor/camera/package.json
generated
vendored
Normal file
85
node_modules/@capacitor/camera/package.json
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"name": "@capacitor/camera",
|
||||
"version": "7.0.2",
|
||||
"description": "The Camera API provides the ability to take a photo with the camera or choose an existing one from the photo album.",
|
||||
"main": "dist/plugin.cjs.js",
|
||||
"module": "dist/esm/index.js",
|
||||
"types": "dist/esm/index.d.ts",
|
||||
"unpkg": "dist/plugin.js",
|
||||
"files": [
|
||||
"android/src/main/",
|
||||
"android/build.gradle",
|
||||
"dist/",
|
||||
"ios/Sources",
|
||||
"ios/Tests",
|
||||
"Package.swift",
|
||||
"CapacitorCamera.podspec"
|
||||
],
|
||||
"author": "Ionic <hi@ionicframework.com>",
|
||||
"license": "MIT",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/ionic-team/capacitor-plugins.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/ionic-team/capacitor-plugins/issues"
|
||||
},
|
||||
"keywords": [
|
||||
"capacitor",
|
||||
"plugin",
|
||||
"native"
|
||||
],
|
||||
"scripts": {
|
||||
"verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
|
||||
"verify:ios": "xcodebuild build -scheme CapacitorCamera -destination generic/platform=iOS",
|
||||
"verify:android": "cd android && ./gradlew clean build test && cd ..",
|
||||
"verify:web": "npm run build",
|
||||
"lint": "npm run eslint && npm run prettier -- --check && npm run swiftlint -- lint",
|
||||
"fmt": "npm run eslint -- --fix && npm run prettier -- --write && npm run swiftlint -- --fix --format",
|
||||
"eslint": "eslint . --ext ts",
|
||||
"prettier": "prettier \"**/*.{css,html,ts,js,java}\"",
|
||||
"swiftlint": "node-swiftlint",
|
||||
"docgen": "docgen --api CameraPlugin --output-readme README.md --output-json dist/docs.json",
|
||||
"build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
|
||||
"clean": "rimraf ./dist",
|
||||
"watch": "tsc --watch",
|
||||
"prepublishOnly": "npm run build",
|
||||
"publish:cocoapod": "pod trunk push ./CapacitorCamera.podspec --allow-warnings"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@capacitor/android": "^7.0.0",
|
||||
"@capacitor/core": "^7.0.0",
|
||||
"@capacitor/docgen": "0.2.2",
|
||||
"@capacitor/ios": "^7.0.0",
|
||||
"@ionic/eslint-config": "^0.4.0",
|
||||
"@ionic/prettier-config": "~1.0.1",
|
||||
"@ionic/swiftlint-config": "^1.1.2",
|
||||
"eslint": "^8.57.0",
|
||||
"prettier": "~2.3.0",
|
||||
"prettier-plugin-java": "~1.0.2",
|
||||
"rimraf": "^6.0.1",
|
||||
"rollup": "^4.26.0",
|
||||
"swiftlint": "^1.0.1",
|
||||
"typescript": "~4.1.5"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@capacitor/core": ">=7.0.0"
|
||||
},
|
||||
"prettier": "@ionic/prettier-config",
|
||||
"swiftlint": "@ionic/swiftlint-config",
|
||||
"eslintConfig": {
|
||||
"extends": "@ionic/eslint-config/recommended"
|
||||
},
|
||||
"capacitor": {
|
||||
"ios": {
|
||||
"src": "ios"
|
||||
},
|
||||
"android": {
|
||||
"src": "android"
|
||||
}
|
||||
},
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"gitHead": "7c53a4c249abe958983f1ac9df04dec7ab89c10e"
|
||||
}
|
||||
21
node_modules/@capacitor/cli/LICENSE
generated
vendored
Normal file
21
node_modules/@capacitor/cli/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017-present Drifty Co.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
84
node_modules/@capacitor/cli/README.md
generated
vendored
Normal file
84
node_modules/@capacitor/cli/README.md
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
# Capacitor CLI
|
||||
|
||||
The Capacitor command-line interface (CLI) is a tool for creating and managing Capacitor applications. While it can be installed globally, it's recommended to install it locally in your project and execute through `npm` scripts.
|
||||
|
||||
## Installation
|
||||
|
||||
### Project Installation (Recommended)
|
||||
|
||||
Install the CLI locally in your project:
|
||||
|
||||
```bash
|
||||
npm install @capacitor/cli --save-dev
|
||||
```
|
||||
|
||||
### Global Installation
|
||||
|
||||
While not recommended for project use, you can install the CLI globally:
|
||||
|
||||
```bash
|
||||
npm install -g @capacitor/cli
|
||||
```
|
||||
|
||||
## Using Capacitor CLI
|
||||
|
||||
The CLI can be used through the `capacitor` or `cap` command. When installed locally, use it through your project's `npm` scripts or `npx`.
|
||||
|
||||
Common commands:
|
||||
|
||||
- `cap init`: Initialize a new Capacitor project
|
||||
- `cap add`: Add a native platform (ios, android)
|
||||
- `cap sync`: Sync your web code to your native projects
|
||||
|
||||
For detailed information, consult the [Getting Started guide](https://capacitorjs.com/docs/getting-started).
|
||||
|
||||
## Local Development
|
||||
|
||||
If you're contributing to the Capacitor CLI or testing local changes:
|
||||
|
||||
1. Clone and setup:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/ionic-team/capacitor.git
|
||||
cd cli
|
||||
npm install
|
||||
```
|
||||
|
||||
2. Build the CLI:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
3. Create a local link:
|
||||
|
||||
```bash
|
||||
npm link
|
||||
```
|
||||
|
||||
4. Development workflow:
|
||||
- Run `npm run watch` to automatically rebuild on changes
|
||||
- Use `capacitor` or `cap` commands to test your changes
|
||||
- Run `npm test` to execute the test suite
|
||||
|
||||
## Debugging
|
||||
|
||||
### Using VS Code Launch Configurations
|
||||
|
||||
The CLI includes VS Code launch configurations for debugging. To debug a CLI command:
|
||||
|
||||
1. Open the project in VS Code
|
||||
2. Right now we don't have debugging working in the ts files, so select one of the .js files inside of /dist/\*\*.js
|
||||
3. Place a breakpoint
|
||||
4. Press F5 or go to Run > Start Debugging
|
||||
5. Select a launch config and run filling out the path you want to run the cli in, and the command that you want run.
|
||||
|
||||
You can add more configurations by copying and modifying the existing ones in `.vscode/launch.json`.
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please read our [Contributing Guide](https://github.com/ionic-team/capacitor/blob/main/CONTRIBUTING.md) for details.
|
||||
|
||||
### License
|
||||
|
||||
- [MIT](https://github.com/ionic-team/capacitor/blob/HEAD/LICENSE)
|
||||
BIN
node_modules/@capacitor/cli/assets/android-template.tar.gz
generated
vendored
Normal file
BIN
node_modules/@capacitor/cli/assets/android-template.tar.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/@capacitor/cli/assets/capacitor-cordova-android-plugins.tar.gz
generated
vendored
Normal file
BIN
node_modules/@capacitor/cli/assets/capacitor-cordova-android-plugins.tar.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/@capacitor/cli/assets/capacitor-cordova-ios-plugins.tar.gz
generated
vendored
Normal file
BIN
node_modules/@capacitor/cli/assets/capacitor-cordova-ios-plugins.tar.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/@capacitor/cli/assets/ios-pods-template.tar.gz
generated
vendored
Normal file
BIN
node_modules/@capacitor/cli/assets/ios-pods-template.tar.gz
generated
vendored
Normal file
Binary file not shown.
BIN
node_modules/@capacitor/cli/assets/ios-spm-template.tar.gz
generated
vendored
Normal file
BIN
node_modules/@capacitor/cli/assets/ios-spm-template.tar.gz
generated
vendored
Normal file
Binary file not shown.
18
node_modules/@capacitor/cli/bin/capacitor
generated
vendored
Executable file
18
node_modules/@capacitor/cli/bin/capacitor
generated
vendored
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env node
|
||||
'use strict';
|
||||
|
||||
var satisfies = require('semver/functions/satisfies');
|
||||
var packageJson = require('../package.json');
|
||||
var requiresNodeVersion = packageJson.engines.node;
|
||||
|
||||
if (!satisfies(process.version, requiresNodeVersion, { includePrerelease: true})) {
|
||||
process.stdout.write(
|
||||
'\x1b[31m[fatal]\x1b[39m The Capacitor CLI requires NodeJS ' + requiresNodeVersion + '\n' +
|
||||
' Please install the latest LTS version.\n'
|
||||
);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
var cli = require('../dist/index');
|
||||
cli.run();
|
||||
52
node_modules/@capacitor/cli/dist/android/add.js
generated
vendored
Normal file
52
node_modules/@capacitor/cli/dist/android/add.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createLocalProperties = exports.addAndroid = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const os_1 = require("os");
|
||||
const path_1 = require("path");
|
||||
const colors_1 = tslib_1.__importDefault(require("../colors"));
|
||||
const common_1 = require("../common");
|
||||
const subprocess_1 = require("../util/subprocess");
|
||||
const template_1 = require("../util/template");
|
||||
async function addAndroid(config) {
|
||||
await (0, common_1.runTask)(`Adding native android project in ${colors_1.default.strong(config.android.platformDir)}`, async () => {
|
||||
return (0, template_1.extractTemplate)(config.cli.assets.android.platformTemplateArchiveAbs, config.android.platformDirAbs);
|
||||
});
|
||||
}
|
||||
exports.addAndroid = addAndroid;
|
||||
async function createLocalProperties(platformDir) {
|
||||
const defaultAndroidPath = (0, path_1.join)((0, os_1.homedir)(), 'Library/Android/sdk');
|
||||
if (await (0, fs_extra_1.pathExists)(defaultAndroidPath)) {
|
||||
const localSettings = `
|
||||
## This file is automatically generated by Android Studio.
|
||||
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
|
||||
#
|
||||
# This file should *NOT* be checked into Version Control Systems,
|
||||
# as it contains information specific to your local configuration.
|
||||
#
|
||||
# Location of the SDK. This is only used by Gradle.
|
||||
# For customization when using a Version Control System, please read the
|
||||
# header note.
|
||||
sdk.dir=${defaultAndroidPath}
|
||||
`;
|
||||
await (0, fs_extra_1.writeFile)((0, path_1.join)(platformDir, 'local.properties'), localSettings, {
|
||||
encoding: 'utf-8',
|
||||
});
|
||||
// Only sync if we were able to create the local properties above, otherwise
|
||||
// this will fail
|
||||
try {
|
||||
await gradleSync(platformDir);
|
||||
}
|
||||
catch (e) {
|
||||
console.error('Error running gradle sync', e);
|
||||
console.error('Unable to infer default Android SDK settings. This is fine, just run npx cap open android and import and sync gradle manually');
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.createLocalProperties = createLocalProperties;
|
||||
async function gradleSync(platformDir) {
|
||||
await (0, subprocess_1.runCommand)(`./gradlew`, [], {
|
||||
cwd: platformDir,
|
||||
});
|
||||
}
|
||||
104
node_modules/@capacitor/cli/dist/android/build.js
generated
vendored
Normal file
104
node_modules/@capacitor/cli/dist/android/build.js
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.buildAndroid = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const path_1 = require("path");
|
||||
const colors_1 = tslib_1.__importDefault(require("../colors"));
|
||||
const common_1 = require("../common");
|
||||
const log_1 = require("../log");
|
||||
const subprocess_1 = require("../util/subprocess");
|
||||
async function buildAndroid(config, buildOptions) {
|
||||
var _a, _b;
|
||||
const releaseType = (_a = buildOptions.androidreleasetype) !== null && _a !== void 0 ? _a : 'AAB';
|
||||
const releaseTypeIsAAB = releaseType === 'AAB';
|
||||
const flavor = (_b = buildOptions.flavor) !== null && _b !== void 0 ? _b : '';
|
||||
const arg = releaseTypeIsAAB ? `:app:bundle${flavor}Release` : `assemble${flavor}Release`;
|
||||
const gradleArgs = [arg];
|
||||
try {
|
||||
await (0, common_1.runTask)('Running Gradle build', async () => (0, subprocess_1.runCommand)('./gradlew', gradleArgs, {
|
||||
cwd: config.android.platformDirAbs,
|
||||
}));
|
||||
}
|
||||
catch (e) {
|
||||
if (e.includes('EACCES')) {
|
||||
throw `gradlew file does not have executable permissions. This can happen if the Android platform was added on a Windows machine. Please run ${colors_1.default.strong(`chmod +x ./${config.android.platformDir}/gradlew`)} and try again.`;
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
const releaseDir = releaseTypeIsAAB
|
||||
? flavor !== ''
|
||||
? `${flavor}Release`
|
||||
: 'release'
|
||||
: flavor !== ''
|
||||
? (0, path_1.join)(flavor, 'release')
|
||||
: 'release';
|
||||
const releasePath = (0, path_1.join)(config.android.appDirAbs, 'build', 'outputs', releaseTypeIsAAB ? 'bundle' : 'apk', releaseDir);
|
||||
const unsignedReleaseName = `app${flavor !== '' ? `-${flavor}` : ''}-release${releaseTypeIsAAB ? '' : '-unsigned'}.${releaseType.toLowerCase()}`;
|
||||
const signedReleaseName = unsignedReleaseName.replace(`-release${releaseTypeIsAAB ? '' : '-unsigned'}.${releaseType.toLowerCase()}`, `-release-signed.${releaseType.toLowerCase()}`);
|
||||
if (buildOptions.signingtype == 'jarsigner') {
|
||||
await signWithJarSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName);
|
||||
}
|
||||
else {
|
||||
await signWithApkSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName);
|
||||
}
|
||||
(0, log_1.logSuccess)(`Successfully generated ${signedReleaseName} at: ${releasePath}`);
|
||||
}
|
||||
exports.buildAndroid = buildAndroid;
|
||||
async function signWithApkSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName) {
|
||||
if (!buildOptions.keystorepath || !buildOptions.keystorepass) {
|
||||
throw 'Missing options. Please supply all options for android signing. (Keystore Path, Keystore Password)';
|
||||
}
|
||||
const signingArgs = [
|
||||
'sign',
|
||||
'--ks',
|
||||
buildOptions.keystorepath,
|
||||
'--ks-pass',
|
||||
`pass:${buildOptions.keystorepass}`,
|
||||
'--in',
|
||||
`${(0, path_1.join)(releasePath, unsignedReleaseName)}`,
|
||||
'--out',
|
||||
`${(0, path_1.join)(releasePath, signedReleaseName)}`,
|
||||
];
|
||||
if (buildOptions.keystorealias) {
|
||||
signingArgs.push('--ks-key-alias', buildOptions.keystorealias);
|
||||
}
|
||||
if (buildOptions.keystorealiaspass) {
|
||||
signingArgs.push('--key-pass', `pass:${buildOptions.keystorealiaspass}`);
|
||||
}
|
||||
await (0, common_1.runTask)('Signing Release', async () => {
|
||||
await (0, subprocess_1.runCommand)('apksigner', signingArgs, {
|
||||
cwd: config.android.platformDirAbs,
|
||||
});
|
||||
});
|
||||
}
|
||||
async function signWithJarSigner(config, buildOptions, releasePath, signedReleaseName, unsignedReleaseName) {
|
||||
if (!buildOptions.keystorepath ||
|
||||
!buildOptions.keystorealias ||
|
||||
!buildOptions.keystorealiaspass ||
|
||||
!buildOptions.keystorepass) {
|
||||
throw 'Missing options. Please supply all options for android signing. (Keystore Path, Keystore Password, Keystore Key Alias, Keystore Key Password)';
|
||||
}
|
||||
const signingArgs = [
|
||||
'-sigalg',
|
||||
'SHA1withRSA',
|
||||
'-digestalg',
|
||||
'SHA1',
|
||||
'-keystore',
|
||||
buildOptions.keystorepath,
|
||||
'-keypass',
|
||||
buildOptions.keystorealiaspass,
|
||||
'-storepass',
|
||||
buildOptions.keystorepass,
|
||||
`-signedjar`,
|
||||
`${(0, path_1.join)(releasePath, signedReleaseName)}`,
|
||||
`${(0, path_1.join)(releasePath, unsignedReleaseName)}`,
|
||||
buildOptions.keystorealias,
|
||||
];
|
||||
await (0, common_1.runTask)('Signing Release', async () => {
|
||||
await (0, subprocess_1.runCommand)('jarsigner', signingArgs, {
|
||||
cwd: config.android.platformDirAbs,
|
||||
});
|
||||
});
|
||||
}
|
||||
94
node_modules/@capacitor/cli/dist/android/common.js
generated
vendored
Normal file
94
node_modules/@capacitor/cli/dist/android/common.js
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.editProjectSettingsAndroid = exports.resolvePlugin = exports.getAndroidPlugins = exports.checkAndroidPackage = void 0;
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path_1 = require("path");
|
||||
const common_1 = require("../common");
|
||||
const cordova_1 = require("../cordova");
|
||||
const plugin_1 = require("../plugin");
|
||||
const fs_1 = require("../util/fs");
|
||||
async function checkAndroidPackage(config) {
|
||||
return (0, common_1.checkCapacitorPlatform)(config, 'android');
|
||||
}
|
||||
exports.checkAndroidPackage = checkAndroidPackage;
|
||||
async function getAndroidPlugins(allPlugins) {
|
||||
const resolved = await Promise.all(allPlugins.map(async (plugin) => await resolvePlugin(plugin)));
|
||||
return resolved.filter((plugin) => !!plugin);
|
||||
}
|
||||
exports.getAndroidPlugins = getAndroidPlugins;
|
||||
async function resolvePlugin(plugin) {
|
||||
var _a;
|
||||
const platform = 'android';
|
||||
if ((_a = plugin.manifest) === null || _a === void 0 ? void 0 : _a.android) {
|
||||
let pluginFilesPath = plugin.manifest.android.src ? plugin.manifest.android.src : platform;
|
||||
const absolutePath = (0, path_1.join)(plugin.rootPath, pluginFilesPath, plugin.id);
|
||||
// Android folder shouldn't have subfolders, but they used to, so search for them for compatibility reasons
|
||||
if (await (0, fs_extra_1.pathExists)(absolutePath)) {
|
||||
pluginFilesPath = (0, path_1.join)(platform, plugin.id);
|
||||
}
|
||||
plugin.android = {
|
||||
type: 0 /* PluginType.Core */,
|
||||
path: (0, fs_1.convertToUnixPath)(pluginFilesPath),
|
||||
};
|
||||
}
|
||||
else if (plugin.xml) {
|
||||
plugin.android = {
|
||||
type: 1 /* PluginType.Cordova */,
|
||||
path: 'src/' + platform,
|
||||
};
|
||||
if ((0, cordova_1.getIncompatibleCordovaPlugins)(platform).includes(plugin.id) || !(0, plugin_1.getPluginPlatform)(plugin, platform)) {
|
||||
plugin.android.type = 2 /* PluginType.Incompatible */;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
exports.resolvePlugin = resolvePlugin;
|
||||
/**
|
||||
* Update an Android project with the desired app name and appId.
|
||||
* This is a little trickier for Android because the appId becomes
|
||||
* the package name.
|
||||
*/
|
||||
async function editProjectSettingsAndroid(config) {
|
||||
const appId = config.app.appId;
|
||||
const appName = config.app.appName
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/"/g, '\\"')
|
||||
.replace(/'/g, "\\'");
|
||||
const buildGradlePath = (0, path_1.resolve)(config.android.appDirAbs, 'build.gradle');
|
||||
const domainPath = appId.split('.').join('/');
|
||||
// Make the package source path to the new plugin Java file
|
||||
const newJavaPath = (0, path_1.resolve)(config.android.srcMainDirAbs, `java/${domainPath}`);
|
||||
if (!(await (0, fs_extra_1.pathExists)(newJavaPath))) {
|
||||
await (0, fs_extra_1.mkdirp)(newJavaPath);
|
||||
}
|
||||
await (0, fs_extra_1.copy)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor/myapp/MainActivity.java'), (0, path_1.resolve)(newJavaPath, 'MainActivity.java'));
|
||||
if (appId.split('.')[1] !== 'getcapacitor') {
|
||||
await (0, fs_extra_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/getcapacitor'));
|
||||
}
|
||||
// Remove our template 'com' folder if their ID doesn't have it
|
||||
if (appId.split('.')[0] !== 'com') {
|
||||
await (0, fs_extra_1.remove)((0, path_1.resolve)(config.android.srcMainDirAbs, 'java/com/'));
|
||||
}
|
||||
// Update the package in the MainActivity java file
|
||||
const activityPath = (0, path_1.resolve)(newJavaPath, 'MainActivity.java');
|
||||
let activityContent = await (0, fs_extra_1.readFile)(activityPath, { encoding: 'utf-8' });
|
||||
activityContent = activityContent.replace(/package ([^;]*)/, `package ${appId}`);
|
||||
await (0, fs_extra_1.writeFile)(activityPath, activityContent, { encoding: 'utf-8' });
|
||||
// Update the applicationId in build.gradle
|
||||
let gradleContent = await (0, fs_extra_1.readFile)(buildGradlePath, { encoding: 'utf-8' });
|
||||
gradleContent = gradleContent.replace(/applicationId "[^"]+"/, `applicationId "${appId}"`);
|
||||
// Update the namespace in build.gradle
|
||||
gradleContent = gradleContent.replace(/namespace "[^"]+"/, `namespace "${appId}"`);
|
||||
await (0, fs_extra_1.writeFile)(buildGradlePath, gradleContent, { encoding: 'utf-8' });
|
||||
// Update the settings in res/values/strings.xml
|
||||
const stringsPath = (0, path_1.resolve)(config.android.resDirAbs, 'values/strings.xml');
|
||||
let stringsContent = await (0, fs_extra_1.readFile)(stringsPath, { encoding: 'utf-8' });
|
||||
stringsContent = stringsContent.replace(/com.getcapacitor.myapp/g, appId);
|
||||
stringsContent = stringsContent.replace(/My App/g, appName);
|
||||
await (0, fs_extra_1.writeFile)(stringsPath, stringsContent);
|
||||
}
|
||||
exports.editProjectSettingsAndroid = editProjectSettingsAndroid;
|
||||
160
node_modules/@capacitor/cli/dist/android/doctor.js
generated
vendored
Normal file
160
node_modules/@capacitor/cli/dist/android/doctor.js
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.doctorAndroid = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path_1 = require("path");
|
||||
const colors_1 = tslib_1.__importDefault(require("../colors"));
|
||||
const common_1 = require("../common");
|
||||
const errors_1 = require("../errors");
|
||||
const log_1 = require("../log");
|
||||
const fs_1 = require("../util/fs");
|
||||
const xml_1 = require("../util/xml");
|
||||
async function doctorAndroid(config) {
|
||||
var _a;
|
||||
try {
|
||||
await (0, common_1.check)([checkAndroidInstalled, () => checkGradlew(config), () => checkAppSrcDirs(config)]);
|
||||
(0, log_1.logSuccess)('Android looking great! 👌');
|
||||
}
|
||||
catch (e) {
|
||||
if (!(0, errors_1.isFatal)(e)) {
|
||||
(0, errors_1.fatal)((_a = e.stack) !== null && _a !== void 0 ? _a : e);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
exports.doctorAndroid = doctorAndroid;
|
||||
async function checkAppSrcDirs(config) {
|
||||
if (!(await (0, fs_extra_1.pathExists)(config.android.appDirAbs))) {
|
||||
return `${colors_1.default.strong(config.android.appDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
|
||||
}
|
||||
if (!(await (0, fs_extra_1.pathExists)(config.android.srcMainDirAbs))) {
|
||||
return `${colors_1.default.strong(config.android.srcMainDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
|
||||
}
|
||||
if (!(await (0, fs_extra_1.pathExists)(config.android.assetsDirAbs))) {
|
||||
return `${colors_1.default.strong(config.android.assetsDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
|
||||
}
|
||||
if (!(await (0, fs_extra_1.pathExists)(config.android.webDirAbs))) {
|
||||
return `${colors_1.default.strong(config.android.webDir)} directory is missing in ${colors_1.default.strong(config.android.platformDir)}`;
|
||||
}
|
||||
const appSrcMainAssetsWwwIndexHtmlDir = (0, path_1.join)(config.android.webDirAbs, 'index.html');
|
||||
if (!(await (0, fs_extra_1.pathExists)(appSrcMainAssetsWwwIndexHtmlDir))) {
|
||||
return `${colors_1.default.strong('index.html')} file is missing in ${colors_1.default.strong(config.android.webDirAbs)}`;
|
||||
}
|
||||
return checkAndroidManifestFile(config);
|
||||
}
|
||||
async function checkAndroidManifestFile(config) {
|
||||
const manifestFileName = 'AndroidManifest.xml';
|
||||
const manifestFilePath = (0, path_1.join)(config.android.srcMainDirAbs, manifestFileName);
|
||||
if (!(await (0, fs_extra_1.pathExists)(manifestFilePath))) {
|
||||
return `${colors_1.default.strong(manifestFileName)} is missing in ${colors_1.default.strong(config.android.srcMainDir)}`;
|
||||
}
|
||||
try {
|
||||
const xmlData = await (0, xml_1.readXML)(manifestFilePath);
|
||||
return checkAndroidManifestData(config, xmlData);
|
||||
}
|
||||
catch (e) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
async function checkAndroidManifestData(config, xmlData) {
|
||||
const manifestNode = xmlData.manifest;
|
||||
if (!manifestNode) {
|
||||
return `Missing ${colors_1.default.input('<manifest>')} XML node in ${colors_1.default.strong(config.android.srcMainDir)}`;
|
||||
}
|
||||
const applicationChildNodes = manifestNode.application;
|
||||
if (!Array.isArray(manifestNode.application)) {
|
||||
return `Missing ${colors_1.default.input('<application>')} XML node as a child node of ${colors_1.default.input('<manifest>')} in ${colors_1.default.strong(config.android.srcMainDir)}`;
|
||||
}
|
||||
let mainActivityClassPath = '';
|
||||
const mainApplicationNode = applicationChildNodes.find((applicationChildNode) => {
|
||||
const activityChildNodes = applicationChildNode.activity;
|
||||
if (!Array.isArray(activityChildNodes)) {
|
||||
return false;
|
||||
}
|
||||
const mainActivityNode = activityChildNodes.find((activityChildNode) => {
|
||||
const intentFilterChildNodes = activityChildNode['intent-filter'];
|
||||
if (!Array.isArray(intentFilterChildNodes)) {
|
||||
return false;
|
||||
}
|
||||
return intentFilterChildNodes.find((intentFilterChildNode) => {
|
||||
const actionChildNodes = intentFilterChildNode.action;
|
||||
if (!Array.isArray(actionChildNodes)) {
|
||||
return false;
|
||||
}
|
||||
const mainActionChildNode = actionChildNodes.find((actionChildNode) => {
|
||||
const androidName = actionChildNode.$['android:name'];
|
||||
return androidName === 'android.intent.action.MAIN';
|
||||
});
|
||||
if (!mainActionChildNode) {
|
||||
return false;
|
||||
}
|
||||
const categoryChildNodes = intentFilterChildNode.category;
|
||||
if (!Array.isArray(categoryChildNodes)) {
|
||||
return false;
|
||||
}
|
||||
return categoryChildNodes.find((categoryChildNode) => {
|
||||
const androidName = categoryChildNode.$['android:name'];
|
||||
return androidName === 'android.intent.category.LAUNCHER';
|
||||
});
|
||||
});
|
||||
});
|
||||
if (mainActivityNode) {
|
||||
mainActivityClassPath = mainActivityNode.$['android:name'];
|
||||
}
|
||||
return mainActivityNode;
|
||||
});
|
||||
if (!mainApplicationNode) {
|
||||
return `Missing main ${colors_1.default.input('<activity>')} XML node in ${colors_1.default.strong(config.android.srcMainDir)}`;
|
||||
}
|
||||
if (!mainActivityClassPath) {
|
||||
return `Missing ${colors_1.default.input('<activity android:name="">')} attribute for MainActivity class in ${colors_1.default.strong(config.android.srcMainDir)}`;
|
||||
}
|
||||
return checkPackage(config, mainActivityClassPath);
|
||||
}
|
||||
async function checkPackage(config, mainActivityClassPath) {
|
||||
const appSrcMainJavaDir = (0, path_1.join)(config.android.srcMainDirAbs, 'java');
|
||||
if (!(await (0, fs_extra_1.pathExists)(appSrcMainJavaDir))) {
|
||||
return `${colors_1.default.strong('java')} directory is missing in ${colors_1.default.strong(appSrcMainJavaDir)}`;
|
||||
}
|
||||
const mainActivityClassName = mainActivityClassPath.split('.').pop();
|
||||
const srcFiles = await (0, fs_1.readdirp)(appSrcMainJavaDir, {
|
||||
filter: (entry) => !entry.stats.isDirectory() &&
|
||||
['.java', '.kt'].includes((0, path_1.extname)(entry.path)) &&
|
||||
mainActivityClassName === (0, path_1.parse)(entry.path).name,
|
||||
});
|
||||
if (srcFiles.length == 0) {
|
||||
return `Main activity file (${mainActivityClassName}) is missing`;
|
||||
}
|
||||
return checkBuildGradle(config);
|
||||
}
|
||||
async function checkBuildGradle(config) {
|
||||
const fileName = 'build.gradle';
|
||||
const filePath = (0, path_1.join)(config.android.appDirAbs, fileName);
|
||||
if (!(await (0, fs_extra_1.pathExists)(filePath))) {
|
||||
return `${colors_1.default.strong(fileName)} file is missing in ${colors_1.default.strong(config.android.appDir)}`;
|
||||
}
|
||||
let fileContent = await (0, fs_extra_1.readFile)(filePath, { encoding: 'utf-8' });
|
||||
fileContent = fileContent.replace(/'|"/g, '').replace(/\s+/g, ' ');
|
||||
const searchFor = `applicationId`;
|
||||
if (fileContent.indexOf(searchFor) === -1) {
|
||||
return `${colors_1.default.strong('build.gradle')} file missing ${colors_1.default.input(`applicationId`)} config in ${filePath}`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async function checkGradlew(config) {
|
||||
const fileName = 'gradlew';
|
||||
const filePath = (0, path_1.join)(config.android.platformDirAbs, fileName);
|
||||
if (!(await (0, fs_extra_1.pathExists)(filePath))) {
|
||||
return `${colors_1.default.strong(fileName)} file is missing in ${colors_1.default.strong(config.android.platformDir)}`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async function checkAndroidInstalled() {
|
||||
/*
|
||||
if (!await isInstalled('android')) {
|
||||
return 'Android is not installed. For information: https://developer.android.com/studio/index.html';
|
||||
}
|
||||
*/
|
||||
return null;
|
||||
}
|
||||
28
node_modules/@capacitor/cli/dist/android/open.js
generated
vendored
Normal file
28
node_modules/@capacitor/cli/dist/android/open.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.openAndroid = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const debug_1 = tslib_1.__importDefault(require("debug"));
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const open_1 = tslib_1.__importDefault(require("open"));
|
||||
const colors_1 = tslib_1.__importDefault(require("../colors"));
|
||||
const log_1 = require("../log");
|
||||
const debug = (0, debug_1.default)('capacitor:android:open');
|
||||
async function openAndroid(config) {
|
||||
const androidStudioPath = await config.android.studioPath;
|
||||
const dir = config.android.platformDirAbs;
|
||||
try {
|
||||
if (!(await (0, fs_extra_1.pathExists)(androidStudioPath))) {
|
||||
throw new Error(`Android Studio does not exist at: ${androidStudioPath}`);
|
||||
}
|
||||
await (0, open_1.default)(dir, { app: { name: androidStudioPath }, wait: false });
|
||||
log_1.logger.info(`Opening Android project at: ${colors_1.default.strong(config.android.platformDir)}.`);
|
||||
}
|
||||
catch (e) {
|
||||
debug('Error opening Android Studio: %O', e);
|
||||
log_1.logger.error('Unable to launch Android Studio. Is it installed?\n' +
|
||||
`Attempted to open Android Studio at: ${colors_1.default.strong(androidStudioPath)}\n` +
|
||||
`You can configure this with the ${colors_1.default.input('CAPACITOR_ANDROID_STUDIO_PATH')} environment variable.`);
|
||||
}
|
||||
}
|
||||
exports.openAndroid = openAndroid;
|
||||
42
node_modules/@capacitor/cli/dist/android/run.js
generated
vendored
Normal file
42
node_modules/@capacitor/cli/dist/android/run.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.runAndroid = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const debug_1 = tslib_1.__importDefault(require("debug"));
|
||||
const path_1 = require("path");
|
||||
const colors_1 = tslib_1.__importDefault(require("../colors"));
|
||||
const common_1 = require("../common");
|
||||
const native_run_1 = require("../util/native-run");
|
||||
const subprocess_1 = require("../util/subprocess");
|
||||
const debug = (0, debug_1.default)('capacitor:android:run');
|
||||
async function runAndroid(config, { target: selectedTarget, flavor: selectedFlavor, forwardPorts: selectedPorts }) {
|
||||
var _a;
|
||||
const target = await (0, common_1.promptForPlatformTarget)(await (0, native_run_1.getPlatformTargets)('android'), selectedTarget);
|
||||
const runFlavor = selectedFlavor || ((_a = config.android) === null || _a === void 0 ? void 0 : _a.flavor) || '';
|
||||
const arg = `assemble${runFlavor}Debug`;
|
||||
const gradleArgs = [arg];
|
||||
debug('Invoking ./gradlew with args: %O', gradleArgs);
|
||||
try {
|
||||
await (0, common_1.runTask)('Running Gradle build', async () => (0, subprocess_1.runCommand)('./gradlew', gradleArgs, {
|
||||
cwd: config.android.platformDirAbs,
|
||||
}));
|
||||
}
|
||||
catch (e) {
|
||||
if (e.includes('EACCES')) {
|
||||
throw `gradlew file does not have executable permissions. This can happen if the Android platform was added on a Windows machine. Please run ${colors_1.default.strong(`chmod +x ./${config.android.platformDir}/gradlew`)} and try again.`;
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
const pathToApk = `${config.android.platformDirAbs}/${config.android.appDir}/build/outputs/apk${runFlavor !== '' ? '/' + runFlavor : ''}/debug`;
|
||||
const apkName = (0, common_1.parseApkNameFromFlavor)(runFlavor);
|
||||
const apkPath = (0, path_1.resolve)(pathToApk, apkName);
|
||||
const nativeRunArgs = ['android', '--app', apkPath, '--target', target.id];
|
||||
if (selectedPorts) {
|
||||
nativeRunArgs.push('--forward', `${selectedPorts}`);
|
||||
}
|
||||
debug('Invoking native-run with args: %O', nativeRunArgs);
|
||||
await (0, common_1.runTask)(`Deploying ${colors_1.default.strong(apkName)} to ${colors_1.default.input(target.id)}`, async () => (0, native_run_1.runNativeRun)(nativeRunArgs));
|
||||
}
|
||||
exports.runAndroid = runAndroid;
|
||||
319
node_modules/@capacitor/cli/dist/android/update.js
generated
vendored
Normal file
319
node_modules/@capacitor/cli/dist/android/update.js
generated
vendored
Normal file
@@ -0,0 +1,319 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.handleCordovaPluginsGradle = exports.installGradlePlugins = exports.updateAndroid = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const debug_1 = tslib_1.__importDefault(require("debug"));
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path_1 = require("path");
|
||||
const colors_1 = tslib_1.__importDefault(require("../colors"));
|
||||
const common_1 = require("../common");
|
||||
const cordova_1 = require("../cordova");
|
||||
const errors_1 = require("../errors");
|
||||
const plugin_1 = require("../plugin");
|
||||
const copy_1 = require("../tasks/copy");
|
||||
const migrate_1 = require("../tasks/migrate");
|
||||
const fs_1 = require("../util/fs");
|
||||
const node_1 = require("../util/node");
|
||||
const template_1 = require("../util/template");
|
||||
const common_2 = require("./common");
|
||||
const platform = 'android';
|
||||
const debug = (0, debug_1.default)('capacitor:android:update');
|
||||
async function updateAndroid(config) {
|
||||
var _a;
|
||||
const plugins = await getPluginsTask(config);
|
||||
const capacitorPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 0 /* PluginType.Core */);
|
||||
(0, plugin_1.printPlugins)(capacitorPlugins, 'android');
|
||||
await writePluginsJson(config, capacitorPlugins);
|
||||
await removePluginsNativeFiles(config);
|
||||
const cordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
|
||||
await (0, migrate_1.patchOldCapacitorPlugins)(config);
|
||||
if (cordovaPlugins.length > 0) {
|
||||
await copyPluginsNativeFiles(config, cordovaPlugins);
|
||||
}
|
||||
if (!(await (0, fs_extra_1.pathExists)(config.android.webDirAbs))) {
|
||||
await (0, copy_1.copy)(config, platform);
|
||||
}
|
||||
await (0, cordova_1.handleCordovaPluginsJS)(cordovaPlugins, config, platform);
|
||||
await (0, cordova_1.checkPluginDependencies)(plugins, platform, (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.failOnUninstalledPlugins);
|
||||
await installGradlePlugins(config, capacitorPlugins, cordovaPlugins);
|
||||
await handleCordovaPluginsGradle(config, cordovaPlugins);
|
||||
await (0, cordova_1.writeCordovaAndroidManifest)(cordovaPlugins, config, platform);
|
||||
const incompatibleCordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
|
||||
(0, plugin_1.printPlugins)(incompatibleCordovaPlugins, platform, 'incompatible');
|
||||
await (0, common_1.checkPlatformVersions)(config, platform);
|
||||
}
|
||||
exports.updateAndroid = updateAndroid;
|
||||
function getGradlePackageName(id) {
|
||||
return id.replace('@', '').replace('/', '-');
|
||||
}
|
||||
async function writePluginsJson(config, plugins) {
|
||||
const classes = await findAndroidPluginClasses(plugins);
|
||||
const pluginsJsonPath = (0, path_1.resolve)(config.android.assetsDirAbs, 'capacitor.plugins.json');
|
||||
await (0, fs_extra_1.writeJSON)(pluginsJsonPath, classes, { spaces: '\t' });
|
||||
}
|
||||
async function findAndroidPluginClasses(plugins) {
|
||||
const entries = [];
|
||||
for (const plugin of plugins) {
|
||||
entries.push(...(await findAndroidPluginClassesInPlugin(plugin)));
|
||||
}
|
||||
return entries;
|
||||
}
|
||||
async function findAndroidPluginClassesInPlugin(plugin) {
|
||||
if (!plugin.android || (0, plugin_1.getPluginType)(plugin, platform) !== 0 /* PluginType.Core */) {
|
||||
return [];
|
||||
}
|
||||
const srcPath = (0, path_1.resolve)(plugin.rootPath, plugin.android.path, 'src/main');
|
||||
const srcFiles = await (0, fs_1.readdirp)(srcPath, {
|
||||
filter: (entry) => !entry.stats.isDirectory() && ['.java', '.kt'].includes((0, path_1.extname)(entry.path)),
|
||||
});
|
||||
const classRegex = /^@(?:CapacitorPlugin|NativePlugin)[\s\S]+?class ([\w]+)/gm;
|
||||
const packageRegex = /^package ([\w.]+);?$/gm;
|
||||
debug('Searching %O source files in %O by %O regex', srcFiles.length, srcPath, classRegex);
|
||||
const entries = await Promise.all(srcFiles.map(async (srcFile) => {
|
||||
const srcFileContents = await (0, fs_extra_1.readFile)(srcFile, { encoding: 'utf-8' });
|
||||
classRegex.lastIndex = 0;
|
||||
const classMatch = classRegex.exec(srcFileContents);
|
||||
if (classMatch) {
|
||||
const className = classMatch[1];
|
||||
debug('Searching %O for package by %O regex', srcFile, packageRegex);
|
||||
packageRegex.lastIndex = 0;
|
||||
const packageMatch = packageRegex.exec(srcFileContents.substring(0, classMatch.index));
|
||||
if (!packageMatch) {
|
||||
(0, errors_1.fatal)(`Package could not be parsed from Android plugin.\n` + `Location: ${colors_1.default.strong(srcFile)}`);
|
||||
}
|
||||
const packageName = packageMatch[1];
|
||||
const classpath = `${packageName}.${className}`;
|
||||
debug('%O is a suitable plugin class', classpath);
|
||||
return {
|
||||
pkg: plugin.id,
|
||||
classpath,
|
||||
};
|
||||
}
|
||||
}));
|
||||
return entries.filter((entry) => !!entry);
|
||||
}
|
||||
async function installGradlePlugins(config, capacitorPlugins, cordovaPlugins) {
|
||||
const capacitorAndroidPackagePath = (0, node_1.resolveNode)(config.app.rootDir, '@capacitor/android', 'package.json');
|
||||
if (!capacitorAndroidPackagePath) {
|
||||
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/android')}.\n` +
|
||||
`Are you sure ${colors_1.default.strong('@capacitor/android')} is installed?`);
|
||||
}
|
||||
const capacitorAndroidPath = (0, path_1.resolve)((0, path_1.dirname)(capacitorAndroidPackagePath), 'capacitor');
|
||||
const settingsPath = config.android.platformDirAbs;
|
||||
const dependencyPath = config.android.appDirAbs;
|
||||
const relativeCapcitorAndroidPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(settingsPath, capacitorAndroidPath));
|
||||
const settingsLines = `// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||
include ':capacitor-android'
|
||||
project(':capacitor-android').projectDir = new File('${relativeCapcitorAndroidPath}')
|
||||
${capacitorPlugins
|
||||
.map((p) => {
|
||||
if (!p.android) {
|
||||
return '';
|
||||
}
|
||||
const relativePluginPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(settingsPath, p.rootPath));
|
||||
return `
|
||||
include ':${getGradlePackageName(p.id)}'
|
||||
project(':${getGradlePackageName(p.id)}').projectDir = new File('${relativePluginPath}/${p.android.path}')
|
||||
`;
|
||||
})
|
||||
.join('')}`;
|
||||
const applyArray = [];
|
||||
const frameworksArray = [];
|
||||
let prefsArray = [];
|
||||
cordovaPlugins.map((p) => {
|
||||
const relativePluginPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(dependencyPath, p.rootPath));
|
||||
const frameworks = (0, plugin_1.getPlatformElement)(p, platform, 'framework');
|
||||
frameworks.map((framework) => {
|
||||
if (framework.$.custom &&
|
||||
framework.$.custom === 'true' &&
|
||||
framework.$.type &&
|
||||
framework.$.type === 'gradleReference') {
|
||||
applyArray.push(`apply from: "${relativePluginPath}/${framework.$.src}"`);
|
||||
}
|
||||
else if (!framework.$.type && !framework.$.custom) {
|
||||
if (framework.$.src.startsWith('platform(')) {
|
||||
frameworksArray.push(` implementation ${framework.$.src}`);
|
||||
}
|
||||
else {
|
||||
frameworksArray.push(` implementation "${framework.$.src}"`);
|
||||
}
|
||||
}
|
||||
});
|
||||
prefsArray = prefsArray.concat((0, plugin_1.getAllElements)(p, platform, 'preference'));
|
||||
});
|
||||
let frameworkString = frameworksArray.join('\n');
|
||||
frameworkString = await replaceFrameworkVariables(config, prefsArray, frameworkString);
|
||||
const dependencyLines = `// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||
|
||||
android {
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_21
|
||||
targetCompatibility JavaVersion.VERSION_21
|
||||
}
|
||||
}
|
||||
|
||||
apply from: "../capacitor-cordova-android-plugins/cordova.variables.gradle"
|
||||
dependencies {
|
||||
${capacitorPlugins
|
||||
.map((p) => {
|
||||
return ` implementation project(':${getGradlePackageName(p.id)}')`;
|
||||
})
|
||||
.join('\n')}
|
||||
${frameworkString}
|
||||
}
|
||||
${applyArray.join('\n')}
|
||||
|
||||
if (hasProperty('postBuildExtras')) {
|
||||
postBuildExtras()
|
||||
}
|
||||
`;
|
||||
await (0, fs_extra_1.writeFile)((0, path_1.join)(settingsPath, 'capacitor.settings.gradle'), settingsLines);
|
||||
await (0, fs_extra_1.writeFile)((0, path_1.join)(dependencyPath, 'capacitor.build.gradle'), dependencyLines);
|
||||
}
|
||||
exports.installGradlePlugins = installGradlePlugins;
|
||||
async function handleCordovaPluginsGradle(config, cordovaPlugins) {
|
||||
var _a, _b, _c;
|
||||
const pluginsGradlePath = (0, path_1.join)(config.android.cordovaPluginsDirAbs, 'build.gradle');
|
||||
const kotlinNeeded = await kotlinNeededCheck(config, cordovaPlugins);
|
||||
const kotlinVersionString = (_c = (_b = (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.preferences) === null || _b === void 0 ? void 0 : _b.GradlePluginKotlinVersion) !== null && _c !== void 0 ? _c : '1.9.25';
|
||||
const frameworksArray = [];
|
||||
let prefsArray = [];
|
||||
const applyArray = [];
|
||||
applyArray.push(`apply from: "cordova.variables.gradle"`);
|
||||
cordovaPlugins.map((p) => {
|
||||
const relativePluginPath = (0, fs_1.convertToUnixPath)((0, path_1.relative)(config.android.cordovaPluginsDirAbs, p.rootPath));
|
||||
const frameworks = (0, plugin_1.getPlatformElement)(p, platform, 'framework');
|
||||
frameworks.map((framework) => {
|
||||
if (!framework.$.type && !framework.$.custom) {
|
||||
frameworksArray.push(framework.$.src);
|
||||
}
|
||||
else if (framework.$.custom &&
|
||||
framework.$.custom === 'true' &&
|
||||
framework.$.type &&
|
||||
framework.$.type === 'gradleReference') {
|
||||
applyArray.push(`apply from: "${relativePluginPath}/${framework.$.src}"`);
|
||||
}
|
||||
});
|
||||
prefsArray = prefsArray.concat((0, plugin_1.getAllElements)(p, platform, 'preference'));
|
||||
});
|
||||
let frameworkString = frameworksArray
|
||||
.map((f) => {
|
||||
if (f.startsWith('platform(')) {
|
||||
return ` implementation ${f}`;
|
||||
}
|
||||
else {
|
||||
return ` implementation "${f}"`;
|
||||
}
|
||||
})
|
||||
.join('\n');
|
||||
frameworkString = await replaceFrameworkVariables(config, prefsArray, frameworkString);
|
||||
if (kotlinNeeded) {
|
||||
frameworkString += `\n implementation "androidx.core:core-ktx:$androidxCoreKTXVersion"`;
|
||||
frameworkString += `\n implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"`;
|
||||
}
|
||||
const applyString = applyArray.join('\n');
|
||||
let buildGradle = await (0, fs_extra_1.readFile)(pluginsGradlePath, { encoding: 'utf-8' });
|
||||
buildGradle = buildGradle.replace(/(SUB-PROJECT DEPENDENCIES START)[\s\S]*(\/\/ SUB-PROJECT DEPENDENCIES END)/, '$1\n' + frameworkString.concat('\n') + ' $2');
|
||||
buildGradle = buildGradle.replace(/(PLUGIN GRADLE EXTENSIONS START)[\s\S]*(\/\/ PLUGIN GRADLE EXTENSIONS END)/, '$1\n' + applyString.concat('\n') + '$2');
|
||||
if (kotlinNeeded) {
|
||||
buildGradle = buildGradle.replace(/(buildscript\s{\n(\t|\s{4})repositories\s{\n((\t{2}|\s{8}).+\n)+(\t|\s{4})}\n(\t|\s{4})dependencies\s{\n(\t{2}|\s{8}).+)\n((\t|\s{4})}\n}\n)/, `$1\n classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"\n$8`);
|
||||
buildGradle = buildGradle.replace(/(ext\s{)/, `$1\n androidxCoreKTXVersion = project.hasProperty('androidxCoreKTXVersion') ? rootProject.ext.androidxCoreKTXVersion : '1.8.0'`);
|
||||
buildGradle = buildGradle.replace(/(buildscript\s{)/, `$1\n ext.kotlin_version = project.hasProperty('kotlin_version') ? rootProject.ext.kotlin_version : '${kotlinVersionString}'`);
|
||||
buildGradle = buildGradle.replace(/(apply\splugin:\s'com\.android\.library')/, `$1\napply plugin: 'kotlin-android'`);
|
||||
buildGradle = buildGradle.replace(/(compileOptions\s{\n((\t{2}|\s{8}).+\n)+(\t|\s{4})})\n(})/, `$1\n sourceSets {\n main.java.srcDirs += 'src/main/kotlin'\n }\n$5`);
|
||||
}
|
||||
await (0, fs_extra_1.writeFile)(pluginsGradlePath, buildGradle);
|
||||
const cordovaVariables = `// DO NOT EDIT THIS FILE! IT IS GENERATED EACH TIME "capacitor update" IS RUN
|
||||
ext {
|
||||
cdvMinSdkVersion = project.hasProperty('minSdkVersion') ? rootProject.ext.minSdkVersion : ${config.android.minVersion}
|
||||
// Plugin gradle extensions can append to this to have code run at the end.
|
||||
cdvPluginPostBuildExtras = []
|
||||
cordovaConfig = [:]
|
||||
}`;
|
||||
await (0, fs_extra_1.writeFile)((0, path_1.join)(config.android.cordovaPluginsDirAbs, 'cordova.variables.gradle'), cordovaVariables);
|
||||
}
|
||||
exports.handleCordovaPluginsGradle = handleCordovaPluginsGradle;
|
||||
async function kotlinNeededCheck(config, cordovaPlugins) {
|
||||
var _a, _b;
|
||||
if (((_b = (_a = config.app.extConfig.cordova) === null || _a === void 0 ? void 0 : _a.preferences) === null || _b === void 0 ? void 0 : _b.GradlePluginKotlinEnabled) !== 'true') {
|
||||
for (const plugin of cordovaPlugins) {
|
||||
const androidPlatform = (0, plugin_1.getPluginPlatform)(plugin, platform);
|
||||
const sourceFiles = androidPlatform['source-file'];
|
||||
if (sourceFiles) {
|
||||
for (const srcFile of sourceFiles) {
|
||||
if (/^.*\.kt$/.test(srcFile['$'].src)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
async function copyPluginsNativeFiles(config, cordovaPlugins) {
|
||||
const pluginsPath = (0, path_1.join)(config.android.cordovaPluginsDirAbs, 'src', 'main');
|
||||
for (const p of cordovaPlugins) {
|
||||
const androidPlatform = (0, plugin_1.getPluginPlatform)(p, platform);
|
||||
if (androidPlatform) {
|
||||
const sourceFiles = androidPlatform['source-file'];
|
||||
if (sourceFiles) {
|
||||
for (const sourceFile of sourceFiles) {
|
||||
const fileName = sourceFile.$.src.split('/').pop();
|
||||
let baseFolder = 'java/';
|
||||
if (fileName.split('.').pop() === 'aidl') {
|
||||
baseFolder = 'aidl/';
|
||||
}
|
||||
const target = sourceFile.$['target-dir'].replace('app/src/main/', '').replace('src/', baseFolder);
|
||||
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, sourceFile.$.src), (0, path_1.join)(pluginsPath, target, fileName));
|
||||
}
|
||||
}
|
||||
const resourceFiles = androidPlatform['resource-file'];
|
||||
if (resourceFiles) {
|
||||
for (const resourceFile of resourceFiles) {
|
||||
const target = resourceFile.$['target'];
|
||||
if (resourceFile.$.src.split('.').pop() === 'aar') {
|
||||
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(pluginsPath, 'libs', target.split('/').pop()));
|
||||
}
|
||||
else if (target !== '.') {
|
||||
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, resourceFile.$.src), (0, path_1.join)(pluginsPath, target));
|
||||
}
|
||||
}
|
||||
}
|
||||
const libFiles = (0, plugin_1.getPlatformElement)(p, platform, 'lib-file');
|
||||
for (const libFile of libFiles) {
|
||||
await (0, fs_extra_1.copy)((0, plugin_1.getFilePath)(config, p, libFile.$.src), (0, path_1.join)(pluginsPath, 'libs', libFile.$.src.split('/').pop()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
async function removePluginsNativeFiles(config) {
|
||||
await (0, fs_extra_1.remove)(config.android.cordovaPluginsDirAbs);
|
||||
await (0, template_1.extractTemplate)(config.cli.assets.android.cordovaPluginsTemplateArchiveAbs, config.android.cordovaPluginsDirAbs);
|
||||
}
|
||||
async function getPluginsTask(config) {
|
||||
return await (0, common_1.runTask)('Updating Android plugins', async () => {
|
||||
const allPlugins = await (0, plugin_1.getPlugins)(config, 'android');
|
||||
const androidPlugins = await (0, common_2.getAndroidPlugins)(allPlugins);
|
||||
return androidPlugins;
|
||||
});
|
||||
}
|
||||
async function getVariablesGradleFile(config) {
|
||||
const variablesFile = (0, path_1.resolve)(config.android.platformDirAbs, 'variables.gradle');
|
||||
let variablesGradle = '';
|
||||
if (await (0, fs_extra_1.pathExists)(variablesFile)) {
|
||||
variablesGradle = await (0, fs_extra_1.readFile)(variablesFile, { encoding: 'utf-8' });
|
||||
}
|
||||
return variablesGradle;
|
||||
}
|
||||
async function replaceFrameworkVariables(config, prefsArray, frameworkString) {
|
||||
const variablesGradle = await getVariablesGradleFile(config);
|
||||
prefsArray.map((preference) => {
|
||||
if (!variablesGradle.includes(preference.$.name)) {
|
||||
frameworkString = frameworkString.replace(new RegExp(('$' + preference.$.name).replace('$', '\\$&'), 'g'), preference.$.default);
|
||||
}
|
||||
});
|
||||
return frameworkString;
|
||||
}
|
||||
26
node_modules/@capacitor/cli/dist/colors.js
generated
vendored
Normal file
26
node_modules/@capacitor/cli/dist/colors.js
generated
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.ancillary = exports.failure = exports.success = exports.input = exports.weak = exports.strong = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const kleur_1 = tslib_1.__importDefault(require("kleur"));
|
||||
exports.strong = kleur_1.default.bold;
|
||||
exports.weak = kleur_1.default.dim;
|
||||
exports.input = kleur_1.default.cyan;
|
||||
exports.success = kleur_1.default.green;
|
||||
exports.failure = kleur_1.default.red;
|
||||
exports.ancillary = kleur_1.default.cyan;
|
||||
const COLORS = {
|
||||
strong: exports.strong,
|
||||
weak: exports.weak,
|
||||
input: exports.input,
|
||||
success: exports.success,
|
||||
failure: exports.failure,
|
||||
ancillary: exports.ancillary,
|
||||
log: {
|
||||
DEBUG: kleur_1.default.magenta,
|
||||
INFO: kleur_1.default.cyan,
|
||||
WARN: kleur_1.default.yellow,
|
||||
ERROR: kleur_1.default.red,
|
||||
},
|
||||
};
|
||||
exports.default = COLORS;
|
||||
412
node_modules/@capacitor/cli/dist/common.js
generated
vendored
Normal file
412
node_modules/@capacitor/cli/dist/common.js
generated
vendored
Normal file
@@ -0,0 +1,412 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseApkNameFromFlavor = exports.checkJDKMajorVersion = exports.resolvePlatform = exports.checkPlatformVersions = exports.getAddedPlatforms = exports.getPlatformTargetName = exports.promptForPlatformTarget = exports.promptForPlatform = exports.isValidEnterprisePlatform = exports.getKnownEnterprisePlatforms = exports.isValidCommunityPlatform = exports.getKnownCommunityPlatforms = exports.isValidPlatform = exports.getKnownPlatforms = exports.selectPlatforms = exports.getProjectPlatformDirectory = exports.getCLIVersion = exports.getCoreVersion = exports.getCapacitorPackageVersion = exports.requireCapacitorPackage = exports.getCapacitorPackage = exports.runTask = exports.runPlatformHook = exports.runHooks = exports.wait = exports.checkAppName = exports.checkAppId = exports.checkAppDir = exports.checkAppConfig = exports.checkCapacitorPlatform = exports.checkPackage = exports.checkWebDir = exports.check = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const utils_terminal_1 = require("@ionic/utils-terminal");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path_1 = require("path");
|
||||
const colors_1 = tslib_1.__importDefault(require("./colors"));
|
||||
const errors_1 = require("./errors");
|
||||
const log_1 = require("./log");
|
||||
const plugin_1 = require("./plugin");
|
||||
const monorepotools_1 = require("./util/monorepotools");
|
||||
const node_1 = require("./util/node");
|
||||
const subprocess_1 = require("./util/subprocess");
|
||||
async function check(checks) {
|
||||
const results = await Promise.all(checks.map((f) => f()));
|
||||
const errors = results.filter((r) => r != null);
|
||||
if (errors.length > 0) {
|
||||
throw errors.join('\n');
|
||||
}
|
||||
}
|
||||
exports.check = check;
|
||||
async function checkWebDir(config) {
|
||||
var _a;
|
||||
// We can skip checking the web dir if a server URL is set.
|
||||
if ((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.url) {
|
||||
return null;
|
||||
}
|
||||
const invalidFolders = ['', '.', '..', '../', './'];
|
||||
if (invalidFolders.includes(config.app.webDir)) {
|
||||
return `"${config.app.webDir}" is not a valid value for webDir`;
|
||||
}
|
||||
if (!(await (0, fs_extra_1.pathExists)(config.app.webDirAbs))) {
|
||||
return (`Could not find the web assets directory: ${colors_1.default.strong((0, utils_terminal_1.prettyPath)(config.app.webDirAbs))}.\n` +
|
||||
`Please create it and make sure it has an ${colors_1.default.strong('index.html')} file. You can change the path of this directory in ${colors_1.default.strong(config.app.extConfigName)} (${colors_1.default.input('webDir')} option). You may need to compile the web assets for your app (typically ${colors_1.default.input('npm run build')}). More info: ${colors_1.default.strong('https://capacitorjs.com/docs/basics/workflow#sync-your-project')}`);
|
||||
}
|
||||
if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(config.app.webDirAbs, 'index.html')))) {
|
||||
return (`The web assets directory (${colors_1.default.strong((0, utils_terminal_1.prettyPath)(config.app.webDirAbs))}) must contain an ${colors_1.default.strong('index.html')} file.\n` +
|
||||
`It will be the entry point for the web portion of the Capacitor app.`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.checkWebDir = checkWebDir;
|
||||
async function checkPackage() {
|
||||
if (!(await (0, fs_extra_1.pathExists)('package.json'))) {
|
||||
if (await (0, fs_extra_1.pathExists)('project.json')) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return (`The Capacitor CLI needs to run at the root of an npm package or in a valid NX monorepo.\n` +
|
||||
`Make sure you have a package.json or project.json file in the directory where you run the Capacitor CLI.\n` +
|
||||
`More info: ${colors_1.default.strong('https://docs.npmjs.com/cli/init')}`);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.checkPackage = checkPackage;
|
||||
async function checkCapacitorPlatform(config, platform) {
|
||||
const pkg = await getCapacitorPackage(config, platform);
|
||||
if (!pkg) {
|
||||
return (`Could not find the ${colors_1.default.input(platform)} platform.\n` +
|
||||
`You must install it in your project first, e.g. w/ ${colors_1.default.input(`npm install @capacitor/${platform}`)}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.checkCapacitorPlatform = checkCapacitorPlatform;
|
||||
async function checkAppConfig(config) {
|
||||
if (!config.app.appId) {
|
||||
return (`Missing ${colors_1.default.input('appId')} for new platform.\n` +
|
||||
`Please add it in ${config.app.extConfigName} or run ${colors_1.default.input('npx cap init')}.`);
|
||||
}
|
||||
if (!config.app.appName) {
|
||||
return (`Missing ${colors_1.default.input('appName')} for new platform.\n` +
|
||||
`Please add it in ${config.app.extConfigName} or run ${colors_1.default.input('npx cap init')}.`);
|
||||
}
|
||||
const appIdError = await checkAppId(config, config.app.appId);
|
||||
if (appIdError) {
|
||||
return appIdError;
|
||||
}
|
||||
const appNameError = await checkAppName(config, config.app.appName);
|
||||
if (appNameError) {
|
||||
return appNameError;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.checkAppConfig = checkAppConfig;
|
||||
async function checkAppDir(config, dir) {
|
||||
if (!/^\S*$/.test(dir)) {
|
||||
return `Your app directory should not contain spaces`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.checkAppDir = checkAppDir;
|
||||
async function checkAppId(config, id) {
|
||||
if (!id) {
|
||||
return `Invalid App ID. App ID is required and cannot be blank.`;
|
||||
}
|
||||
if (/^[a-zA-Z][\w]*(?:\.[a-zA-Z][\w]*)+$/.test(id.toLowerCase())) {
|
||||
return null;
|
||||
}
|
||||
return `
|
||||
Invalid App ID "${id}". Your App ID must meet the following requirements to be valid on both iOS and Android:
|
||||
- Must be in Java package form with no dashes (ex: com.example.app)
|
||||
- It must have at least two segments (one or more dots).
|
||||
- Each segment must start with a letter.
|
||||
- All characters must be alphanumeric or an underscore [a-zA-Z][a-zA-Z0-9]+.
|
||||
|
||||
If you would like to skip validation, run "cap init" with the "--skip-appid-validation" flag.
|
||||
`;
|
||||
}
|
||||
exports.checkAppId = checkAppId;
|
||||
async function checkAppName(config, name) {
|
||||
// We allow pretty much anything right now, have fun
|
||||
if (!(name === null || name === void 0 ? void 0 : name.length)) {
|
||||
return `Must provide an app name. For example: 'Spacebook'`;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.checkAppName = checkAppName;
|
||||
async function wait(time) {
|
||||
return new Promise((resolve) => setTimeout(resolve, time));
|
||||
}
|
||||
exports.wait = wait;
|
||||
async function runHooks(config, platformName, dir, hook) {
|
||||
await runPlatformHook(config, platformName, dir, hook);
|
||||
const allPlugins = await (0, plugin_1.getPlugins)(config, platformName);
|
||||
for (const p of allPlugins) {
|
||||
await runPlatformHook(config, platformName, p.rootPath, hook);
|
||||
}
|
||||
}
|
||||
exports.runHooks = runHooks;
|
||||
async function runPlatformHook(config, platformName, platformDir, hook) {
|
||||
var _a;
|
||||
const { spawn } = await Promise.resolve().then(() => tslib_1.__importStar(require('child_process')));
|
||||
let pkg;
|
||||
if ((0, monorepotools_1.isNXMonorepo)(platformDir)) {
|
||||
pkg = await (0, fs_extra_1.readJSON)((0, path_1.join)((0, monorepotools_1.findNXMonorepoRoot)(platformDir), 'package.json'));
|
||||
}
|
||||
else {
|
||||
pkg = await (0, fs_extra_1.readJSON)((0, path_1.join)(platformDir, 'package.json'));
|
||||
}
|
||||
const cmd = (_a = pkg.scripts) === null || _a === void 0 ? void 0 : _a[hook];
|
||||
if (!cmd) {
|
||||
return;
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
const p = spawn(cmd, {
|
||||
stdio: 'inherit',
|
||||
shell: true,
|
||||
cwd: platformDir,
|
||||
env: {
|
||||
INIT_CWD: platformDir,
|
||||
CAPACITOR_ROOT_DIR: config.app.rootDir,
|
||||
CAPACITOR_WEB_DIR: config.app.webDirAbs,
|
||||
CAPACITOR_CONFIG: JSON.stringify(config.app.extConfig),
|
||||
CAPACITOR_PLATFORM_NAME: platformName,
|
||||
...process.env,
|
||||
},
|
||||
});
|
||||
p.on('close', (code) => {
|
||||
if (code === 0) {
|
||||
resolve();
|
||||
}
|
||||
else {
|
||||
reject(new Error(`${hook} hook on ${platformName} failed with error code: ${code} while running command: ${cmd}`));
|
||||
}
|
||||
});
|
||||
p.on('error', (err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.runPlatformHook = runPlatformHook;
|
||||
async function runTask(title, fn) {
|
||||
const chain = log_1.output.createTaskChain();
|
||||
chain.next(title);
|
||||
try {
|
||||
const value = await fn();
|
||||
chain.end();
|
||||
return value;
|
||||
}
|
||||
catch (e) {
|
||||
chain.fail();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
exports.runTask = runTask;
|
||||
async function getCapacitorPackage(config, name) {
|
||||
const packagePath = (0, node_1.resolveNode)(config.app.rootDir, `@capacitor/${name}`, 'package.json');
|
||||
if (!packagePath) {
|
||||
return null;
|
||||
}
|
||||
return (0, fs_extra_1.readJSON)(packagePath);
|
||||
}
|
||||
exports.getCapacitorPackage = getCapacitorPackage;
|
||||
async function requireCapacitorPackage(config, name) {
|
||||
const pkg = await getCapacitorPackage(config, name);
|
||||
if (!pkg) {
|
||||
(0, errors_1.fatal)(`Unable to find node_modules/@capacitor/${name}.\n` +
|
||||
`Are you sure ${colors_1.default.strong(`@capacitor/${name}`)} is installed?`);
|
||||
}
|
||||
return pkg;
|
||||
}
|
||||
exports.requireCapacitorPackage = requireCapacitorPackage;
|
||||
async function getCapacitorPackageVersion(config, platform) {
|
||||
return (await requireCapacitorPackage(config, platform)).version;
|
||||
}
|
||||
exports.getCapacitorPackageVersion = getCapacitorPackageVersion;
|
||||
async function getCoreVersion(config) {
|
||||
return getCapacitorPackageVersion(config, 'core');
|
||||
}
|
||||
exports.getCoreVersion = getCoreVersion;
|
||||
async function getCLIVersion(config) {
|
||||
return getCapacitorPackageVersion(config, 'cli');
|
||||
}
|
||||
exports.getCLIVersion = getCLIVersion;
|
||||
function getPlatformDirectory(config, platform) {
|
||||
switch (platform) {
|
||||
case 'android':
|
||||
return config.android.platformDirAbs;
|
||||
case 'ios':
|
||||
return config.ios.platformDirAbs;
|
||||
case 'web':
|
||||
return config.web.platformDirAbs;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
async function getProjectPlatformDirectory(config, platform) {
|
||||
const platformPath = getPlatformDirectory(config, platform);
|
||||
if (platformPath && (await (0, fs_extra_1.pathExists)(platformPath))) {
|
||||
return platformPath;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.getProjectPlatformDirectory = getProjectPlatformDirectory;
|
||||
async function selectPlatforms(config, selectedPlatformName) {
|
||||
if (selectedPlatformName) {
|
||||
// already passed in a platform name
|
||||
const platformName = selectedPlatformName.toLowerCase().trim();
|
||||
if (!(await isValidPlatform(platformName))) {
|
||||
(0, errors_1.fatal)(`Invalid platform: ${colors_1.default.input(platformName)}`);
|
||||
}
|
||||
else if (!(await getProjectPlatformDirectory(config, platformName))) {
|
||||
if (platformName === 'web') {
|
||||
(0, errors_1.fatal)(`Could not find the web platform directory.\n` + `Make sure ${colors_1.default.strong(config.app.webDir)} exists.`);
|
||||
}
|
||||
(0, errors_1.fatal)(`${colors_1.default.strong(platformName)} platform has not been added yet.\n` +
|
||||
`See the docs for adding the ${colors_1.default.strong(platformName)} platform: ${colors_1.default.strong(`https://capacitorjs.com/docs/${platformName}#adding-the-${platformName}-platform`)}`);
|
||||
}
|
||||
// return the platform in an string array
|
||||
return [platformName];
|
||||
}
|
||||
// wasn't given a platform name, so let's
|
||||
// get the platforms that have already been created
|
||||
return getAddedPlatforms(config);
|
||||
}
|
||||
exports.selectPlatforms = selectPlatforms;
|
||||
async function getKnownPlatforms() {
|
||||
return ['web', 'android', 'ios'];
|
||||
}
|
||||
exports.getKnownPlatforms = getKnownPlatforms;
|
||||
async function isValidPlatform(platform) {
|
||||
return (await getKnownPlatforms()).includes(platform);
|
||||
}
|
||||
exports.isValidPlatform = isValidPlatform;
|
||||
async function getKnownCommunityPlatforms() {
|
||||
return ['electron'];
|
||||
}
|
||||
exports.getKnownCommunityPlatforms = getKnownCommunityPlatforms;
|
||||
async function isValidCommunityPlatform(platform) {
|
||||
return (await getKnownCommunityPlatforms()).includes(platform);
|
||||
}
|
||||
exports.isValidCommunityPlatform = isValidCommunityPlatform;
|
||||
async function getKnownEnterprisePlatforms() {
|
||||
return ['windows'];
|
||||
}
|
||||
exports.getKnownEnterprisePlatforms = getKnownEnterprisePlatforms;
|
||||
async function isValidEnterprisePlatform(platform) {
|
||||
return (await getKnownEnterprisePlatforms()).includes(platform);
|
||||
}
|
||||
exports.isValidEnterprisePlatform = isValidEnterprisePlatform;
|
||||
async function promptForPlatform(platforms, promptMessage, selectedPlatformName) {
|
||||
const { prompt } = await Promise.resolve().then(() => tslib_1.__importStar(require('prompts')));
|
||||
if (!selectedPlatformName) {
|
||||
const answers = await prompt([
|
||||
{
|
||||
type: 'select',
|
||||
name: 'mode',
|
||||
message: promptMessage,
|
||||
choices: platforms.map((p) => ({ title: p, value: p })),
|
||||
},
|
||||
], { onCancel: () => process.exit(1) });
|
||||
return answers.mode.toLowerCase().trim();
|
||||
}
|
||||
const platformName = selectedPlatformName.toLowerCase().trim();
|
||||
if (!(await isValidPlatform(platformName))) {
|
||||
const knownPlatforms = await getKnownPlatforms();
|
||||
(0, errors_1.fatal)(`Invalid platform: ${colors_1.default.input(platformName)}.\n` + `Valid platforms include: ${knownPlatforms.join(', ')}`);
|
||||
}
|
||||
return platformName;
|
||||
}
|
||||
exports.promptForPlatform = promptForPlatform;
|
||||
async function promptForPlatformTarget(targets, selectedTarget) {
|
||||
const { prompt } = await Promise.resolve().then(() => tslib_1.__importStar(require('prompts')));
|
||||
const validTargets = targets.filter((t) => t.id !== undefined);
|
||||
if (!selectedTarget) {
|
||||
if (validTargets.length === 1) {
|
||||
return validTargets[0];
|
||||
}
|
||||
else {
|
||||
const answers = await prompt([
|
||||
{
|
||||
type: 'select',
|
||||
name: 'target',
|
||||
message: 'Please choose a target device:',
|
||||
choices: validTargets.map((t) => ({
|
||||
title: `${getPlatformTargetName(t)} (${t.id})`,
|
||||
value: t,
|
||||
})),
|
||||
},
|
||||
], { onCancel: () => process.exit(1) });
|
||||
return answers.target;
|
||||
}
|
||||
}
|
||||
const targetID = selectedTarget.trim();
|
||||
const target = targets.find((t) => t.id === targetID);
|
||||
if (!target) {
|
||||
(0, errors_1.fatal)(`Invalid target ID: ${colors_1.default.input(targetID)}.\n` + `Valid targets are: ${targets.map((t) => t.id).join(', ')}`);
|
||||
}
|
||||
return target;
|
||||
}
|
||||
exports.promptForPlatformTarget = promptForPlatformTarget;
|
||||
function getPlatformTargetName(target) {
|
||||
var _a, _b, _c;
|
||||
return `${(_c = (_b = (_a = target.name) !== null && _a !== void 0 ? _a : target.model) !== null && _b !== void 0 ? _b : target.id) !== null && _c !== void 0 ? _c : '?'}${target.virtual ? ` (${target.platform === 'ios' ? 'simulator' : 'emulator'})` : ''}`;
|
||||
}
|
||||
exports.getPlatformTargetName = getPlatformTargetName;
|
||||
async function getAddedPlatforms(config) {
|
||||
const platforms = [];
|
||||
if (await getProjectPlatformDirectory(config, config.android.name)) {
|
||||
platforms.push(config.android.name);
|
||||
}
|
||||
if (await getProjectPlatformDirectory(config, config.ios.name)) {
|
||||
platforms.push(config.ios.name);
|
||||
}
|
||||
platforms.push(config.web.name);
|
||||
return platforms;
|
||||
}
|
||||
exports.getAddedPlatforms = getAddedPlatforms;
|
||||
async function checkPlatformVersions(config, platform) {
|
||||
const semver = await Promise.resolve().then(() => tslib_1.__importStar(require('semver')));
|
||||
const coreVersion = await getCoreVersion(config);
|
||||
const platformVersion = await getCapacitorPackageVersion(config, platform);
|
||||
if (semver.diff(coreVersion, platformVersion) === 'minor' || semver.diff(coreVersion, platformVersion) === 'major') {
|
||||
log_1.logger.warn(`${colors_1.default.strong('@capacitor/core')}${colors_1.default.weak(`@${coreVersion}`)} version doesn't match ${colors_1.default.strong(`@capacitor/${platform}`)}${colors_1.default.weak(`@${platformVersion}`)} version.\n` +
|
||||
`Consider updating to a matching version, e.g. w/ ${colors_1.default.input(`npm install @capacitor/core@${platformVersion}`)}`);
|
||||
}
|
||||
}
|
||||
exports.checkPlatformVersions = checkPlatformVersions;
|
||||
function resolvePlatform(config, platform) {
|
||||
if (platform[0] !== '@') {
|
||||
const core = (0, node_1.resolveNode)(config.app.rootDir, `@capacitor/${platform}`, 'package.json');
|
||||
if (core) {
|
||||
return (0, path_1.dirname)(core);
|
||||
}
|
||||
const community = (0, node_1.resolveNode)(config.app.rootDir, `@capacitor-community/${platform}`, 'package.json');
|
||||
if (community) {
|
||||
return (0, path_1.dirname)(community);
|
||||
}
|
||||
const enterprise = (0, node_1.resolveNode)(config.app.rootDir, `@ionic-enterprise/capacitor-${platform}`, 'package.json');
|
||||
if (enterprise) {
|
||||
return (0, path_1.dirname)(enterprise);
|
||||
}
|
||||
}
|
||||
// third-party
|
||||
const thirdParty = (0, node_1.resolveNode)(config.app.rootDir, platform, 'package.json');
|
||||
if (thirdParty) {
|
||||
return (0, path_1.dirname)(thirdParty);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.resolvePlatform = resolvePlatform;
|
||||
async function checkJDKMajorVersion() {
|
||||
try {
|
||||
const string = await (0, subprocess_1.runCommand)('java', ['--version']);
|
||||
const versionRegex = RegExp(/([0-9]+)\.?([0-9]*)\.?([0-9]*)/);
|
||||
const versionMatch = versionRegex.exec(string);
|
||||
if (versionMatch === null) {
|
||||
return -1;
|
||||
}
|
||||
const firstVersionNumber = parseInt(versionMatch[1]);
|
||||
const secondVersionNumber = parseInt(versionMatch[2]);
|
||||
if (typeof firstVersionNumber === 'number' && firstVersionNumber != 1) {
|
||||
return firstVersionNumber;
|
||||
}
|
||||
else if (typeof secondVersionNumber === 'number' && firstVersionNumber == 1 && secondVersionNumber < 9) {
|
||||
return secondVersionNumber;
|
||||
}
|
||||
else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
exports.checkJDKMajorVersion = checkJDKMajorVersion;
|
||||
function parseApkNameFromFlavor(flavor) {
|
||||
const convertedName = flavor.replace(/([A-Z])/g, '$1').toLowerCase();
|
||||
return `app-${convertedName ? `${convertedName}-` : ''}debug.apk`;
|
||||
}
|
||||
exports.parseApkNameFromFlavor = parseApkNameFromFlavor;
|
||||
393
node_modules/@capacitor/cli/dist/config.js
generated
vendored
Normal file
393
node_modules/@capacitor/cli/dist/config.js
generated
vendored
Normal file
@@ -0,0 +1,393 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.writeConfig = exports.loadConfig = exports.CONFIG_FILE_NAME_JSON = exports.CONFIG_FILE_NAME_JS = exports.CONFIG_FILE_NAME_TS = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const debug_1 = tslib_1.__importDefault(require("debug"));
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path_1 = require("path");
|
||||
const colors_1 = tslib_1.__importDefault(require("./colors"));
|
||||
const common_1 = require("./common");
|
||||
const errors_1 = require("./errors");
|
||||
const log_1 = require("./log");
|
||||
const fn_1 = require("./util/fn");
|
||||
const js_1 = require("./util/js");
|
||||
const monorepotools_1 = require("./util/monorepotools");
|
||||
const node_1 = require("./util/node");
|
||||
const promise_1 = require("./util/promise");
|
||||
const subprocess_1 = require("./util/subprocess");
|
||||
const debug = (0, debug_1.default)('capacitor:config');
|
||||
exports.CONFIG_FILE_NAME_TS = 'capacitor.config.ts';
|
||||
exports.CONFIG_FILE_NAME_JS = 'capacitor.config.js';
|
||||
exports.CONFIG_FILE_NAME_JSON = 'capacitor.config.json';
|
||||
async function loadConfig() {
|
||||
var _a, _b, _c, _d;
|
||||
const appRootDir = process.cwd();
|
||||
const cliRootDir = (0, path_1.dirname)(__dirname);
|
||||
const conf = await loadExtConfig(appRootDir);
|
||||
const depsForNx = await (async () => {
|
||||
var _a, _b;
|
||||
if ((0, monorepotools_1.isNXMonorepo)(appRootDir)) {
|
||||
const rootOfNXMonorepo = (0, monorepotools_1.findNXMonorepoRoot)(appRootDir);
|
||||
const pkgJSONOfMonorepoRoot = await (0, fn_1.tryFn)(fs_extra_1.readJSON, (0, path_1.resolve)(rootOfNXMonorepo, 'package.json'));
|
||||
const devDependencies = (_a = pkgJSONOfMonorepoRoot === null || pkgJSONOfMonorepoRoot === void 0 ? void 0 : pkgJSONOfMonorepoRoot.devDependencies) !== null && _a !== void 0 ? _a : {};
|
||||
const dependencies = (_b = pkgJSONOfMonorepoRoot === null || pkgJSONOfMonorepoRoot === void 0 ? void 0 : pkgJSONOfMonorepoRoot.dependencies) !== null && _b !== void 0 ? _b : {};
|
||||
return {
|
||||
devDependencies,
|
||||
dependencies,
|
||||
};
|
||||
}
|
||||
return {};
|
||||
})();
|
||||
const appId = (_a = conf.extConfig.appId) !== null && _a !== void 0 ? _a : '';
|
||||
const appName = (_b = conf.extConfig.appName) !== null && _b !== void 0 ? _b : '';
|
||||
const webDir = (_c = conf.extConfig.webDir) !== null && _c !== void 0 ? _c : 'www';
|
||||
const cli = await loadCLIConfig(cliRootDir);
|
||||
const config = {
|
||||
android: await loadAndroidConfig(appRootDir, conf.extConfig, cli),
|
||||
ios: await loadIOSConfig(appRootDir, conf.extConfig),
|
||||
web: await loadWebConfig(appRootDir, webDir),
|
||||
cli,
|
||||
app: {
|
||||
rootDir: appRootDir,
|
||||
appId,
|
||||
appName,
|
||||
webDir,
|
||||
webDirAbs: (0, path_1.resolve)(appRootDir, webDir),
|
||||
package: (_d = (await (0, fn_1.tryFn)(fs_extra_1.readJSON, (0, path_1.resolve)(appRootDir, 'package.json')))) !== null && _d !== void 0 ? _d : {
|
||||
name: appName,
|
||||
version: '1.0.0',
|
||||
...depsForNx,
|
||||
},
|
||||
...conf,
|
||||
},
|
||||
};
|
||||
debug('config: %O', config);
|
||||
return config;
|
||||
}
|
||||
exports.loadConfig = loadConfig;
|
||||
async function writeConfig(extConfig, extConfigFilePath) {
|
||||
switch ((0, path_1.extname)(extConfigFilePath)) {
|
||||
case '.json': {
|
||||
await (0, fs_extra_1.writeJSON)(extConfigFilePath, extConfig, { spaces: 2 });
|
||||
break;
|
||||
}
|
||||
case '.ts': {
|
||||
await (0, fs_extra_1.writeFile)(extConfigFilePath, formatConfigTS(extConfig));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.writeConfig = writeConfig;
|
||||
async function loadExtConfigTS(rootDir, extConfigName, extConfigFilePath) {
|
||||
var _a;
|
||||
try {
|
||||
const tsPath = (0, node_1.resolveNode)(rootDir, 'typescript');
|
||||
if (!tsPath) {
|
||||
(0, errors_1.fatal)('Could not find installation of TypeScript.\n' +
|
||||
`To use ${colors_1.default.strong(extConfigName)} files, you must install TypeScript in your project, e.g. w/ ${colors_1.default.input('npm install -D typescript')}`);
|
||||
}
|
||||
const ts = require(tsPath); // eslint-disable-line @typescript-eslint/no-var-requires
|
||||
const extConfigObject = (0, node_1.requireTS)(ts, extConfigFilePath);
|
||||
const extConfig = extConfigObject.default ? await extConfigObject.default : extConfigObject;
|
||||
return {
|
||||
extConfigType: 'ts',
|
||||
extConfigName,
|
||||
extConfigFilePath: extConfigFilePath,
|
||||
extConfig,
|
||||
};
|
||||
}
|
||||
catch (e) {
|
||||
if (!(0, errors_1.isFatal)(e)) {
|
||||
(0, errors_1.fatal)(`Parsing ${colors_1.default.strong(extConfigName)} failed.\n\n${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
async function loadExtConfigJS(rootDir, extConfigName, extConfigFilePath) {
|
||||
var _a;
|
||||
try {
|
||||
return {
|
||||
extConfigType: 'js',
|
||||
extConfigName,
|
||||
extConfigFilePath: extConfigFilePath,
|
||||
extConfig: await require(extConfigFilePath),
|
||||
};
|
||||
}
|
||||
catch (e) {
|
||||
(0, errors_1.fatal)(`Parsing ${colors_1.default.strong(extConfigName)} failed.\n\n${(_a = e.stack) !== null && _a !== void 0 ? _a : e}`);
|
||||
}
|
||||
}
|
||||
async function loadExtConfig(rootDir) {
|
||||
var _a;
|
||||
const extConfigFilePathTS = (0, path_1.resolve)(rootDir, exports.CONFIG_FILE_NAME_TS);
|
||||
if (await (0, fs_extra_1.pathExists)(extConfigFilePathTS)) {
|
||||
return loadExtConfigTS(rootDir, exports.CONFIG_FILE_NAME_TS, extConfigFilePathTS);
|
||||
}
|
||||
const extConfigFilePathJS = (0, path_1.resolve)(rootDir, exports.CONFIG_FILE_NAME_JS);
|
||||
if (await (0, fs_extra_1.pathExists)(extConfigFilePathJS)) {
|
||||
return loadExtConfigJS(rootDir, exports.CONFIG_FILE_NAME_JS, extConfigFilePathJS);
|
||||
}
|
||||
const extConfigFilePath = (0, path_1.resolve)(rootDir, exports.CONFIG_FILE_NAME_JSON);
|
||||
return {
|
||||
extConfigType: 'json',
|
||||
extConfigName: exports.CONFIG_FILE_NAME_JSON,
|
||||
extConfigFilePath: extConfigFilePath,
|
||||
extConfig: (_a = (await (0, fn_1.tryFn)(fs_extra_1.readJSON, extConfigFilePath))) !== null && _a !== void 0 ? _a : {},
|
||||
};
|
||||
}
|
||||
async function loadCLIConfig(rootDir) {
|
||||
const assetsDir = 'assets';
|
||||
const assetsDirAbs = (0, path_1.join)(rootDir, assetsDir);
|
||||
const iosPlatformTemplateArchive = 'ios-pods-template.tar.gz';
|
||||
const iosCordovaPluginsTemplateArchive = 'capacitor-cordova-ios-plugins.tar.gz';
|
||||
const androidPlatformTemplateArchive = 'android-template.tar.gz';
|
||||
const androidCordovaPluginsTemplateArchive = 'capacitor-cordova-android-plugins.tar.gz';
|
||||
return {
|
||||
rootDir,
|
||||
assetsDir,
|
||||
assetsDirAbs,
|
||||
assets: {
|
||||
ios: {
|
||||
platformTemplateArchive: iosPlatformTemplateArchive,
|
||||
platformTemplateArchiveAbs: (0, path_1.resolve)(assetsDirAbs, iosPlatformTemplateArchive),
|
||||
cordovaPluginsTemplateArchive: iosCordovaPluginsTemplateArchive,
|
||||
cordovaPluginsTemplateArchiveAbs: (0, path_1.resolve)(assetsDirAbs, iosCordovaPluginsTemplateArchive),
|
||||
},
|
||||
android: {
|
||||
platformTemplateArchive: androidPlatformTemplateArchive,
|
||||
platformTemplateArchiveAbs: (0, path_1.resolve)(assetsDirAbs, androidPlatformTemplateArchive),
|
||||
cordovaPluginsTemplateArchive: androidCordovaPluginsTemplateArchive,
|
||||
cordovaPluginsTemplateArchiveAbs: (0, path_1.resolve)(assetsDirAbs, androidCordovaPluginsTemplateArchive),
|
||||
},
|
||||
},
|
||||
package: await (0, fs_extra_1.readJSON)((0, path_1.resolve)(rootDir, 'package.json')),
|
||||
os: determineOS(process.platform),
|
||||
};
|
||||
}
|
||||
async function loadAndroidConfig(rootDir, extConfig, cliConfig) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
|
||||
const name = 'android';
|
||||
const platformDir = (_b = (_a = extConfig.android) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : 'android';
|
||||
const platformDirAbs = (0, path_1.resolve)(rootDir, platformDir);
|
||||
const appDir = 'app';
|
||||
const srcDir = `${appDir}/src`;
|
||||
const srcMainDir = `${srcDir}/main`;
|
||||
const assetsDir = `${srcMainDir}/assets`;
|
||||
const webDir = `${assetsDir}/public`;
|
||||
const resDir = `${srcMainDir}/res`;
|
||||
let apkPath = `${appDir}/build/outputs/apk/`;
|
||||
const flavor = ((_c = extConfig.android) === null || _c === void 0 ? void 0 : _c.flavor) || '';
|
||||
if ((_d = extConfig.android) === null || _d === void 0 ? void 0 : _d.flavor) {
|
||||
apkPath = `${apkPath}/${(_e = extConfig.android) === null || _e === void 0 ? void 0 : _e.flavor}`;
|
||||
}
|
||||
const apkName = (0, common_1.parseApkNameFromFlavor)(flavor);
|
||||
const buildOutputDir = `${apkPath}/debug`;
|
||||
const cordovaPluginsDir = 'capacitor-cordova-android-plugins';
|
||||
const studioPath = (0, promise_1.lazy)(() => determineAndroidStudioPath(cliConfig.os));
|
||||
const buildOptions = {
|
||||
keystorePath: (_g = (_f = extConfig.android) === null || _f === void 0 ? void 0 : _f.buildOptions) === null || _g === void 0 ? void 0 : _g.keystorePath,
|
||||
keystorePassword: (_j = (_h = extConfig.android) === null || _h === void 0 ? void 0 : _h.buildOptions) === null || _j === void 0 ? void 0 : _j.keystorePassword,
|
||||
keystoreAlias: (_l = (_k = extConfig.android) === null || _k === void 0 ? void 0 : _k.buildOptions) === null || _l === void 0 ? void 0 : _l.keystoreAlias,
|
||||
keystoreAliasPassword: (_o = (_m = extConfig.android) === null || _m === void 0 ? void 0 : _m.buildOptions) === null || _o === void 0 ? void 0 : _o.keystoreAliasPassword,
|
||||
signingType: (_q = (_p = extConfig.android) === null || _p === void 0 ? void 0 : _p.buildOptions) === null || _q === void 0 ? void 0 : _q.signingType,
|
||||
releaseType: (_s = (_r = extConfig.android) === null || _r === void 0 ? void 0 : _r.buildOptions) === null || _s === void 0 ? void 0 : _s.releaseType,
|
||||
};
|
||||
return {
|
||||
name,
|
||||
minVersion: '23',
|
||||
studioPath,
|
||||
platformDir,
|
||||
platformDirAbs,
|
||||
cordovaPluginsDir,
|
||||
cordovaPluginsDirAbs: (0, path_1.resolve)(platformDirAbs, cordovaPluginsDir),
|
||||
appDir,
|
||||
appDirAbs: (0, path_1.resolve)(platformDirAbs, appDir),
|
||||
srcDir,
|
||||
srcDirAbs: (0, path_1.resolve)(platformDirAbs, srcDir),
|
||||
srcMainDir,
|
||||
srcMainDirAbs: (0, path_1.resolve)(platformDirAbs, srcMainDir),
|
||||
assetsDir,
|
||||
assetsDirAbs: (0, path_1.resolve)(platformDirAbs, assetsDir),
|
||||
webDir,
|
||||
webDirAbs: (0, path_1.resolve)(platformDirAbs, webDir),
|
||||
resDir,
|
||||
resDirAbs: (0, path_1.resolve)(platformDirAbs, resDir),
|
||||
apkName,
|
||||
buildOutputDir,
|
||||
buildOutputDirAbs: (0, path_1.resolve)(platformDirAbs, buildOutputDir),
|
||||
flavor,
|
||||
buildOptions,
|
||||
};
|
||||
}
|
||||
async function loadIOSConfig(rootDir, extConfig) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
||||
const name = 'ios';
|
||||
const platformDir = (_b = (_a = extConfig.ios) === null || _a === void 0 ? void 0 : _a.path) !== null && _b !== void 0 ? _b : 'ios';
|
||||
const platformDirAbs = (0, path_1.resolve)(rootDir, platformDir);
|
||||
const scheme = (_d = (_c = extConfig.ios) === null || _c === void 0 ? void 0 : _c.scheme) !== null && _d !== void 0 ? _d : 'App';
|
||||
const nativeProjectDir = 'App';
|
||||
const nativeProjectDirAbs = (0, path_1.resolve)(platformDirAbs, nativeProjectDir);
|
||||
const nativeTargetDir = `${nativeProjectDir}/App`;
|
||||
const nativeTargetDirAbs = (0, path_1.resolve)(platformDirAbs, nativeTargetDir);
|
||||
const nativeXcodeProjDir = `${nativeProjectDir}/App.xcodeproj`;
|
||||
const nativeXcodeProjDirAbs = (0, path_1.resolve)(platformDirAbs, nativeXcodeProjDir);
|
||||
const nativeXcodeWorkspaceDirAbs = (0, promise_1.lazy)(() => determineXcodeWorkspaceDirAbs(nativeProjectDirAbs));
|
||||
const podPath = (0, promise_1.lazy)(() => determineGemfileOrCocoapodPath(rootDir, platformDirAbs, nativeProjectDirAbs));
|
||||
const webDirAbs = (0, promise_1.lazy)(() => determineIOSWebDirAbs(nativeProjectDirAbs, nativeTargetDirAbs, nativeXcodeProjDirAbs));
|
||||
const cordovaPluginsDir = 'capacitor-cordova-ios-plugins';
|
||||
const buildOptions = {
|
||||
exportMethod: (_f = (_e = extConfig.ios) === null || _e === void 0 ? void 0 : _e.buildOptions) === null || _f === void 0 ? void 0 : _f.exportMethod,
|
||||
xcodeSigningStyle: (_h = (_g = extConfig.ios) === null || _g === void 0 ? void 0 : _g.buildOptions) === null || _h === void 0 ? void 0 : _h.signingStyle,
|
||||
signingCertificate: (_k = (_j = extConfig.ios) === null || _j === void 0 ? void 0 : _j.buildOptions) === null || _k === void 0 ? void 0 : _k.signingCertificate,
|
||||
provisioningProfile: (_m = (_l = extConfig.ios) === null || _l === void 0 ? void 0 : _l.buildOptions) === null || _m === void 0 ? void 0 : _m.provisioningProfile,
|
||||
};
|
||||
return {
|
||||
name,
|
||||
minVersion: '14.0',
|
||||
platformDir,
|
||||
platformDirAbs,
|
||||
scheme,
|
||||
cordovaPluginsDir,
|
||||
cordovaPluginsDirAbs: (0, path_1.resolve)(platformDirAbs, cordovaPluginsDir),
|
||||
nativeProjectDir,
|
||||
nativeProjectDirAbs,
|
||||
nativeTargetDir,
|
||||
nativeTargetDirAbs,
|
||||
nativeXcodeProjDir,
|
||||
nativeXcodeProjDirAbs,
|
||||
nativeXcodeWorkspaceDir: (0, promise_1.lazy)(async () => (0, path_1.relative)(platformDirAbs, await nativeXcodeWorkspaceDirAbs)),
|
||||
nativeXcodeWorkspaceDirAbs,
|
||||
webDir: (0, promise_1.lazy)(async () => (0, path_1.relative)(platformDirAbs, await webDirAbs)),
|
||||
webDirAbs,
|
||||
podPath,
|
||||
buildOptions,
|
||||
};
|
||||
}
|
||||
async function loadWebConfig(rootDir, webDir) {
|
||||
const platformDir = webDir;
|
||||
const platformDirAbs = (0, path_1.resolve)(rootDir, platformDir);
|
||||
return {
|
||||
name: 'web',
|
||||
platformDir,
|
||||
platformDirAbs,
|
||||
};
|
||||
}
|
||||
function determineOS(os) {
|
||||
switch (os) {
|
||||
case 'darwin':
|
||||
return "mac" /* OS.Mac */;
|
||||
case 'win32':
|
||||
return "windows" /* OS.Windows */;
|
||||
case 'linux':
|
||||
return "linux" /* OS.Linux */;
|
||||
}
|
||||
return "unknown" /* OS.Unknown */;
|
||||
}
|
||||
async function determineXcodeWorkspaceDirAbs(nativeProjectDirAbs) {
|
||||
return (0, path_1.resolve)(nativeProjectDirAbs, 'App.xcworkspace');
|
||||
}
|
||||
async function determineIOSWebDirAbs(nativeProjectDirAbs, nativeTargetDirAbs, nativeXcodeProjDirAbs) {
|
||||
const re = /path\s=\spublic[\s\S]+?sourceTree\s=\s([^;]+)/;
|
||||
const pbxprojPath = (0, path_1.resolve)(nativeXcodeProjDirAbs, 'project.pbxproj');
|
||||
try {
|
||||
const pbxproj = await (0, fs_extra_1.readFile)(pbxprojPath, { encoding: 'utf8' });
|
||||
const m = pbxproj.match(re);
|
||||
if (m && m[1] === 'SOURCE_ROOT') {
|
||||
log_1.logger.warn(`Using the iOS project root for the ${colors_1.default.strong('public')} directory is deprecated.\n` +
|
||||
`Please follow the Upgrade Guide to move ${colors_1.default.strong('public')} inside the iOS target directory: ${colors_1.default.strong('https://capacitorjs.com/docs/updating/3-0#move-public-into-the-ios-target-directory')}`);
|
||||
return (0, path_1.resolve)(nativeProjectDirAbs, 'public');
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return (0, path_1.resolve)(nativeTargetDirAbs, 'public');
|
||||
}
|
||||
async function determineAndroidStudioPath(os) {
|
||||
if (process.env.CAPACITOR_ANDROID_STUDIO_PATH) {
|
||||
return process.env.CAPACITOR_ANDROID_STUDIO_PATH;
|
||||
}
|
||||
switch (os) {
|
||||
case "mac" /* OS.Mac */:
|
||||
return '/Applications/Android Studio.app';
|
||||
case "windows" /* OS.Windows */: {
|
||||
const { runCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./util/subprocess')));
|
||||
let p = 'C:\\Program Files\\Android\\Android Studio\\bin\\studio64.exe';
|
||||
try {
|
||||
if (!(await (0, fs_extra_1.pathExists)(p))) {
|
||||
let commandResult = await runCommand('REG', [
|
||||
'QUERY',
|
||||
'HKEY_LOCAL_MACHINE\\SOFTWARE\\Android Studio',
|
||||
'/v',
|
||||
'Path',
|
||||
]);
|
||||
commandResult = commandResult.replace(/(\r\n|\n|\r)/gm, '');
|
||||
const i = commandResult.indexOf('REG_SZ');
|
||||
if (i > 0) {
|
||||
p = commandResult.substring(i + 6).trim() + '\\bin\\studio64.exe';
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
debug(`Error checking registry for Android Studio path: %O`, e);
|
||||
break;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
case "linux" /* OS.Linux */:
|
||||
return '/usr/local/android-studio/bin/studio.sh';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
async function determineGemfileOrCocoapodPath(rootDir, platformDir, nativeProjectDirAbs) {
|
||||
if (process.env.CAPACITOR_COCOAPODS_PATH) {
|
||||
return process.env.CAPACITOR_COCOAPODS_PATH;
|
||||
}
|
||||
let gemfilePath = '';
|
||||
if (await (0, fs_extra_1.pathExists)((0, path_1.resolve)(rootDir, 'Gemfile'))) {
|
||||
gemfilePath = (0, path_1.resolve)(rootDir, 'Gemfile');
|
||||
}
|
||||
else if (await (0, fs_extra_1.pathExists)((0, path_1.resolve)(platformDir, 'Gemfile'))) {
|
||||
gemfilePath = (0, path_1.resolve)(platformDir, 'Gemfile');
|
||||
}
|
||||
else if (await (0, fs_extra_1.pathExists)((0, path_1.resolve)(nativeProjectDirAbs, 'Gemfile'))) {
|
||||
gemfilePath = (0, path_1.resolve)(nativeProjectDirAbs, 'Gemfile');
|
||||
}
|
||||
const appSpecificGemfileExists = gemfilePath != '';
|
||||
// Multi-app projects might share a single global 'Gemfile' at the Git repository root directory.
|
||||
if (!appSpecificGemfileExists) {
|
||||
try {
|
||||
const output = await (0, subprocess_1.getCommandOutput)('git', ['rev-parse', '--show-toplevel'], { cwd: rootDir });
|
||||
if (output != null) {
|
||||
gemfilePath = (0, path_1.resolve)(output, 'Gemfile');
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
// Nothing
|
||||
}
|
||||
}
|
||||
try {
|
||||
const gemfileText = (await (0, fs_extra_1.readFile)(gemfilePath)).toString();
|
||||
if (!gemfileText) {
|
||||
return 'pod';
|
||||
}
|
||||
const cocoapodsInGemfile = new RegExp(/gem\s+['"]cocoapods/).test(gemfileText);
|
||||
if (cocoapodsInGemfile) {
|
||||
return 'bundle exec pod';
|
||||
}
|
||||
else {
|
||||
return 'pod';
|
||||
}
|
||||
}
|
||||
catch {
|
||||
return 'pod';
|
||||
}
|
||||
}
|
||||
function formatConfigTS(extConfig) {
|
||||
// TODO: <reference> tags
|
||||
return `import type { CapacitorConfig } from '@capacitor/cli';
|
||||
|
||||
const config: CapacitorConfig = ${(0, js_1.formatJSObject)(extConfig)};
|
||||
|
||||
export default config;\n`;
|
||||
}
|
||||
801
node_modules/@capacitor/cli/dist/cordova.js
generated
vendored
Normal file
801
node_modules/@capacitor/cli/dist/cordova.js
generated
vendored
Normal file
@@ -0,0 +1,801 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.writeCordovaAndroidManifest = exports.getCordovaPreferences = exports.needsStaticPod = exports.getIncompatibleCordovaPlugins = exports.checkPluginDependencies = exports.logCordovaManualSteps = exports.getCordovaPlugins = exports.handleCordovaPluginsJS = exports.autoGenerateConfig = exports.removePluginFiles = exports.createEmptyCordovaJS = exports.copyCordovaJS = exports.copyPluginsJS = exports.generateCordovaPluginsJSFile = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path_1 = require("path");
|
||||
const plist_1 = tslib_1.__importDefault(require("plist"));
|
||||
const prompts_1 = tslib_1.__importDefault(require("prompts"));
|
||||
const common_1 = require("./android/common");
|
||||
const colors_1 = tslib_1.__importDefault(require("./colors"));
|
||||
const errors_1 = require("./errors");
|
||||
const common_2 = require("./ios/common");
|
||||
const log_1 = require("./log");
|
||||
const plugin_1 = require("./plugin");
|
||||
const node_1 = require("./util/node");
|
||||
const term_1 = require("./util/term");
|
||||
const xml_1 = require("./util/xml");
|
||||
/**
|
||||
* Build the root cordova_plugins.js file referencing each Plugin JS file.
|
||||
*/
|
||||
function generateCordovaPluginsJSFile(config, plugins, platform) {
|
||||
const pluginModules = [];
|
||||
const pluginExports = [];
|
||||
plugins.map((p) => {
|
||||
const pluginId = p.xml.$.id;
|
||||
const jsModules = (0, plugin_1.getJSModules)(p, platform);
|
||||
jsModules.map((jsModule) => {
|
||||
const clobbers = [];
|
||||
const merges = [];
|
||||
let clobbersModule = '';
|
||||
let mergesModule = '';
|
||||
let runsModule = '';
|
||||
let clobberKey = '';
|
||||
let mergeKey = '';
|
||||
if (jsModule.clobbers) {
|
||||
jsModule.clobbers.map((clobber) => {
|
||||
clobbers.push(clobber.$.target);
|
||||
clobberKey = clobber.$.target;
|
||||
});
|
||||
clobbersModule = `,
|
||||
"clobbers": [
|
||||
"${clobbers.join('",\n "')}"
|
||||
]`;
|
||||
}
|
||||
if (jsModule.merges) {
|
||||
jsModule.merges.map((merge) => {
|
||||
merges.push(merge.$.target);
|
||||
mergeKey = merge.$.target;
|
||||
});
|
||||
mergesModule = `,
|
||||
"merges": [
|
||||
"${merges.join('",\n "')}"
|
||||
]`;
|
||||
}
|
||||
if (jsModule.runs) {
|
||||
runsModule = ',\n "runs": true';
|
||||
}
|
||||
const pluginModule = {
|
||||
clobber: clobberKey,
|
||||
merge: mergeKey,
|
||||
// mimics Cordova's module name logic if the name attr is missing
|
||||
pluginContent: `{
|
||||
"id": "${pluginId + '.' + (jsModule.$.name || jsModule.$.src.match(/([^/]+)\.js/)[1])}",
|
||||
"file": "plugins/${pluginId}/${jsModule.$.src}",
|
||||
"pluginId": "${pluginId}"${clobbersModule}${mergesModule}${runsModule}
|
||||
}`,
|
||||
};
|
||||
pluginModules.push(pluginModule);
|
||||
});
|
||||
pluginExports.push(`"${pluginId}": "${p.xml.$.version}"`);
|
||||
});
|
||||
return `
|
||||
cordova.define('cordova/plugin_list', function(require, exports, module) {
|
||||
module.exports = [
|
||||
${pluginModules
|
||||
.sort((a, b) => a.clobber && b.clobber // Clobbers in alpha order
|
||||
? a.clobber.localeCompare(b.clobber)
|
||||
: a.clobber || b.clobber // Clobbers before anything else
|
||||
? b.clobber.localeCompare(a.clobber)
|
||||
: a.merge.localeCompare(b.merge))
|
||||
.map((e) => e.pluginContent)
|
||||
.join(',\n ')}
|
||||
];
|
||||
module.exports.metadata =
|
||||
// TOP OF METADATA
|
||||
{
|
||||
${pluginExports.join(',\n ')}
|
||||
};
|
||||
// BOTTOM OF METADATA
|
||||
});
|
||||
`;
|
||||
}
|
||||
exports.generateCordovaPluginsJSFile = generateCordovaPluginsJSFile;
|
||||
/**
|
||||
* Build the plugins/* files for each Cordova plugin installed.
|
||||
*/
|
||||
async function copyPluginsJS(config, cordovaPlugins, platform) {
|
||||
const webDir = await getWebDir(config, platform);
|
||||
const pluginsDir = (0, path_1.join)(webDir, 'plugins');
|
||||
const cordovaPluginsJSFile = (0, path_1.join)(webDir, 'cordova_plugins.js');
|
||||
await removePluginFiles(config, platform);
|
||||
await Promise.all(cordovaPlugins.map(async (p) => {
|
||||
const pluginId = p.xml.$.id;
|
||||
const pluginDir = (0, path_1.join)(pluginsDir, pluginId, 'www');
|
||||
await (0, fs_extra_1.ensureDir)(pluginDir);
|
||||
const jsModules = (0, plugin_1.getJSModules)(p, platform);
|
||||
await Promise.all(jsModules.map(async (jsModule) => {
|
||||
const filePath = (0, path_1.join)(webDir, 'plugins', pluginId, jsModule.$.src);
|
||||
await (0, fs_extra_1.copy)((0, path_1.join)(p.rootPath, jsModule.$.src), filePath);
|
||||
let data = await (0, fs_extra_1.readFile)(filePath, { encoding: 'utf-8' });
|
||||
data = data.trim();
|
||||
// mimics Cordova's module name logic if the name attr is missing
|
||||
const name = pluginId + '.' + (jsModule.$.name || (0, path_1.basename)(jsModule.$.src, (0, path_1.extname)(jsModule.$.src)));
|
||||
data = `cordova.define("${name}", function(require, exports, module) { \n${data}\n});`;
|
||||
data = data.replace(/<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script\s*>/gi, '');
|
||||
await (0, fs_extra_1.writeFile)(filePath, data, { encoding: 'utf-8' });
|
||||
}));
|
||||
const assets = (0, plugin_1.getAssets)(p, platform);
|
||||
await Promise.all(assets.map(async (asset) => {
|
||||
const filePath = (0, path_1.join)(webDir, asset.$.target);
|
||||
await (0, fs_extra_1.copy)((0, path_1.join)(p.rootPath, asset.$.src), filePath);
|
||||
}));
|
||||
}));
|
||||
await (0, fs_extra_1.writeFile)(cordovaPluginsJSFile, generateCordovaPluginsJSFile(config, cordovaPlugins, platform));
|
||||
}
|
||||
exports.copyPluginsJS = copyPluginsJS;
|
||||
async function copyCordovaJS(config, platform) {
|
||||
const cordovaPath = (0, node_1.resolveNode)(config.app.rootDir, '@capacitor/core', 'cordova.js');
|
||||
if (!cordovaPath) {
|
||||
(0, errors_1.fatal)(`Unable to find ${colors_1.default.strong('node_modules/@capacitor/core/cordova.js')}.\n` +
|
||||
`Are you sure ${colors_1.default.strong('@capacitor/core')} is installed?`);
|
||||
}
|
||||
return (0, fs_extra_1.copy)(cordovaPath, (0, path_1.join)(await getWebDir(config, platform), 'cordova.js'));
|
||||
}
|
||||
exports.copyCordovaJS = copyCordovaJS;
|
||||
async function createEmptyCordovaJS(config, platform) {
|
||||
const webDir = await getWebDir(config, platform);
|
||||
await (0, fs_extra_1.writeFile)((0, path_1.join)(webDir, 'cordova.js'), '');
|
||||
await (0, fs_extra_1.writeFile)((0, path_1.join)(webDir, 'cordova_plugins.js'), '');
|
||||
}
|
||||
exports.createEmptyCordovaJS = createEmptyCordovaJS;
|
||||
async function removePluginFiles(config, platform) {
|
||||
const webDir = await getWebDir(config, platform);
|
||||
const pluginsDir = (0, path_1.join)(webDir, 'plugins');
|
||||
const cordovaPluginsJSFile = (0, path_1.join)(webDir, 'cordova_plugins.js');
|
||||
await (0, fs_extra_1.remove)(pluginsDir);
|
||||
await (0, fs_extra_1.remove)(cordovaPluginsJSFile);
|
||||
}
|
||||
exports.removePluginFiles = removePluginFiles;
|
||||
async function autoGenerateConfig(config, cordovaPlugins, platform) {
|
||||
var _a, _b, _c, _d;
|
||||
let xmlDir = (0, path_1.join)(config.android.resDirAbs, 'xml');
|
||||
const fileName = 'config.xml';
|
||||
if (platform === 'ios') {
|
||||
xmlDir = config.ios.nativeTargetDirAbs;
|
||||
}
|
||||
await (0, fs_extra_1.ensureDir)(xmlDir);
|
||||
const cordovaConfigXMLFile = (0, path_1.join)(xmlDir, fileName);
|
||||
await (0, fs_extra_1.remove)(cordovaConfigXMLFile);
|
||||
const pluginEntries = [];
|
||||
cordovaPlugins.map((p) => {
|
||||
const currentPlatform = (0, plugin_1.getPluginPlatform)(p, platform);
|
||||
if (currentPlatform) {
|
||||
const configFiles = currentPlatform['config-file'];
|
||||
if (configFiles) {
|
||||
const configXMLEntries = configFiles.filter(function (item) {
|
||||
var _a;
|
||||
return (_a = item.$) === null || _a === void 0 ? void 0 : _a.target.includes(fileName);
|
||||
});
|
||||
configXMLEntries.map((entry) => {
|
||||
if (entry.feature) {
|
||||
const feature = { feature: entry.feature };
|
||||
pluginEntries.push(feature);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
let accessOriginString = [];
|
||||
if ((_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.cordova) === null || _b === void 0 ? void 0 : _b.accessOrigins) {
|
||||
accessOriginString = await Promise.all(config.app.extConfig.cordova.accessOrigins.map(async (host) => {
|
||||
return `
|
||||
<access origin="${host}" />`;
|
||||
}));
|
||||
}
|
||||
else {
|
||||
accessOriginString.push(`<access origin="*" />`);
|
||||
}
|
||||
const pluginEntriesString = await Promise.all(pluginEntries.map(async (item) => {
|
||||
const xmlString = await (0, xml_1.writeXML)(item);
|
||||
return xmlString;
|
||||
}));
|
||||
let pluginPreferencesString = [];
|
||||
if ((_d = (_c = config.app.extConfig) === null || _c === void 0 ? void 0 : _c.cordova) === null || _d === void 0 ? void 0 : _d.preferences) {
|
||||
pluginPreferencesString = await Promise.all(Object.entries(config.app.extConfig.cordova.preferences).map(async ([key, value]) => {
|
||||
return `
|
||||
<preference name="${key}" value="${value}" />`;
|
||||
}));
|
||||
}
|
||||
const content = `<?xml version='1.0' encoding='utf-8'?>
|
||||
<widget version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
|
||||
${accessOriginString.join('')}
|
||||
${pluginEntriesString.join('')}
|
||||
${pluginPreferencesString.join('')}
|
||||
</widget>`;
|
||||
await (0, fs_extra_1.writeFile)(cordovaConfigXMLFile, content);
|
||||
}
|
||||
exports.autoGenerateConfig = autoGenerateConfig;
|
||||
async function getWebDir(config, platform) {
|
||||
if (platform === 'ios') {
|
||||
return config.ios.webDirAbs;
|
||||
}
|
||||
if (platform === 'android') {
|
||||
return config.android.webDirAbs;
|
||||
}
|
||||
return '';
|
||||
}
|
||||
async function handleCordovaPluginsJS(cordovaPlugins, config, platform) {
|
||||
const webDir = await getWebDir(config, platform);
|
||||
await (0, fs_extra_1.mkdirp)(webDir);
|
||||
if (cordovaPlugins.length > 0) {
|
||||
(0, plugin_1.printPlugins)(cordovaPlugins, platform, 'cordova');
|
||||
await copyCordovaJS(config, platform);
|
||||
await copyPluginsJS(config, cordovaPlugins, platform);
|
||||
}
|
||||
else {
|
||||
await removePluginFiles(config, platform);
|
||||
await createEmptyCordovaJS(config, platform);
|
||||
}
|
||||
await autoGenerateConfig(config, cordovaPlugins, platform);
|
||||
}
|
||||
exports.handleCordovaPluginsJS = handleCordovaPluginsJS;
|
||||
async function getCordovaPlugins(config, platform) {
|
||||
const allPlugins = await (0, plugin_1.getPlugins)(config, platform);
|
||||
let plugins = [];
|
||||
if (platform === config.ios.name) {
|
||||
plugins = await (0, common_2.getIOSPlugins)(allPlugins);
|
||||
}
|
||||
else if (platform === config.android.name) {
|
||||
plugins = await (0, common_1.getAndroidPlugins)(allPlugins);
|
||||
}
|
||||
return plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
|
||||
}
|
||||
exports.getCordovaPlugins = getCordovaPlugins;
|
||||
async function logCordovaManualSteps(cordovaPlugins, config, platform) {
|
||||
cordovaPlugins.map((p) => {
|
||||
const editConfig = (0, plugin_1.getPlatformElement)(p, platform, 'edit-config');
|
||||
const configFile = (0, plugin_1.getPlatformElement)(p, platform, 'config-file');
|
||||
editConfig.concat(configFile).map(async (configElement) => {
|
||||
if (configElement.$ && !configElement.$.target.includes('config.xml')) {
|
||||
if (platform === config.ios.name) {
|
||||
if (configElement.$.target.includes('Info.plist')) {
|
||||
logiOSPlist(configElement, config, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
exports.logCordovaManualSteps = logCordovaManualSteps;
|
||||
async function logiOSPlist(configElement, config, plugin) {
|
||||
var _a, _b;
|
||||
let plistPath = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Info.plist');
|
||||
if ((_a = config.app.extConfig.ios) === null || _a === void 0 ? void 0 : _a.scheme) {
|
||||
plistPath = (0, path_1.resolve)(config.ios.nativeProjectDirAbs, `${(_b = config.app.extConfig.ios) === null || _b === void 0 ? void 0 : _b.scheme}-Info.plist`);
|
||||
}
|
||||
if (!(await (0, fs_extra_1.pathExists)(plistPath))) {
|
||||
plistPath = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Base.lproj', 'Info.plist');
|
||||
}
|
||||
if (await (0, fs_extra_1.pathExists)(plistPath)) {
|
||||
const xmlMeta = await (0, xml_1.readXML)(plistPath);
|
||||
const data = await (0, fs_extra_1.readFile)(plistPath, { encoding: 'utf-8' });
|
||||
const trimmedPlistData = data.replace(/(\t|\r|\n)/g, '');
|
||||
const plistData = plist_1.default.parse(data);
|
||||
const dict = xmlMeta.plist.dict.pop();
|
||||
if (!dict.key.includes(configElement.$.parent)) {
|
||||
let xml = buildConfigFileXml(configElement);
|
||||
xml = `<key>${configElement.$.parent}</key>${getConfigFileTagContent(xml)}`;
|
||||
log_1.logger.warn(`Configuration required for ${colors_1.default.strong(plugin.id)}.\n` + `Add the following to Info.plist:\n` + xml);
|
||||
}
|
||||
else if (configElement.array || configElement.dict) {
|
||||
if (configElement.array && configElement.array.length > 0 && configElement.array[0].string) {
|
||||
let xml = '';
|
||||
configElement.array[0].string.map((element) => {
|
||||
const d = plistData[configElement.$.parent];
|
||||
if (Array.isArray(d) && !d.includes(element)) {
|
||||
xml = xml.concat(`<string>${element}</string>\n`);
|
||||
}
|
||||
});
|
||||
if (xml.length > 0) {
|
||||
log_1.logger.warn(`Configuration required for ${colors_1.default.strong(plugin.id)}.\n` +
|
||||
`Add the following in the existing ${colors_1.default.strong(configElement.$.parent)} array of your Info.plist:\n` +
|
||||
xml);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let xml = buildConfigFileXml(configElement);
|
||||
xml = `<key>${configElement.$.parent}</key>${getConfigFileTagContent(xml)}`;
|
||||
xml = `<plist version="1.0"><dict>${xml}</dict></plist>`;
|
||||
const parseXmlToSearchable = (childElementsObj, arrayToAddTo) => {
|
||||
for (const childElement of childElementsObj) {
|
||||
const childElementName = childElement['#name'];
|
||||
const toAdd = { name: childElementName };
|
||||
if (childElementName === 'key' || childElementName === 'string') {
|
||||
toAdd.value = childElement['_'];
|
||||
}
|
||||
else {
|
||||
if (childElement['$']) {
|
||||
toAdd.attrs = { ...childElement['$'] };
|
||||
}
|
||||
if (childElement['$$']) {
|
||||
toAdd.children = [];
|
||||
parseXmlToSearchable(childElement['$$'], toAdd['children']);
|
||||
}
|
||||
}
|
||||
arrayToAddTo.push(toAdd);
|
||||
}
|
||||
};
|
||||
const existingElements = (0, xml_1.parseXML)(trimmedPlistData, {
|
||||
explicitChildren: true,
|
||||
trim: true,
|
||||
preserveChildrenOrder: true,
|
||||
});
|
||||
const parsedExistingElements = [];
|
||||
const rootKeyOfExistingElements = Object.keys(existingElements)[0];
|
||||
const rootOfExistingElementsToAdd = { name: rootKeyOfExistingElements, children: [] };
|
||||
if (existingElements[rootKeyOfExistingElements]['$']) {
|
||||
rootOfExistingElementsToAdd.attrs = {
|
||||
...existingElements[rootKeyOfExistingElements]['$'],
|
||||
};
|
||||
}
|
||||
parseXmlToSearchable(existingElements[rootKeyOfExistingElements]['$$'], rootOfExistingElementsToAdd['children']);
|
||||
parsedExistingElements.push(rootOfExistingElementsToAdd);
|
||||
const requiredElements = (0, xml_1.parseXML)(xml, {
|
||||
explicitChildren: true,
|
||||
trim: true,
|
||||
preserveChildrenOrder: true,
|
||||
});
|
||||
const parsedRequiredElements = [];
|
||||
const rootKeyOfRequiredElements = Object.keys(requiredElements)[0];
|
||||
const rootOfRequiredElementsToAdd = { name: rootKeyOfRequiredElements, children: [] };
|
||||
if (requiredElements[rootKeyOfRequiredElements]['$']) {
|
||||
rootOfRequiredElementsToAdd.attrs = {
|
||||
...requiredElements[rootKeyOfRequiredElements]['$'],
|
||||
};
|
||||
}
|
||||
parseXmlToSearchable(requiredElements[rootKeyOfRequiredElements]['$$'], rootOfRequiredElementsToAdd['children']);
|
||||
parsedRequiredElements.push(rootOfRequiredElementsToAdd);
|
||||
const doesContainElements = (requiredElementsArray, existingElementsArray) => {
|
||||
for (const requiredElement of requiredElementsArray) {
|
||||
if (requiredElement.name === 'key' || requiredElement.name === 'string') {
|
||||
let foundMatch = false;
|
||||
for (const existingElement of existingElementsArray) {
|
||||
if (existingElement.name === requiredElement.name &&
|
||||
(existingElement.value === requiredElement.value ||
|
||||
/^[$].{1,}$/.test(requiredElement.value.trim()))) {
|
||||
foundMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundMatch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
let foundMatch = false;
|
||||
for (const existingElement of existingElementsArray) {
|
||||
if (existingElement.name === requiredElement.name) {
|
||||
if ((requiredElement.children !== undefined) === (existingElement.children !== undefined)) {
|
||||
if (doesContainElements(requiredElement.children, existingElement.children)) {
|
||||
foundMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!foundMatch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (!doesContainElements(parsedRequiredElements, parsedExistingElements)) {
|
||||
logPossibleMissingItem(configElement, plugin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
logPossibleMissingItem(configElement, plugin);
|
||||
}
|
||||
}
|
||||
function logPossibleMissingItem(configElement, plugin) {
|
||||
let xml = buildConfigFileXml(configElement);
|
||||
xml = getConfigFileTagContent(xml);
|
||||
xml = removeOuterTags(xml);
|
||||
log_1.logger.warn(`Configuration might be missing for ${colors_1.default.strong(plugin.id)}.\n` +
|
||||
`Add the following to the existing ${colors_1.default.strong(configElement.$.parent)} entry of Info.plist:\n` +
|
||||
xml);
|
||||
}
|
||||
function buildConfigFileXml(configElement) {
|
||||
return (0, xml_1.buildXmlElement)(configElement, 'config-file');
|
||||
}
|
||||
function getConfigFileTagContent(str) {
|
||||
return str.replace(/<config-file.+">|<\/config-file>/g, '');
|
||||
}
|
||||
function removeOuterTags(str) {
|
||||
const start = str.indexOf('>') + 1;
|
||||
const end = str.lastIndexOf('<');
|
||||
return str.substring(start, end);
|
||||
}
|
||||
async function checkPluginDependencies(plugins, platform, failOnMissingDeps = false) {
|
||||
const pluginDeps = new Map();
|
||||
const cordovaPlugins = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 1 /* PluginType.Cordova */);
|
||||
const incompatible = plugins.filter((p) => (0, plugin_1.getPluginType)(p, platform) === 2 /* PluginType.Incompatible */);
|
||||
await Promise.all(cordovaPlugins.map(async (p) => {
|
||||
let allDependencies = [];
|
||||
allDependencies = allDependencies.concat((0, plugin_1.getPlatformElement)(p, platform, 'dependency'));
|
||||
if (p.xml['dependency']) {
|
||||
allDependencies = allDependencies.concat(p.xml['dependency']);
|
||||
}
|
||||
allDependencies = allDependencies.filter((dep) => !getIncompatibleCordovaPlugins(platform).includes(dep.$.id) &&
|
||||
incompatible.filter((p) => p.id === dep.$.id || p.xml.$.id === dep.$.id).length === 0);
|
||||
if (allDependencies) {
|
||||
await Promise.all(allDependencies.map(async (dep) => {
|
||||
var _a;
|
||||
let plugin = dep.$.id;
|
||||
let version = dep.$.version;
|
||||
if (plugin.includes('@') && plugin.indexOf('@') !== 0) {
|
||||
[plugin, version] = plugin.split('@');
|
||||
}
|
||||
if (cordovaPlugins.filter((p) => p.id === plugin || p.xml.$.id === plugin).length === 0) {
|
||||
if ((_a = dep.$.url) === null || _a === void 0 ? void 0 : _a.startsWith('http')) {
|
||||
plugin = dep.$.url;
|
||||
version = dep.$.commit;
|
||||
}
|
||||
const deps = pluginDeps.get(p.id) || [];
|
||||
deps.push(`${plugin}${version ? colors_1.default.weak(` (${version})`) : ''}`);
|
||||
pluginDeps.set(p.id, deps);
|
||||
}
|
||||
}));
|
||||
}
|
||||
}));
|
||||
if (pluginDeps.size > 0) {
|
||||
let msg = `${colors_1.default.failure(colors_1.default.strong('Plugins are missing dependencies.'))}\n` +
|
||||
`Cordova plugin dependencies must be installed in your project (e.g. w/ ${colors_1.default.input('npm install')}).\n`;
|
||||
for (const [plugin, deps] of pluginDeps.entries()) {
|
||||
msg += `\n ${colors_1.default.strong(plugin)} is missing dependencies:\n` + deps.map((d) => ` - ${d}`).join('\n');
|
||||
}
|
||||
if (failOnMissingDeps) {
|
||||
(0, errors_1.fatal)(`${msg}\n`);
|
||||
}
|
||||
log_1.logger.warn(`${msg}\n`);
|
||||
}
|
||||
}
|
||||
exports.checkPluginDependencies = checkPluginDependencies;
|
||||
function getIncompatibleCordovaPlugins(platform) {
|
||||
const pluginList = [
|
||||
'cordova-plugin-splashscreen',
|
||||
'cordova-plugin-ionic-webview',
|
||||
'cordova-plugin-crosswalk-webview',
|
||||
'cordova-plugin-wkwebview-engine',
|
||||
'cordova-plugin-console',
|
||||
'cordova-plugin-music-controls',
|
||||
'cordova-plugin-add-swift-support',
|
||||
'cordova-plugin-ionic-keyboard',
|
||||
'cordova-plugin-braintree',
|
||||
'@ionic-enterprise/filesystem',
|
||||
'@ionic-enterprise/keyboard',
|
||||
'@ionic-enterprise/splashscreen',
|
||||
'cordova-support-google-services',
|
||||
];
|
||||
if (platform === 'ios') {
|
||||
pluginList.push('cordova-plugin-statusbar', '@ionic-enterprise/statusbar', 'SalesforceMobileSDK-CordovaPlugin');
|
||||
}
|
||||
if (platform === 'android') {
|
||||
pluginList.push('cordova-plugin-compat');
|
||||
}
|
||||
return pluginList;
|
||||
}
|
||||
exports.getIncompatibleCordovaPlugins = getIncompatibleCordovaPlugins;
|
||||
function needsStaticPod(plugin) {
|
||||
return useFrameworks(plugin);
|
||||
}
|
||||
exports.needsStaticPod = needsStaticPod;
|
||||
function useFrameworks(plugin) {
|
||||
const podspecs = (0, plugin_1.getPlatformElement)(plugin, 'ios', 'podspec');
|
||||
const frameworkPods = podspecs.filter((podspec) => podspec.pods.filter((pods) => pods.$ && pods.$['use-frameworks'] === 'true').length > 0);
|
||||
return frameworkPods.length > 0;
|
||||
}
|
||||
async function getCordovaPreferences(config) {
|
||||
var _a, _b, _c, _d, _e;
|
||||
const configXml = (0, path_1.join)(config.app.rootDir, 'config.xml');
|
||||
let cordova = {};
|
||||
if (await (0, fs_extra_1.pathExists)(configXml)) {
|
||||
cordova.preferences = {};
|
||||
const xmlMeta = await (0, xml_1.readXML)(configXml);
|
||||
if (xmlMeta.widget.preference) {
|
||||
xmlMeta.widget.preference.map((pref) => {
|
||||
cordova.preferences[pref.$.name] = pref.$.value;
|
||||
});
|
||||
}
|
||||
}
|
||||
if (cordova.preferences && Object.keys(cordova.preferences).length > 0) {
|
||||
if ((0, term_1.isInteractive)()) {
|
||||
const answers = await (0, log_1.logPrompt)(`${colors_1.default.strong(`Cordova preferences can be automatically ported to ${colors_1.default.strong(config.app.extConfigName)}.`)}\n` +
|
||||
`Keep in mind: Not all values can be automatically migrated from ${colors_1.default.strong('config.xml')}. There may be more work to do.\n` +
|
||||
`More info: ${colors_1.default.strong('https://capacitorjs.com/docs/cordova/migrating-from-cordova-to-capacitor')}`, {
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: `Migrate Cordova preferences from config.xml?`,
|
||||
initial: true,
|
||||
});
|
||||
if (answers.confirm) {
|
||||
if ((_b = (_a = config.app.extConfig) === null || _a === void 0 ? void 0 : _a.cordova) === null || _b === void 0 ? void 0 : _b.preferences) {
|
||||
const answers = await (0, prompts_1.default)([
|
||||
{
|
||||
type: 'confirm',
|
||||
name: 'confirm',
|
||||
message: `${config.app.extConfigName} already contains Cordova preferences. Overwrite?`,
|
||||
},
|
||||
], { onCancel: () => process.exit(1) });
|
||||
if (!answers.confirm) {
|
||||
cordova = (_c = config.app.extConfig) === null || _c === void 0 ? void 0 : _c.cordova;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
cordova = (_d = config.app.extConfig) === null || _d === void 0 ? void 0 : _d.cordova;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
cordova = (_e = config.app.extConfig) === null || _e === void 0 ? void 0 : _e.cordova;
|
||||
}
|
||||
return cordova;
|
||||
}
|
||||
exports.getCordovaPreferences = getCordovaPreferences;
|
||||
async function writeCordovaAndroidManifest(cordovaPlugins, config, platform, cleartext) {
|
||||
var _a;
|
||||
const manifestPath = (0, path_1.join)(config.android.cordovaPluginsDirAbs, 'src', 'main', 'AndroidManifest.xml');
|
||||
const rootXMLEntries = [];
|
||||
const applicationXMLEntries = [];
|
||||
const applicationXMLAttributes = [];
|
||||
let prefsArray = [];
|
||||
cordovaPlugins.map(async (p) => {
|
||||
const editConfig = (0, plugin_1.getPlatformElement)(p, platform, 'edit-config');
|
||||
const configFile = (0, plugin_1.getPlatformElement)(p, platform, 'config-file');
|
||||
prefsArray = prefsArray.concat((0, plugin_1.getAllElements)(p, platform, 'preference'));
|
||||
editConfig.concat(configFile).map(async (configElement) => {
|
||||
var _a, _b;
|
||||
if (configElement.$ &&
|
||||
(((_a = configElement.$.target) === null || _a === void 0 ? void 0 : _a.includes('AndroidManifest.xml')) ||
|
||||
((_b = configElement.$.file) === null || _b === void 0 ? void 0 : _b.includes('AndroidManifest.xml')))) {
|
||||
const keys = Object.keys(configElement).filter((k) => k !== '$');
|
||||
keys.map((k) => {
|
||||
configElement[k].map(async (e) => {
|
||||
const xmlElement = (0, xml_1.buildXmlElement)(e, k);
|
||||
const pathParts = getPathParts(configElement.$.parent || configElement.$.target);
|
||||
if (pathParts.length > 1) {
|
||||
if (pathParts.pop() === 'application') {
|
||||
if (configElement.$.mode && configElement.$.mode === 'merge' && xmlElement.startsWith('<application')) {
|
||||
Object.keys(e.$).map((ek) => {
|
||||
applicationXMLAttributes.push(`${ek}="${e.$[ek]}"`);
|
||||
});
|
||||
}
|
||||
else if (!applicationXMLEntries.includes(xmlElement) &&
|
||||
!contains(applicationXMLEntries, xmlElement, k)) {
|
||||
applicationXMLEntries.push(xmlElement);
|
||||
}
|
||||
}
|
||||
else {
|
||||
const manifestPathOfCapApp = (0, path_1.join)(config.android.appDirAbs, 'src', 'main', 'AndroidManifest.xml');
|
||||
const manifestContentTrimmed = (await (0, fs_extra_1.readFile)(manifestPathOfCapApp))
|
||||
.toString()
|
||||
.trim()
|
||||
.replace(/\n|\t|\r/g, '')
|
||||
.replace(/[\s]{1,}</g, '<')
|
||||
.replace(/>[\s]{1,}/g, '>')
|
||||
.replace(/[\s]{2,}/g, ' ');
|
||||
const requiredManifestContentTrimmed = xmlElement
|
||||
.trim()
|
||||
.replace(/\n|\t|\r/g, '')
|
||||
.replace(/[\s]{1,}</g, '<')
|
||||
.replace(/>[\s]{1,}/g, '>')
|
||||
.replace(/[\s]{2,}/g, ' ');
|
||||
const pathPartList = getPathParts(configElement.$.parent || configElement.$.target);
|
||||
const doesXmlManifestContainRequiredInfo = (requiredElements, existingElements, pathTarget) => {
|
||||
const findElementsToSearchIn = (existingElements, pathTarget) => {
|
||||
const parts = [...pathTarget];
|
||||
const elementsToSearchNextIn = [];
|
||||
for (const existingElement of existingElements) {
|
||||
if (existingElement.name === pathTarget[0]) {
|
||||
if (existingElement.children) {
|
||||
for (const el of existingElement.children) {
|
||||
elementsToSearchNextIn.push(el);
|
||||
}
|
||||
}
|
||||
else {
|
||||
elementsToSearchNextIn.push(existingElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (elementsToSearchNextIn.length === 0) {
|
||||
return [];
|
||||
}
|
||||
else {
|
||||
parts.splice(0, 1);
|
||||
if (parts.length <= 0) {
|
||||
return elementsToSearchNextIn;
|
||||
}
|
||||
else {
|
||||
return findElementsToSearchIn(elementsToSearchNextIn, parts);
|
||||
}
|
||||
}
|
||||
};
|
||||
const parseXmlToSearchable = (childElementsObj, arrayToAddTo) => {
|
||||
for (const childElementKey of Object.keys(childElementsObj)) {
|
||||
for (const occurannceOfElement of childElementsObj[childElementKey]) {
|
||||
const toAdd = { name: childElementKey };
|
||||
if (occurannceOfElement['$']) {
|
||||
toAdd.attrs = { ...occurannceOfElement['$'] };
|
||||
}
|
||||
if (occurannceOfElement['$$']) {
|
||||
toAdd.children = [];
|
||||
parseXmlToSearchable(occurannceOfElement['$$'], toAdd['children']);
|
||||
}
|
||||
arrayToAddTo.push(toAdd);
|
||||
}
|
||||
}
|
||||
};
|
||||
const doesElementMatch = (requiredElement, existingElement) => {
|
||||
var _a;
|
||||
if (requiredElement.name !== existingElement.name) {
|
||||
return false;
|
||||
}
|
||||
if ((requiredElement.attrs !== undefined) !== (existingElement.attrs !== undefined)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (requiredElement.attrs !== undefined) {
|
||||
const requiredELementAttrKeys = Object.keys(requiredElement.attrs);
|
||||
for (const key of requiredELementAttrKeys) {
|
||||
if (!/^[$].{1,}$/.test(requiredElement.attrs[key].trim())) {
|
||||
if (requiredElement.attrs[key] !== existingElement.attrs[key]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((requiredElement.children !== undefined) !== (existingElement.children !== undefined) &&
|
||||
((_a = requiredElement.children) === null || _a === void 0 ? void 0 : _a.length) !== 0) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (requiredElement.children !== undefined) {
|
||||
// each req element is in existing element
|
||||
for (const requiredElementItem of requiredElement.children) {
|
||||
let foundRequiredElement = false;
|
||||
for (const existingElementItem of existingElement.children) {
|
||||
const foundRequiredElementIn = doesElementMatch(requiredElementItem, existingElementItem);
|
||||
if (foundRequiredElementIn) {
|
||||
foundRequiredElement = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundRequiredElement) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (requiredElement.children === undefined && existingElement.children === undefined) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
let foundRequiredElement = false;
|
||||
for (const existingElementItem of existingElement.children) {
|
||||
const foundRequiredElementIn = doesElementMatch(requiredElement, existingElementItem);
|
||||
if (foundRequiredElementIn) {
|
||||
foundRequiredElement = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundRequiredElement) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
const parsedExistingElements = [];
|
||||
const rootKeyOfExistingElements = Object.keys(existingElements)[0];
|
||||
const rootOfExistingElementsToAdd = { name: rootKeyOfExistingElements, children: [] };
|
||||
if (existingElements[rootKeyOfExistingElements]['$']) {
|
||||
rootOfExistingElementsToAdd.attrs = {
|
||||
...existingElements[rootKeyOfExistingElements]['$'],
|
||||
};
|
||||
}
|
||||
parseXmlToSearchable(existingElements[rootKeyOfExistingElements]['$$'], rootOfExistingElementsToAdd['children']);
|
||||
parsedExistingElements.push(rootOfExistingElementsToAdd);
|
||||
const parsedRequiredElements = [];
|
||||
const rootKeyOfRequiredElements = Object.keys(requiredElements)[0];
|
||||
const rootOfRequiredElementsToAdd = { name: rootKeyOfRequiredElements, children: [] };
|
||||
if (requiredElements[rootKeyOfRequiredElements]['$']) {
|
||||
rootOfRequiredElementsToAdd.attrs = {
|
||||
...requiredElements[rootKeyOfRequiredElements]['$'],
|
||||
};
|
||||
}
|
||||
if (requiredElements[rootKeyOfRequiredElements]['$$'] !== undefined) {
|
||||
parseXmlToSearchable(requiredElements[rootKeyOfRequiredElements]['$$'], rootOfRequiredElementsToAdd['children']);
|
||||
}
|
||||
parsedRequiredElements.push(rootOfRequiredElementsToAdd);
|
||||
const elementsToSearch = findElementsToSearchIn(parsedExistingElements, pathTarget);
|
||||
for (const requiredElement of parsedRequiredElements) {
|
||||
let foundMatch = false;
|
||||
for (const existingElement of elementsToSearch) {
|
||||
const doesContain = doesElementMatch(requiredElement, existingElement);
|
||||
if (doesContain) {
|
||||
foundMatch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!foundMatch) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
if (!doesXmlManifestContainRequiredInfo((0, xml_1.parseXML)(requiredManifestContentTrimmed, {
|
||||
explicitChildren: true,
|
||||
trim: true,
|
||||
}), (0, xml_1.parseXML)(manifestContentTrimmed, {
|
||||
explicitChildren: true,
|
||||
trim: true,
|
||||
}), pathPartList)) {
|
||||
log_1.logger.warn(`Android Configuration required for ${colors_1.default.strong(p.id)}.\n` +
|
||||
`Add the following to AndroidManifest.xml:\n` +
|
||||
xmlElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!rootXMLEntries.includes(xmlElement) && !contains(rootXMLEntries, xmlElement, k)) {
|
||||
rootXMLEntries.push(xmlElement);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
const cleartextString = 'android:usesCleartextTraffic="true"';
|
||||
const cleartextValue = (cleartext || ((_a = config.app.extConfig.server) === null || _a === void 0 ? void 0 : _a.cleartext)) && !applicationXMLAttributes.includes(cleartextString)
|
||||
? cleartextString
|
||||
: '';
|
||||
let content = `<?xml version='1.0' encoding='utf-8'?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:amazon="http://schemas.amazon.com/apk/res/android">
|
||||
<application ${applicationXMLAttributes.join('\n')} ${cleartextValue}>
|
||||
${applicationXMLEntries.join('\n')}
|
||||
</application>
|
||||
${rootXMLEntries.join('\n')}
|
||||
</manifest>`;
|
||||
content = content.replace(new RegExp('$PACKAGE_NAME'.replace('$', '\\$&'), 'g'), '${applicationId}');
|
||||
for (const preference of prefsArray) {
|
||||
content = content.replace(new RegExp(('$' + preference.$.name).replace('$', '\\$&'), 'g'), preference.$.default);
|
||||
}
|
||||
if (await (0, fs_extra_1.pathExists)(manifestPath)) {
|
||||
await (0, fs_extra_1.writeFile)(manifestPath, content);
|
||||
}
|
||||
}
|
||||
exports.writeCordovaAndroidManifest = writeCordovaAndroidManifest;
|
||||
function getPathParts(path) {
|
||||
const rootPath = 'manifest';
|
||||
path = path.replace('/*', rootPath);
|
||||
const parts = path.split('/').filter((part) => part !== '');
|
||||
if (parts.length > 1 || parts.includes(rootPath)) {
|
||||
return parts;
|
||||
}
|
||||
return [rootPath, path];
|
||||
}
|
||||
function contains(entries, obj, k) {
|
||||
const element = (0, xml_1.parseXML)(obj);
|
||||
for (const entry of entries) {
|
||||
const current = (0, xml_1.parseXML)(entry);
|
||||
if (element &&
|
||||
current &&
|
||||
current[k] &&
|
||||
element[k] &&
|
||||
current[k].$ &&
|
||||
element[k].$ &&
|
||||
element[k].$['android:name'] === current[k].$['android:name']) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
648
node_modules/@capacitor/cli/dist/declarations.d.ts
generated
vendored
Normal file
648
node_modules/@capacitor/cli/dist/declarations.d.ts
generated
vendored
Normal file
@@ -0,0 +1,648 @@
|
||||
export interface CapacitorConfig {
|
||||
/**
|
||||
* The unique identifier of your packaged app.
|
||||
*
|
||||
* This is also known as the Bundle ID in iOS and the Application ID in
|
||||
* Android. It must be in reverse domain name notation, generally
|
||||
* representing a domain name that you or your company owns.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
appId?: string;
|
||||
/**
|
||||
* The human-friendly name of your app.
|
||||
*
|
||||
* This should be what you'd see in the App Store, but can be changed after
|
||||
* within each native platform after it is generated.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
appName?: string;
|
||||
/**
|
||||
* The directory of your compiled web assets.
|
||||
*
|
||||
* This directory should contain the final `index.html` of your app.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
webDir?: string;
|
||||
/**
|
||||
* The build configuration (as defined by the native app) under which Capacitor
|
||||
* will send statements to the log system. This applies to log statements in
|
||||
* native code as well as statements redirected from JavaScript (`console.debug`,
|
||||
* `console.error`, etc.). Enabling logging will let statements render in the
|
||||
* Xcode and Android Studio windows but can leak information on device if enabled
|
||||
* in released builds.
|
||||
*
|
||||
* 'none' = logs are never produced
|
||||
* 'debug' = logs are produced in debug builds but not production builds
|
||||
* 'production' = logs are always produced
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @default debug
|
||||
*/
|
||||
loggingBehavior?: 'none' | 'debug' | 'production';
|
||||
/**
|
||||
* User agent of Capacitor Web View.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
overrideUserAgent?: string;
|
||||
/**
|
||||
* String to append to the original user agent of Capacitor Web View.
|
||||
*
|
||||
* This is disregarded if `overrideUserAgent` is used.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
appendUserAgent?: string;
|
||||
/**
|
||||
* Background color of the Capacitor Web View.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
backgroundColor?: string;
|
||||
/**
|
||||
* Enable zooming within the Capacitor Web View.
|
||||
*
|
||||
* @default false
|
||||
* @since 6.0.0
|
||||
*/
|
||||
zoomEnabled?: boolean;
|
||||
/**
|
||||
* Whether to give the webview initial focus.
|
||||
*
|
||||
* @since 7.0.0
|
||||
* @default true
|
||||
*/
|
||||
initialFocus?: boolean;
|
||||
android?: {
|
||||
/**
|
||||
* Specify a custom path to the native Android project.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @default android
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* User agent of Capacitor Web View on Android.
|
||||
*
|
||||
* Overrides global `overrideUserAgent` option.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
overrideUserAgent?: string;
|
||||
/**
|
||||
* String to append to the original user agent of Capacitor Web View for Android.
|
||||
*
|
||||
* Overrides global `appendUserAgent` option.
|
||||
*
|
||||
* This is disregarded if `overrideUserAgent` is used.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
appendUserAgent?: string;
|
||||
/**
|
||||
* Background color of the Capacitor Web View for Android.
|
||||
*
|
||||
* Overrides global `backgroundColor` option.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
backgroundColor?: string;
|
||||
/**
|
||||
* Enable zooming within the Capacitor Web View for Android.
|
||||
*
|
||||
* @default false
|
||||
* @since 6.0.0
|
||||
*/
|
||||
zoomEnabled?: boolean;
|
||||
/**
|
||||
* Enable mixed content in the Capacitor Web View for Android.
|
||||
*
|
||||
* [Mixed
|
||||
* content](https://developer.mozilla.org/en-US/docs/Web/Security/Mixed_content)
|
||||
* is disabled by default for security. During development, you may need to
|
||||
* enable it to allow the Web View to load files from different schemes.
|
||||
*
|
||||
* **This is not intended for use in production.**
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @default false
|
||||
*/
|
||||
allowMixedContent?: boolean;
|
||||
/**
|
||||
* This enables a simpler keyboard which may have some limitations.
|
||||
*
|
||||
* This will capture JS keys using an alternative
|
||||
* [`InputConnection`](https://developer.android.com/reference/android/view/inputmethod/InputConnection).
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @default false
|
||||
*/
|
||||
captureInput?: boolean;
|
||||
/**
|
||||
* Always enable debuggable web content.
|
||||
*
|
||||
* This is automatically enabled during development.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @default false
|
||||
*/
|
||||
webContentsDebuggingEnabled?: boolean;
|
||||
/**
|
||||
* The build configuration under which Capacitor will generate logs on Android.
|
||||
*
|
||||
* Overrides global `loggingBehavior` option.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @default debug
|
||||
*/
|
||||
loggingBehavior?: 'none' | 'debug' | 'production';
|
||||
/**
|
||||
* Allowlist of plugins to include during `npx cap sync` for Android.
|
||||
*
|
||||
* Overrides global `includePlugins` option.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
includePlugins?: string[];
|
||||
/**
|
||||
* Android flavor to use.
|
||||
*
|
||||
* If the app has flavors declared in the `build.gradle`
|
||||
* configure the flavor you want to run with `npx cap run` command.
|
||||
*
|
||||
* @since 3.1.0
|
||||
*/
|
||||
flavor?: string;
|
||||
/**
|
||||
* Whether to give the webview initial focus.
|
||||
*
|
||||
* Overrides global `initialFocus` option.
|
||||
*
|
||||
* @since 3.5.1
|
||||
* @default true
|
||||
*/
|
||||
initialFocus?: boolean;
|
||||
/**
|
||||
* The minimum supported webview version on Android supported by your app.
|
||||
*
|
||||
* The minimum supported cannot be lower than version `55`, which is required for Capacitor.
|
||||
*
|
||||
* If the device uses a lower WebView version, an error message will be shown on Logcat.
|
||||
* If `server.errorPath` is configured, the WebView will redirect to that file, so can be
|
||||
* used to show a custom error.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @default 60
|
||||
*/
|
||||
minWebViewVersion?: number;
|
||||
/**
|
||||
* The minimum supported Huawei webview version on Android supported by your app.
|
||||
*
|
||||
* The minimum supported cannot be lower than version `10`, which is required for Capacitor.
|
||||
*
|
||||
* If the device uses a lower WebView version, an error message will be shown on Logcat.
|
||||
* If `server.errorPath` is configured, the WebView will redirect to that file, so can be
|
||||
* used to show a custom error.
|
||||
*
|
||||
* @since 4.6.4
|
||||
* @default 10
|
||||
*/
|
||||
minHuaweiWebViewVersion?: number;
|
||||
buildOptions?: {
|
||||
/**
|
||||
* Path to your keystore
|
||||
*
|
||||
* @since 4.4.0
|
||||
*/
|
||||
keystorePath?: string;
|
||||
/**
|
||||
* Password to your keystore
|
||||
*
|
||||
* @since 4.4.0
|
||||
*/
|
||||
keystorePassword?: string;
|
||||
/**
|
||||
* Alias in the keystore to use
|
||||
*
|
||||
* @since 4.4.0
|
||||
*/
|
||||
keystoreAlias?: string;
|
||||
/**
|
||||
* Password for the alias in the keystore to use
|
||||
*
|
||||
* @since 4.4.0
|
||||
*/
|
||||
keystoreAliasPassword?: string;
|
||||
/**
|
||||
* Bundle type for your release build
|
||||
*
|
||||
* @since 4.4.0
|
||||
* @default "AAB"
|
||||
*/
|
||||
releaseType?: 'AAB' | 'APK';
|
||||
/**
|
||||
* Program to sign your build with
|
||||
*
|
||||
* @since 5.1.0
|
||||
* @default "jarsigner"
|
||||
*/
|
||||
signingType?: 'apksigner' | 'jarsigner';
|
||||
};
|
||||
/**
|
||||
* Use legacy [addJavascriptInterface](https://developer.android.com/reference/android/webkit/WebView#addJavascriptInterface(java.lang.Object,%20java.lang.String))
|
||||
* instead of the new and more secure [addWebMessageListener](https://developer.android.com/reference/androidx/webkit/WebViewCompat#addWebMessageListener(android.webkit.WebView,java.lang.String,java.util.Set%3Cjava.lang.String%3E,androidx.webkit.WebViewCompat.WebMessageListener))
|
||||
*
|
||||
* @since 4.5.0
|
||||
* @default false
|
||||
*/
|
||||
useLegacyBridge?: boolean;
|
||||
/**
|
||||
* Make service worker requests go through Capacitor bridge.
|
||||
* Set it to false to use your own handling.
|
||||
*
|
||||
* @since 7.0.0
|
||||
* @default true
|
||||
*/
|
||||
resolveServiceWorkerRequests?: boolean;
|
||||
/**
|
||||
* If set to "force", margins will be adjusted for edge to edge regardless of any other settings.
|
||||
* If set to "auto", or is missing, will check for Android 15 and the setting of [windowOptOutEdgeToEdgeEnforcement](https://developer.android.com/reference/android/R.attr#windowOptOutEdgeToEdgeEnforcement) and will adjust margins if on Android 15 and windowOptOutEdgeToEdgeEnforcement is false/missing.
|
||||
* If set to "disable", will not adjust margins at all.
|
||||
* In Capacitor 8, this default will be changed to 'auto'
|
||||
*
|
||||
* @since 7.1.0
|
||||
* @default disable
|
||||
*/
|
||||
adjustMarginsForEdgeToEdge?: 'auto' | 'force' | 'disable';
|
||||
};
|
||||
ios?: {
|
||||
/**
|
||||
* Specify a custom path to the native iOS project.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @default ios
|
||||
*/
|
||||
path?: string;
|
||||
/**
|
||||
* iOS build scheme to use.
|
||||
*
|
||||
* Usually this matches your app's target in Xcode. You can use the
|
||||
* following command to list schemes:
|
||||
*
|
||||
* ```shell
|
||||
* xcodebuild -workspace ios/App/App.xcworkspace -list
|
||||
* ```
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @default App
|
||||
*/
|
||||
scheme?: string;
|
||||
/**
|
||||
* User agent of Capacitor Web View on iOS.
|
||||
*
|
||||
* Overrides global `overrideUserAgent` option.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
overrideUserAgent?: string;
|
||||
/**
|
||||
* String to append to the original user agent of Capacitor Web View for iOS.
|
||||
*
|
||||
* Overrides global `appendUserAgent` option.
|
||||
*
|
||||
* This is disregarded if `overrideUserAgent` is used.
|
||||
*
|
||||
* @since 1.4.0
|
||||
*/
|
||||
appendUserAgent?: string;
|
||||
/**
|
||||
* Background color of the Capacitor Web View for iOS.
|
||||
*
|
||||
* Overrides global `backgroundColor` option.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
backgroundColor?: string;
|
||||
/**
|
||||
* Enable zooming within the Capacitor Web View for iOS.
|
||||
*
|
||||
* @default false
|
||||
* @since 6.0.0
|
||||
*/
|
||||
zoomEnabled?: boolean;
|
||||
/**
|
||||
* Configure the scroll view's content inset adjustment behavior.
|
||||
*
|
||||
* This will set the
|
||||
* [`contentInsetAdjustmentBehavior`](https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior)
|
||||
* property on the Web View's
|
||||
* [`UIScrollView`](https://developer.apple.com/documentation/uikit/uiscrollview).
|
||||
*
|
||||
* @since 2.0.0
|
||||
* @default never
|
||||
*/
|
||||
contentInset?: 'automatic' | 'scrollableAxes' | 'never' | 'always';
|
||||
/**
|
||||
* Configure whether the scroll view is scrollable.
|
||||
*
|
||||
* This will set the
|
||||
* [`isScrollEnabled`](https://developer.apple.com/documentation/uikit/uiscrollview/1619395-isscrollenabled)
|
||||
* property on the Web View's
|
||||
* [`UIScrollView`](https://developer.apple.com/documentation/uikit/uiscrollview).
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
scrollEnabled?: boolean;
|
||||
/**
|
||||
* Configure custom linker flags for compiling Cordova plugins.
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @default []
|
||||
*/
|
||||
cordovaLinkerFlags?: string[];
|
||||
/**
|
||||
* Allow destination previews when pressing on links.
|
||||
*
|
||||
* This will set the
|
||||
* [`allowsLinkPreview`](https://developer.apple.com/documentation/webkit/wkwebview/1415000-allowslinkpreview)
|
||||
* property on the Web View, instead of using the default value.
|
||||
*
|
||||
* @since 2.0.0
|
||||
*/
|
||||
allowsLinkPreview?: boolean;
|
||||
/**
|
||||
* The build configuration under which Capacitor will generate logs on iOS.
|
||||
*
|
||||
* Overrides global `loggingBehavior` option.
|
||||
*
|
||||
* @since 3.0.0
|
||||
* @default debug
|
||||
*/
|
||||
loggingBehavior?: 'none' | 'debug' | 'production';
|
||||
/**
|
||||
* Allowlist of plugins to include during `npx cap sync` for iOS.
|
||||
*
|
||||
* Overrides global `includePlugins` option.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
includePlugins?: string[];
|
||||
/**
|
||||
* Sets WKWebView configuration for limitsNavigationsToAppBoundDomains.
|
||||
*
|
||||
* If the Info.plist file includes `WKAppBoundDomains` key, it's recommended to
|
||||
* set this option to true, otherwise some features won't work.
|
||||
* But as side effect, it blocks navigation outside the domains in the
|
||||
* `WKAppBoundDomains` list.
|
||||
* `localhost` (or the value configured as `server.hostname`) also needs to be
|
||||
* added to the `WKAppBoundDomains` list.
|
||||
*
|
||||
* @since 3.1.0
|
||||
* @default false
|
||||
*/
|
||||
limitsNavigationsToAppBoundDomains?: boolean;
|
||||
/**
|
||||
* The content mode for the web view to use when it loads and renders web content.
|
||||
*
|
||||
* - 'recommended': The content mode that is appropriate for the current device.
|
||||
* - 'desktop': The content mode that represents a desktop experience.
|
||||
* - 'mobile': The content mode that represents a mobile experience.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @default recommended
|
||||
*/
|
||||
preferredContentMode?: 'recommended' | 'desktop' | 'mobile';
|
||||
/**
|
||||
* Configure if Capacitor will handle local/push notifications.
|
||||
* Set to false if you want to use your own UNUserNotificationCenter to handle notifications.
|
||||
*
|
||||
* @since 4.5.0
|
||||
* @default true
|
||||
*/
|
||||
handleApplicationNotifications?: boolean;
|
||||
/**
|
||||
* Using Xcode 14.3, on iOS 16.4 and greater, enable debuggable web content for release builds.
|
||||
*
|
||||
* If not set, it's `true` for development builds.
|
||||
*
|
||||
* @since 4.8.0
|
||||
* @default false
|
||||
*/
|
||||
webContentsDebuggingEnabled?: boolean;
|
||||
/**
|
||||
* Whether to give the webview initial focus.
|
||||
*
|
||||
* Overrides global `initialFocus` option.
|
||||
*
|
||||
* @since 7.0.0
|
||||
* @default true
|
||||
*/
|
||||
initialFocus?: boolean;
|
||||
buildOptions?: {
|
||||
/**
|
||||
* The signing style to use when building the app for distribution.
|
||||
*
|
||||
* @since 7.1.0
|
||||
* @default 'automatic'
|
||||
*/
|
||||
signingStyle?: 'automatic' | 'manual';
|
||||
/**
|
||||
* The method used by xcodebuild to export the archive
|
||||
*
|
||||
* @since 7.1.0
|
||||
* @default 'app-store-connect'
|
||||
*/
|
||||
exportMethod?: string;
|
||||
/**
|
||||
* A certificate name, SHA-1 hash, or automatic selector to use for signing for iOS builds.
|
||||
*
|
||||
* @since 7.1.0
|
||||
*/
|
||||
signingCertificate?: string;
|
||||
/**
|
||||
* A provisioning profile name or UUID for iOS builds.
|
||||
*
|
||||
* @since 7.1.0
|
||||
*/
|
||||
provisioningProfile?: string;
|
||||
};
|
||||
};
|
||||
server?: {
|
||||
/**
|
||||
* Configure the local hostname of the device.
|
||||
*
|
||||
* It is recommended to keep this as `localhost` as it allows the use of
|
||||
* Web APIs that would otherwise require a [secure
|
||||
* context](https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts)
|
||||
* such as
|
||||
* [`navigator.geolocation`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/geolocation)
|
||||
* and
|
||||
* [`MediaDevices.getUserMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia).
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @default localhost
|
||||
*/
|
||||
hostname?: string;
|
||||
/**
|
||||
* Configure the local scheme on iOS.
|
||||
*
|
||||
* [Can't be set to schemes that the WKWebView already handles, such as http or https](https://developer.apple.com/documentation/webkit/wkwebviewconfiguration/2875766-seturlschemehandler)
|
||||
* This can be useful when migrating from
|
||||
* [`cordova-plugin-ionic-webview`](https://github.com/ionic-team/cordova-plugin-ionic-webview),
|
||||
* where the default scheme on iOS is `ionic`.
|
||||
*
|
||||
* @since 1.2.0
|
||||
* @default capacitor
|
||||
*/
|
||||
iosScheme?: string;
|
||||
/**
|
||||
* Configure the local scheme on Android.
|
||||
*
|
||||
* Custom schemes on Android are unable to change the URL path as of Webview 117. Changing this value from anything other than `http` or `https` can result in your
|
||||
* application unable to resolve routing. If you must change this for some reason, consider using a hash-based url strategy, but there are no guarentees that this
|
||||
* will continue to work long term as allowing non-standard schemes to modify query parameters and url fragments is only allowed for compatibility reasons.
|
||||
* https://ionic.io/blog/capacitor-android-customscheme-issue-with-chrome-117
|
||||
*
|
||||
* @since 1.2.0
|
||||
* @default https
|
||||
*/
|
||||
androidScheme?: string;
|
||||
/**
|
||||
* Load an external URL in the Web View.
|
||||
*
|
||||
* This is intended for use with live-reload servers.
|
||||
*
|
||||
* **This is not intended for use in production.**
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
url?: string;
|
||||
/**
|
||||
* Allow cleartext traffic in the Web View.
|
||||
*
|
||||
* On Android, all cleartext traffic is disabled by default as of API 28.
|
||||
*
|
||||
* This is intended for use with live-reload servers where unencrypted HTTP
|
||||
* traffic is often used.
|
||||
*
|
||||
* **This is not intended for use in production.**
|
||||
*
|
||||
* @since 1.5.0
|
||||
* @default false
|
||||
*/
|
||||
cleartext?: boolean;
|
||||
/**
|
||||
* Set additional URLs the Web View can navigate to.
|
||||
*
|
||||
* By default, all external URLs are opened in the external browser (not
|
||||
* the Web View).
|
||||
*
|
||||
* **This is not intended for use in production.**
|
||||
*
|
||||
* @since 1.0.0
|
||||
* @default []
|
||||
*/
|
||||
allowNavigation?: string[];
|
||||
/**
|
||||
* Specify path to a local html page to display in case of errors.
|
||||
* On Android the html file won't have access to Capacitor plugins.
|
||||
*
|
||||
* @since 4.0.0
|
||||
* @default null
|
||||
*/
|
||||
errorPath?: string;
|
||||
/**
|
||||
* Append a path to the app URL.
|
||||
*
|
||||
* Allows loading from other paths than the default `/index.html`.
|
||||
* @since 7.3.0
|
||||
* @default null
|
||||
*/
|
||||
appStartPath?: string;
|
||||
};
|
||||
cordova?: {
|
||||
/**
|
||||
* Populates <access> tags in the config.xml with the origin set to
|
||||
* the values entered here.
|
||||
* If not provided, a single <access origin="*" /> tag gets included.
|
||||
* It only has effect on a few Cordova plugins that respect the whitelist.
|
||||
*
|
||||
* @since 3.3.0
|
||||
*/
|
||||
accessOrigins?: string[];
|
||||
/**
|
||||
* Configure Cordova preferences.
|
||||
*
|
||||
* @since 1.3.0
|
||||
*/
|
||||
preferences?: {
|
||||
[key: string]: string | undefined;
|
||||
};
|
||||
/**
|
||||
* Fail on cap update/sync if the CLI detects that a cordova plugin
|
||||
* has uninstalled dependencies.
|
||||
*
|
||||
* @default false
|
||||
* @since 7.4.0
|
||||
*/
|
||||
failOnUninstalledPlugins?: boolean;
|
||||
};
|
||||
/**
|
||||
* Configure plugins.
|
||||
*
|
||||
* This is an object with configuration values specified by plugin class
|
||||
* name.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
plugins?: PluginsConfig;
|
||||
/**
|
||||
* Allowlist of plugins to include during `npx cap sync`.
|
||||
*
|
||||
* This should be an array of strings representing the npm package name of
|
||||
* plugins to include when running `npx cap sync`. If unset, Capacitor will
|
||||
* inspect `package.json` for a list of potential plugins.
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
includePlugins?: string[];
|
||||
}
|
||||
export interface PluginsConfig {
|
||||
/**
|
||||
* Plugin configuration by class name.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
[key: string]: {
|
||||
[key: string]: any;
|
||||
} | undefined;
|
||||
/**
|
||||
* Capacitor Cookies plugin configuration
|
||||
*
|
||||
* @since 4.3.0
|
||||
*/
|
||||
CapacitorCookies?: {
|
||||
/**
|
||||
* Enable CapacitorCookies to override the global `document.cookie` on native.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
enabled?: boolean;
|
||||
};
|
||||
/**
|
||||
* Capacitor Http plugin configuration
|
||||
*
|
||||
* @since 4.3.0
|
||||
*/
|
||||
CapacitorHttp?: {
|
||||
/**
|
||||
* Enable CapacitorHttp to override the global `fetch` and `XMLHttpRequest` on native.
|
||||
*
|
||||
* @default false
|
||||
*/
|
||||
enabled?: boolean;
|
||||
};
|
||||
}
|
||||
2
node_modules/@capacitor/cli/dist/declarations.js
generated
vendored
Normal file
2
node_modules/@capacitor/cli/dist/declarations.js
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
13
node_modules/@capacitor/cli/dist/definitions.js
generated
vendored
Normal file
13
node_modules/@capacitor/cli/dist/definitions.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.XcodeExportMethod = void 0;
|
||||
var XcodeExportMethod;
|
||||
(function (XcodeExportMethod) {
|
||||
XcodeExportMethod["AppStoreConnect"] = "app-store-connect";
|
||||
XcodeExportMethod["ReleaseTesting"] = "release-testing";
|
||||
XcodeExportMethod["Enterprise"] = "enterprise";
|
||||
XcodeExportMethod["Debugging"] = "debugging";
|
||||
XcodeExportMethod["DeveloperID"] = "developer-id";
|
||||
XcodeExportMethod["MacApplication"] = "mac-application";
|
||||
XcodeExportMethod["Validation"] = "validation";
|
||||
})(XcodeExportMethod = exports.XcodeExportMethod || (exports.XcodeExportMethod = {}));
|
||||
27
node_modules/@capacitor/cli/dist/errors.js
generated
vendored
Normal file
27
node_modules/@capacitor/cli/dist/errors.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isFatal = exports.fatal = exports.FatalException = exports.BaseException = void 0;
|
||||
class BaseException extends Error {
|
||||
constructor(message, code) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
this.code = code;
|
||||
}
|
||||
}
|
||||
exports.BaseException = BaseException;
|
||||
class FatalException extends BaseException {
|
||||
constructor(message, exitCode = 1) {
|
||||
super(message, 'FATAL');
|
||||
this.message = message;
|
||||
this.exitCode = exitCode;
|
||||
}
|
||||
}
|
||||
exports.FatalException = FatalException;
|
||||
function fatal(message) {
|
||||
throw new FatalException(message);
|
||||
}
|
||||
exports.fatal = fatal;
|
||||
function isFatal(e) {
|
||||
return e && e instanceof FatalException;
|
||||
}
|
||||
exports.isFatal = isFatal;
|
||||
109
node_modules/@capacitor/cli/dist/framework-configs.js
generated
vendored
Normal file
109
node_modules/@capacitor/cli/dist/framework-configs.js
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.detectFramework = void 0;
|
||||
const FRAMEWORK_CONFIGS = [
|
||||
{
|
||||
name: 'Angular',
|
||||
isMatch: (config) => hasDependency(config, '@angular/cli'),
|
||||
webDir: 'dist',
|
||||
priority: 3,
|
||||
},
|
||||
{
|
||||
name: 'Create React App',
|
||||
isMatch: (config) => hasDependency(config, 'react-scripts'),
|
||||
webDir: 'build',
|
||||
priority: 3,
|
||||
},
|
||||
{
|
||||
name: 'Ember',
|
||||
isMatch: (config) => hasDependency(config, 'ember-cli'),
|
||||
webDir: 'dist',
|
||||
priority: 3,
|
||||
},
|
||||
{
|
||||
name: 'Gatsby',
|
||||
isMatch: (config) => hasDependency(config, 'gatsby'),
|
||||
webDir: 'public',
|
||||
priority: 2,
|
||||
},
|
||||
{
|
||||
name: 'Ionic Angular',
|
||||
isMatch: (config) => hasDependency(config, '@ionic/angular'),
|
||||
webDir: 'www',
|
||||
priority: 1,
|
||||
},
|
||||
{
|
||||
name: 'Ionic React',
|
||||
isMatch: (config) => hasDependency(config, '@ionic/react'),
|
||||
webDir: 'build',
|
||||
priority: 1,
|
||||
},
|
||||
{
|
||||
name: 'Ionic Vue',
|
||||
isMatch: (config) => hasDependency(config, '@ionic/vue'),
|
||||
webDir: 'public',
|
||||
priority: 1,
|
||||
},
|
||||
{
|
||||
name: 'Next',
|
||||
isMatch: (config) => hasDependency(config, 'next'),
|
||||
webDir: 'public',
|
||||
priority: 2,
|
||||
},
|
||||
{
|
||||
name: 'Preact',
|
||||
isMatch: (config) => hasDependency(config, 'preact-cli'),
|
||||
webDir: 'build',
|
||||
priority: 3,
|
||||
},
|
||||
{
|
||||
name: 'Stencil',
|
||||
isMatch: (config) => hasDependency(config, '@stencil/core'),
|
||||
webDir: 'www',
|
||||
priority: 3,
|
||||
},
|
||||
{
|
||||
name: 'Svelte',
|
||||
isMatch: (config) => hasDependency(config, 'svelte') && hasDependency(config, 'sirv-cli'),
|
||||
webDir: 'public',
|
||||
priority: 3,
|
||||
},
|
||||
{
|
||||
name: 'Vite',
|
||||
isMatch: (config) => hasDependency(config, 'vite'),
|
||||
webDir: 'dist',
|
||||
priority: 2,
|
||||
},
|
||||
{
|
||||
name: 'Vue',
|
||||
isMatch: (config) => hasDependency(config, '@vue/cli-service'),
|
||||
webDir: 'dist',
|
||||
priority: 3,
|
||||
},
|
||||
];
|
||||
function detectFramework(config) {
|
||||
const frameworks = FRAMEWORK_CONFIGS.filter((f) => f.isMatch(config)).sort((a, b) => {
|
||||
if (a.priority < b.priority)
|
||||
return -1;
|
||||
if (a.priority > b.priority)
|
||||
return 1;
|
||||
return 0;
|
||||
});
|
||||
return frameworks[0];
|
||||
}
|
||||
exports.detectFramework = detectFramework;
|
||||
function hasDependency(config, depName) {
|
||||
const deps = getDependencies(config);
|
||||
return deps.includes(depName);
|
||||
}
|
||||
function getDependencies(config) {
|
||||
var _a, _b, _c, _d;
|
||||
const deps = [];
|
||||
if ((_b = (_a = config === null || config === void 0 ? void 0 : config.app) === null || _a === void 0 ? void 0 : _a.package) === null || _b === void 0 ? void 0 : _b.dependencies) {
|
||||
deps.push(...Object.keys(config.app.package.dependencies));
|
||||
}
|
||||
if ((_d = (_c = config === null || config === void 0 ? void 0 : config.app) === null || _c === void 0 ? void 0 : _c.package) === null || _d === void 0 ? void 0 : _d.devDependencies) {
|
||||
deps.push(...Object.keys(config.app.package.devDependencies));
|
||||
}
|
||||
return deps;
|
||||
}
|
||||
249
node_modules/@capacitor/cli/dist/index.js
generated
vendored
Normal file
249
node_modules/@capacitor/cli/dist/index.js
generated
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.runProgram = exports.run = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const commander_1 = require("commander");
|
||||
const path_1 = require("path");
|
||||
const colors_1 = tslib_1.__importDefault(require("./colors"));
|
||||
const config_1 = require("./config");
|
||||
const errors_1 = require("./errors");
|
||||
const ipc_1 = require("./ipc");
|
||||
const log_1 = require("./log");
|
||||
const telemetry_1 = require("./telemetry");
|
||||
const cli_1 = require("./util/cli");
|
||||
const emoji_1 = require("./util/emoji");
|
||||
process.on('unhandledRejection', (error) => {
|
||||
console.error(colors_1.default.failure('[fatal]'), error);
|
||||
});
|
||||
process.on('message', ipc_1.receive);
|
||||
async function run() {
|
||||
try {
|
||||
const config = await (0, config_1.loadConfig)();
|
||||
runProgram(config);
|
||||
}
|
||||
catch (e) {
|
||||
process.exitCode = (0, errors_1.isFatal)(e) ? e.exitCode : 1;
|
||||
log_1.logger.error(e.message ? e.message : String(e));
|
||||
}
|
||||
}
|
||||
exports.run = run;
|
||||
function runProgram(config) {
|
||||
commander_1.program.version(config.cli.package.version);
|
||||
commander_1.program
|
||||
.command('config', { hidden: true })
|
||||
.description(`print evaluated Capacitor config`)
|
||||
.option('--json', 'Print in JSON format')
|
||||
.action((0, cli_1.wrapAction)(async ({ json }) => {
|
||||
const { configCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/config')));
|
||||
await configCommand(config, json);
|
||||
}));
|
||||
commander_1.program
|
||||
.command('create [directory] [name] [id]', { hidden: true })
|
||||
.description('Creates a new Capacitor project')
|
||||
.action((0, cli_1.wrapAction)(async () => {
|
||||
const { createCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/create')));
|
||||
await createCommand();
|
||||
}));
|
||||
commander_1.program
|
||||
.command('init [appName] [appId]')
|
||||
.description(`Initialize Capacitor configuration`)
|
||||
.option('--web-dir <value>', 'Optional: Directory of your projects built web assets')
|
||||
.option('--skip-appid-validation', 'Optional: Skip validating the app ID for iOS and Android compatibility')
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (appName, appId, { webDir, skipAppidValidation }) => {
|
||||
const { initCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/init')));
|
||||
await initCommand(config, appName, appId, webDir, skipAppidValidation);
|
||||
})));
|
||||
commander_1.program
|
||||
.command('serve', { hidden: true })
|
||||
.description('Serves a Capacitor Progressive Web App in the browser')
|
||||
.action((0, cli_1.wrapAction)(async () => {
|
||||
const { serveCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/serve')));
|
||||
await serveCommand();
|
||||
}));
|
||||
commander_1.program
|
||||
.command('sync [platform]')
|
||||
.description(`${colors_1.default.input('copy')} + ${colors_1.default.input('update')}`)
|
||||
.option('--deployment', 'Optional: if provided, pod install will use --deployment option')
|
||||
.option('--inline', 'Optional: if true, all source maps will be inlined for easier debugging on mobile devices', false)
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { deployment, inline }) => {
|
||||
const { syncCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/sync')));
|
||||
await syncCommand(config, platform, deployment, inline);
|
||||
})));
|
||||
commander_1.program
|
||||
.command('update [platform]')
|
||||
.description(`updates the native plugins and dependencies based on ${colors_1.default.strong('package.json')}`)
|
||||
.option('--deployment', 'Optional: if provided, pod install will use --deployment option')
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { deployment }) => {
|
||||
const { updateCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/update')));
|
||||
await updateCommand(config, platform, deployment);
|
||||
})));
|
||||
commander_1.program
|
||||
.command('copy [platform]')
|
||||
.description('copies the web app build into the native app')
|
||||
.option('--inline', 'Optional: if true, all source maps will be inlined for easier debugging on mobile devices', false)
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { inline }) => {
|
||||
const { copyCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/copy')));
|
||||
await copyCommand(config, platform, inline);
|
||||
})));
|
||||
commander_1.program
|
||||
.command('build <platform>')
|
||||
.description('builds the release version of the selected platform')
|
||||
.option('--scheme <schemeToBuild>', 'iOS Scheme to build')
|
||||
.option('--flavor <flavorToBuild>', 'Android Flavor to build')
|
||||
.option('--keystorepath <keystorePath>', 'Path to the keystore')
|
||||
.option('--keystorepass <keystorePass>', 'Password to the keystore')
|
||||
.option('--keystorealias <keystoreAlias>', 'Key Alias in the keystore')
|
||||
.option('--configuration <name>', 'Configuration name of the iOS Scheme')
|
||||
.option('--keystorealiaspass <keystoreAliasPass>', 'Password for the Key Alias')
|
||||
.addOption(new commander_1.Option('--androidreleasetype <androidreleasetype>', 'Android release type; APK or AAB').choices([
|
||||
'AAB',
|
||||
'APK',
|
||||
]))
|
||||
.addOption(new commander_1.Option('--signing-type <signingtype>', 'Program used to sign apps (default: jarsigner)').choices([
|
||||
'apksigner',
|
||||
'jarsigner',
|
||||
]))
|
||||
.addOption(new commander_1.Option('--xcode-team-id <xcodeTeamID>', 'The Developer team to use for building and exporting the archive'))
|
||||
.addOption(new commander_1.Option('--xcode-export-method <xcodeExportMethod>', 'Describes how xcodebuild should export the archive (default: app-store-connect)').choices([
|
||||
'app-store-connect',
|
||||
'release-testing',
|
||||
'enterprise',
|
||||
'debugging',
|
||||
'developer-id',
|
||||
'mac-application',
|
||||
'validation',
|
||||
]))
|
||||
.addOption(new commander_1.Option('--xcode-signing-style <xcodeSigningStyle>', 'The iOS signing style to use when building the app for distribution (default: automatic)').choices(['automatic', 'manual']))
|
||||
.addOption(new commander_1.Option('--xcode-signing-certificate <xcodeSigningCertificate>', 'A certificate name, SHA-1 hash, or automatic selector to use for signing for iOS builds'))
|
||||
.addOption(new commander_1.Option('--xcode-provisioning-profile <xcodeProvisioningProfile>', 'A provisioning profile name or UUID for iOS builds'))
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { scheme, flavor, keystorepath, keystorepass, keystorealias, keystorealiaspass, androidreleasetype, signingType, configuration, xcodeTeamId, xcodeExportMethod, xcodeSigningStyle, xcodeSigningCertificate, xcodeProvisioningProfile, }) => {
|
||||
const { buildCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/build')));
|
||||
await buildCommand(config, platform, {
|
||||
scheme,
|
||||
flavor,
|
||||
keystorepath,
|
||||
keystorepass,
|
||||
keystorealias,
|
||||
keystorealiaspass,
|
||||
androidreleasetype,
|
||||
signingtype: signingType,
|
||||
configuration,
|
||||
xcodeTeamId,
|
||||
xcodeExportMethod,
|
||||
xcodeSigningType: xcodeSigningStyle,
|
||||
xcodeSigningCertificate,
|
||||
xcodeProvisioningProfile,
|
||||
});
|
||||
})));
|
||||
commander_1.program
|
||||
.command(`run [platform]`)
|
||||
.description(`runs ${colors_1.default.input('sync')}, then builds and deploys the native app`)
|
||||
.option('--scheme <schemeName>', 'set the scheme of the iOS project')
|
||||
.option('--flavor <flavorName>', 'set the flavor of the Android project (flavor dimensions not yet supported)')
|
||||
.option('--list', 'list targets, then quit')
|
||||
.addOption(new commander_1.Option('--json').hideHelp())
|
||||
.option('--target <id>', 'use a specific target')
|
||||
.option('--no-sync', `do not run ${colors_1.default.input('sync')}`)
|
||||
.option('--forwardPorts <port:port>', 'Automatically run "adb reverse" for better live-reloading support')
|
||||
.option('-l, --live-reload', 'Enable Live Reload')
|
||||
.option('--host <host>', 'Host used for live reload')
|
||||
.option('--port <port>', 'Port used for live reload')
|
||||
.option('--configuration <name>', 'Configuration name of the iOS Scheme')
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { scheme, flavor, list, json, target, sync, forwardPorts, liveReload, host, port, configuration }) => {
|
||||
const { runCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/run')));
|
||||
await runCommand(config, platform, {
|
||||
scheme,
|
||||
flavor,
|
||||
list,
|
||||
json,
|
||||
target,
|
||||
sync,
|
||||
forwardPorts,
|
||||
liveReload,
|
||||
host,
|
||||
port,
|
||||
configuration,
|
||||
});
|
||||
})));
|
||||
commander_1.program
|
||||
.command('open [platform]')
|
||||
.description('opens the native project workspace (Xcode for iOS)')
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform) => {
|
||||
const { openCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/open')));
|
||||
await openCommand(config, platform);
|
||||
})));
|
||||
commander_1.program
|
||||
.command('add [platform]')
|
||||
.description('add a native platform project')
|
||||
.option('--packagemanager <packageManager>', 'The package manager to use for dependency installs (CocoaPods or SPM)')
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform, { packagemanager }) => {
|
||||
const { addCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/add')));
|
||||
const configWritable = config;
|
||||
if (packagemanager === 'SPM') {
|
||||
configWritable.cli.assets.ios.platformTemplateArchive = 'ios-spm-template.tar.gz';
|
||||
configWritable.cli.assets.ios.platformTemplateArchiveAbs = (0, path_1.resolve)(configWritable.cli.assetsDirAbs, configWritable.cli.assets.ios.platformTemplateArchive);
|
||||
}
|
||||
await addCommand(configWritable, platform);
|
||||
})));
|
||||
commander_1.program
|
||||
.command('ls [platform]')
|
||||
.description('list installed Cordova and Capacitor plugins')
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform) => {
|
||||
const { listCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/list')));
|
||||
await listCommand(config, platform);
|
||||
})));
|
||||
commander_1.program
|
||||
.command('doctor [platform]')
|
||||
.description('checks the current setup for common errors')
|
||||
.action((0, cli_1.wrapAction)((0, telemetry_1.telemetryAction)(config, async (platform) => {
|
||||
const { doctorCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/doctor')));
|
||||
await doctorCommand(config, platform);
|
||||
})));
|
||||
commander_1.program
|
||||
.command('telemetry [on|off]', { hidden: true })
|
||||
.description('enable or disable telemetry')
|
||||
.action((0, cli_1.wrapAction)(async (onOrOff) => {
|
||||
const { telemetryCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/telemetry')));
|
||||
await telemetryCommand(onOrOff);
|
||||
}));
|
||||
commander_1.program
|
||||
.command('📡', { hidden: true })
|
||||
.description('IPC receiver command')
|
||||
.action(() => {
|
||||
// no-op: IPC messages are received via `process.on('message')`
|
||||
});
|
||||
commander_1.program
|
||||
.command('plugin:generate', { hidden: true })
|
||||
.description('start a new Capacitor plugin')
|
||||
.action((0, cli_1.wrapAction)(async () => {
|
||||
const { newPluginCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/new-plugin')));
|
||||
await newPluginCommand();
|
||||
}));
|
||||
commander_1.program
|
||||
.command('migrate')
|
||||
.option('--noprompt', 'do not prompt for confirmation')
|
||||
.option('--packagemanager <packageManager>', 'The package manager to use for dependency installs (npm, pnpm, yarn)')
|
||||
.description('Migrate your current Capacitor app to the latest major version of Capacitor.')
|
||||
.action((0, cli_1.wrapAction)(async ({ noprompt, packagemanager }) => {
|
||||
const { migrateCommand } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/migrate')));
|
||||
await migrateCommand(config, noprompt, packagemanager);
|
||||
}));
|
||||
commander_1.program
|
||||
.command('spm-migration-assistant')
|
||||
.description('Remove Cocoapods from project and switch to Swift Package Manager')
|
||||
.action((0, cli_1.wrapAction)(async () => {
|
||||
const { migrateToSPM } = await Promise.resolve().then(() => tslib_1.__importStar(require('./tasks/migrate-spm')));
|
||||
await migrateToSPM(config);
|
||||
}));
|
||||
commander_1.program.arguments('[command]').action((0, cli_1.wrapAction)(async (cmd) => {
|
||||
if (typeof cmd === 'undefined') {
|
||||
log_1.output.write(`\n ${(0, emoji_1.emoji)('⚡️', '--')} ${colors_1.default.strong('Capacitor - Cross-Platform apps with JavaScript and the Web')} ${(0, emoji_1.emoji)('⚡️', '--')}\n\n`);
|
||||
commander_1.program.outputHelp();
|
||||
}
|
||||
else {
|
||||
(0, errors_1.fatal)(`Unknown command: ${colors_1.default.input(cmd)}`);
|
||||
}
|
||||
}));
|
||||
commander_1.program.parse(process.argv);
|
||||
}
|
||||
exports.runProgram = runProgram;
|
||||
13
node_modules/@capacitor/cli/dist/ios/add.js
generated
vendored
Normal file
13
node_modules/@capacitor/cli/dist/ios/add.js
generated
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.addIOS = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const colors_1 = tslib_1.__importDefault(require("../colors"));
|
||||
const common_1 = require("../common");
|
||||
const template_1 = require("../util/template");
|
||||
async function addIOS(config) {
|
||||
await (0, common_1.runTask)(`Adding native Xcode project in ${colors_1.default.strong(config.ios.platformDir)}`, () => {
|
||||
return (0, template_1.extractTemplate)(config.cli.assets.ios.platformTemplateArchiveAbs, config.ios.platformDirAbs);
|
||||
});
|
||||
}
|
||||
exports.addIOS = addIOS;
|
||||
96
node_modules/@capacitor/cli/dist/ios/build.js
generated
vendored
Normal file
96
node_modules/@capacitor/cli/dist/ios/build.js
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.buildiOS = void 0;
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path_1 = require("path");
|
||||
const rimraf_1 = require("rimraf");
|
||||
const common_1 = require("../common");
|
||||
const definitions_1 = require("../definitions");
|
||||
const log_1 = require("../log");
|
||||
const spm_1 = require("../util/spm");
|
||||
const subprocess_1 = require("../util/subprocess");
|
||||
async function buildiOS(config, buildOptions) {
|
||||
var _a, _b, _c, _d;
|
||||
const theScheme = (_a = buildOptions.scheme) !== null && _a !== void 0 ? _a : 'App';
|
||||
const packageManager = await (0, spm_1.checkPackageManager)(config);
|
||||
let typeOfBuild;
|
||||
let projectName;
|
||||
if (packageManager == 'Cocoapods') {
|
||||
typeOfBuild = '-workspace';
|
||||
projectName = (0, path_1.basename)(await config.ios.nativeXcodeWorkspaceDirAbs);
|
||||
}
|
||||
else {
|
||||
typeOfBuild = '-project';
|
||||
projectName = (0, path_1.basename)(await config.ios.nativeXcodeProjDirAbs);
|
||||
}
|
||||
if (buildOptions.xcodeSigningType == 'manual' &&
|
||||
(!buildOptions.xcodeSigningCertificate || !buildOptions.xcodeProvisioningProfile)) {
|
||||
throw 'Manually signed Xcode builds require a signing certificate and provisioning profile.';
|
||||
}
|
||||
const buildArgs = [
|
||||
typeOfBuild,
|
||||
projectName,
|
||||
'-scheme',
|
||||
`${theScheme}`,
|
||||
'-destination',
|
||||
`generic/platform=iOS`,
|
||||
'-archivePath',
|
||||
`${theScheme}.xcarchive`,
|
||||
'archive',
|
||||
'-configuration',
|
||||
buildOptions.configuration,
|
||||
];
|
||||
if (buildOptions.xcodeTeamId) {
|
||||
buildArgs.push(`DEVELOPMENT_TEAM=${buildOptions.xcodeTeamId}`);
|
||||
}
|
||||
if (buildOptions.xcodeSigningType == 'manual') {
|
||||
buildArgs.push(`PROVISIONING_PROFILE_SPECIFIER=${buildOptions.xcodeProvisioningProfile}`);
|
||||
}
|
||||
await (0, common_1.runTask)('Building xArchive', async () => (0, subprocess_1.runCommand)('xcodebuild', buildArgs, {
|
||||
cwd: config.ios.nativeProjectDirAbs,
|
||||
}));
|
||||
const manualSigningContents = `<key>provisioningProfiles</key>
|
||||
<dict>
|
||||
<key>${config.app.appId}</key>
|
||||
<string>${(_b = buildOptions.xcodeProvisioningProfile) !== null && _b !== void 0 ? _b : ''}</string>
|
||||
</dict>
|
||||
<key>signingCertificate</key>
|
||||
<string>${(_c = buildOptions.xcodeSigningCertificate) !== null && _c !== void 0 ? _c : ''}</string>`;
|
||||
const archivePlistContents = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>method</key>
|
||||
<string>${(_d = buildOptions.xcodeExportMethod) !== null && _d !== void 0 ? _d : definitions_1.XcodeExportMethod.AppStoreConnect}</string>
|
||||
<key>signingStyle</key>
|
||||
<string>${buildOptions.xcodeSigningType}</string>
|
||||
${buildOptions.xcodeSigningType == 'manual' ? manualSigningContents : ''}
|
||||
</dict>
|
||||
</plist>`;
|
||||
const archivePlistPath = (0, path_1.join)(`${config.ios.nativeProjectDirAbs}`, 'archive.plist');
|
||||
(0, fs_extra_1.writeFileSync)(archivePlistPath, archivePlistContents);
|
||||
const archiveArgs = [
|
||||
'archive',
|
||||
'-archivePath',
|
||||
`${theScheme}.xcarchive`,
|
||||
'-exportArchive',
|
||||
'-exportOptionsPlist',
|
||||
'archive.plist',
|
||||
'-exportPath',
|
||||
'output',
|
||||
'-configuration',
|
||||
buildOptions.configuration,
|
||||
];
|
||||
if (buildOptions.xcodeSigningType == 'automatic') {
|
||||
archiveArgs.push('-allowProvisioningUpdates');
|
||||
}
|
||||
await (0, common_1.runTask)('Building IPA', async () => (0, subprocess_1.runCommand)('xcodebuild', archiveArgs, {
|
||||
cwd: config.ios.nativeProjectDirAbs,
|
||||
}));
|
||||
await (0, common_1.runTask)('Cleaning up', async () => {
|
||||
(0, fs_extra_1.unlinkSync)(archivePlistPath);
|
||||
rimraf_1.rimraf.sync((0, path_1.join)(config.ios.nativeProjectDirAbs, `${theScheme}.xcarchive`));
|
||||
});
|
||||
(0, log_1.logSuccess)(`Successfully generated an IPA at: ${(0, path_1.join)(config.ios.nativeProjectDirAbs, 'output')}`);
|
||||
}
|
||||
exports.buildiOS = buildiOS;
|
||||
105
node_modules/@capacitor/cli/dist/ios/common.js
generated
vendored
Normal file
105
node_modules/@capacitor/cli/dist/ios/common.js
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getMajoriOSVersion = exports.editProjectSettingsIOS = exports.resolvePlugin = exports.getIOSPlugins = exports.checkCocoaPods = exports.checkBundler = exports.checkIOSPackage = void 0;
|
||||
const tslib_1 = require("tslib");
|
||||
const child_process_1 = require("child_process");
|
||||
const fs_extra_1 = require("fs-extra");
|
||||
const path_1 = require("path");
|
||||
const colors_1 = tslib_1.__importDefault(require("../colors"));
|
||||
const common_1 = require("../common");
|
||||
const cordova_1 = require("../cordova");
|
||||
const log_1 = require("../log");
|
||||
const plugin_1 = require("../plugin");
|
||||
const subprocess_1 = require("../util/subprocess");
|
||||
async function checkIOSPackage(config) {
|
||||
return (0, common_1.checkCapacitorPlatform)(config, 'ios');
|
||||
}
|
||||
exports.checkIOSPackage = checkIOSPackage;
|
||||
function execBundler() {
|
||||
try {
|
||||
const bundleOutput = (0, child_process_1.execSync)('bundle &> /dev/null ; echo $?');
|
||||
return parseInt(bundleOutput.toString());
|
||||
}
|
||||
catch (e) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
async function checkBundler(config) {
|
||||
if (config.cli.os === "mac" /* OS.Mac */) {
|
||||
let bundlerResult = execBundler();
|
||||
if (bundlerResult === 1) {
|
||||
// Bundler version is outdated
|
||||
log_1.logger.info(`Using ${colors_1.default.strong('Gemfile')}: Bundler update needed...`);
|
||||
await (0, subprocess_1.runCommand)('gem', ['install', 'bundler']);
|
||||
bundlerResult = execBundler();
|
||||
}
|
||||
if (bundlerResult === 0) {
|
||||
// Bundler in use, all gems current
|
||||
log_1.logger.info(`Using ${colors_1.default.strong('Gemfile')}: RubyGems bundle installed`);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.checkBundler = checkBundler;
|
||||
async function checkCocoaPods(config) {
|
||||
if (!(await (0, subprocess_1.isInstalled)(await config.ios.podPath)) && config.cli.os === "mac" /* OS.Mac */) {
|
||||
return (`CocoaPods is not installed.\n` +
|
||||
`See this install guide: ${colors_1.default.strong('https://capacitorjs.com/docs/getting-started/environment-setup#homebrew')}`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
exports.checkCocoaPods = checkCocoaPods;
|
||||
async function getIOSPlugins(allPlugins) {
|
||||
const resolved = await Promise.all(allPlugins.map(async (plugin) => await resolvePlugin(plugin)));
|
||||
return resolved.filter((plugin) => !!plugin);
|
||||
}
|
||||
exports.getIOSPlugins = getIOSPlugins;
|
||||
async function resolvePlugin(plugin) {
|
||||
var _a, _b;
|
||||
const platform = 'ios';
|
||||
if ((_a = plugin.manifest) === null || _a === void 0 ? void 0 : _a.ios) {
|
||||
plugin.ios = {
|
||||
name: plugin.name,
|
||||
type: 0 /* PluginType.Core */,
|
||||
path: (_b = plugin.manifest.ios.src) !== null && _b !== void 0 ? _b : platform,
|
||||
};
|
||||
}
|
||||
else if (plugin.xml) {
|
||||
plugin.ios = {
|
||||
name: plugin.name,
|
||||
type: 1 /* PluginType.Cordova */,
|
||||
path: 'src/' + platform,
|
||||
};
|
||||
if ((0, cordova_1.getIncompatibleCordovaPlugins)(platform).includes(plugin.id) || !(0, plugin_1.getPluginPlatform)(plugin, platform)) {
|
||||
plugin.ios.type = 2 /* PluginType.Incompatible */;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return plugin;
|
||||
}
|
||||
exports.resolvePlugin = resolvePlugin;
|
||||
/**
|
||||
* Update the native project files with the desired app id and app name
|
||||
*/
|
||||
async function editProjectSettingsIOS(config) {
|
||||
const appId = config.app.appId;
|
||||
const appName = config.app.appName.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
||||
const pbxPath = `${config.ios.nativeXcodeProjDirAbs}/project.pbxproj`;
|
||||
const plistPath = (0, path_1.resolve)(config.ios.nativeTargetDirAbs, 'Info.plist');
|
||||
let plistContent = await (0, fs_extra_1.readFile)(plistPath, { encoding: 'utf-8' });
|
||||
plistContent = plistContent.replace(/<key>CFBundleDisplayName<\/key>[\s\S]?\s+<string>([^<]*)<\/string>/, `<key>CFBundleDisplayName</key>\n <string>${appName}</string>`);
|
||||
let pbxContent = await (0, fs_extra_1.readFile)(pbxPath, { encoding: 'utf-8' });
|
||||
pbxContent = pbxContent.replace(/PRODUCT_BUNDLE_IDENTIFIER = ([^;]+)/g, `PRODUCT_BUNDLE_IDENTIFIER = ${appId}`);
|
||||
await (0, fs_extra_1.writeFile)(plistPath, plistContent, { encoding: 'utf-8' });
|
||||
await (0, fs_extra_1.writeFile)(pbxPath, pbxContent, { encoding: 'utf-8' });
|
||||
}
|
||||
exports.editProjectSettingsIOS = editProjectSettingsIOS;
|
||||
function getMajoriOSVersion(config) {
|
||||
const pbx = (0, fs_extra_1.readFileSync)((0, path_1.join)(config.ios.nativeXcodeProjDirAbs, 'project.pbxproj'), 'utf-8');
|
||||
const searchString = 'IPHONEOS_DEPLOYMENT_TARGET = ';
|
||||
const iosVersion = pbx.substring(pbx.indexOf(searchString) + searchString.length, pbx.indexOf(searchString) + searchString.length + 2);
|
||||
return iosVersion;
|
||||
}
|
||||
exports.getMajoriOSVersion = getMajoriOSVersion;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user