commit
366507604a
7 changed files with 269 additions and 52 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,9 +1,12 @@
|
|||
.vscode/*
|
||||
|
||||
# Key for embedding
|
||||
key.json
|
||||
|
||||
# NPM things
|
||||
package.json
|
||||
package-lock.json
|
||||
node_modules/
|
||||
|
||||
# Yarn things
|
||||
yarn.lock
|
||||
yarn.lock
|
||||
|
|
|
@ -299,7 +299,7 @@
|
|||
<button id="settings-btn-close" class="close"></button>
|
||||
</div>
|
||||
<div class="ui separator"></div>
|
||||
<iframe id="page-overlay" src="/pages/configuration.html"></iframe>
|
||||
<iframe id="page-overlay" src="pages/configuration.html"></iframe>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -345,5 +345,8 @@
|
|||
src="js/initalize/debug.populate.js"
|
||||
type="text/javascript"></script>
|
||||
<script src="js/initalize/ui.populate.js" type="text/javascript"></script>
|
||||
|
||||
<!-- Deals with webui communication -->
|
||||
<script src="js/webui.js" type="text/javascript"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
127
js/index.js
127
js/index.js
|
@ -1,6 +1,86 @@
|
|||
//TODO FIND OUT WHY I HAVE TO RESIZE A TEXTBOX AND THEN START USING IT TO AVOID THE 1px WHITE LINE ON LEFT EDGES DURING IMG2IMG
|
||||
//...lmao did setting min width 200 on info div fix that accidentally? once the canvas is infinite and the menu bar is hideable it'll probably be a problem again
|
||||
|
||||
/**
|
||||
* Workaround for Firefox bug #733698
|
||||
*
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=733698
|
||||
*
|
||||
* Workaround by https://github.com/subzey on https://gist.github.com/subzey/2030480
|
||||
*
|
||||
* Replaces and handles NS_ERROR_FAILURE errors triggered by 733698.
|
||||
*/
|
||||
(function () {
|
||||
var FakeTextMetrics,
|
||||
proto,
|
||||
fontSetterNative,
|
||||
measureTextNative,
|
||||
fillTextNative,
|
||||
strokeTextNative;
|
||||
|
||||
if (
|
||||
!window.CanvasRenderingContext2D ||
|
||||
!window.TextMetrics ||
|
||||
!(proto = window.CanvasRenderingContext2D.prototype) ||
|
||||
!proto.hasOwnProperty("font") ||
|
||||
!proto.hasOwnProperty("mozTextStyle") ||
|
||||
typeof proto.__lookupSetter__ !== "function" ||
|
||||
!(fontSetterNative = proto.__lookupSetter__("font"))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
proto.__defineSetter__("font", function (value) {
|
||||
try {
|
||||
return fontSetterNative.call(this, value);
|
||||
} catch (e) {
|
||||
if (e.name !== "NS_ERROR_FAILURE") {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
measureTextNative = proto.measureText;
|
||||
FakeTextMetrics = function () {
|
||||
this.width = 0;
|
||||
this.isFake = true;
|
||||
this.__proto__ = window.TextMetrics.prototype;
|
||||
};
|
||||
proto.measureText = function ($0) {
|
||||
try {
|
||||
return measureTextNative.apply(this, arguments);
|
||||
} catch (e) {
|
||||
if (e.name !== "NS_ERROR_FAILURE") {
|
||||
throw e;
|
||||
} else {
|
||||
return new FakeTextMetrics();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
fillTextNative = proto.fillText;
|
||||
proto.fillText = function ($0, $1, $2, $3) {
|
||||
try {
|
||||
fillTextNative.apply(this, arguments);
|
||||
} catch (e) {
|
||||
if (e.name !== "NS_ERROR_FAILURE") {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
strokeTextNative = proto.strokeText;
|
||||
proto.strokeText = function ($0, $1, $2, $3) {
|
||||
try {
|
||||
strokeTextNative.apply(this, arguments);
|
||||
} catch (e) {
|
||||
if (e.name !== "NS_ERROR_FAILURE") {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
window.onload = startup;
|
||||
|
||||
var stableDiffusionData = {
|
||||
|
@ -91,7 +171,7 @@ function startup() {
|
|||
? hostEl.value.substring(0, hostEl.value.length - 1)
|
||||
: hostEl.value;
|
||||
hostEl.value = host;
|
||||
localStorage.setItem("host", host);
|
||||
localStorage.setItem("openoutpaint/host", host);
|
||||
checkConnection();
|
||||
};
|
||||
});
|
||||
|
@ -112,7 +192,7 @@ function testHostConfiguration() {
|
|||
* Check host configuration
|
||||
*/
|
||||
const hostEl = document.getElementById("host");
|
||||
hostEl.value = localStorage.getItem("host");
|
||||
hostEl.value = localStorage.getItem("openoutpaint/host");
|
||||
|
||||
const requestHost = (prompt, def = "http://127.0.0.1:7860") => {
|
||||
let value = window.prompt(prompt, def);
|
||||
|
@ -121,12 +201,12 @@ function testHostConfiguration() {
|
|||
value = value.endsWith("/") ? value.substring(0, value.length - 1) : value;
|
||||
host = value;
|
||||
hostEl.value = host;
|
||||
localStorage.setItem("host", host);
|
||||
localStorage.setItem("openoutpaint/host", host);
|
||||
|
||||
testHostConfiguration();
|
||||
};
|
||||
|
||||
const current = localStorage.getItem("host");
|
||||
const current = localStorage.getItem("openoutpaint/host");
|
||||
if (current) {
|
||||
if (!current.match(/^https?:\/\/[a-z0-9][a-z0-9.]+[a-z0-9](:[0-9]+)?$/i))
|
||||
requestHost(
|
||||
|
@ -507,19 +587,19 @@ function changeMaskBlur() {
|
|||
stableDiffusionData.mask_blur = parseInt(
|
||||
document.getElementById("maskBlur").value
|
||||
);
|
||||
localStorage.setItem("mask_blur", stableDiffusionData.mask_blur);
|
||||
localStorage.setItem("openoutpaint/mask_blur", stableDiffusionData.mask_blur);
|
||||
}
|
||||
|
||||
function changeSeed() {
|
||||
stableDiffusionData.seed = document.getElementById("seed").value;
|
||||
localStorage.setItem("seed", stableDiffusionData.seed);
|
||||
localStorage.setItem("openoutpaint/seed", stableDiffusionData.seed);
|
||||
}
|
||||
|
||||
function changeHiResFix() {
|
||||
stableDiffusionData.enable_hr = Boolean(
|
||||
document.getElementById("cbxHRFix").checked
|
||||
);
|
||||
localStorage.setItem("enable_hr", stableDiffusionData.enable_hr);
|
||||
localStorage.setItem("openoutpaint/enable_hr", stableDiffusionData.enable_hr);
|
||||
}
|
||||
|
||||
function changeSyncCursorSize() {
|
||||
|
@ -800,7 +880,10 @@ function changeStyles() {
|
|||
});
|
||||
}
|
||||
|
||||
localStorage.setItem("promptStyle", JSON.stringify(selectedString));
|
||||
localStorage.setItem(
|
||||
"openoutpaint/promptStyle",
|
||||
JSON.stringify(selectedString)
|
||||
);
|
||||
|
||||
// change the model
|
||||
if (selectedString.length > 0)
|
||||
|
@ -821,16 +904,16 @@ async function getSamplers() {
|
|||
}));
|
||||
|
||||
// Initial sampler
|
||||
if (localStorage.getItem("sampler") != null) {
|
||||
samplerAutoComplete.value = localStorage.getItem("sampler");
|
||||
if (localStorage.getItem("openoutpaint/sampler") != null) {
|
||||
samplerAutoComplete.value = localStorage.getItem("openoutpaint/sampler");
|
||||
} else {
|
||||
samplerAutoComplete.value = data[0].name;
|
||||
localStorage.setItem("sampler", samplerAutoComplete.value);
|
||||
localStorage.setItem("openoutpaint/sampler", samplerAutoComplete.value);
|
||||
}
|
||||
|
||||
samplerAutoComplete.onchange.on(({value}) => {
|
||||
stableDiffusionData.sampler_index = value;
|
||||
localStorage.setItem("sampler", value);
|
||||
localStorage.setItem("openoutpaint/sampler", value);
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn("[index] Failed to fetch samplers");
|
||||
|
@ -841,8 +924,8 @@ async function upscaleAndDownload() {
|
|||
// Future improvements: some upscalers take a while to upscale, so we should show a loading bar or something, also a slider for the upscale amount
|
||||
|
||||
// get cropped canvas, send it to upscaler, download result
|
||||
var upscale_factor = localStorage.getItem("upscale_x")
|
||||
? localStorage.getItem("upscale_x")
|
||||
var upscale_factor = localStorage.getItem("openoutpaint/upscale_x")
|
||||
? localStorage.getItem("openoutpaint/upscale_x")
|
||||
: 2;
|
||||
var upscaler = upscalerAutoComplete.value;
|
||||
var croppedCanvas = cropCanvas(
|
||||
|
@ -896,21 +979,23 @@ async function upscaleAndDownload() {
|
|||
function loadSettings() {
|
||||
// set default values if not set
|
||||
var _mask_blur =
|
||||
localStorage.getItem("mask_blur") == null
|
||||
localStorage.getItem("openoutpaint/mask_blur") == null
|
||||
? 0
|
||||
: localStorage.getItem("mask_blur");
|
||||
: localStorage.getItem("openoutpaint/mask_blur");
|
||||
var _seed =
|
||||
localStorage.getItem("seed") == null ? -1 : localStorage.getItem("seed");
|
||||
localStorage.getItem("openoutpaint/seed") == null
|
||||
? -1
|
||||
: localStorage.getItem("openoutpaint/seed");
|
||||
|
||||
let _enable_hr =
|
||||
localStorage.getItem("enable_hr") === null
|
||||
localStorage.getItem("openoutpaint/enable_hr") === null
|
||||
? false
|
||||
: localStorage.getItem("enable_hr") === "true";
|
||||
: localStorage.getItem("openoutpaint/enable_hr") === "true";
|
||||
|
||||
let _sync_cursor_size =
|
||||
localStorage.getItem("sync_cursor_size") === null
|
||||
localStorage.getItem("openoutpaint/sync_cursor_size") === null
|
||||
? true
|
||||
: localStorage.getItem("sync_cursor_size") === "true";
|
||||
: localStorage.getItem("openoutpaint/sync_cursor_size") === "true";
|
||||
|
||||
// set the values into the UI
|
||||
document.getElementById("maskBlur").value = Number(_mask_blur);
|
||||
|
|
|
@ -3,10 +3,14 @@ const imageCollection = layers.registerCollection(
|
|||
"image",
|
||||
{
|
||||
w: parseInt(
|
||||
(localStorage && localStorage.getItem("settings.canvas-width")) || 2048
|
||||
(localStorage &&
|
||||
localStorage.getItem("openoutpaint/settings.canvas-width")) ||
|
||||
2048
|
||||
),
|
||||
h: parseInt(
|
||||
(localStorage && localStorage.getItem("settings.canvas-height")) || 2048
|
||||
(localStorage &&
|
||||
localStorage.getItem("openoutpaint/settings.canvas-height")) ||
|
||||
2048
|
||||
),
|
||||
},
|
||||
{
|
||||
|
@ -57,7 +61,7 @@ const uiCtx = uiCanvas.getContext("2d", {desynchronized: true});
|
|||
* Here we setup canvas dynamic scaling
|
||||
*/
|
||||
(() => {
|
||||
let expandSize = localStorage.getItem("expand-size") || 1024;
|
||||
let expandSize = localStorage.getItem("openoutpaint/expand-size") || 1024;
|
||||
expandSize = parseInt(expandSize, 10);
|
||||
|
||||
const askSize = () => {
|
||||
|
@ -66,7 +70,7 @@ const uiCtx = uiCanvas.getContext("2d", {desynchronized: true});
|
|||
if (!by) return null;
|
||||
else {
|
||||
const len = parseInt(by, 10);
|
||||
localStorage.setItem("expand-size", len);
|
||||
localStorage.setItem("openoutpaint/expand-size", len);
|
||||
expandSize = len;
|
||||
return len;
|
||||
}
|
||||
|
|
26
js/prompt.js
26
js/prompt.js
|
@ -20,8 +20,8 @@ async function getStyles() {
|
|||
/** @type {string[]} */
|
||||
let stored = null;
|
||||
try {
|
||||
stored = JSON.parse(localStorage.getItem("promptStyle"));
|
||||
// doesn't seem to throw a syntaxerror if the localstorage item simply doesn't exist?
|
||||
stored = JSON.parse(localStorage.getItem("openoutpaint/promptStyle"));
|
||||
// doesn't seem to throw a syntaxerror if the localStorage item simply doesn't exist?
|
||||
if (stored == null) stored = [];
|
||||
} catch (e) {
|
||||
stored = [];
|
||||
|
@ -40,11 +40,14 @@ async function getStyles() {
|
|||
selected = value;
|
||||
}
|
||||
stableDiffusionData.styles = selected;
|
||||
localStorage.setItem("promptStyle", JSON.stringify(selected));
|
||||
localStorage.setItem(
|
||||
"openoutpaint/promptStyle",
|
||||
JSON.stringify(selected)
|
||||
);
|
||||
});
|
||||
|
||||
styleSelectElement.value = stored;
|
||||
localStorage.setItem("promptStyle", JSON.stringify(stored));
|
||||
localStorage.setItem("openoutpaint/promptStyle", JSON.stringify(stored));
|
||||
} catch (e) {
|
||||
console.warn("[index] Failed to fetch prompt styles");
|
||||
console.warn(e);
|
||||
|
@ -66,18 +69,21 @@ async function getStyles() {
|
|||
promptEl.oninput = () => {
|
||||
stableDiffusionData.prompt = promptEl.value;
|
||||
promptEl.title = promptEl.value;
|
||||
localStorage.setItem("prompt", stableDiffusionData.prompt);
|
||||
localStorage.setItem("openoutpaint/prompt", stableDiffusionData.prompt);
|
||||
};
|
||||
|
||||
negativePromptEl.oninput = () => {
|
||||
stableDiffusionData.negative_prompt = negativePromptEl.value;
|
||||
negativePromptEl.title = negativePromptEl.value;
|
||||
localStorage.setItem("neg_prompt", stableDiffusionData.negative_prompt);
|
||||
localStorage.setItem(
|
||||
"openoutpaint/neg_prompt",
|
||||
stableDiffusionData.negative_prompt
|
||||
);
|
||||
};
|
||||
|
||||
// Load from local storage if set
|
||||
const storedPrompt = localStorage.getItem("prompt");
|
||||
const storedNeg = localStorage.getItem("neg_prompt");
|
||||
const storedPrompt = localStorage.getItem("openoutpaint/prompt");
|
||||
const storedNeg = localStorage.getItem("openoutpaint/neg_prompt");
|
||||
const promptDefaultValue =
|
||||
storedPrompt === null ? defaultPrompt : storedPrompt;
|
||||
const negativePromptDefaultValue =
|
||||
|
@ -137,7 +143,7 @@ async function getStyles() {
|
|||
stableDiffusionData.prompt = prompt;
|
||||
promptEl.title = prompt;
|
||||
promptEl.value = prompt;
|
||||
localStorage.setItem("prompt", prompt);
|
||||
localStorage.setItem("openoutpaint/prompt", prompt);
|
||||
});
|
||||
promptBtn.textContent = (samePrompt ? "= " : "") + prompt;
|
||||
|
||||
|
@ -147,7 +153,7 @@ async function getStyles() {
|
|||
stableDiffusionData.negative_prompt = negative;
|
||||
negativePromptEl.title = negative;
|
||||
negativePromptEl.value = negative;
|
||||
localStorage.setItem("neg_prompt", negative);
|
||||
localStorage.setItem("openoutpaint/neg_prompt", negative);
|
||||
});
|
||||
negativeBtn.textContent = (sameNegativePrompt ? "= " : "") + negative;
|
||||
|
||||
|
|
109
js/webui.js
Normal file
109
js/webui.js
Normal file
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* This file should only be actually loaded if we are in a trusted environment.
|
||||
*/
|
||||
(async () => {
|
||||
// Check if key file exists
|
||||
const response = await fetch("key.json");
|
||||
|
||||
/** @type {{host?: string, trusted?: boolean, key: string}} */
|
||||
let data = null;
|
||||
if (response.status === 200) {
|
||||
data = await response.json();
|
||||
console.info("[webui] key.json loaded successfully");
|
||||
}
|
||||
if (response.status !== 200 || (!data.key && !data.trusted)) {
|
||||
console.warn(
|
||||
"[webui] An accessible key.json file with a 'key' or 'trusted' should be provided to allow for messaging"
|
||||
);
|
||||
console.warn(data);
|
||||
return;
|
||||
}
|
||||
|
||||
const key = data.key;
|
||||
|
||||
// Check if we are running inside an iframe or embed
|
||||
try {
|
||||
const frame = window.frameElement;
|
||||
|
||||
if (frame === null) {
|
||||
console.info("[webui] Not running inside a frame");
|
||||
} else {
|
||||
console.info(
|
||||
`[webui] Window is child of '${window.parent.document.URL}'`
|
||||
);
|
||||
if (data.host && !window.parent.document.URL.startsWith(data.host)) {
|
||||
console.warn(
|
||||
`[webui] Window does not trust parent '${window.parent.document.URL}'`
|
||||
);
|
||||
console.warn("[webui] Will NOT setup message listeners");
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`[webui] Running in a third party iframe or embed, and blocked by CORS`
|
||||
);
|
||||
console.warn(e);
|
||||
return;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
let parentWindow = null;
|
||||
|
||||
if (!data.trusted) console.debug(`[webui] Loaded key`);
|
||||
|
||||
window.addEventListener("message", ({data, origin, source}) => {
|
||||
if (!data.trusted && data.key !== key) {
|
||||
console.warn(
|
||||
`[webui] Message with incorrect key was received from '${origin}'`
|
||||
);
|
||||
console.warn(data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parentWindow && !data.type === "openoutpaint/init") {
|
||||
console.warn(`[webui] Communication has not been initialized`);
|
||||
}
|
||||
|
||||
try {
|
||||
switch (data.type) {
|
||||
case "openoutpaint/init":
|
||||
parentWindow = source;
|
||||
console.debug(
|
||||
`[webui] Communication with '${origin}' has been initialized`
|
||||
);
|
||||
break;
|
||||
case "openoutpaint/add-resource":
|
||||
{
|
||||
const image = document.createElement("img");
|
||||
image.src = data.image.dataURL;
|
||||
image.onload = async () => {
|
||||
await tools.stamp.state.addResource(
|
||||
data.image.resourceName || "External Resource",
|
||||
image
|
||||
);
|
||||
tools.stamp.enable();
|
||||
};
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.warn(`[webui] Unsupported message type: ${data.type}`);
|
||||
break;
|
||||
}
|
||||
|
||||
// Send acknowledgement
|
||||
parentWindow &&
|
||||
parentWindow.postMessage({
|
||||
type: "openoutpaint/ack",
|
||||
message: data,
|
||||
});
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
`[webui] Message of type '${data.type}' has invalid format`
|
||||
);
|
||||
console.warn(e);
|
||||
console.warn(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
|
@ -4,22 +4,22 @@
|
|||
<meta charset="utf-8" />
|
||||
<title>openOutpaint 🐠</title>
|
||||
<!-- CSS Variables -->
|
||||
<link href="/css/colors.css" rel="stylesheet" />
|
||||
<link href="/css/icons.css" rel="stylesheet" />
|
||||
<link href="../css/colors.css" rel="stylesheet" />
|
||||
<link href="../css/icons.css" rel="stylesheet" />
|
||||
|
||||
<link href="/css/index.css" rel="stylesheet" />
|
||||
<link href="/css/layers.css" rel="stylesheet" />
|
||||
<link href="../css/index.css" rel="stylesheet" />
|
||||
<link href="../css/layers.css" rel="stylesheet" />
|
||||
|
||||
<link href="/css/ui/generic.css" rel="stylesheet" />
|
||||
<link href="../css/ui/generic.css" rel="stylesheet" />
|
||||
|
||||
<link href="/css/ui/history.css" rel="stylesheet" />
|
||||
<link href="/css/ui/layers.css" rel="stylesheet" />
|
||||
<link href="/css/ui/toolbar.css" rel="stylesheet" />
|
||||
<link href="../css/ui/history.css" rel="stylesheet" />
|
||||
<link href="../css/ui/layers.css" rel="stylesheet" />
|
||||
<link href="../css/ui/toolbar.css" rel="stylesheet" />
|
||||
|
||||
<!-- Tool Specific CSS -->
|
||||
<link href="/css/ui/tool/dream.css" rel="stylesheet" />
|
||||
<link href="/css/ui/tool/stamp.css" rel="stylesheet" />
|
||||
<link href="/css/ui/tool/colorbrush.css" rel="stylesheet" />
|
||||
<link href="../css/ui/tool/dream.css" rel="stylesheet" />
|
||||
<link href="../css/ui/tool/stamp.css" rel="stylesheet" />
|
||||
<link href="../css/ui/tool/colorbrush.css" rel="stylesheet" />
|
||||
|
||||
<link rel="icon" type="image/x-icon" href="favicon.ico" />
|
||||
|
||||
|
@ -65,14 +65,21 @@
|
|||
const canvasHeight = document.getElementById("canvas-height");
|
||||
|
||||
function writeToLocalStorage() {
|
||||
localStorage.setItem("settings.canvas-width", canvasWidth.value);
|
||||
localStorage.setItem("settings.canvas-height", canvasHeight.value);
|
||||
localStorage.setItem(
|
||||
"openoutpaint/settings.canvas-width",
|
||||
canvasWidth.value
|
||||
);
|
||||
localStorage.setItem(
|
||||
"openoutpaint/settings.canvas-height",
|
||||
canvasHeight.value
|
||||
);
|
||||
}
|
||||
|
||||
// Loads values from local storage
|
||||
canvasWidth.value = localStorage.getItem("settings.canvas-width") || 2048;
|
||||
canvasWidth.value =
|
||||
localStorage.getItem("openoutpaint/settings.canvas-width") || 2048;
|
||||
canvasHeight.value =
|
||||
localStorage.getItem("settings.canvas-height") || 2048;
|
||||
localStorage.getItem("openoutpaint/settings.canvas-height") || 2048;
|
||||
|
||||
writeToLocalStorage();
|
||||
|
||||
|
|
Loading…
Reference in a new issue