You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
28 KiB
286 lines
28 KiB
/*
|
|
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
|
|
if you want to view the source, please visit the github repository of this plugin
|
|
*/
|
|
|
|
var __create = Object.create;
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __getProtoOf = Object.getPrototypeOf;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __markAsModule = (target) => __defProp(target, "__esModule", { value: true });
|
|
var __export = (target, all) => {
|
|
__markAsModule(target);
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __reExport = (target, module2, desc) => {
|
|
if (module2 && typeof module2 === "object" || typeof module2 === "function") {
|
|
for (let key of __getOwnPropNames(module2))
|
|
if (!__hasOwnProp.call(target, key) && key !== "default")
|
|
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
|
|
}
|
|
return target;
|
|
};
|
|
var __toModule = (module2) => {
|
|
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
|
|
};
|
|
var __async = (__this, __arguments, generator) => {
|
|
return new Promise((resolve, reject) => {
|
|
var fulfilled = (value) => {
|
|
try {
|
|
step(generator.next(value));
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
};
|
|
var rejected = (value) => {
|
|
try {
|
|
step(generator.throw(value));
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
};
|
|
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
step((generator = generator.apply(__this, __arguments)).next());
|
|
});
|
|
};
|
|
|
|
// main.ts
|
|
__export(exports, {
|
|
default: () => main_default
|
|
});
|
|
|
|
// src/App.ts
|
|
var import_obsidian3 = __toModule(require("obsidian"));
|
|
|
|
// src/Modal.ts
|
|
var import_obsidian = __toModule(require("obsidian"));
|
|
var CameraModal = class extends import_obsidian.Modal {
|
|
constructor(app2, cameraSettings) {
|
|
super(app2);
|
|
this.videoStream = null;
|
|
this.chosenFolderPath = cameraSettings.chosenFolderPath;
|
|
}
|
|
onOpen() {
|
|
return __async(this, null, function* () {
|
|
const { contentEl } = this;
|
|
const webCamContainer = contentEl.createDiv();
|
|
const statusMsg = webCamContainer.createEl("span", {
|
|
text: "Loading.."
|
|
});
|
|
const videoEl = webCamContainer.createEl("video");
|
|
const buttonsDiv = webCamContainer.createDiv();
|
|
const firstRow = buttonsDiv.createDiv();
|
|
const secondRow = buttonsDiv.createDiv();
|
|
const recordVideoButton = firstRow.createEl("button", {
|
|
text: "Start recording"
|
|
});
|
|
const switchCameraButton = firstRow.createEl("button", {
|
|
text: "Switch Camera"
|
|
});
|
|
const snapPhotoButton = firstRow.createEl("button", {
|
|
text: "Take a snap"
|
|
});
|
|
firstRow.style.display = "none";
|
|
secondRow.style.display = "none";
|
|
const filePicker = secondRow.createEl("input", {
|
|
placeholder: "Choose image file from system",
|
|
type: "file"
|
|
});
|
|
filePicker.id = "filepicker";
|
|
filePicker.accept = "image/*,video/*";
|
|
filePicker.capture = "camera";
|
|
filePicker.style.display = "none";
|
|
const label = secondRow.createEl("label");
|
|
label.textContent = "Upload";
|
|
label.style.cursor = "pointer";
|
|
label.style.display = "inline-block";
|
|
label.style.margin = "5px 0px";
|
|
label.style.padding = "5px";
|
|
label.style.border = "0.5px solid #555";
|
|
label.htmlFor = "filepicker";
|
|
label.innerHTML = "⇧ Upload";
|
|
label.appendChild(filePicker);
|
|
secondRow.appendChild(label);
|
|
videoEl.autoplay = true;
|
|
videoEl.muted = true;
|
|
const chunks = [];
|
|
let recorder = null;
|
|
this.videoStream = null;
|
|
const cameras = (yield navigator.mediaDevices.enumerateDevices()).filter((d) => d.kind === "videoinput");
|
|
if (cameras.length <= 1)
|
|
switchCameraButton.style.display = "none";
|
|
let cameraIndex = 0;
|
|
const getVideoStream = () => __async(this, null, function* () {
|
|
try {
|
|
return yield navigator.mediaDevices.getUserMedia({
|
|
video: { deviceId: cameras[cameraIndex].deviceId },
|
|
audio: true
|
|
});
|
|
} catch (error) {
|
|
console.log(error);
|
|
return null;
|
|
}
|
|
});
|
|
this.videoStream = yield getVideoStream();
|
|
if (this.videoStream) {
|
|
firstRow.style.display = "block";
|
|
secondRow.style.display = "block";
|
|
statusMsg.style.display = "none";
|
|
} else {
|
|
secondRow.style.display = "block";
|
|
statusMsg.textContent = "Error in loading videostream in your device..";
|
|
}
|
|
const handleImageSelectChange = (file, isImage = true) => __async(this, null, function* () {
|
|
const chosenFile = file;
|
|
const bufferFile = yield chosenFile.arrayBuffer();
|
|
saveFile(bufferFile, isImage, chosenFile.name.split(" ").join("-"));
|
|
});
|
|
filePicker.onchange = () => {
|
|
var _a;
|
|
if (!((_a = filePicker.files) == null ? void 0 : _a.length))
|
|
return;
|
|
const selectedFile = filePicker.files[0];
|
|
label.textContent = `Selected: ${selectedFile.name}`;
|
|
const isImage = selectedFile.type.startsWith("image/");
|
|
handleImageSelectChange(selectedFile, isImage);
|
|
};
|
|
const view = this.app.workspace.getActiveViewOfType(import_obsidian.MarkdownView);
|
|
const saveFile = (file, isImage = false, fileName = "") => __async(this, null, function* () {
|
|
if (!fileName) {
|
|
const dateString = (new Date() + "").slice(4, 28).split(" ").join("_").split(":").join("-");
|
|
fileName = isImage ? `image_${dateString}.png` : `video_${dateString}.webm`;
|
|
}
|
|
new import_obsidian.Notice(`Adding new ${isImage ? "Image" : "Video"} to vault...`);
|
|
const filePath = this.chosenFolderPath + "/" + fileName;
|
|
const folderExists = app.vault.getAbstractFileByPath(this.chosenFolderPath);
|
|
if (!folderExists)
|
|
yield app.vault.createFolder(this.chosenFolderPath);
|
|
const fileExists = app.vault.getAbstractFileByPath(filePath);
|
|
if (!fileExists)
|
|
yield app.vault.createBinary(filePath, file);
|
|
if (!view)
|
|
return new import_obsidian.Notice(`Saved to ${filePath}`);
|
|
const cursor = view.editor.getCursor();
|
|
view.editor.replaceRange(isImage ? `![${fileName}](${filePath})
|
|
` : `
|
|
![[${filePath}]]
|
|
`, cursor);
|
|
this.close();
|
|
});
|
|
switchCameraButton.onclick = () => __async(this, null, function* () {
|
|
cameraIndex = (cameraIndex + 1) % cameras.length;
|
|
this.videoStream = yield navigator.mediaDevices.getUserMedia({
|
|
video: { deviceId: cameras[cameraIndex].deviceId },
|
|
audio: true
|
|
});
|
|
videoEl.srcObject = this.videoStream;
|
|
videoEl.play();
|
|
});
|
|
snapPhotoButton.onclick = () => {
|
|
const canvas = webCamContainer.createEl("canvas");
|
|
canvas.style.display = "none";
|
|
const { videoHeight, videoWidth } = videoEl;
|
|
canvas.height = videoHeight;
|
|
canvas.width = videoWidth;
|
|
canvas.getContext("2d").drawImage(videoEl, 0, 0, videoWidth, videoHeight);
|
|
canvas.toBlob((blob) => __async(this, null, function* () {
|
|
const bufferFile = yield blob.arrayBuffer();
|
|
saveFile(bufferFile, true);
|
|
}), "image/png");
|
|
};
|
|
videoEl.srcObject = this.videoStream;
|
|
recordVideoButton.onclick = () => __async(this, null, function* () {
|
|
switchCameraButton.disabled = true;
|
|
if (!recorder) {
|
|
recorder = new MediaRecorder(this.videoStream, {
|
|
mimeType: "video/webm"
|
|
});
|
|
}
|
|
let isRecording = recorder && recorder.state === "recording";
|
|
if (isRecording) {
|
|
recorder.stop();
|
|
} else {
|
|
recorder.start();
|
|
}
|
|
isRecording = !isRecording;
|
|
recordVideoButton.innerText = isRecording ? "Stop Recording" : "Start Recording";
|
|
recorder.ondataavailable = (e) => chunks.push(e.data);
|
|
recorder.onstop = (_) => __async(this, null, function* () {
|
|
const blob = new Blob(chunks, {
|
|
type: "audio/ogg; codecs=opus"
|
|
});
|
|
const bufferFile = yield blob.arrayBuffer();
|
|
saveFile(bufferFile, false);
|
|
});
|
|
});
|
|
});
|
|
}
|
|
onClose() {
|
|
var _a;
|
|
const { contentEl } = this;
|
|
(_a = this.videoStream) == null ? void 0 : _a.getTracks().forEach((track) => {
|
|
track.stop();
|
|
});
|
|
contentEl.empty();
|
|
}
|
|
};
|
|
var Modal_default = CameraModal;
|
|
|
|
// src/SettingsTab.ts
|
|
var import_obsidian2 = __toModule(require("obsidian"));
|
|
var DEFAULT_SETTINGS = {
|
|
chosenFolderPath: "attachments/snaps"
|
|
};
|
|
var CameraSettingsTab = class extends import_obsidian2.PluginSettingTab {
|
|
constructor(app2, plugin) {
|
|
super(app2, plugin);
|
|
this.plugin = plugin;
|
|
}
|
|
display() {
|
|
const { containerEl } = this;
|
|
containerEl.empty();
|
|
containerEl.createEl("h2", { text: "Obsidian-Camera settings" });
|
|
new import_obsidian2.Setting(containerEl).setName("Folder Path").setDesc("Folder where the videos and snaps should be saved").addText((text) => text.setPlaceholder("Enter your secret").setValue(this.plugin.settings.chosenFolderPath).onChange((value) => __async(this, null, function* () {
|
|
this.plugin.settings.chosenFolderPath = value;
|
|
yield this.plugin.saveSettings();
|
|
})));
|
|
}
|
|
};
|
|
|
|
// src/App.ts
|
|
var ObsidianCamera = class extends import_obsidian3.Plugin {
|
|
onload() {
|
|
return __async(this, null, function* () {
|
|
yield this.loadSettings();
|
|
this.addRibbonIcon("camera", "Obsidian Camera", (evt) => {
|
|
new Modal_default(this.app, this.settings).open();
|
|
});
|
|
this.addSettingTab(new CameraSettingsTab(this.app, this));
|
|
this.addCommand({
|
|
id: "Open camera modal",
|
|
name: "Open camera modal / File Picker",
|
|
callback: () => {
|
|
new Modal_default(this.app, this.settings).open();
|
|
}
|
|
});
|
|
});
|
|
}
|
|
loadSettings() {
|
|
return __async(this, null, function* () {
|
|
this.settings = Object.assign({}, DEFAULT_SETTINGS, yield this.loadData());
|
|
});
|
|
}
|
|
saveSettings() {
|
|
return __async(this, null, function* () {
|
|
yield this.saveData(this.settings);
|
|
});
|
|
}
|
|
};
|
|
|
|
// main.ts
|
|
var main_default = ObsidianCamera;
|
|
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsibWFpbi50cyIsICJzcmMvQXBwLnRzIiwgInNyYy9Nb2RhbC50cyIsICJzcmMvU2V0dGluZ3NUYWIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImltcG9ydCBPYnNpZGlhbkNhbWVyYSBmcm9tIFwic3JjL0FwcFwiO1xuXG5leHBvcnQgZGVmYXVsdCBPYnNpZGlhbkNhbWVyYSIsICJpbXBvcnQgeyBQbHVnaW4gfSBmcm9tIFwib2JzaWRpYW5cIjtcbmltcG9ydCBDYW1lcmFNb2RhbCBmcm9tIFwiLi9Nb2RhbFwiO1xuaW1wb3J0IENhbWVyYVNldHRpbmdzVGFiLCB7IERFRkFVTFRfU0VUVElOR1MsIENhbWVyYVBsdWdpblNldHRpbmdzIH0gZnJvbSBcIi4vU2V0dGluZ3NUYWJcIjtcblxuZXhwb3J0IGRlZmF1bHQgY2xhc3MgT2JzaWRpYW5DYW1lcmEgZXh0ZW5kcyBQbHVnaW4ge1xuICBzZXR0aW5nczogQ2FtZXJhUGx1Z2luU2V0dGluZ3M7XG4gIGFzeW5jIG9ubG9hZCgpIHtcbiAgICBhd2FpdCB0aGlzLmxvYWRTZXR0aW5ncygpO1xuICAgIHRoaXMuYWRkUmliYm9uSWNvbihcImNhbWVyYVwiLCBcIk9ic2lkaWFuIENhbWVyYVwiLCAoZXZ0OiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgICBuZXcgQ2FtZXJhTW9kYWwodGhpcy5hcHAsIHRoaXMuc2V0dGluZ3MpLm9wZW4oKTtcbiAgICB9KTtcbiAgICB0aGlzLmFkZFNldHRpbmdUYWIobmV3IENhbWVyYVNldHRpbmdzVGFiKHRoaXMuYXBwLCB0aGlzKSk7XG5cbiAgICB0aGlzLmFkZENvbW1hbmQoe1xuICAgICAgaWQ6IFwiT3BlbiBjYW1lcmEgbW9kYWxcIixcbiAgICAgIG5hbWU6IFwiT3BlbiBjYW1lcmEgbW9kYWwgLyBGaWxlIFBpY2tlclwiLFxuICAgICAgY2FsbGJhY2s6ICgpID0+IHtcbiAgICAgICAgbmV3IENhbWVyYU1vZGFsKHRoaXMuYXBwLCB0aGlzLnNldHRpbmdzKS5vcGVuKCk7XG4gICAgICB9LFxuICAgIH0pO1xuICB9XG5cblxuICBhc3luYyBsb2FkU2V0dGluZ3MoKSB7XG4gICAgdGhpcy5zZXR0aW5ncyA9IE9iamVjdC5hc3NpZ24oe30sIERFRkFVTFRfU0VUVElOR1MsIGF3YWl0IHRoaXMubG9hZERhdGEoKSk7XG4gIH1cblxuICBhc3luYyBzYXZlU2V0dGluZ3MoKSB7XG4gICAgYXdhaXQgdGhpcy5zYXZlRGF0YSh0aGlzLnNldHRpbmdzKTtcbiAgfVxufVxuIiwgImltcG9ydCB7IEFwcCwgTWFya2Rvd25WaWV3LCBNb2RhbCwgTm90aWNlIH0gZnJvbSBcIm9ic2lkaWFuXCI7XG5pbXBvcnQgeyBDYW1lcmFQbHVnaW5TZXR0aW5ncyB9IGZyb20gXCIuL1NldHRpbmdzVGFiXCI7XG5cbmNsYXNzIENhbWVyYU1vZGFsIGV4dGVuZHMgTW9kYWwge1xuXHRjaG9zZW5Gb2xkZXJQYXRoOiBzdHJpbmc7XG5cdHZpZGVvU3RyZWFtOiBNZWRpYVN0cmVhbSA9IG51bGw7XG5cdGNvbnN0cnVjdG9yKGFwcDogQXBwLCBjYW1lcmFTZXR0aW5nczogQ2FtZXJhUGx1Z2luU2V0dGluZ3MpIHtcblx0XHRzdXBlcihhcHApO1xuXHRcdHRoaXMuY2hvc2VuRm9sZGVyUGF0aCA9IGNhbWVyYVNldHRpbmdzLmNob3NlbkZvbGRlclBhdGg7XG5cdH1cblxuXHRhc3luYyBvbk9wZW4oKSB7XG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XG5cdFx0Y29uc3Qgd2ViQ2FtQ29udGFpbmVyID0gY29udGVudEVsLmNyZWF0ZURpdigpO1xuXG5cdFx0Y29uc3Qgc3RhdHVzTXNnID0gd2ViQ2FtQ29udGFpbmVyLmNyZWF0ZUVsKFwic3BhblwiLCB7XG5cdFx0XHR0ZXh0OiBcIkxvYWRpbmcuLlwiLFxuXHRcdH0pO1xuXHRcdGNvbnN0IHZpZGVvRWwgPSB3ZWJDYW1Db250YWluZXIuY3JlYXRlRWwoXCJ2aWRlb1wiKTtcblx0XHRjb25zdCBidXR0b25zRGl2ID0gd2ViQ2FtQ29udGFpbmVyLmNyZWF0ZURpdigpO1xuXHRcdGNvbnN0IGZpcnN0Um93ID0gYnV0dG9uc0Rpdi5jcmVhdGVEaXYoKTtcblx0XHRjb25zdCBzZWNvbmRSb3cgPSBidXR0b25zRGl2LmNyZWF0ZURpdigpO1xuXHRcdGNvbnN0IHJlY29yZFZpZGVvQnV0dG9uID0gZmlyc3RSb3cuY3JlYXRlRWwoXCJidXR0b25cIiwge1xuXHRcdFx0dGV4dDogXCJTdGFydCByZWNvcmRpbmdcIixcblx0XHR9KTtcblx0XHRjb25zdCBzd2l0Y2hDYW1lcmFCdXR0b24gPSBmaXJzdFJvdy5jcmVhdGVFbChcImJ1dHRvblwiLCB7XG5cdFx0XHR0ZXh0OiBcIlN3aXRjaCBDYW1lcmFcIixcblx0XHR9KTtcblx0XHRjb25zdCBzbmFwUGhvdG9CdXR0b24gPSBmaXJzdFJvdy5jcmVhdGVFbChcImJ1dHRvblwiLCB7XG5cdFx0XHR0ZXh0OiBcIlRha2UgYSBzbmFwXCIsXG5cdFx0fSk7XG5cdFx0Zmlyc3RSb3cuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuXHRcdHNlY29uZFJvdy5zdHlsZS5kaXNwbGF5ID0gXCJub25lXCI7XG5cblx0XHRjb25zdCBmaWxlUGlja2VyID0gc2Vjb25kUm93LmNyZWF0ZUVsKFwiaW5wdXRcIiwge1xuXHRcdFx0cGxhY2Vob2xkZXI6IFwiQ2hvb3NlIGltYWdlIGZpbGUgZnJvbSBzeXN0ZW1cIixcblx0XHRcdHR5cGU6IFwiZmlsZVwiLFxuXHRcdH0pO1xuXHRcdGZpbGVQaWNrZXIuaWQgPSBcImZpbGVwaWNrZXJcIjtcblx0XHRmaWxlUGlja2VyLmFjY2VwdCA9IFwiaW1hZ2UvKix2aWRlby8qXCI7XG5cdFx0ZmlsZVBpY2tlci5jYXB0dXJlID0gXCJjYW1lcmFcIjsgLy8gYmFjayBjYW1lcmEgYnkgZGVmYXVsdCBmb3IgbW9iaWxlIHNjcmVlbnNcblxuXHRcdGZpbGVQaWNrZXIuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuXG5cdFx0Y29uc3QgbGFiZWwgPSBzZWNvbmRSb3cuY3JlYXRlRWwoXCJsYWJlbFwiKTtcblx0XHRsYWJlbC50ZXh0Q29udGVudCA9IFwiVXBsb2FkXCI7XG5cdFx0bGFiZWwuc3R5bGUuY3Vyc29yID0gXCJwb2ludGVyXCI7XG5cdFx0bGFiZWwuc3R5bGUuZGlzcGxheSA9IFwiaW5saW5lLWJsb2NrXCI7XG5cdFx0bGFiZWwuc3R5bGUubWFyZ2luID0gXCI1cHggMHB4XCI7XG5cdFx0bGFiZWwuc3R5bGUucGFkZGluZyA9IFwiNXB4XCI7XG5cdFx0bGFiZWwuc3R5bGUuYm9yZGVyID0gXCIwLjVweCBzb2xpZCAjNTU1XCI7XG5cdFx0bGFiZWwuaHRtbEZvciA9IFwiZmlsZXBpY2tlclwiO1xuXHRcdGxhYmVsLmlubmVySFRNTCA9IFwiJiM4Njc5OyBVcGxvYWRcIjtcblxuXHRcdGxhYmVsLmFwcGVuZENoaWxkKGZpbGVQaWNrZXIpO1xuXG5cdFx0c2Vjb25kUm93LmFwcGVuZENoaWxkKGxhYmVsKTtcblxuXHRcdHZpZGVvRWwuYXV0b3BsYXkgPSB0cnVlO1xuXHRcdHZpZGVvRWwubXV0ZWQgPSB0cnVlO1xuXHRcdGNvbnN0IGNodW5rczogQmxvYlBhcnRbXSA9IFtdO1xuXHRcdGxldCByZWNvcmRlcjogTWVkaWFSZWNvcmRlciA9IG51bGw7XG5cdFx0dGhpcy52aWRlb1N0cmVhbSA9IG51bGw7XG5cblx0XHRjb25zdCBjYW1lcmFzID0gKFxuXHRcdFx0YXdhaXQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5lbnVtZXJhdGVEZXZpY2VzKClcblx0XHQpLmZpbHRlcigoZCkgPT4gZC5raW5kID09PSBcInZpZGVvaW5wdXRcIik7XG5cblx0XHRpZiAoY2FtZXJhcy5sZW5ndGggPD0gMSkgc3dpdGNoQ2FtZXJhQnV0dG9uLnN0eWxlLmRpc3BsYXkgPSBcIm5vbmVcIjtcblx0XHRsZXQgY2FtZXJhSW5kZXggPSAwO1xuXG5cdFx0Y29uc3QgZ2V0VmlkZW9TdHJlYW0gPSBhc3luYyAoKSA9PiB7XG5cdFx0XHR0cnkge1xuXHRcdFx0XHRyZXR1cm4gYXdhaXQgbmF2aWdhdG9yLm1lZGlhRGV2aWNlcy5nZXRVc2VyTWVkaWEoe1xuXHRcdFx0XHRcdHZpZGVvOiB7IGRldmljZUlkOiBjYW1lcmFzW2NhbWVyYUluZGV4XS5kZXZpY2VJZCB9LFxuXHRcdFx0XHRcdGF1ZGlvOiB0cnVlLFxuXHRcdFx0XHR9KTtcblx0XHRcdH0gY2F0Y2ggKGVycm9yKSB7XG5cdFx0XHRcdGNvbnNvbGUubG9nKGVycm9yKTtcblx0XHRcdFx0cmV0dXJuIG51bGw7XG5cdFx0XHR9XG5cdFx0fTtcblxuXHRcdHRoaXMudmlkZW9TdHJlYW0gPSBhd2FpdCBnZXRWaWRlb1N0cmVhbSgpO1xuXHRcdGlmICh0aGlzLnZpZGVvU3RyZWFtKSB7XG5cdFx0XHRmaXJzdFJvdy5zdHlsZS5kaXNwbGF5ID0gXCJibG9ja1wiO1xuXHRcdFx0c2Vjb25kUm93LnN0eWxlLmRpc3BsYXkgPSBcImJsb2NrXCI7XG5cdFx0XHRzdGF0dXNNc2cuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuXHRcdH0gZWxzZSB7XG5cdFx0XHRzZWNvbmRSb3cuc3R5bGUuZGlzcGxheSA9IFwiYmxvY2tcIjtcblx0XHRcdHN0YXR1c01zZy50ZXh0Q29udGVudCA9XG5cdFx0XHRcdFwiRXJyb3IgaW4gbG9hZGluZyB2aWRlb3N0cmVhbSBpbiB5b3VyIGRldmljZS4uXCI7XG5cdFx0fVxuXG5cdFx0Y29uc3QgaGFuZGxlSW1hZ2VTZWxlY3RDaGFuZ2UgPSBhc3luYyAoXG5cdFx0XHRmaWxlOiBGaWxlLFxuXHRcdFx0aXNJbWFnZTogYm9vbGVhbiA9IHRydWVcblx0XHQpID0+IHtcblx0XHRcdGNvbnN0IGNob3NlbkZpbGUgPSBmaWxlO1xuXHRcdFx0Y29uc3QgYnVmZmVyRmlsZSA9IGF3YWl0IGNob3NlbkZpbGUuYXJyYXlCdWZmZXIoKTtcblx0XHRcdHNhdmVGaWxlKGJ1ZmZlckZpbGUsIGlzSW1hZ2UsIGNob3NlbkZpbGUubmFtZS5zcGxpdChcIiBcIikuam9pbihcIi1cIikpO1xuXHRcdH07XG5cblx0XHRmaWxlUGlja2VyLm9uY2hhbmdlID0gKCkgPT4ge1xuXHRcdFx0aWYgKCFmaWxlUGlja2VyLmZpbGVzPy5sZW5ndGgpIHJldHVybjtcblx0XHRcdGNvbnN0IHNlbGVjdGVkRmlsZSA9IGZpbGVQaWNrZXIuZmlsZXNbMF07XG5cdFx0XHRsYWJlbC50ZXh0Q29udGVudCA9IGBTZWxlY3RlZDogJHtzZWxlY3RlZEZpbGUubmFtZX1gO1xuXHRcdFx0Y29uc3QgaXNJbWFnZSA9IHNlbGVjdGVkRmlsZS50eXBlLnN0YXJ0c1dpdGgoXCJpbWFnZS9cIik7XG5cdFx0XHRoYW5kbGVJbWFnZVNlbGVjdENoYW5nZShzZWxlY3RlZEZpbGUsIGlzSW1hZ2UpO1xuXHRcdH07XG5cblx0XHRjb25zdCB2aWV3ID0gdGhpcy5hcHAud29ya3NwYWNlLmdldEFjdGl2ZVZpZXdPZlR5cGUoTWFya2Rvd25WaWV3KTtcblxuXHRcdGNvbnN0IHNhdmVGaWxlID0gYXN5bmMgKFxuXHRcdFx0ZmlsZTogQXJyYXlCdWZmZXIsXG5cdFx0XHRpc0ltYWdlID0gZmFsc2UsXG5cdFx0XHRmaWxlTmFtZSA9IFwiXCJcblx0XHQpID0+IHtcblx0XHRcdGlmICghZmlsZU5hbWUpIHtcblx0XHRcdFx0Y29uc3QgZGF0ZVN0cmluZyA9IChuZXcgRGF0ZSgpICsgXCJcIilcblx0XHRcdFx0XHQuc2xpY2UoNCwgMjgpXG5cdFx0XHRcdFx0LnNwbGl0KFwiIFwiKVxuXHRcdFx0XHRcdC5qb2luKFwiX1wiKVxuXHRcdFx0XHRcdC5zcGxpdChcIjpcIilcblx0XHRcdFx0XHQuam9pbihcIi1cIik7XG5cdFx0XHRcdGZpbGVOYW1lID0gaXNJbWFnZVxuXHRcdFx0XHRcdD8gYGltYWdlXyR7ZGF0ZVN0cmluZ30ucG5nYFxuXHRcdFx0XHRcdDogYHZpZGVvXyR7ZGF0ZVN0cmluZ30ud2VibWA7XG5cdFx0XHR9XG5cdFx0XHRuZXcgTm90aWNlKGBBZGRpbmcgbmV3ICR7aXNJbWFnZSA/IFwiSW1hZ2VcIiA6IFwiVmlkZW9cIn0gdG8gdmF1bHQuLi5gKTtcblxuXHRcdFx0Y29uc3QgZmlsZVBhdGggPSB0aGlzLmNob3NlbkZvbGRlclBhdGggKyBcIi9cIiArIGZpbGVOYW1lO1xuXHRcdFx0Y29uc3QgZm9sZGVyRXhpc3RzID0gYXBwLnZhdWx0LmdldEFic3RyYWN0RmlsZUJ5UGF0aChcblx0XHRcdFx0dGhpcy5jaG9zZW5Gb2xkZXJQYXRoXG5cdFx0XHQpO1xuXHRcdFx0aWYgKCFmb2xkZXJFeGlzdHMpXG5cdFx0XHRcdGF3YWl0IGFwcC52YXVsdC5jcmVhdGVGb2xkZXIodGhpcy5jaG9zZW5Gb2xkZXJQYXRoKTtcblx0XHRcdGNvbnN0IGZpbGVFeGlzdHMgPSBhcHAudmF1bHQuZ2V0QWJzdHJhY3RGaWxlQnlQYXRoKGZpbGVQYXRoKTtcblx0XHRcdGlmICghZmlsZUV4aXN0cykgYXdhaXQgYXBwLnZhdWx0LmNyZWF0ZUJpbmFyeShmaWxlUGF0aCwgZmlsZSk7XG5cblx0XHRcdGlmICghdmlldykgcmV0dXJuIG5ldyBOb3RpY2UoYFNhdmVkIHRvICR7ZmlsZVBhdGh9YCk7XG5cblx0XHRcdGNvbnN0IGN1cnNvciA9IHZpZXcuZWRpdG9yLmdldEN1cnNvcigpO1xuXHRcdFx0dmlldy5lZGl0b3IucmVwbGFjZVJhbmdlKFxuXHRcdFx0XHRpc0ltYWdlXG5cdFx0XHRcdFx0PyBgIVske2ZpbGVOYW1lfV0oJHtmaWxlUGF0aH0pXFxuYFxuXHRcdFx0XHRcdDogYFxcbiFbWyR7ZmlsZVBhdGh9XV1cXG5gLFxuXHRcdFx0XHRjdXJzb3Jcblx0XHRcdCk7XG5cdFx0XHR0aGlzLmNsb3NlKCk7XG5cdFx0fTtcblxuXHRcdHN3aXRjaENhbWVyYUJ1dHRvbi5vbmNsaWNrID0gYXN5bmMgKCkgPT4ge1xuXHRcdFx0Y2FtZXJhSW5kZXggPSAoY2FtZXJhSW5kZXggKyAxKSAlIGNhbWVyYXMubGVuZ3RoO1xuXHRcdFx0dGhpcy52aWRlb1N0cmVhbSA9IGF3YWl0IG5hdmlnYXRvci5tZWRpYURldmljZXMuZ2V0VXNlck1lZGlhKHtcblx0XHRcdFx0dmlkZW86IHsgZGV2aWNlSWQ6IGNhbWVyYXNbY2FtZXJhSW5kZXhdLmRldmljZUlkIH0sXG5cdFx0XHRcdGF1ZGlvOiB0cnVlLFxuXHRcdFx0fSk7XG5cdFx0XHR2aWRlb0VsLnNyY09iamVjdCA9IHRoaXMudmlkZW9TdHJlYW07XG5cdFx0XHR2aWRlb0VsLnBsYXkoKTtcblx0XHR9O1xuXG5cdFx0c25hcFBob3RvQnV0dG9uLm9uY2xpY2sgPSAoKSA9PiB7XG5cdFx0XHRjb25zdCBjYW52YXMgPSB3ZWJDYW1Db250YWluZXIuY3JlYXRlRWwoXCJjYW52YXNcIik7XG5cdFx0XHRjYW52YXMuc3R5bGUuZGlzcGxheSA9IFwibm9uZVwiO1xuXHRcdFx0Y29uc3QgeyB2aWRlb0hlaWdodCwgdmlkZW9XaWR0aCB9ID0gdmlkZW9FbDtcblx0XHRcdGNhbnZhcy5oZWlnaHQgPSB2aWRlb0hlaWdodDtcblx0XHRcdGNhbnZhcy53aWR0aCA9IHZpZGVvV2lkdGg7XG5cblx0XHRcdGNhbnZhc1xuXHRcdFx0XHQuZ2V0Q29udGV4dChcIjJkXCIpXG5cdFx0XHRcdC5kcmF3SW1hZ2UodmlkZW9FbCwgMCwgMCwgdmlkZW9XaWR0aCwgdmlkZW9IZWlnaHQpO1xuXHRcdFx0Y2FudmFzLnRvQmxvYihhc3luYyAoYmxvYikgPT4ge1xuXHRcdFx0XHRjb25zdCBidWZmZXJGaWxlID0gYXdhaXQgYmxvYi5hcnJheUJ1ZmZlcigpO1xuXHRcdFx0XHRzYXZlRmlsZShidWZmZXJGaWxlLCB0cnVlKTtcblx0XHRcdH0sIFwiaW1hZ2UvcG5nXCIpO1xuXHRcdH07XG5cblx0XHR2aWRlb0VsLnNyY09iamVjdCA9IHRoaXMudmlkZW9TdHJlYW07XG5cblx0XHRyZWNvcmRWaWRlb0J1dHRvbi5vbmNsaWNrID0gYXN5bmMgKCkgPT4ge1xuXHRcdFx0c3dpdGNoQ2FtZXJhQnV0dG9uLmRpc2FibGVkID0gdHJ1ZTtcblx0XHRcdGlmICghcmVjb3JkZXIpIHtcblx0XHRcdFx0cmVjb3JkZXIgPSBuZXcgTWVkaWFSZWNvcmRlcih0aGlzLnZpZGVvU3RyZWFtLCB7XG5cdFx0XHRcdFx0bWltZVR5cGU6IFwidmlkZW8vd2VibVwiLFxuXHRcdFx0XHR9KTtcblx0XHRcdH1cblxuXHRcdFx0bGV0IGlzUmVjb3JkaW5nOiBib29sZWFuID1cblx0XHRcdFx0cmVjb3JkZXIgJiYgcmVjb3JkZXIuc3RhdGUgPT09IFwicmVjb3JkaW5nXCI7XG5cdFx0XHRpZiAoaXNSZWNvcmRpbmcpIHtcblx0XHRcdFx0cmVjb3JkZXIuc3RvcCgpO1xuXHRcdFx0fSBlbHNlIHtcblx0XHRcdFx0cmVjb3JkZXIuc3RhcnQoKTtcblx0XHRcdH1cblx0XHRcdGlzUmVjb3JkaW5nID0gIWlzUmVjb3JkaW5nO1xuXHRcdFx0cmVjb3JkVmlkZW9CdXR0b24uaW5uZXJUZXh0ID0gaXNSZWNvcmRpbmdcblx0XHRcdFx0PyBcIlN0b3AgUmVjb3JkaW5nXCJcblx0XHRcdFx0OiBcIlN0YXJ0IFJlY29yZGluZ1wiO1xuXG5cdFx0XHRyZWNvcmRlci5vbmRhdGFhdmFpbGFibGUgPSAoZSkgPT4gY2h1bmtzLnB1c2goZS5kYXRhKTtcblx0XHRcdHJlY29yZGVyLm9uc3RvcCA9IGFzeW5jIChfKSA9PiB7XG5cdFx0XHRcdGNvbnN0IGJsb2IgPSBuZXcgQmxvYihjaHVua3MsIHtcblx0XHRcdFx0XHR0eXBlOiBcImF1ZGlvL29nZzsgY29kZWNzPW9wdXNcIixcblx0XHRcdFx0fSk7XG5cdFx0XHRcdGNvbnN0IGJ1ZmZlckZpbGUgPSBhd2FpdCBibG9iLmFycmF5QnVmZmVyKCk7XG5cdFx0XHRcdHNhdmVGaWxlKGJ1ZmZlckZpbGUsIGZhbHNlKTtcblx0XHRcdH07XG5cdFx0fTtcblx0fVxuXG5cdG9uQ2xvc2UoKSB7XG5cdFx0Y29uc3QgeyBjb250ZW50RWwgfSA9IHRoaXM7XG5cdFx0dGhpcy52aWRlb1N0cmVhbT8uZ2V0VHJhY2tzKCkuZm9yRWFjaCgodHJhY2spID0+IHtcblx0XHRcdHRyYWNrLnN0b3AoKTtcblx0XHR9KTtcblx0XHRjb250ZW50RWwuZW1wdHkoKTtcblx0fVxufVxuXG5leHBvcnQgZGVmYXVsdCBDYW1lcmFNb2RhbDtcbiIsICJpbXBvcnQgT2JzaWRpYW5DYW1lcmEgZnJvbSBcIm1haW5cIjtcbmltcG9ydCB7IEFwcCwgUGx1Z2luU2V0dGluZ1RhYiwgU2V0dGluZyB9IGZyb20gXCJvYnNpZGlhblwiO1xuXG5leHBvcnQgaW50ZXJmYWNlIENhbWVyYVBsdWdpblNldHRpbmdzIHtcblx0Y2hvc2VuRm9sZGVyUGF0aDogc3RyaW5nO1xufVxuXG5leHBvcnQgY29uc3QgREVGQVVMVF9TRVRUSU5HUzogQ2FtZXJhUGx1Z2luU2V0dGluZ3MgPSB7XG5cdGNob3NlbkZvbGRlclBhdGg6IFwiYXR0YWNobWVudHMvc25hcHNcIixcbn07XG5cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIENhbWVyYVNldHRpbmdzVGFiIGV4dGVuZHMgUGx1Z2luU2V0dGluZ1RhYiB7XG5cdHBsdWdpbjogT2JzaWRpYW5DYW1lcmE7XG5cblx0Y29uc3RydWN0b3IoYXBwOiBBcHAsIHBsdWdpbjogT2JzaWRpYW5DYW1lcmEpIHtcblx0XHRzdXBlcihhcHAsIHBsdWdpbik7XG5cdFx0dGhpcy5wbHVnaW4gPSBwbHVnaW47XG5cdH1cblxuXHRkaXNwbGF5KCk6IHZvaWQge1xuXHRcdGNvbnN0IHsgY29udGFpbmVyRWwgfSA9IHRoaXM7XG5cdFx0Y29udGFpbmVyRWwuZW1wdHkoKTtcblx0XHRjb250YWluZXJFbC5jcmVhdGVFbChcImgyXCIsIHsgdGV4dDogXCJPYnNpZGlhbi1DYW1lcmEgc2V0dGluZ3NcIiB9KTtcblxuXHRcdG5ldyBTZXR0aW5nKGNvbnRhaW5lckVsKVxuXHRcdFx0LnNldE5hbWUoXCJGb2xkZXIgUGF0aFwiKVxuXHRcdFx0LnNldERlc2MoXCJGb2xkZXIgd2hlcmUgdGhlIHZpZGVvcyBhbmQgc25hcHMgc2hvdWxkIGJlIHNhdmVkXCIpXG5cdFx0XHQuYWRkVGV4dCgodGV4dCkgPT5cblx0XHRcdFx0dGV4dFxuXHRcdFx0XHRcdC5zZXRQbGFjZWhvbGRlcihcIkVudGVyIHlvdXIgc2VjcmV0XCIpXG5cdFx0XHRcdFx0LnNldFZhbHVlKHRoaXMucGx1Z2luLnNldHRpbmdzLmNob3NlbkZvbGRlclBhdGgpXG5cdFx0XHRcdFx0Lm9uQ2hhbmdlKGFzeW5jICh2YWx1ZSkgPT4ge1xuXHRcdFx0XHRcdFx0dGhpcy5wbHVnaW4uc2V0dGluZ3MuY2hvc2VuRm9sZGVyUGF0aCA9IHZhbHVlO1xuXHRcdFx0XHRcdFx0YXdhaXQgdGhpcy5wbHVnaW4uc2F2ZVNldHRpbmdzKCk7XG5cdFx0XHRcdFx0fSlcblx0XHRcdCk7XG5cdH1cbn1cbiJdLAogICJtYXBwaW5ncyI6ICI7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBOzs7QUNBQSx1QkFBdUI7OztBQ0F2QixzQkFBaUQ7QUFHakQsZ0NBQTBCLHNCQUFNO0FBQUEsRUFHL0IsWUFBWSxNQUFVLGdCQUFzQztBQUMzRCxVQUFNO0FBRlAsdUJBQTJCO0FBRzFCLFNBQUssbUJBQW1CLGVBQWU7QUFBQTtBQUFBLEVBR2xDLFNBQVM7QUFBQTtBQUNkLFlBQU0sRUFBRSxjQUFjO0FBQ3RCLFlBQU0sa0JBQWtCLFVBQVU7QUFFbEMsWUFBTSxZQUFZLGdCQUFnQixTQUFTLFFBQVE7QUFBQSxRQUNsRCxNQUFNO0FBQUE7QUFFUCxZQUFNLFVBQVUsZ0JBQWdCLFNBQVM7QUFDekMsWUFBTSxhQUFhLGdCQUFnQjtBQUNuQyxZQUFNLFdBQVcsV0FBVztBQUM1QixZQUFNLFlBQVksV0FBVztBQUM3QixZQUFNLG9CQUFvQixTQUFTLFNBQVMsVUFBVTtBQUFBLFFBQ3JELE1BQU07QUFBQTtBQUVQLFlBQU0scUJBQXFCLFNBQVMsU0FBUyxVQUFVO0FBQUEsUUFDdEQsTUFBTTtBQUFBO0FBRVAsWUFBTSxrQkFBa0IsU0FBUyxTQUFTLFVBQVU7QUFBQSxRQUNuRCxNQUFNO0FBQUE7QUFFUCxlQUFTLE1BQU0sVUFBVTtBQUN6QixnQkFBVSxNQUFNLFVBQVU7QUFFMUIsWUFBTSxhQUFhLFVBQVUsU0FBUyxTQUFTO0FBQUEsUUFDOUMsYUFBYTtBQUFBLFFBQ2IsTUFBTTtBQUFBO0FBRVAs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
|