diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 0000000000000000000000000000000000000000..66e47f98033efe1121f5761de68113c15d320fa9
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,11 @@
+# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/codespaces-linux/.devcontainer/base.Dockerfile
+
+FROM mcr.microsoft.com/vscode/devcontainers/universal:2-focal
+
+USER root
+
+COPY packages.txt /root/packages.txt
+RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
+ && xargs -r -a /root/packages.txt apt-get install -y
+
+USER codespace
\ No newline at end of file
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000000000000000000000000000000000000..a251cda29d931a8ce46fc06a0e046f2adf8cddae
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,35 @@
+{
+ "postCreateCommand": "oryx build -p virtualenv_name=.venv --log-file /tmp/oryx-build.log --manifest-dir /tmp || echo 'Could not auto-build. Skipping.' && make set-env",
+ "hostRequirements": {
+ "gpus": 1
+ },
+ "features": {
+ "ghcr.io/devcontainers/features/nvidia-cuda:1": {
+ "installCudnn": true
+ }
+ },
+ "build": {
+ "dockerfile": "Dockerfile"
+ },
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "GitHub.vscode-pull-request-github",
+ "bradlc.vscode-tailwindcss",
+ "svelte.svelte-vscode",
+ "csstools.postcss"
+ ]
+ }
+ },
+ "mounts": [
+ "source=codespaces-linux-var-lib-docker,target=/var/lib/docker,type=volume"
+ ],
+ "runArgs": [
+ "--cap-add=SYS_PTRACE",
+ "--security-opt",
+ "seccomp=unconfined",
+ "--privileged",
+ "--init"
+ ],
+ "remoteUser": "codespace"
+}
\ No newline at end of file
diff --git a/.devcontainer/packages.txt b/.devcontainer/packages.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f682f571cbb17c1e8fd86c367335bae446a77299
--- /dev/null
+++ b/.devcontainer/packages.txt
@@ -0,0 +1,32 @@
+python3-opencv
+libopencv-dev
+libopencv-core-dev
+pkg-config
+libopencv-imgcodecs-dev
+libopencv-dev
+libopencv-contrib-dev
+build-essential
+cmake
+git
+pkg-config
+libgtk-3-dev
+libavcodec-dev
+libavformat-dev
+libswscale-dev
+libv4l-dev
+libxvidcore-dev
+libx264-dev
+libjpeg-dev
+libpng-dev
+libtiff-dev
+gfortran
+openexr
+libatlas-base-dev
+python3-dev
+python3-numpy
+libtbb2
+libtbb-dev
+libdc1394-22-dev
+libopenexr-dev
+libgstreamer-plugins-base1.0-dev
+libgstreamer1.0-dev
\ No newline at end of file
diff --git a/.devcontainer/setup-python-tools.sh b/.devcontainer/setup-python-tools.sh
new file mode 100644
index 0000000000000000000000000000000000000000..643b1ee52c1c9de36bc92aa72801925611c61841
--- /dev/null
+++ b/.devcontainer/setup-python-tools.sh
@@ -0,0 +1,64 @@
+#!/usr/bin/env bash
+
+set -e
+
+PYTHON=${1:-"python"}
+USERNAME=${2-"automatic"}
+
+# Make sure we run the command as non-root user
+sudoUserIf() {
+ if [ "$(id -u)" -eq 0 ] && [ "${USERNAME}" != "root" ]; then
+ sudo -u ${USERNAME} "$@"
+ else
+ "$@"
+ fi
+}
+
+installPythonPackage() {
+ PACKAGE=${1:-""}
+ VERSION=${2:-"latest"}
+
+ # pip skips installation if the package is already installed
+ echo "Installing $PACKAGE..."
+ if [ "${VERSION}" = "latest" ]; then
+ sudoUserIf ${PYTHON} -m pip install ${PACKAGE} --no-cache-dir
+ else
+ sudoUserIf ${PYTHON} -m pip install ${PACKAGE}=="${VERSION}" --no-cache-dir
+ fi
+}
+
+# If in automatic mode, determine if a user already exists, if not use vscode
+if [ "${USERNAME}" = "auto" ] || [ "${USERNAME}" = "automatic" ]; then
+ USERNAME=""
+ POSSIBLE_USERS=("vscode" "node" "codespace" "$(awk -v val=1000 -F ":" '$3==val{print $1}' /etc/passwd)")
+ for CURRENT_USER in ${POSSIBLE_USERS[@]}; do
+ if id -u ${CURRENT_USER} > /dev/null 2>&1; then
+ USERNAME=${CURRENT_USER}
+ break
+ fi
+ done
+ if [ "${USERNAME}" = "" ]; then
+ USERNAME=vscode
+ fi
+elif [ "${USERNAME}" = "none" ]; then
+ USERNAME=root
+ USER_UID=0
+ USER_GID=0
+fi
+
+# Make sure that Python is available
+if ! ${PYTHON} --version > /dev/null ; then
+ echo "You need to install Python before installing packages"
+ exit 1
+fi
+
+installPythonPackage "numpy" "latest"
+installPythonPackage "pandas" "latest"
+installPythonPackage "scipy" "latest"
+installPythonPackage "matplotlib" "latest"
+installPythonPackage "seaborn" "latest"
+installPythonPackage "scikit-learn" "latest"
+installPythonPackage "tensorflow" "latest"
+installPythonPackage "keras" "latest"
+installPythonPackage "torch" "latest"
+installPythonPackage "requests" "latest"
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000000000000000000000000000000000000..818d649bf21cdef29b21f885c8f770f9baa1714e
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,31 @@
+*.7z filter=lfs diff=lfs merge=lfs -text
+*.arrow filter=lfs diff=lfs merge=lfs -text
+*.bin filter=lfs diff=lfs merge=lfs -text
+*.bz2 filter=lfs diff=lfs merge=lfs -text
+*.ftz filter=lfs diff=lfs merge=lfs -text
+*.gz filter=lfs diff=lfs merge=lfs -text
+*.h5 filter=lfs diff=lfs merge=lfs -text
+*.joblib filter=lfs diff=lfs merge=lfs -text
+*.lfs.* filter=lfs diff=lfs merge=lfs -text
+*.model filter=lfs diff=lfs merge=lfs -text
+*.msgpack filter=lfs diff=lfs merge=lfs -text
+*.npy filter=lfs diff=lfs merge=lfs -text
+*.npz filter=lfs diff=lfs merge=lfs -text
+*.onnx filter=lfs diff=lfs merge=lfs -text
+*.ot filter=lfs diff=lfs merge=lfs -text
+*.parquet filter=lfs diff=lfs merge=lfs -text
+*.pickle filter=lfs diff=lfs merge=lfs -text
+*.pkl filter=lfs diff=lfs merge=lfs -text
+*.pb filter=lfs diff=lfs merge=lfs -text
+*.pt filter=lfs diff=lfs merge=lfs -text
+*.pth filter=lfs diff=lfs merge=lfs -text
+*.rar filter=lfs diff=lfs merge=lfs -text
+saved_model/**/* filter=lfs diff=lfs merge=lfs -text
+*.tar.* filter=lfs diff=lfs merge=lfs -text
+*.tflite filter=lfs diff=lfs merge=lfs -text
+*.tgz filter=lfs diff=lfs merge=lfs -text
+*.wasm filter=lfs diff=lfs merge=lfs -text
+*.xz filter=lfs diff=lfs merge=lfs -text
+*.zip filter=lfs diff=lfs merge=lfs -text
+*.zst filter=lfs diff=lfs merge=lfs -text
+*tfevents* filter=lfs diff=lfs merge=lfs -text
diff --git a/.github/workflows/size.yml b/.github/workflows/size.yml
new file mode 100644
index 0000000000000000000000000000000000000000..20a13c3c025a89bd507f0497d7e2d34ee2742fb6
--- /dev/null
+++ b/.github/workflows/size.yml
@@ -0,0 +1,16 @@
+name: Check file size
+on: # or directly `on: [push]` to run the action on every push on any branch
+ pull_request:
+ branches: [main]
+
+ # to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+jobs:
+ sync-to-hub:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Check large files
+ uses: ActionsDesk/lfs-warning@v2.0
+ with:
+ filesizelimit: 10485760 # this is 10MB so we can sync to HF Spaces
\ No newline at end of file
diff --git a/.github/workflows/sync.yml b/.github/workflows/sync.yml
new file mode 100644
index 0000000000000000000000000000000000000000..77f4f26b277f3d1447728760d56bc42feedcd5e2
--- /dev/null
+++ b/.github/workflows/sync.yml
@@ -0,0 +1,20 @@
+name: Sync to Hugging Face hub
+on:
+ push:
+ tags:
+ - '*'
+
+ # to run this workflow manually from the Actions tab
+ workflow_dispatch:
+
+jobs:
+ sync-to-hub:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ with:
+ fetch-depth: 0
+ - name: Push to hub
+ env:
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
+ run: git push https://radames:$HF_TOKEN@huggingface.co/spaces/huggingface-projects/stable-diffusion-multiplayer main --force
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e3b62af90d42bf1fde95bec032091ea065a32f1d
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,21 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
+venv/
+__pycache__/
+flagged/
+data
+data.db
+data.json
+rooms.db
+sd-multiplayer-data/
\ No newline at end of file
diff --git a/.nvmrc b/.nvmrc
new file mode 100644
index 0000000000000000000000000000000000000000..25bf17fc5aaabd17402e77a2b16f95fbea7310d2
--- /dev/null
+++ b/.nvmrc
@@ -0,0 +1 @@
+18
\ No newline at end of file
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000000000000000000000000000000000000..95b8441fca8c81ccbdf240b0a6992382e98a1084
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,6 @@
+{
+ "recommendations": [
+ "bradlc.vscode-tailwindcss",
+ "svelte.svelte-vscode"
+ ],
+}
\ No newline at end of file
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000000000000000000000000000000000000..55ec6c861e117958a741759c6d017c08640555ca
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "terminal.integrated.defaultProfile.linux": "zsh"
+}
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..00006b379cfa8e68b33a8a4ad9942617106f2242
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,12 @@
+set-env:
+ pip install -r requirements.txt
+ cd frontend && npm install && cp .env.development.example .env.development && cp .env.example .env
+build-client:
+ cd frontend && npm install && npm run build && rm -rf ../static && cp -r build/ ../static/
+build-dev:
+ cd frontend && npm install && npm run build-dev && rm -rf ../static && cp -r build/ ../static/
+run-front-dev:
+ cd frontend && npm install && npm run dev
+run-prod:
+ python app.py
+build-all: run-prod
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..effd294619cb4273874805d4f92d9f39a521329e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,14 @@
+---
+title: Stable Diffusion Multiplayer
+emoji: 👥⚙️🎨
+colorFrom: yellow
+colorTo: gray
+sdk: gradio
+sdk_version: 3.4
+app_file: run.py
+fullWidth: true
+pinned: false
+duplicated_from: huggingface-projects/stable-diffusion-multiplayer
+---
+
+Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
diff --git a/frontend/.env.development.example b/frontend/.env.development.example
new file mode 100644
index 0000000000000000000000000000000000000000..24559d3cb54ac92e8bcafb6ad671dcda96675d15
--- /dev/null
+++ b/frontend/.env.development.example
@@ -0,0 +1,3 @@
+PUBLIC_WS_INPAINTING="ws://0.0.0.0:7860/gradio/queue/join"
+PUBLIC_UPLOADS="https://d26smi9133w0oo.cloudfront.net"
+PUBLIC_API_BASE="/server/api"
\ No newline at end of file
diff --git a/frontend/.env.example b/frontend/.env.example
new file mode 100644
index 0000000000000000000000000000000000000000..e379e91824b15c244b8f543a69295af3c2ae0098
--- /dev/null
+++ b/frontend/.env.example
@@ -0,0 +1,3 @@
+PUBLIC_WS_INPAINTING="wss://spaces.huggingface.tech/huggingface-projects/stable-diffusion-multiplayer/gradio/queue/join"
+PUBLIC_UPLOADS="https://d26smi9133w0oo.cloudfront.net"
+PUBLIC_API_BASE="/api"
\ No newline at end of file
diff --git a/frontend/.eslintignore b/frontend/.eslintignore
new file mode 100644
index 0000000000000000000000000000000000000000..38972655faff07d2cc0383044bbf9f43b22c2248
--- /dev/null
+++ b/frontend/.eslintignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..3ccf435f02ce260ecb9b59ecfbb042c0dff1ea26
--- /dev/null
+++ b/frontend/.eslintrc.cjs
@@ -0,0 +1,20 @@
+module.exports = {
+ root: true,
+ parser: '@typescript-eslint/parser',
+ extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'],
+ plugins: ['svelte3', '@typescript-eslint'],
+ ignorePatterns: ['*.cjs'],
+ overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }],
+ settings: {
+ 'svelte3/typescript': () => require('typescript')
+ },
+ parserOptions: {
+ sourceType: 'module',
+ ecmaVersion: 2020
+ },
+ env: {
+ browser: true,
+ es2017: true,
+ node: true
+ }
+};
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..c24b60bf42cdf67f4d227ea610bae07f26d74b49
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1,12 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+.vercel
+.output
+venv/
+__pycache__/
\ No newline at end of file
diff --git a/frontend/.npmrc b/frontend/.npmrc
new file mode 100644
index 0000000000000000000000000000000000000000..b6f27f135954640c8cc5bfd7b8c9922ca6eb2aad
--- /dev/null
+++ b/frontend/.npmrc
@@ -0,0 +1 @@
+engine-strict=true
diff --git a/frontend/.prettierignore b/frontend/.prettierignore
new file mode 100644
index 0000000000000000000000000000000000000000..38972655faff07d2cc0383044bbf9f43b22c2248
--- /dev/null
+++ b/frontend/.prettierignore
@@ -0,0 +1,13 @@
+.DS_Store
+node_modules
+/build
+/.svelte-kit
+/package
+.env
+.env.*
+!.env.example
+
+# Ignore files for PNPM, NPM and YARN
+pnpm-lock.yaml
+package-lock.json
+yarn.lock
diff --git a/frontend/.prettierrc b/frontend/.prettierrc
new file mode 100644
index 0000000000000000000000000000000000000000..d177cd62dd136ec70ff54638f5a17be7ed277ad0
--- /dev/null
+++ b/frontend/.prettierrc
@@ -0,0 +1,8 @@
+{
+ "useTabs": true,
+ "singleQuote": true,
+ "trailingComma": "none",
+ "printWidth": 100,
+ "pluginSearchDirs": ["."],
+ "overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
+}
diff --git a/frontend/README.md b/frontend/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..5c91169b0ca6508bb24301c957a9edea5abf2b01
--- /dev/null
+++ b/frontend/README.md
@@ -0,0 +1,38 @@
+# create-svelte
+
+Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/master/packages/create-svelte).
+
+## Creating a project
+
+If you're seeing this, you've probably already done this step. Congrats!
+
+```bash
+# create a new project in the current directory
+npm create svelte@latest
+
+# create a new project in my-app
+npm create svelte@latest my-app
+```
+
+## Developing
+
+Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
+
+```bash
+npm run dev
+
+# or start the server and open the app in a new browser tab
+npm run dev -- --open
+```
+
+## Building
+
+To create a production version of your app:
+
+```bash
+npm run build
+```
+
+You can preview the production build with `npm run preview`.
+
+> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..8cecf989e5f350219601e38b3e029868ba6c30ef
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,52 @@
+{
+ "name": "frontend",
+ "version": "0.0.1",
+ "scripts": {
+ "dev": "NODE_ENV=development vite --config vite.config.dev.ts dev",
+ "build-dev": "vite build --mode development",
+ "build": "vite build",
+ "preview": "vite preview",
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
+ "lint": "prettier --check . && eslint .",
+ "format": "prettier --write ."
+ },
+ "devDependencies": {
+ "@sveltejs/adapter-static": "^1.0.0-next.43",
+ "@sveltejs/kit": "^1.0.0-next.504",
+ "@tailwindcss/forms": "^0.5.3",
+ "@tailwindcss/line-clamp": "^0.4.2",
+ "@types/cookie": "^0.5.1",
+ "@types/d3-array": "^3.0.3",
+ "@types/d3-drag": "^3.0.1",
+ "@types/d3-selection": "^3.0.3",
+ "@types/d3-zoom": "^3.0.1",
+ "@typescript-eslint/eslint-plugin": "^5.38.0",
+ "@typescript-eslint/parser": "^5.38.0",
+ "autoprefixer": "^10.4.12",
+ "d3-scale": "^4.0.2",
+ "eslint": "^8.24.0",
+ "eslint-config-prettier": "^8.3.0",
+ "eslint-plugin-svelte3": "^4.0.0",
+ "postcss": "^8.4.16",
+ "prettier": "^2.6.2",
+ "prettier-plugin-svelte": "^2.7.1",
+ "svelte": "^3.46.0",
+ "svelte-check": "^2.9.1",
+ "svelte-preprocess": "^4.10.7",
+ "tailwindcss": "^3.1.8",
+ "tslib": "^2.3.1",
+ "typescript": "^4.7.4",
+ "vite": "^3.1.3"
+ },
+ "type": "module",
+ "dependencies": {
+ "@fontsource/fira-mono": "^4.5.0",
+ "@liveblocks/client": "^0.18.2",
+ "d3-array": "^3.2.0",
+ "d3-drag": "^3.0.0",
+ "d3-selection": "^3.0.0",
+ "d3-zoom": "^3.0.0",
+ "nanoid": "^4.0.0"
+ }
+}
diff --git a/frontend/postcss.config.cjs b/frontend/postcss.config.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..33ad091d26d8a9dc95ebdf616e217d985ec215b8
--- /dev/null
+++ b/frontend/postcss.config.cjs
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/frontend/src/app.css b/frontend/src/app.css
new file mode 100644
index 0000000000000000000000000000000000000000..2a426e9f12c93e5a53be15ac59c24639845f0552
--- /dev/null
+++ b/frontend/src/app.css
@@ -0,0 +1,25 @@
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
+
+/* Firefox */
+.x-scroll {
+ scrollbar-width: thin;
+ scrollbar-color: white #2F6DCB;
+}
+
+/* Chrome, Edge, and Safari */
+.x-scroll::-webkit-scrollbar {
+ width: 4px;
+}
+
+.x-scroll::-webkit-scrollbar-track {
+ background: white;
+ border-radius: 100px;
+}
+
+.x-scroll::-webkit-scrollbar-thumb {
+ background-color: #2F6DCB;
+ border-radius: 100px;
+ border: 2px solid #2F6DCB;
+}
\ No newline at end of file
diff --git a/frontend/src/app.d.ts b/frontend/src/app.d.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6df70db5c4696c94d65be78ccbf74df42f85ec9c
--- /dev/null
+++ b/frontend/src/app.d.ts
@@ -0,0 +1,29 @@
+// See https://kit.svelte.dev/docs/types#app
+// for information about these interfaces
+// and what to do when importing types
+import type { ZoomTransform } from 'd3-zoom';
+
+declare global {
+ namespace App {
+ // interface Locals {}
+ // interface PageData {}
+ // interface Platform {}
+ interface Window {
+ parentIFrame: unknown;
+ }
+ }
+ interface Error {
+ code: number;
+ }
+ interface Event {
+ relatedTarget: EventTarget | null;
+ transform: ZoomTransform;
+ x: number;
+ y: number;
+ subject: {
+ x: number;
+ y: number;
+ }
+ sourceEvent: PointerEvent | MouseEvent | TouchEvent
+ }
+}
diff --git a/frontend/src/app.html b/frontend/src/app.html
new file mode 100644
index 0000000000000000000000000000000000000000..fc38e90b871bdfb71da4f91243c7d2552149ab58
--- /dev/null
+++ b/frontend/src/app.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+ %sveltekit.head%
+
+
+ %sveltekit.body%
+
+
+
\ No newline at end of file
diff --git a/frontend/src/lib/About.svelte b/frontend/src/lib/About.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..b26df909f9f091f9ebd623e9eab8e0ede8d3674c
--- /dev/null
+++ b/frontend/src/lib/About.svelte
@@ -0,0 +1,67 @@
+
+
+
+
+
+
Stable Difussion Multiplayer
+
+
+
diff --git a/frontend/src/lib/App.svelte b/frontend/src/lib/App.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..0ca63124a168c62fde744fb7a6f80f507fa09b04
--- /dev/null
+++ b/frontend/src/lib/App.svelte
@@ -0,0 +1,240 @@
+
+
+
+
+ {$loadingState}
+
+{#if showModal}
+
+{/if}
+
+
+
+
+
+ {#if $others}
+ {#each [...$others] as { connectionId, presence } (connectionId)}
+ {#if (presence?.status === Status.loading || presence?.status === Status.prompting || presence?.status === Status.masking) && presence?.frame}
+
+ {/if}
+ {#if presence?.cursor}
+
+ {/if}
+ {/each}
+ {/if}
+
+
+
+
+
+
+
+
diff --git a/frontend/src/lib/Buttons/AboutButton.svelte b/frontend/src/lib/Buttons/AboutButton.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..36c0d00b9ffa6333939f2c84548f3a58c0a6880d
--- /dev/null
+++ b/frontend/src/lib/Buttons/AboutButton.svelte
@@ -0,0 +1,43 @@
+
+
+
+
+ More
+
+ Instructions: move the blue square,
+ click "🖍 Paint".
+
+
+
+
diff --git a/frontend/src/lib/Buttons/DragButton.svelte b/frontend/src/lib/Buttons/DragButton.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..26b13d7e193c92676663c384bbb90c82882a39f0
--- /dev/null
+++ b/frontend/src/lib/Buttons/DragButton.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/frontend/src/lib/Buttons/MaskButton.svelte b/frontend/src/lib/Buttons/MaskButton.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..6968a2828ea0b274bd3232d57a7777e6aebf22ef
--- /dev/null
+++ b/frontend/src/lib/Buttons/MaskButton.svelte
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/frontend/src/lib/Buttons/PPButton.svelte b/frontend/src/lib/Buttons/PPButton.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..095afc2dcf3b3b46d4b2df7d8b396287bbebfdac
--- /dev/null
+++ b/frontend/src/lib/Buttons/PPButton.svelte
@@ -0,0 +1,29 @@
+
+
+
+
+
diff --git a/frontend/src/lib/Buttons/RoomsSelector.svelte b/frontend/src/lib/Buttons/RoomsSelector.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..519bf4038bd81edf72d14f1d33d0ddf366a22100
--- /dev/null
+++ b/frontend/src/lib/Buttons/RoomsSelector.svelte
@@ -0,0 +1,136 @@
+
+
+
+
+ {#if loadingRooms && selectedRoom}
+
+ {#if !collapsed}
+
+ {/if}
+
+
(isLoading ? null : (collapsed = !collapsed))}
+ >
+ {#if selectedRoom}
+
+
+
+ {selectedRoom?.room_id}
+
+
+
+
+ {selectedRoom?.users_count} / {MAX_CAPACITY}
+
+
+ {:else}
+
+
+
+ Loading...
+
+ ... / ...
+
+
+ {/if}
+
+
+ {:else}
+
+ loading rooms
+
+ {/if}
+
+
+
diff --git a/frontend/src/lib/Buttons/ShareWithCommunity.svelte b/frontend/src/lib/Buttons/ShareWithCommunity.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..6b8cea3b5e2746bdce83676e30c761beec18af18
--- /dev/null
+++ b/frontend/src/lib/Buttons/ShareWithCommunity.svelte
@@ -0,0 +1,80 @@
+
+
+
+
diff --git a/frontend/src/lib/Buttons/UndoButton.svelte b/frontend/src/lib/Buttons/UndoButton.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..0911581e2554c9f57d9ef2152c1ef822fede63ed
--- /dev/null
+++ b/frontend/src/lib/Buttons/UndoButton.svelte
@@ -0,0 +1,20 @@
+
+
+
+
+
diff --git a/frontend/src/lib/Cursor.svelte b/frontend/src/lib/Cursor.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..01edf3cfa3f3ae254de526c9bcdedc86eedb6d98
--- /dev/null
+++ b/frontend/src/lib/Cursor.svelte
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
diff --git a/frontend/src/lib/Frame.svelte b/frontend/src/lib/Frame.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..eb24e7280643c3e333d921e926fc0a4ab336766d
--- /dev/null
+++ b/frontend/src/lib/Frame.svelte
@@ -0,0 +1,39 @@
+
+
+
+
+
+ {#if status === Status.loading || status === Status.processing}
+
+
Someone is painting:
+ {:else if status === Status.masking}
+
Someone is masking
+ {:else if status === Status.prompting}
+
Someone is typing:
+ {/if}
+ {#if prompt}
+
"{prompt}"
+ {/if}
+
+
+
diff --git a/frontend/src/lib/Icons/Cursor.svelte b/frontend/src/lib/Icons/Cursor.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..642d3439a119362610595a82c329a0f809ae6d8b
--- /dev/null
+++ b/frontend/src/lib/Icons/Cursor.svelte
@@ -0,0 +1,24 @@
+
+
+
diff --git a/frontend/src/lib/Icons/IconCommunity.svelte b/frontend/src/lib/Icons/IconCommunity.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..1598a86853b16a80dac239aecf5002d49491e951
--- /dev/null
+++ b/frontend/src/lib/Icons/IconCommunity.svelte
@@ -0,0 +1,25 @@
+
+
+
diff --git a/frontend/src/lib/Icons/LiveBlocks.svelte b/frontend/src/lib/Icons/LiveBlocks.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..bb3a756f83e5e1f3598d6f5354f708df7aa5ffa9
--- /dev/null
+++ b/frontend/src/lib/Icons/LiveBlocks.svelte
@@ -0,0 +1,117 @@
+
+
+
diff --git a/frontend/src/lib/Icons/LoadingIcon.svelte b/frontend/src/lib/Icons/LoadingIcon.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..063b65f64a63675f3650a9aabed01127a1063489
--- /dev/null
+++ b/frontend/src/lib/Icons/LoadingIcon.svelte
@@ -0,0 +1,23 @@
+
+
+
diff --git a/frontend/src/lib/Icons/Mask.svelte b/frontend/src/lib/Icons/Mask.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..2fc31874230f1c09e8ad2744c86cdf92cc9b8682
--- /dev/null
+++ b/frontend/src/lib/Icons/Mask.svelte
@@ -0,0 +1,17 @@
+
+
+
diff --git a/frontend/src/lib/Icons/Move.svelte b/frontend/src/lib/Icons/Move.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..e35a51241284ba87f30174e34328b2161d8f7809
--- /dev/null
+++ b/frontend/src/lib/Icons/Move.svelte
@@ -0,0 +1,20 @@
+
+
+
diff --git a/frontend/src/lib/Icons/People.svelte b/frontend/src/lib/Icons/People.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..8a991cf1c37a0bba8425e7e2d1d400dddafb1204
--- /dev/null
+++ b/frontend/src/lib/Icons/People.svelte
@@ -0,0 +1,29 @@
+
+
+
diff --git a/frontend/src/lib/Icons/Pin.svelte b/frontend/src/lib/Icons/Pin.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..11b60f89cdf716ab969f899f13162b0fad60737b
--- /dev/null
+++ b/frontend/src/lib/Icons/Pin.svelte
@@ -0,0 +1,16 @@
+
+
+
diff --git a/frontend/src/lib/Icons/Room.svelte b/frontend/src/lib/Icons/Room.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..c88815b4825615f416227ba7e0a8e6da3e78e741
--- /dev/null
+++ b/frontend/src/lib/Icons/Room.svelte
@@ -0,0 +1,16 @@
+
+
+
diff --git a/frontend/src/lib/Icons/Undo.svelte b/frontend/src/lib/Icons/Undo.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..58a60715bf5e8c9c452c2d612d9a1f002235b2f0
--- /dev/null
+++ b/frontend/src/lib/Icons/Undo.svelte
@@ -0,0 +1,21 @@
+
+
+
diff --git a/frontend/src/lib/Menu.svelte b/frontend/src/lib/Menu.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..f75b85953fb0fba720aa40ed8a561198d3fff410
--- /dev/null
+++ b/frontend/src/lib/Menu.svelte
@@ -0,0 +1,57 @@
+
+
+ {
+ if (e.key === 'Enter') {
+ dispatch('showModal', { showModal: true });
+ }
+ }}
+/>
+
+
{
+ $toggleAbout = !$toggleAbout;
+ }}
+ />
+
+
+
+
diff --git a/frontend/src/lib/PaintCanvas.svelte b/frontend/src/lib/PaintCanvas.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..b29bced450808a680347ca60a1263e0ba2b365fd
--- /dev/null
+++ b/frontend/src/lib/PaintCanvas.svelte
@@ -0,0 +1,284 @@
+
+
+
+
+
+
+
+
diff --git a/frontend/src/lib/PaintFrame.svelte b/frontend/src/lib/PaintFrame.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..ca27252c4d4e437420007cb64444bbbf03081f48
--- /dev/null
+++ b/frontend/src/lib/PaintFrame.svelte
@@ -0,0 +1,320 @@
+
+
+
+
+
+ {#if isLoading}
+
+ {/if}
+ {#if $myPresence?.status !== 'masking'}
+
+ {/if}
+
+
+ {#if prompt}
+
+ {prompt}
+
+ {/if}
+
+
+
+
toggleDrag()}
+ title="Enable dragging to move the frame"
+ >
+ {#if $loadingState !== ''}
+
+ {#if $loadingState === 'NFSW'}
+
NSFW Alert
+
+ Possible NSFW result detected, please try again
+
+ {/if}
+
{$loadingState}...
+
+ {:else}
+
{dragEnabled ? '🤚 Drag me' : '🤚 Enable Drag'}
+ {/if}
+
+
+
+ {#if !isLoading}
+
+
+
+
+ {/if}
+
+
+
+
+
+
+
diff --git a/frontend/src/lib/PromptModal.svelte b/frontend/src/lib/PromptModal.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..d24b7910c89bb3ec2526ec7e0be5efeeffe28fb5
--- /dev/null
+++ b/frontend/src/lib/PromptModal.svelte
@@ -0,0 +1,92 @@
+
+
+
diff --git a/frontend/src/lib/constants.ts b/frontend/src/lib/constants.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b2e5c7453d915b4110ae86eafd60f97862ab55ab
--- /dev/null
+++ b/frontend/src/lib/constants.ts
@@ -0,0 +1,21 @@
+export const COLORS = [
+ '#505669',
+ '#414AA6',
+ '#1C5B92',
+ '#216B44',
+ '#893301',
+ '#912728',
+ '#98184D',
+ '#743095',
+ '#5F4199',
+ '#8f3f94'
+];
+
+export const EMOJIS = ['🐝', '🐌', '🐞', '🐜', '🦋', '🐛', '🐝', '🐞', '🦟', '🦗', '🕷', '🦂', '🐢', '🐍', '🦎', '🦖', '🦕', '🐙', '🦑', '🐠', '🐟', '🐡', '🐬', '🦈', '🐳', '🐋', '🐊', '🐅', '🐆', '🦓', '🦍', '🦧', '🐘', '🦛', '🦏', '🐪', '🐫', '🦒', '🐃', '🐂', '🐄', '🐎', '🐖',
+ '🐏', '🐑', '🐐', '🐕', '🐩', '🐈', '🐓', '🦃', '🦅', '🦆', '🦢', '🦉', '🦚', '🦜', '🦇', '🐁', '🐀', '🐿', '🐇', '🐿', '🦔', '🦇', '🐻', '🐻', '🐨', '🐼', '🐵', '🙈', '🙉', '🙊', '🐒', '🐉', '🐲', '🦕', '🦖', '🐊', '🐢', '🦎', '🐍', '🐦', '🐧', '🦅', '🦆', '🦉', '🦇']
+
+export const MAX_CAPACITY = 50;
+
+export const GRID_SIZE = 32
+
+export const FRAME_SIZE = 512
\ No newline at end of file
diff --git a/frontend/src/lib/liveblocks/LiveblocksProvider.svelte b/frontend/src/lib/liveblocks/LiveblocksProvider.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..440663e97a99504e8b6a328daaec4c4302b01019
--- /dev/null
+++ b/frontend/src/lib/liveblocks/LiveblocksProvider.svelte
@@ -0,0 +1,19 @@
+
+
+
+
diff --git a/frontend/src/lib/liveblocks/RoomProvider.svelte b/frontend/src/lib/liveblocks/RoomProvider.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..c2a6d0dd8266043c486e5a8710ca1eb675dbfef0
--- /dev/null
+++ b/frontend/src/lib/liveblocks/RoomProvider.svelte
@@ -0,0 +1,32 @@
+
+
+
+
diff --git a/frontend/src/lib/liveblocks/index.ts b/frontend/src/lib/liveblocks/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6f403bc6800cac218c95b17e7321c11032e4baad
--- /dev/null
+++ b/frontend/src/lib/liveblocks/index.ts
@@ -0,0 +1,22 @@
+export * from "./symbols";
+export * from "./useUpdateMyPresence";
+export * from "./useMyPresence";
+export * from "./useOthers";
+export * from "./useObject";
+export * from "./useList";
+export * from "./useSelf";
+export * from "./useRoom";
+export * from "./useUndo";
+export * from "./useRedo";
+export * from "./useBatch";
+export * from "./useHistory";
+export * from "./useErrorListener";
+export * from "./useEventListener";
+export * from "./useBroadcastEvent";
+export * from "./useRooms";
+export * from "./useConnectionStatus"
+/**
+ * These components were built to (mostly) match the
+ * liveblocks-react library
+ * https://liveblocks.io/docs/api-reference/liveblocks-react
+ */
diff --git a/frontend/src/lib/liveblocks/symbols.ts b/frontend/src/lib/liveblocks/symbols.ts
new file mode 100644
index 0000000000000000000000000000000000000000..7eb097ebcb6cc7c02dddce6b93e42275785b6d1a
--- /dev/null
+++ b/frontend/src/lib/liveblocks/symbols.ts
@@ -0,0 +1,3 @@
+// Symbols are used for context to avoid polluting the global scope
+export const clientSymbol = Symbol();
+export const roomSymbol = Symbol();
diff --git a/frontend/src/lib/liveblocks/useBatch.ts b/frontend/src/lib/liveblocks/useBatch.ts
new file mode 100644
index 0000000000000000000000000000000000000000..01e661ed7f20823f9c96b94cdb9a5427ce49bb2a
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useBatch.ts
@@ -0,0 +1,15 @@
+// @ts-nocheck
+import { useRoom } from "./useRoom";
+
+/**
+ * Works similarly to `liveblocks-react` useBatch
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useBatch
+ *
+ * const batch = useBatch()
+ * batch(() => {
+ * // ...
+ * })
+ */
+export function useBatch() {
+ return useRoom().batch;
+}
diff --git a/frontend/src/lib/liveblocks/useBroadcastEvent.ts b/frontend/src/lib/liveblocks/useBroadcastEvent.ts
new file mode 100644
index 0000000000000000000000000000000000000000..10f99bd547dd6eb8c03a099db6578777e0f818f1
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useBroadcastEvent.ts
@@ -0,0 +1,17 @@
+
+import { useRoom } from "./useRoom";
+import type { Json, BroadcastOptions } from "@liveblocks/client";
+
+export function useBroadcastEvent(): (
+ event: TRoomEvent,
+ options?: BroadcastOptions
+) => void {
+ const room = useRoom();
+
+ return (
+ event: TRoomEvent,
+ options: BroadcastOptions = { shouldQueueEventIfNotReady: false }
+ ) => {
+ room.broadcastEvent(event, options);
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/lib/liveblocks/useConnectionStatus.ts b/frontend/src/lib/liveblocks/useConnectionStatus.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b80c7b284eca19488a58e57de0d1253482a6ea22
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useConnectionStatus.ts
@@ -0,0 +1,28 @@
+import { onDestroy } from "svelte";
+import { writable, type Writable } from "svelte/store";
+import { useRoom } from "./useRoom";
+
+
+enum ConnectionStatus {
+ "closed" = "closed",
+ "authenticating" = "authenticating",
+ "unavailable" = "unavailable",
+ "failed" = "failed",
+ "open" = "open",
+ "connecting" = "connecting",
+}
+type TConnectionStatus = keyof typeof ConnectionStatus
+
+export function useConnectionStatus(): Writable {
+ const room = useRoom();
+ const statusStorage = writable(ConnectionStatus.closed);
+
+ const unsubscribeConnection = room.subscribe("connection", (status: TConnectionStatus) => {
+ statusStorage.set(status);
+ });
+ onDestroy(() => {
+ unsubscribeConnection();
+ });
+
+ return statusStorage;
+}
diff --git a/frontend/src/lib/liveblocks/useErrorListener.ts b/frontend/src/lib/liveblocks/useErrorListener.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3bbba01c1a95744407135657ab399085054278ff
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useErrorListener.ts
@@ -0,0 +1,14 @@
+
+import { onDestroy } from "svelte";
+import { useRoom } from "./useRoom";
+
+
+export function useErrorListener(callback: (err: Error) => void): void {
+ const room = useRoom();
+
+ const unsubscribe = room.events.error.subscribe((e: Error) => callback(e))
+
+ onDestroy(() => {
+ unsubscribe();
+ });
+}
\ No newline at end of file
diff --git a/frontend/src/lib/liveblocks/useEventListener.ts b/frontend/src/lib/liveblocks/useEventListener.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3b67850b17e184be2d90357c8d4a201ea0bd1b55
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useEventListener.ts
@@ -0,0 +1,23 @@
+
+import { onDestroy } from "svelte";
+import { useRoom } from "./useRoom";
+import type { Json } from "@liveblocks/client";
+
+export function userEventListener(
+ callback: (eventData: { connectionId: number; event: TRoomEvent }) => void
+): void {
+ const room = useRoom();
+
+ const listener = (eventData: {
+ connectionId: number;
+ event: TRoomEvent;
+ }) => {
+ callback(eventData);
+ }
+
+ const unsubscribe = room.events.customEvent.subscribe(listener);
+
+ onDestroy(() => {
+ unsubscribe();
+ });
+}
diff --git a/frontend/src/lib/liveblocks/useHistory.ts b/frontend/src/lib/liveblocks/useHistory.ts
new file mode 100644
index 0000000000000000000000000000000000000000..01be14a93adb1e8b543635cafe468c1dc4b77c95
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useHistory.ts
@@ -0,0 +1,13 @@
+// @ts-nocheck
+/**
+ * Works similarly to `liveblocks-react` useHistory
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useHistory
+ *
+ * const history = useHistory()
+ * history.pause()
+ */
+import { useRoom } from "./useRoom";
+
+export function useHistory() {
+ return useRoom().history;
+}
diff --git a/frontend/src/lib/liveblocks/useList.ts b/frontend/src/lib/liveblocks/useList.ts
new file mode 100644
index 0000000000000000000000000000000000000000..bc9c8edd1c05332f304c1a033cf349fadd8daffa
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useList.ts
@@ -0,0 +1,47 @@
+// @ts-nocheck
+import { LiveList } from "@liveblocks/client";
+import { useStorage } from "./useStorage";
+import { onDestroy } from "svelte";
+import type { Writable } from "svelte/store";
+import { writable } from "svelte/store";
+import { useRoom } from "./useRoom";
+
+/**
+ * Works similarly to `liveblocks-react` useList
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useList
+ *
+ * The main difference is that it returns a Svelte store:
+ * const list = useList()
+ * $list.push([{ item: 1 }])
+ * console.log([...$list])
+ */
+export function useList(
+ name: string,
+ initial?: any[]
+): Writable> {
+ const room = useRoom();
+ const rootStore = useStorage();
+ const list = writable>();
+ let unsubscribe = () => {};
+
+ const unsubscribeRoot = rootStore.subscribe((root) => {
+ if (!root) {
+ return;
+ }
+
+ if (!root.get(name)) {
+ root.set(name, new LiveList(initial));
+ }
+
+ list.set(root.get(name));
+
+ unsubscribe();
+ unsubscribe = room.subscribe(root.get(name) as LiveList, (newList) => {
+ list.set(newList);
+ });
+ });
+
+ onDestroy(unsubscribeRoot);
+
+ return list;
+}
diff --git a/frontend/src/lib/liveblocks/useMyPresence.ts b/frontend/src/lib/liveblocks/useMyPresence.ts
new file mode 100644
index 0000000000000000000000000000000000000000..192b99f53e4e98c1d412ad24d38b4c6a2d737873
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useMyPresence.ts
@@ -0,0 +1,44 @@
+// @ts-nocheck
+import type { Presence } from "@liveblocks/client";
+import { onDestroy } from "svelte";
+import { writable } from "svelte/store";
+import { useRoom } from "./useRoom";
+
+/**
+ * Works similarly to `liveblocks-react` useMyPresence
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useMyPresence
+ *
+ * The main difference is that it returns a custom Svelte store:
+ * const presence = useMyPresence()
+ * presence.update({ name: 'Chris })
+ * console.log($presence.name)
+ * {$presence.count}
+ *
+ * USAGE NOTE:
+ * This is a custom Svelte store, `set` does nothing, only `update`.
+ * `update` does NOT take a function like regular Svelte stores,
+ * it takes an object and works like `useUpdateMyPresence` in Liveblocks
+ */
+
+export function useMyPresence(_options: { addToHistory: boolean } = {}) {
+ const room = useRoom();
+ const { subscribe, set } = writable();
+
+ function update(newPresence, options?: { addToHistory: boolean }
+ ) {
+ room.updatePresence(newPresence, { ..._options, ...options });
+ }
+
+ const unsubscribePresence = room.subscribe("my-presence", (presence) => {
+ set(presence);
+ });
+
+ onDestroy(() => {
+ unsubscribePresence();
+ });
+
+ return {
+ subscribe,
+ update,
+ };
+}
diff --git a/frontend/src/lib/liveblocks/useObject.ts b/frontend/src/lib/liveblocks/useObject.ts
new file mode 100644
index 0000000000000000000000000000000000000000..43e0c1a0faa2d5d558372aa828efdf933e0326d8
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useObject.ts
@@ -0,0 +1,44 @@
+// @ts-nocheck
+import { LiveObject } from "@liveblocks/client";
+import { useStorage } from "./useStorage";
+import { onDestroy } from "svelte";
+import type { Writable } from "svelte/store";
+import { writable } from "svelte/store";
+import { useRoom } from "./useRoom";
+
+/**
+ * Works similarly to `liveblocks-react` useObject
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useObject
+ *
+ * The main difference is that it returns a Svelte store:
+ * const obj = useObject()
+ * $obj.set('name', 'Chris')
+ * console.log($obj.get('name'))
+ */
+export function useObject(name: string, initial?: any): Writable {
+ const room = useRoom();
+ const rootStore = useStorage();
+ const list = writable();
+ let unsubscribe = () => {};
+
+ const unsubscribeRoot = rootStore.subscribe((root) => {
+ if (!root) {
+ return;
+ }
+
+ if (!root.get(name)) {
+ root.set(name, new LiveObject(initial));
+ }
+
+ list.set(root.get(name));
+
+ unsubscribe();
+ unsubscribe = room.subscribe(root.get(name) as LiveObject, (newObject) => {
+ list.set(newObject);
+ });
+ });
+
+ onDestroy(unsubscribeRoot);
+
+ return list;
+}
diff --git a/frontend/src/lib/liveblocks/useOthers.ts b/frontend/src/lib/liveblocks/useOthers.ts
new file mode 100644
index 0000000000000000000000000000000000000000..beca7469e592d5f7f56b6fab589a9ad67f153a47
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useOthers.ts
@@ -0,0 +1,29 @@
+// @ts-nocheck
+import type { Others } from "@liveblocks/client";
+import { onDestroy } from "svelte";
+import type { Writable } from "svelte/store";
+import { writable } from "svelte/store";
+import { useRoom } from "./useRoom";
+
+/**
+ * Works similarly to `liveblocks-react` useOthers
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useOthers
+ *
+ * The main difference is that it returns a Svelte store:
+ * const others = useOthers()
+ * console.log($others.value)
+ * {#each [...$others] as other}
+ * ...
+ */
+export function useOthers(): Writable {
+ const room = useRoom();
+ const others = writable();
+
+ const unsubscribe = room.subscribe("others", (newOthers) => {
+ others.set(newOthers);
+ });
+
+ onDestroy(unsubscribe);
+
+ return others;
+}
diff --git a/frontend/src/lib/liveblocks/useRedo.ts b/frontend/src/lib/liveblocks/useRedo.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f138eba3f112f6046e53e8c18c2771cef12f13d8
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useRedo.ts
@@ -0,0 +1,12 @@
+/**
+ * Works similarly to `liveblocks-react` useRedo
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useRedo
+ *
+ * const redo = useRedo()
+ * redo()
+ */
+import { useRoom } from "./useRoom";
+
+export function useRedo() {
+ return useRoom().history.redo;
+}
diff --git a/frontend/src/lib/liveblocks/useRoom.ts b/frontend/src/lib/liveblocks/useRoom.ts
new file mode 100644
index 0000000000000000000000000000000000000000..b2f7198d462bdffddfb6b6c53ddc33b688f3fd2b
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useRoom.ts
@@ -0,0 +1,22 @@
+// @ts-nocheck
+import { getContext } from "svelte";
+import type { Room } from "@liveblocks/client";
+import { roomSymbol } from "./symbols";
+
+/**
+ * Works similarly to `liveblocks-react` useRoom
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useRoom
+ *
+ * This does NOT return a Svelte store, just the plain room object
+ * const room = useRoom()
+ * room.history.undo()
+ */
+export function useRoom(): Room {
+ const room = getContext(roomSymbol);
+
+ if (!room) {
+ throw new Error("Use RoomProvider as parent with id prop");
+ }
+
+ return room;
+}
diff --git a/frontend/src/lib/liveblocks/useRooms.ts b/frontend/src/lib/liveblocks/useRooms.ts
new file mode 100644
index 0000000000000000000000000000000000000000..9e6f6d309a47597212f62150bd16ac4d50fc0c50
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useRooms.ts
@@ -0,0 +1,23 @@
+import { onDestroy } from "svelte";
+import { writable, type Writable } from "svelte/store";
+import type { RoomResponse } from '$lib/types';
+import { PUBLIC_API_BASE } from '$env/static/public';
+
+const INTERVAL = 10000
+
+export function useRooms(): Writable {
+ const roomsStorage = writable([]);
+
+ const interval = setInterval(
+ () => {
+ refreshRooms().then((rooms) => roomsStorage.set(rooms))
+ }, INTERVAL);
+ refreshRooms().then((rooms) => roomsStorage.set(rooms))
+ onDestroy(() => {
+ clearInterval(interval);
+ });
+ return roomsStorage
+}
+async function refreshRooms() {
+ return fetch(PUBLIC_API_BASE + '/rooms').then((res) => res.json());
+}
\ No newline at end of file
diff --git a/frontend/src/lib/liveblocks/useSelf.ts b/frontend/src/lib/liveblocks/useSelf.ts
new file mode 100644
index 0000000000000000000000000000000000000000..3adf9176712446acf11f581db5576fd41e40fcf8
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useSelf.ts
@@ -0,0 +1,32 @@
+import { onDestroy } from "svelte";
+import type { Writable } from "svelte/store";
+import { writable } from "svelte/store";
+import { useRoom } from "./useRoom";
+
+/**
+ * Works similarly to `liveblocks-react` useSelf
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useSelf
+ *
+ * The main difference is that it returns a Svelte store:
+ * const self = useSelf()
+ * console.log($self.info.id)
+ * {$self.info.name}
+ */
+export function useSelf(): Writable {
+ const room = useRoom();
+ const self = writable();
+
+ const unsubscribeConnection = room.subscribe("connection", () => {
+ self.set(room.getSelf());
+ });
+ const unsubscribe = room.subscribe("my-presence", () => {
+ self.set(room.getSelf());
+ });
+
+ onDestroy(() => {
+ unsubscribeConnection();
+ unsubscribe();
+ });
+
+ return self;
+}
diff --git a/frontend/src/lib/liveblocks/useStorage.ts b/frontend/src/lib/liveblocks/useStorage.ts
new file mode 100644
index 0000000000000000000000000000000000000000..90f8c9949d192aa3e5025cbe177be21b610890d0
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useStorage.ts
@@ -0,0 +1,22 @@
+// @ts-nocheck
+import type { LiveObject } from "@liveblocks/client";
+import type { Writable } from "svelte/store";
+import { writable } from "svelte/store";
+import { useRoom } from "./useRoom";
+
+/**
+ * No `liveblocks-react` public API equivalent, but useStorage is used internally
+ */
+export function useStorage(): Writable {
+ const room = useRoom();
+ const rootStore = writable();
+
+ async function fetchStorage() {
+ const { root }: { root: LiveObject } = await room!.getStorage();
+ rootStore.set(root);
+ }
+
+ fetchStorage();
+
+ return rootStore;
+}
diff --git a/frontend/src/lib/liveblocks/useUndo.ts b/frontend/src/lib/liveblocks/useUndo.ts
new file mode 100644
index 0000000000000000000000000000000000000000..0d2ca281f8a4f8448593eb6bb929de6ab91774c5
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useUndo.ts
@@ -0,0 +1,12 @@
+/**
+ * Works similarly to `liveblocks-react` useUndo
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useUndo
+ *
+ * const undo = useUndo()
+ * undo()
+ */
+import { useRoom } from "./useRoom";
+
+export function useUndo() {
+ return useRoom().history.undo;
+}
diff --git a/frontend/src/lib/liveblocks/useUpdateMyPresence.ts b/frontend/src/lib/liveblocks/useUpdateMyPresence.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d0427098c56b52cff05c78c8149f57400fb65dfd
--- /dev/null
+++ b/frontend/src/lib/liveblocks/useUpdateMyPresence.ts
@@ -0,0 +1,20 @@
+import { useMyPresence } from "./useMyPresence";
+
+/**
+ * Works similarly to `liveblocks-react` useUpdateMyPresence
+ * https://liveblocks.io/docs/api-reference/liveblocks-react#useUpdateMyPresence
+ *
+ * const updateMyPresence = useUpdateMyPresence()
+ * updateMyPresence({ name: 'Chris' })
+ *
+ *
+ * Can also import useMyPresence instead and use .update() instead:
+ *
+ * const myPresence = useMyPresence()
+ * myPresence.update({ name: 'Chris' })
+ */
+
+export function useUpdateMyPresence(): (val: any) => void {
+ const presence = useMyPresence();
+ return (updatedPresence) => presence.update(updatedPresence);
+}
diff --git a/frontend/src/lib/store.ts b/frontend/src/lib/store.ts
new file mode 100644
index 0000000000000000000000000000000000000000..18137c12361461449e5fdcc628563a0548faf238
--- /dev/null
+++ b/frontend/src/lib/store.ts
@@ -0,0 +1,15 @@
+import { writable } from 'svelte/store';
+import { type ZoomTransform, zoomIdentity } from 'd3-zoom';
+
+export const loadingState = writable('');
+export const currZoomTransform = writable(zoomIdentity);
+export const canvasEl = writable();
+export const maskEl = writable();
+export const selectedRoomID = writable();
+export const toggleAbout = writable(false);
+export const isRenderingCanvas = writable(false);
+export const showModal = writable(false);
+export const canvasSize = writable<{
+ width: number;
+ height: number;
+}>({ width: 512 * 16, height: 512 * 16 });
diff --git a/frontend/src/lib/types.ts b/frontend/src/lib/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..96fc4b3f0ba0248da9c44a99e9a95794853f9e79
--- /dev/null
+++ b/frontend/src/lib/types.ts
@@ -0,0 +1,54 @@
+export enum Status {
+ ready = 'ready',
+ loading = 'loading',
+ prompting = 'prompting',
+ processing = 'processing',
+ dragging = 'dragging',
+ masking = 'masking',
+}
+
+export type Presence = {
+ cursor: {
+ x: number;
+ y: number;
+ } | null;
+ frame: {
+ x: number;
+ y: number;
+ };
+ status: Status;
+ currentPrompt: string
+}
+
+export type User = string;
+
+export type PromptImgObject = {
+ prompt: string;
+ imgURL: string;
+ position: {
+ x: number;
+ y: number;
+ }
+ date: number;
+ id: string;
+ room: string;
+};
+
+export type PromptImgKey = string;
+
+export interface RoomResponse {
+ id: number;
+ room_id: string;
+ users_count: number;
+}
+
+
+export enum ConnectionStatus {
+ "closed" = "closed",
+ "authenticating" = "authenticating",
+ "unavailable" = "unavailable",
+ "failed" = "failed",
+ "open" = "open",
+ "connecting" = "connecting",
+}
+export type TConnectionStatus = keyof typeof ConnectionStatus
diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f394f161ae1508cee5c2b443df1421f7bf2f3507
--- /dev/null
+++ b/frontend/src/lib/utils.ts
@@ -0,0 +1,74 @@
+import { PUBLIC_API_BASE } from '$env/static/public';
+import { GRID_SIZE, FRAME_SIZE } from '$lib/constants';
+export function base64ToBlob(base64image: string): Promise {
+ return new Promise((resolve) => {
+ const img = new Image();
+ img.onload = async () => {
+ const w = img.width;
+ const h = img.height;
+ const canvas = document.createElement('canvas');
+ canvas.width = w;
+ canvas.height = h;
+ const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
+ ctx.drawImage(img, 0, 0, w, h);
+
+ const imgBlob: Blob = await new Promise((r) =>
+ canvas.toBlob(r as BlobCallback, 'image/jpeg', 0.95)
+ );
+ resolve(imgBlob);
+ };
+ img.src = base64image;
+ });
+}
+
+export async function uploadImage(imagBlob: Blob, params: {
+ prompt: string;
+ position: { x: number; y: number };
+ date: number;
+ id: string;
+ room: string;
+}): Promise<{
+ url: string;
+ filename: string;
+}> {
+ // simple regex slugify string for file name
+ const promptSlug = slugify(params.prompt);
+ const key = `${params.position.x}_${params.position.y}`;
+ const fileName = `sd-${params.room}-${params.id}-${promptSlug}-${key}.jpeg`;
+
+ const file = new File([imagBlob], fileName, { type: 'image/jpeg' });
+
+ const formData = new FormData()
+ formData.append('file', file)
+
+ const response = await fetch(PUBLIC_API_BASE + "/uploadfile", {
+ method: 'POST',
+ body: formData
+ });
+ if (response.status === 200) {
+ const data = await response.json();
+ return data;
+ }
+ throw new Error('Failed to upload image');
+}
+export function round(pos: number, canvasSize: {
+ width: number;
+ height: number;
+}) {
+ const max = canvasSize.width - FRAME_SIZE
+ const value = pos % GRID_SIZE < GRID_SIZE / 2 ? pos - (pos % GRID_SIZE) : pos + GRID_SIZE - (pos % GRID_SIZE);
+ return Math.max(0, Math.min(Math.round(value), max))
+}
+
+
+function slugify(text: string) {
+ if (!text) return '';
+ return text
+ .toString()
+ .toLowerCase()
+ .replace(/\s+/g, '-')
+ .replace(/[^\w\-]+/g, '')
+ .replace(/\-\-+/g, '-')
+ .replace(/^-+/, '')
+ .replace(/-+$/, '');
+}
\ No newline at end of file
diff --git a/frontend/src/routes/+layout.svelte b/frontend/src/routes/+layout.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..2e511e004988ec574f1b3d5406d22bb9d4f558cd
--- /dev/null
+++ b/frontend/src/routes/+layout.svelte
@@ -0,0 +1,5 @@
+
+
+
diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..16d900edc9041e03815e5071d89e56e75393e281
--- /dev/null
+++ b/frontend/src/routes/+page.svelte
@@ -0,0 +1,99 @@
+
+
+ ($toggleAbout = false)} />
+
+{#if loading}
+
+{:else}
+
+ {#if roomId}
+
+
+
+ {:else}
+
+
No room selected
+
Please select a room in the URL
+
+ {/if}
+
+{/if}
diff --git a/frontend/src/routes/+page.ts b/frontend/src/routes/+page.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c8cacf0895342e5b27842850d40b3efc28f5a4ab
--- /dev/null
+++ b/frontend/src/routes/+page.ts
@@ -0,0 +1 @@
+export const prerender = true;
\ No newline at end of file
diff --git a/frontend/static/favicon.png b/frontend/static/favicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097
Binary files /dev/null and b/frontend/static/favicon.png differ
diff --git a/frontend/static/robots.txt b/frontend/static/robots.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e9e57dc4d41b9b46e05112e9f45b7ea6ac0ba15e
--- /dev/null
+++ b/frontend/static/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/frontend/svelte.config.js b/frontend/svelte.config.js
new file mode 100644
index 0000000000000000000000000000000000000000..31f9ae87b0c9e6c12cfede65a027ea0cb1dda1db
--- /dev/null
+++ b/frontend/svelte.config.js
@@ -0,0 +1,23 @@
+import adapter from '@sveltejs/adapter-static';
+import preprocess from 'svelte-preprocess';
+
+const dev = process.env.NODE_ENV === 'development';
+console.log(dev)
+/** @type {import('@sveltejs/kit').Config} */
+const config = {
+ preprocess: [
+ preprocess({
+ postcss: true
+ })
+ ],
+ kit: {
+ adapter: adapter({
+ pages: 'build',
+ assets: 'build',
+ fallback: null,
+ precompress: false
+ })
+ }
+};
+
+export default config;
diff --git a/frontend/tailwind.config.cjs b/frontend/tailwind.config.cjs
new file mode 100644
index 0000000000000000000000000000000000000000..8012d9571321dc60aa6943b1e5c497aeb2827309
--- /dev/null
+++ b/frontend/tailwind.config.cjs
@@ -0,0 +1,6 @@
+/** @type {import('tailwindcss').Config} */
+module.exports = {
+ content: ['./src/**/*.{html,js,svelte,ts}'],
+ theme: {},
+ plugins: [require('@tailwindcss/forms'), require('@tailwindcss/line-clamp')]
+};
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
new file mode 100644
index 0000000000000000000000000000000000000000..6ae0c8c44d08a78140c9c62c1b0f745edd05e804
--- /dev/null
+++ b/frontend/tsconfig.json
@@ -0,0 +1,17 @@
+{
+ "extends": "./.svelte-kit/tsconfig.json",
+ "compilerOptions": {
+ "allowJs": true,
+ "checkJs": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "resolveJsonModule": true,
+ "skipLibCheck": true,
+ "sourceMap": true,
+ "strict": true
+ }
+ // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
+ //
+ // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
+ // from the referenced tsconfig.json - TypeScript does not merge them in
+}
diff --git a/frontend/vite.config.dev.ts b/frontend/vite.config.dev.ts
new file mode 100644
index 0000000000000000000000000000000000000000..42bc3e497505eba631a58c5cd175eab4fcdc7bf5
--- /dev/null
+++ b/frontend/vite.config.dev.ts
@@ -0,0 +1,18 @@
+import { sveltekit } from '@sveltejs/kit/vite';
+import type { UserConfig } from 'vite';
+
+const config: UserConfig = {
+ plugins: [sveltekit()],
+ server: {
+ // host: "0.0.0.0",
+ proxy: {
+ '/server': {
+ target: 'http://localhost:7860',
+ changeOrigin: true,
+ cookieDomainRewrite: 'localhost',
+ rewrite: (path) => path.replace(/^\/server/, '')
+ }
+ }
+ }
+};
+export default config;
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts
new file mode 100644
index 0000000000000000000000000000000000000000..16950342c1a41f60729f1abfcbbf67676c08e1bb
--- /dev/null
+++ b/frontend/vite.config.ts
@@ -0,0 +1,8 @@
+import { sveltekit } from '@sveltejs/kit/vite';
+import type { UserConfig } from 'vite';
+
+const config: UserConfig = {
+ plugins: [sveltekit()]
+};
+
+export default config;
diff --git a/packages.txt b/packages.txt
new file mode 100644
index 0000000000000000000000000000000000000000..f682f571cbb17c1e8fd86c367335bae446a77299
--- /dev/null
+++ b/packages.txt
@@ -0,0 +1,32 @@
+python3-opencv
+libopencv-dev
+libopencv-core-dev
+pkg-config
+libopencv-imgcodecs-dev
+libopencv-dev
+libopencv-contrib-dev
+build-essential
+cmake
+git
+pkg-config
+libgtk-3-dev
+libavcodec-dev
+libavformat-dev
+libswscale-dev
+libv4l-dev
+libxvidcore-dev
+libx264-dev
+libjpeg-dev
+libpng-dev
+libtiff-dev
+gfortran
+openexr
+libatlas-base-dev
+python3-dev
+python3-numpy
+libtbb2
+libtbb-dev
+libdc1394-22-dev
+libopenexr-dev
+libgstreamer-plugins-base1.0-dev
+libgstreamer1.0-dev
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
new file mode 100644
index 0000000000000000000000000000000000000000..5528149338478e9cd9dfa579e49b8853d02fc915
--- /dev/null
+++ b/requirements.txt
@@ -0,0 +1,18 @@
+--extra-index-url https://download.pytorch.org/whl/cu113
+torch
+huggingface_hub
+git+https://github.com/huggingface/diffusers.git@9f476388
+transformers
+scikit-image==0.19.3
+Pillow==9.2.0
+opencv-python-headless==4.6.0.66
+fastapi==0.85.1
+uvicorn==0.18.3
+httpx==0.23.0
+gradio==3.6
+boto3==1.24.93
+python-magic==0.4.27
+fastapi-utils==0.2.1
+shortuuid==1.0
+tqdm==4.64
+accelerate
\ No newline at end of file
diff --git a/run.py b/run.py
new file mode 100644
index 0000000000000000000000000000000000000000..49268cdd5158672828979238fbcbe914c9ddb119
--- /dev/null
+++ b/run.py
@@ -0,0 +1,4 @@
+import os
+
+os.system("cd stablediffusion-infinity/PyPatchMatch && make")
+os.system("cd stablediffusion-infinity && python app.py")
\ No newline at end of file
diff --git a/stablediffusion-infinity/.gitignore b/stablediffusion-infinity/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..38b84904fc24f4bf036c31605cfa75fe3c1424d1
--- /dev/null
+++ b/stablediffusion-infinity/.gitignore
@@ -0,0 +1,9 @@
+__pycache__/
+.ipynb_checkpoints/
+build/
+.idea/
+travis.sh
+*.iml
+.token
+libpatchmatch.so
+rooms.db
\ No newline at end of file
diff --git a/stablediffusion-infinity/.gitmodules b/stablediffusion-infinity/.gitmodules
new file mode 100644
index 0000000000000000000000000000000000000000..25cb6b4682681d244d6792acc6a08257a37b4650
--- /dev/null
+++ b/stablediffusion-infinity/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "PyPatchMatch"]
+ path = PyPatchMatch
+ url = https://github.com/vacancy/PyPatchMatch
diff --git a/stablediffusion-infinity/LICENSE b/stablediffusion-infinity/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..261eeb9e9f8b2b4b0d119366dda99c6fd7d35c64
--- /dev/null
+++ b/stablediffusion-infinity/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/stablediffusion-infinity/PyPatchMatch/.gitignore b/stablediffusion-infinity/PyPatchMatch/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..6f1ff24ac28a273b19fd3103973c9e83a62a377c
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/.gitignore
@@ -0,0 +1,3 @@
+/build/
+__pycache__
+*.py[cod]
diff --git a/stablediffusion-infinity/PyPatchMatch/LICENSE b/stablediffusion-infinity/PyPatchMatch/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..7a41bf3b46e727b16d1a5b93ff8bee88868d1d93
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 Jiayuan Mao
+
+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.
diff --git a/stablediffusion-infinity/PyPatchMatch/Makefile b/stablediffusion-infinity/PyPatchMatch/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..791465529833fe4f6cc2825fa633d06e2e843038
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/Makefile
@@ -0,0 +1,54 @@
+#
+# Makefile
+# Jiayuan Mao, 2019-01-09 13:59
+#
+
+SRC_DIR = csrc
+INC_DIR = csrc
+OBJ_DIR = build/obj
+TARGET = libpatchmatch.so
+
+LIB_TARGET = $(TARGET)
+INCLUDE_DIR = -I $(SRC_DIR) -I $(INC_DIR)
+
+CXX = $(ENVIRONMENT_OPTIONS) g++
+CXXFLAGS = -std=c++14
+CXXFLAGS += -Ofast -ffast-math -w
+# CXXFLAGS += -g
+CXXFLAGS += $(shell pkg-config --cflags opencv.pc) -fPIC
+CXXFLAGS += $(INCLUDE_DIR)
+LDFLAGS = $(shell pkg-config --cflags --libs opencv.pc) -shared -fPIC
+
+
+CXXSOURCES = $(shell find $(SRC_DIR)/ -name "*.cpp")
+OBJS = $(addprefix $(OBJ_DIR)/,$(CXXSOURCES:.cpp=.o))
+DEPFILES = $(OBJS:.o=.d)
+
+.PHONY: all clean rebuild test
+
+all: $(LIB_TARGET)
+
+$(OBJ_DIR)/%.o: %.cpp
+ @echo "[CC] $< ..."
+ @$(CXX) -c $< $(CXXFLAGS) -o $@
+
+$(OBJ_DIR)/%.d: %.cpp
+ @mkdir -pv $(dir $@)
+ @echo "[dep] $< ..."
+ @$(CXX) $(INCLUDE_DIR) $(CXXFLAGS) -MM -MT "$(OBJ_DIR)/$(<:.cpp=.o) $(OBJ_DIR)/$(<:.cpp=.d)" "$<" > "$@"
+
+sinclude $(DEPFILES)
+
+$(LIB_TARGET): $(OBJS)
+ @echo "[link] $(LIB_TARGET) ..."
+ @$(CXX) $(OBJS) -o $@ $(CXXFLAGS) $(LDFLAGS)
+
+clean:
+ rm -rf $(OBJ_DIR) $(LIB_TARGET)
+
+rebuild:
+ +@make clean
+ +@make
+
+# vim:ft=make
+#
diff --git a/stablediffusion-infinity/PyPatchMatch/README.md b/stablediffusion-infinity/PyPatchMatch/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..12b49aadadfe0ff51c2873b2671c0ca020bc3506
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/README.md
@@ -0,0 +1,64 @@
+PatchMatch based Inpainting
+=====================================
+This library implements the PatchMatch based inpainting algorithm. It provides both C++ and Python interfaces.
+This implementation is heavily based on the implementation by Younesse ANDAM:
+(younesse-cv/PatchMatch)[https://github.com/younesse-cv/PatchMatch], with some bugs fix.
+
+Usage
+-------------------------------------
+
+You need to first install OpenCV to compile the C++ libraries. Then, run `make` to compile the
+shared library `libpatchmatch.so`.
+
+For Python users (example available at `examples/py_example.py`)
+
+```python
+import patch_match
+
+image = ... # either a numpy ndarray or a PIL Image object.
+mask = ... # either a numpy ndarray or a PIL Image object.
+result = patch_match.inpaint(image, mask, patch_size=5)
+```
+
+For C++ users (examples available at `examples/cpp_example.cpp`)
+
+```cpp
+#include "inpaint.h"
+
+int main() {
+ cv::Mat image = ...
+ cv::Mat mask = ...
+
+ cv::Mat result = Inpainting(image, mask, 5).run();
+
+ return 0;
+}
+```
+
+
+README and COPYRIGHT by Younesse ANDAM
+-------------------------------------
+@Author: Younesse ANDAM
+
+@Contact: younesse.andam@gmail.com
+
+Description: This project is a personal implementation of an algorithm called PATCHMATCH that restores missing areas in an image.
+The algorithm is presented in the following paper
+ PatchMatch A Randomized Correspondence Algorithm
+ for Structural Image Editing
+ by C.Barnes,E.Shechtman,A.Finkelstein and Dan B.Goldman
+ ACM Transactions on Graphics (Proc. SIGGRAPH), vol.28, aug-2009
+
+ For more information please refer to
+ http://www.cs.princeton.edu/gfx/pubs/Barnes_2009_PAR/index.php
+
+Copyright (c) 2010-2011
+
+
+Requirements
+-------------------------------------
+
+To run the project you need to install Opencv library and link it to your project.
+Opencv can be download it here
+http://opencv.org/downloads.html
+
diff --git a/stablediffusion-infinity/PyPatchMatch/csrc/inpaint.cpp b/stablediffusion-infinity/PyPatchMatch/csrc/inpaint.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..de1f4b0c8bc74a2d4daf712827a903cc1385a2a7
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/csrc/inpaint.cpp
@@ -0,0 +1,234 @@
+#include
+#include
+#include
+#include
+#include
+
+#include "inpaint.h"
+
+namespace {
+ static std::vector kDistance2Similarity;
+
+ void init_kDistance2Similarity() {
+ double base[11] = {1.0, 0.99, 0.96, 0.83, 0.38, 0.11, 0.02, 0.005, 0.0006, 0.0001, 0};
+ int length = (PatchDistanceMetric::kDistanceScale + 1);
+ kDistance2Similarity.resize(length);
+ for (int i = 0; i < length; ++i) {
+ double t = (double) i / length;
+ int j = (int) (100 * t);
+ int k = j + 1;
+ double vj = (j < 11) ? base[j] : 0;
+ double vk = (k < 11) ? base[k] : 0;
+ kDistance2Similarity[i] = vj + (100 * t - j) * (vk - vj);
+ }
+ }
+
+
+ inline void _weighted_copy(const MaskedImage &source, int ys, int xs, cv::Mat &target, int yt, int xt, double weight) {
+ if (source.is_masked(ys, xs)) return;
+ if (source.is_globally_masked(ys, xs)) return;
+
+ auto source_ptr = source.get_image(ys, xs);
+ auto target_ptr = target.ptr(yt, xt);
+
+#pragma unroll
+ for (int c = 0; c < 3; ++c)
+ target_ptr[c] += static_cast(source_ptr[c]) * weight;
+ target_ptr[3] += weight;
+ }
+}
+
+/**
+ * This algorithme uses a version proposed by Xavier Philippeau.
+ */
+
+Inpainting::Inpainting(cv::Mat image, cv::Mat mask, const PatchDistanceMetric *metric)
+ : m_initial(image, mask), m_distance_metric(metric), m_pyramid(), m_source2target(), m_target2source() {
+ _initialize_pyramid();
+}
+
+Inpainting::Inpainting(cv::Mat image, cv::Mat mask, cv::Mat global_mask, const PatchDistanceMetric *metric)
+ : m_initial(image, mask, global_mask), m_distance_metric(metric), m_pyramid(), m_source2target(), m_target2source() {
+ _initialize_pyramid();
+}
+
+void Inpainting::_initialize_pyramid() {
+ auto source = m_initial;
+ m_pyramid.push_back(source);
+ while (source.size().height > m_distance_metric->patch_size() && source.size().width > m_distance_metric->patch_size()) {
+ source = source.downsample();
+ m_pyramid.push_back(source);
+ }
+
+ if (kDistance2Similarity.size() == 0) {
+ init_kDistance2Similarity();
+ }
+}
+
+cv::Mat Inpainting::run(bool verbose, bool verbose_visualize, unsigned int random_seed) {
+ srand(random_seed);
+ const int nr_levels = m_pyramid.size();
+
+ MaskedImage source, target;
+ for (int level = nr_levels - 1; level >= 0; --level) {
+ if (verbose) std::cerr << "Inpainting level: " << level << std::endl;
+
+ source = m_pyramid[level];
+
+ if (level == nr_levels - 1) {
+ target = source.clone();
+ target.clear_mask();
+ m_source2target = NearestNeighborField(source, target, m_distance_metric);
+ m_target2source = NearestNeighborField(target, source, m_distance_metric);
+ } else {
+ m_source2target = NearestNeighborField(source, target, m_distance_metric, m_source2target);
+ m_target2source = NearestNeighborField(target, source, m_distance_metric, m_target2source);
+ }
+
+ if (verbose) std::cerr << "Initialization done." << std::endl;
+
+ if (verbose_visualize) {
+ auto visualize_size = m_initial.size();
+ cv::Mat source_visualize(visualize_size, m_initial.image().type());
+ cv::resize(source.image(), source_visualize, visualize_size);
+ cv::imshow("Source", source_visualize);
+ cv::Mat target_visualize(visualize_size, m_initial.image().type());
+ cv::resize(target.image(), target_visualize, visualize_size);
+ cv::imshow("Target", target_visualize);
+ cv::waitKey(0);
+ }
+
+ target = _expectation_maximization(source, target, level, verbose);
+ }
+
+ return target.image();
+}
+
+// EM-Like algorithm (see "PatchMatch" - page 6).
+// Returns a double sized target image (unless level = 0).
+MaskedImage Inpainting::_expectation_maximization(MaskedImage source, MaskedImage target, int level, bool verbose) {
+ const int nr_iters_em = 1 + 2 * level;
+ const int nr_iters_nnf = static_cast(std::min(7, 1 + level));
+ const int patch_size = m_distance_metric->patch_size();
+
+ MaskedImage new_source, new_target;
+
+ for (int iter_em = 0; iter_em < nr_iters_em; ++iter_em) {
+ if (iter_em != 0) {
+ m_source2target.set_target(new_target);
+ m_target2source.set_source(new_target);
+ target = new_target;
+ }
+
+ if (verbose) std::cerr << "EM Iteration: " << iter_em << std::endl;
+
+ auto size = source.size();
+ for (int i = 0; i < size.height; ++i) {
+ for (int j = 0; j < size.width; ++j) {
+ if (!source.contains_mask(i, j, patch_size)) {
+ m_source2target.set_identity(i, j);
+ m_target2source.set_identity(i, j);
+ }
+ }
+ }
+ if (verbose) std::cerr << " NNF minimization started." << std::endl;
+ m_source2target.minimize(nr_iters_nnf);
+ m_target2source.minimize(nr_iters_nnf);
+ if (verbose) std::cerr << " NNF minimization finished." << std::endl;
+
+ // Instead of upsizing the final target, we build the last target from the next level source image.
+ // Thus, the final target is less blurry (see "Space-Time Video Completion" - page 5).
+ bool upscaled = false;
+ if (level >= 1 && iter_em == nr_iters_em - 1) {
+ new_source = m_pyramid[level - 1];
+ new_target = target.upsample(new_source.size().width, new_source.size().height, m_pyramid[level - 1].global_mask());
+ upscaled = true;
+ } else {
+ new_source = m_pyramid[level];
+ new_target = target.clone();
+ }
+
+ auto vote = cv::Mat(new_target.size(), CV_64FC4);
+ vote.setTo(cv::Scalar::all(0));
+
+ // Votes for best patch from NNF Source->Target (completeness) and Target->Source (coherence).
+ _expectation_step(m_source2target, 1, vote, new_source, upscaled);
+ if (verbose) std::cerr << " Expectation source to target finished." << std::endl;
+ _expectation_step(m_target2source, 0, vote, new_source, upscaled);
+ if (verbose) std::cerr << " Expectation target to source finished." << std::endl;
+
+ // Compile votes and update pixel values.
+ _maximization_step(new_target, vote);
+ if (verbose) std::cerr << " Minimization step finished." << std::endl;
+ }
+
+ return new_target;
+}
+
+// Expectation step: vote for best estimations of each pixel.
+void Inpainting::_expectation_step(
+ const NearestNeighborField &nnf, bool source2target,
+ cv::Mat &vote, const MaskedImage &source, bool upscaled
+) {
+ auto source_size = nnf.source_size();
+ auto target_size = nnf.target_size();
+ const int patch_size = m_distance_metric->patch_size();
+
+ for (int i = 0; i < source_size.height; ++i) {
+ for (int j = 0; j < source_size.width; ++j) {
+ if (nnf.source().is_globally_masked(i, j)) continue;
+ int yp = nnf.at(i, j, 0), xp = nnf.at(i, j, 1), dp = nnf.at(i, j, 2);
+ double w = kDistance2Similarity[dp];
+
+ for (int di = -patch_size; di <= patch_size; ++di) {
+ for (int dj = -patch_size; dj <= patch_size; ++dj) {
+ int ys = i + di, xs = j + dj, yt = yp + di, xt = xp + dj;
+ if (!(ys >= 0 && ys < source_size.height && xs >= 0 && xs < source_size.width)) continue;
+ if (nnf.source().is_globally_masked(ys, xs)) continue;
+ if (!(yt >= 0 && yt < target_size.height && xt >= 0 && xt < target_size.width)) continue;
+ if (nnf.target().is_globally_masked(yt, xt)) continue;
+
+ if (!source2target) {
+ std::swap(ys, yt);
+ std::swap(xs, xt);
+ }
+
+ if (upscaled) {
+ for (int uy = 0; uy < 2; ++uy) {
+ for (int ux = 0; ux < 2; ++ux) {
+ _weighted_copy(source, 2 * ys + uy, 2 * xs + ux, vote, 2 * yt + uy, 2 * xt + ux, w);
+ }
+ }
+ } else {
+ _weighted_copy(source, ys, xs, vote, yt, xt, w);
+ }
+ }
+ }
+ }
+ }
+}
+
+// Maximization Step: maximum likelihood of target pixel.
+void Inpainting::_maximization_step(MaskedImage &target, const cv::Mat &vote) {
+ auto target_size = target.size();
+ for (int i = 0; i < target_size.height; ++i) {
+ for (int j = 0; j < target_size.width; ++j) {
+ const double *source_ptr = vote.ptr(i, j);
+ unsigned char *target_ptr = target.get_mutable_image(i, j);
+
+ if (target.is_globally_masked(i, j)) {
+ continue;
+ }
+
+ if (source_ptr[3] > 0) {
+ unsigned char r = cv::saturate_cast(source_ptr[0] / source_ptr[3]);
+ unsigned char g = cv::saturate_cast(source_ptr[1] / source_ptr[3]);
+ unsigned char b = cv::saturate_cast(source_ptr[2] / source_ptr[3]);
+ target_ptr[0] = r, target_ptr[1] = g, target_ptr[2] = b;
+ } else {
+ target.set_mask(i, j, 0);
+ }
+ }
+ }
+}
+
diff --git a/stablediffusion-infinity/PyPatchMatch/csrc/inpaint.h b/stablediffusion-infinity/PyPatchMatch/csrc/inpaint.h
new file mode 100644
index 0000000000000000000000000000000000000000..a59b1d347ea5fe92976a4fda10a820d6508f51da
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/csrc/inpaint.h
@@ -0,0 +1,27 @@
+#pragma once
+
+#include
+
+#include "masked_image.h"
+#include "nnf.h"
+
+class Inpainting {
+public:
+ Inpainting(cv::Mat image, cv::Mat mask, const PatchDistanceMetric *metric);
+ Inpainting(cv::Mat image, cv::Mat mask, cv::Mat global_mask, const PatchDistanceMetric *metric);
+ cv::Mat run(bool verbose = false, bool verbose_visualize = false, unsigned int random_seed = 1212);
+
+private:
+ void _initialize_pyramid(void);
+ MaskedImage _expectation_maximization(MaskedImage source, MaskedImage target, int level, bool verbose);
+ void _expectation_step(const NearestNeighborField &nnf, bool source2target, cv::Mat &vote, const MaskedImage &source, bool upscaled);
+ void _maximization_step(MaskedImage &target, const cv::Mat &vote);
+
+ MaskedImage m_initial;
+ std::vector m_pyramid;
+
+ NearestNeighborField m_source2target;
+ NearestNeighborField m_target2source;
+ const PatchDistanceMetric *m_distance_metric;
+};
+
diff --git a/stablediffusion-infinity/PyPatchMatch/csrc/masked_image.cpp b/stablediffusion-infinity/PyPatchMatch/csrc/masked_image.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..448a776b3cda9f39f4dd0ad908f1b135c647ca8f
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/csrc/masked_image.cpp
@@ -0,0 +1,138 @@
+#include "masked_image.h"
+#include
+#include
+
+const cv::Size MaskedImage::kDownsampleKernelSize = cv::Size(6, 6);
+const int MaskedImage::kDownsampleKernel[6] = {1, 5, 10, 10, 5, 1};
+
+bool MaskedImage::contains_mask(int y, int x, int patch_size) const {
+ auto mask_size = size();
+ for (int dy = -patch_size; dy <= patch_size; ++dy) {
+ for (int dx = -patch_size; dx <= patch_size; ++dx) {
+ int yy = y + dy, xx = x + dx;
+ if (yy >= 0 && yy < mask_size.height && xx >= 0 && xx < mask_size.width) {
+ if (is_masked(yy, xx) && !is_globally_masked(yy, xx)) return true;
+ }
+ }
+ }
+ return false;
+}
+
+MaskedImage MaskedImage::downsample() const {
+ const auto &kernel_size = MaskedImage::kDownsampleKernelSize;
+ const auto &kernel = MaskedImage::kDownsampleKernel;
+
+ const auto size = this->size();
+ const auto new_size = cv::Size(size.width / 2, size.height / 2);
+
+ auto ret = MaskedImage(new_size.width, new_size.height);
+ if (!m_global_mask.empty()) ret.init_global_mask_mat();
+ for (int y = 0; y < size.height - 1; y += 2) {
+ for (int x = 0; x < size.width - 1; x += 2) {
+ int r = 0, g = 0, b = 0, ksum = 0;
+ bool is_gmasked = true;
+
+ for (int dy = -kernel_size.height / 2 + 1; dy <= kernel_size.height / 2; ++dy) {
+ for (int dx = -kernel_size.width / 2 + 1; dx <= kernel_size.width / 2; ++dx) {
+ int yy = y + dy, xx = x + dx;
+ if (yy >= 0 && yy < size.height && xx >= 0 && xx < size.width) {
+ if (!is_globally_masked(yy, xx)) {
+ is_gmasked = false;
+ }
+ if (!is_masked(yy, xx)) {
+ auto source_ptr = get_image(yy, xx);
+ int k = kernel[kernel_size.height / 2 - 1 + dy] * kernel[kernel_size.width / 2 - 1 + dx];
+ r += source_ptr[0] * k, g += source_ptr[1] * k, b += source_ptr[2] * k;
+ ksum += k;
+ }
+ }
+ }
+ }
+
+ if (ksum > 0) r /= ksum, g /= ksum, b /= ksum;
+
+ if (!m_global_mask.empty()) {
+ ret.set_global_mask(y / 2, x / 2, is_gmasked);
+ }
+ if (ksum > 0) {
+ auto target_ptr = ret.get_mutable_image(y / 2, x / 2);
+ target_ptr[0] = r, target_ptr[1] = g, target_ptr[2] = b;
+ ret.set_mask(y / 2, x / 2, 0);
+ } else {
+ ret.set_mask(y / 2, x / 2, 1);
+ }
+ }
+ }
+
+ return ret;
+}
+
+MaskedImage MaskedImage::upsample(int new_w, int new_h) const {
+ const auto size = this->size();
+ auto ret = MaskedImage(new_w, new_h);
+ if (!m_global_mask.empty()) ret.init_global_mask_mat();
+ for (int y = 0; y < new_h; ++y) {
+ for (int x = 0; x < new_w; ++x) {
+ int yy = y * size.height / new_h;
+ int xx = x * size.width / new_w;
+
+ if (is_globally_masked(yy, xx)) {
+ ret.set_global_mask(y, x, 1);
+ ret.set_mask(y, x, 1);
+ } else {
+ if (!m_global_mask.empty()) ret.set_global_mask(y, x, 0);
+
+ if (is_masked(yy, xx)) {
+ ret.set_mask(y, x, 1);
+ } else {
+ auto source_ptr = get_image(yy, xx);
+ auto target_ptr = ret.get_mutable_image(y, x);
+ for (int c = 0; c < 3; ++c)
+ target_ptr[c] = source_ptr[c];
+ ret.set_mask(y, x, 0);
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+MaskedImage MaskedImage::upsample(int new_w, int new_h, const cv::Mat &new_global_mask) const {
+ auto ret = upsample(new_w, new_h);
+ ret.set_global_mask_mat(new_global_mask);
+ return ret;
+}
+
+void MaskedImage::compute_image_gradients() {
+ if (m_image_grad_computed) {
+ return;
+ }
+
+ const auto size = m_image.size();
+ m_image_grady = cv::Mat(size, CV_8UC3);
+ m_image_gradx = cv::Mat(size, CV_8UC3);
+ m_image_grady = cv::Scalar::all(0);
+ m_image_gradx = cv::Scalar::all(0);
+
+ for (int i = 1; i < size.height - 1; ++i) {
+ const auto *ptr = m_image.ptr(i, 0);
+ const auto *ptry1 = m_image.ptr(i + 1, 0);
+ const auto *ptry2 = m_image.ptr(i - 1, 0);
+ const auto *ptrx1 = m_image.ptr(i, 0) + 3;
+ const auto *ptrx2 = m_image.ptr(i, 0) - 3;
+ auto *mptry = m_image_grady.ptr(i, 0);
+ auto *mptrx = m_image_gradx.ptr(i, 0);
+ for (int j = 3; j < size.width * 3 - 3; ++j) {
+ mptry[j] = (ptry1[j] / 2 - ptry2[j] / 2) + 128;
+ mptrx[j] = (ptrx1[j] / 2 - ptrx2[j] / 2) + 128;
+ }
+ }
+
+ m_image_grad_computed = true;
+}
+
+void MaskedImage::compute_image_gradients() const {
+ const_cast(this)->compute_image_gradients();
+}
+
diff --git a/stablediffusion-infinity/PyPatchMatch/csrc/masked_image.h b/stablediffusion-infinity/PyPatchMatch/csrc/masked_image.h
new file mode 100644
index 0000000000000000000000000000000000000000..52caf272d0534c35b79eedaea53d0c56e5cf942e
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/csrc/masked_image.h
@@ -0,0 +1,112 @@
+#pragma once
+
+#include
+
+class MaskedImage {
+public:
+ MaskedImage() : m_image(), m_mask(), m_global_mask(), m_image_grady(), m_image_gradx(), m_image_grad_computed(false) {
+ // pass
+ }
+ MaskedImage(cv::Mat image, cv::Mat mask) : m_image(image), m_mask(mask), m_image_grad_computed(false) {
+ // pass
+ }
+ MaskedImage(cv::Mat image, cv::Mat mask, cv::Mat global_mask) : m_image(image), m_mask(mask), m_global_mask(global_mask), m_image_grad_computed(false) {
+ // pass
+ }
+ MaskedImage(cv::Mat image, cv::Mat mask, cv::Mat global_mask, cv::Mat grady, cv::Mat gradx, bool grad_computed) :
+ m_image(image), m_mask(mask), m_global_mask(global_mask),
+ m_image_grady(grady), m_image_gradx(gradx), m_image_grad_computed(grad_computed) {
+ // pass
+ }
+ MaskedImage(int width, int height) : m_global_mask(), m_image_grady(), m_image_gradx() {
+ m_image = cv::Mat(cv::Size(width, height), CV_8UC3);
+ m_image = cv::Scalar::all(0);
+
+ m_mask = cv::Mat(cv::Size(width, height), CV_8U);
+ m_mask = cv::Scalar::all(0);
+ }
+ inline MaskedImage clone() {
+ return MaskedImage(
+ m_image.clone(), m_mask.clone(), m_global_mask.clone(),
+ m_image_grady.clone(), m_image_gradx.clone(), m_image_grad_computed
+ );
+ }
+
+ inline cv::Size size() const {
+ return m_image.size();
+ }
+ inline const cv::Mat &image() const {
+ return m_image;
+ }
+ inline const cv::Mat &mask() const {
+ return m_mask;
+ }
+ inline const cv::Mat &global_mask() const {
+ return m_global_mask;
+ }
+ inline const cv::Mat &grady() const {
+ assert(m_image_grad_computed);
+ return m_image_grady;
+ }
+ inline const cv::Mat &gradx() const {
+ assert(m_image_grad_computed);
+ return m_image_gradx;
+ }
+
+ inline void init_global_mask_mat() {
+ m_global_mask = cv::Mat(m_mask.size(), CV_8U);
+ m_global_mask.setTo(cv::Scalar(0));
+ }
+ inline void set_global_mask_mat(const cv::Mat &other) {
+ m_global_mask = other;
+ }
+
+ inline bool is_masked(int y, int x) const {
+ return static_cast(m_mask.at(y, x));
+ }
+ inline bool is_globally_masked(int y, int x) const {
+ return !m_global_mask.empty() && static_cast(m_global_mask.at(y, x));
+ }
+ inline void set_mask(int y, int x, bool value) {
+ m_mask.at(y, x) = static_cast(value);
+ }
+ inline void set_global_mask(int y, int x, bool value) {
+ m_global_mask.at(y, x) = static_cast(value);
+ }
+ inline void clear_mask() {
+ m_mask.setTo(cv::Scalar(0));
+ }
+
+ inline const unsigned char *get_image(int y, int x) const {
+ return m_image.ptr(y, x);
+ }
+ inline unsigned char *get_mutable_image(int y, int x) {
+ return m_image.ptr(y, x);
+ }
+
+ inline unsigned char get_image(int y, int x, int c) const {
+ return m_image.ptr(y, x)[c];
+ }
+ inline int get_image_int(int y, int x, int c) const {
+ return static_cast(m_image.ptr(y, x)[c]);
+ }
+
+ bool contains_mask(int y, int x, int patch_size) const;
+ MaskedImage downsample() const;
+ MaskedImage upsample(int new_w, int new_h) const;
+ MaskedImage upsample(int new_w, int new_h, const cv::Mat &new_global_mask) const;
+ void compute_image_gradients();
+ void compute_image_gradients() const;
+
+ static const cv::Size kDownsampleKernelSize;
+ static const int kDownsampleKernel[6];
+
+private:
+ cv::Mat m_image;
+ cv::Mat m_mask;
+ cv::Mat m_global_mask;
+ cv::Mat m_image_grady;
+ cv::Mat m_image_gradx;
+ bool m_image_grad_computed = false;
+};
+
diff --git a/stablediffusion-infinity/PyPatchMatch/csrc/nnf.cpp b/stablediffusion-infinity/PyPatchMatch/csrc/nnf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..efa2751e8ad07a65c41a589010bcd79eb54cdfff
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/csrc/nnf.cpp
@@ -0,0 +1,268 @@
+#include
+#include
+#include
+
+#include "masked_image.h"
+#include "nnf.h"
+
+/**
+* Nearest-Neighbor Field (see PatchMatch algorithm).
+* This algorithme uses a version proposed by Xavier Philippeau.
+*
+*/
+
+template
+T clamp(T value, T min_value, T max_value) {
+ return std::min(std::max(value, min_value), max_value);
+}
+
+void NearestNeighborField::_randomize_field(int max_retry, bool reset) {
+ auto this_size = source_size();
+ for (int i = 0; i < this_size.height; ++i) {
+ for (int j = 0; j < this_size.width; ++j) {
+ if (m_source.is_globally_masked(i, j)) continue;
+
+ auto this_ptr = mutable_ptr(i, j);
+ int distance = reset ? PatchDistanceMetric::kDistanceScale : this_ptr[2];
+ if (distance < PatchDistanceMetric::kDistanceScale) {
+ continue;
+ }
+
+ int i_target = 0, j_target = 0;
+ for (int t = 0; t < max_retry; ++t) {
+ i_target = rand() % this_size.height;
+ j_target = rand() % this_size.width;
+ if (m_target.is_globally_masked(i_target, j_target)) continue;
+
+ distance = _distance(i, j, i_target, j_target);
+ if (distance < PatchDistanceMetric::kDistanceScale)
+ break;
+ }
+
+ this_ptr[0] = i_target, this_ptr[1] = j_target, this_ptr[2] = distance;
+ }
+ }
+}
+
+void NearestNeighborField::_initialize_field_from(const NearestNeighborField &other, int max_retry) {
+ const auto &this_size = source_size();
+ const auto &other_size = other.source_size();
+ double fi = static_cast(this_size.height) / other_size.height;
+ double fj = static_cast(this_size.width) / other_size.width;
+
+ for (int i = 0; i < this_size.height; ++i) {
+ for (int j = 0; j < this_size.width; ++j) {
+ if (m_source.is_globally_masked(i, j)) continue;
+
+ int ilow = static_cast(std::min(i / fi, static_cast(other_size.height - 1)));
+ int jlow = static_cast(std::min(j / fj, static_cast(other_size.width - 1)));
+ auto this_value = mutable_ptr(i, j);
+ auto other_value = other.ptr(ilow, jlow);
+
+ this_value[0] = static_cast(other_value[0] * fi);
+ this_value[1] = static_cast(other_value[1] * fj);
+ this_value[2] = _distance(i, j, this_value[0], this_value[1]);
+ }
+ }
+
+ _randomize_field(max_retry, false);
+}
+
+void NearestNeighborField::minimize(int nr_pass) {
+ const auto &this_size = source_size();
+ while (nr_pass--) {
+ for (int i = 0; i < this_size.height; ++i)
+ for (int j = 0; j < this_size.width; ++j) {
+ if (m_source.is_globally_masked(i, j)) continue;
+ if (at(i, j, 2) > 0) _minimize_link(i, j, +1);
+ }
+ for (int i = this_size.height - 1; i >= 0; --i)
+ for (int j = this_size.width - 1; j >= 0; --j) {
+ if (m_source.is_globally_masked(i, j)) continue;
+ if (at(i, j, 2) > 0) _minimize_link(i, j, -1);
+ }
+ }
+}
+
+void NearestNeighborField::_minimize_link(int y, int x, int direction) {
+ const auto &this_size = source_size();
+ const auto &this_target_size = target_size();
+ auto this_ptr = mutable_ptr(y, x);
+
+ // propagation along the y direction.
+ if (y - direction >= 0 && y - direction < this_size.height && !m_source.is_globally_masked(y - direction, x)) {
+ int yp = at(y - direction, x, 0) + direction;
+ int xp = at(y - direction, x, 1);
+ int dp = _distance(y, x, yp, xp);
+ if (dp < at(y, x, 2)) {
+ this_ptr[0] = yp, this_ptr[1] = xp, this_ptr[2] = dp;
+ }
+ }
+
+ // propagation along the x direction.
+ if (x - direction >= 0 && x - direction < this_size.width && !m_source.is_globally_masked(y, x - direction)) {
+ int yp = at(y, x - direction, 0);
+ int xp = at(y, x - direction, 1) + direction;
+ int dp = _distance(y, x, yp, xp);
+ if (dp < at(y, x, 2)) {
+ this_ptr[0] = yp, this_ptr[1] = xp, this_ptr[2] = dp;
+ }
+ }
+
+ // random search with a progressive step size.
+ int random_scale = (std::min(this_target_size.height, this_target_size.width) - 1) / 2;
+ while (random_scale > 0) {
+ int yp = this_ptr[0] + (rand() % (2 * random_scale + 1) - random_scale);
+ int xp = this_ptr[1] + (rand() % (2 * random_scale + 1) - random_scale);
+ yp = clamp(yp, 0, target_size().height - 1);
+ xp = clamp(xp, 0, target_size().width - 1);
+
+ if (m_target.is_globally_masked(yp, xp)) {
+ random_scale /= 2;
+ }
+
+ int dp = _distance(y, x, yp, xp);
+ if (dp < at(y, x, 2)) {
+ this_ptr[0] = yp, this_ptr[1] = xp, this_ptr[2] = dp;
+ }
+ random_scale /= 2;
+ }
+}
+
+const int PatchDistanceMetric::kDistanceScale = 65535;
+const int PatchSSDDistanceMetric::kSSDScale = 9 * 255 * 255;
+
+namespace {
+
+inline int pow2(int i) {
+ return i * i;
+}
+
+int distance_masked_images(
+ const MaskedImage &source, int ys, int xs,
+ const MaskedImage &target, int yt, int xt,
+ int patch_size
+) {
+ long double distance = 0;
+ long double wsum = 0;
+
+ source.compute_image_gradients();
+ target.compute_image_gradients();
+
+ auto source_size = source.size();
+ auto target_size = target.size();
+
+ for (int dy = -patch_size; dy <= patch_size; ++dy) {
+ const int yys = ys + dy, yyt = yt + dy;
+
+ if (yys <= 0 || yys >= source_size.height - 1 || yyt <= 0 || yyt >= target_size.height - 1) {
+ distance += (long double)(PatchSSDDistanceMetric::kSSDScale) * (2 * patch_size + 1);
+ wsum += 2 * patch_size + 1;
+ continue;
+ }
+
+ const auto *p_si = source.image().ptr(yys, 0);
+ const auto *p_ti = target.image().ptr(yyt, 0);
+ const auto *p_sm = source.mask().ptr(yys, 0);
+ const auto *p_tm = target.mask().ptr(yyt, 0);
+
+ const unsigned char *p_sgm = nullptr;
+ const unsigned char *p_tgm = nullptr;
+ if (!source.global_mask().empty()) {
+ p_sgm = source.global_mask().ptr(yys, 0);
+ p_tgm = target.global_mask().ptr(yyt, 0);
+ }
+
+ const auto *p_sgy = source.grady().ptr(yys, 0);
+ const auto *p_tgy = target.grady().ptr(yyt, 0);
+ const auto *p_sgx = source.gradx().ptr(yys, 0);
+ const auto *p_tgx = target.gradx().ptr(yyt, 0);
+
+ for (int dx = -patch_size; dx <= patch_size; ++dx) {
+ int xxs = xs + dx, xxt = xt + dx;
+ wsum += 1;
+
+ if (xxs <= 0 || xxs >= source_size.width - 1 || xxt <= 0 || xxt >= source_size.width - 1) {
+ distance += PatchSSDDistanceMetric::kSSDScale;
+ continue;
+ }
+
+ if (p_sm[xxs] || p_tm[xxt] || (p_sgm && p_sgm[xxs]) || (p_tgm && p_tgm[xxt]) ) {
+ distance += PatchSSDDistanceMetric::kSSDScale;
+ continue;
+ }
+
+ int ssd = 0;
+ for (int c = 0; c < 3; ++c) {
+ int s_value = p_si[xxs * 3 + c];
+ int t_value = p_ti[xxt * 3 + c];
+ int s_gy = p_sgy[xxs * 3 + c];
+ int t_gy = p_tgy[xxt * 3 + c];
+ int s_gx = p_sgx[xxs * 3 + c];
+ int t_gx = p_tgx[xxt * 3 + c];
+
+ ssd += pow2(static_cast(s_value) - t_value);
+ ssd += pow2(static_cast(s_gx) - t_gx);
+ ssd += pow2(static_cast(s_gy) - t_gy);
+ }
+ distance += ssd;
+ }
+ }
+
+ distance /= (long double)(PatchSSDDistanceMetric::kSSDScale);
+
+ int res = int(PatchDistanceMetric::kDistanceScale * distance / wsum);
+ if (res < 0 || res > PatchDistanceMetric::kDistanceScale) return PatchDistanceMetric::kDistanceScale;
+ return res;
+}
+
+}
+
+int PatchSSDDistanceMetric::operator ()(const MaskedImage &source, int source_y, int source_x, const MaskedImage &target, int target_y, int target_x) const {
+ return distance_masked_images(source, source_y, source_x, target, target_y, target_x, m_patch_size);
+}
+
+int DebugPatchSSDDistanceMetric::operator ()(const MaskedImage &source, int source_y, int source_x, const MaskedImage &target, int target_y, int target_x) const {
+ fprintf(stderr, "DebugPatchSSDDistanceMetric: %d %d %d %d\n", source.size().width, source.size().height, m_width, m_height);
+ return distance_masked_images(source, source_y, source_x, target, target_y, target_x, m_patch_size);
+}
+
+int RegularityGuidedPatchDistanceMetricV1::operator ()(const MaskedImage &source, int source_y, int source_x, const MaskedImage &target, int target_y, int target_x) const {
+ double dx = remainder(double(source_x - target_x) / source.size().width, m_dx1);
+ double dy = remainder(double(source_y - target_y) / source.size().height, m_dy2);
+
+ double score1 = sqrt(dx * dx + dy *dy) / m_scale;
+ if (score1 < 0 || score1 > 1) score1 = 1;
+ score1 *= PatchDistanceMetric::kDistanceScale;
+
+ double score2 = distance_masked_images(source, source_y, source_x, target, target_y, target_x, m_patch_size);
+ double score = score1 * m_weight + score2 / (1 + m_weight);
+ return static_cast(score / (1 + m_weight));
+}
+
+int RegularityGuidedPatchDistanceMetricV2::operator ()(const MaskedImage &source, int source_y, int source_x, const MaskedImage &target, int target_y, int target_x) const {
+ if (target_y < 0 || target_y >= target.size().height || target_x < 0 || target_x >= target.size().width)
+ return PatchDistanceMetric::kDistanceScale;
+
+ int source_scale = m_ijmap.size().height / source.size().height;
+ int target_scale = m_ijmap.size().height / target.size().height;
+
+ // fprintf(stderr, "RegularityGuidedPatchDistanceMetricV2 %d %d %d %d\n", source_y * source_scale, m_ijmap.size().height, source_x * source_scale, m_ijmap.size().width);
+
+ double score1 = PatchDistanceMetric::kDistanceScale;
+ if (!source.is_globally_masked(source_y, source_x) && !target.is_globally_masked(target_y, target_x)) {
+ auto source_ij = m_ijmap.ptr(source_y * source_scale, source_x * source_scale);
+ auto target_ij = m_ijmap.ptr(target_y * target_scale, target_x * target_scale);
+
+ float di = fabs(source_ij[0] - target_ij[0]); if (di > 0.5) di = 1 - di;
+ float dj = fabs(source_ij[1] - target_ij[1]); if (dj > 0.5) dj = 1 - dj;
+ score1 = sqrt(di * di + dj *dj) / 0.707;
+ if (score1 < 0 || score1 > 1) score1 = 1;
+ score1 *= PatchDistanceMetric::kDistanceScale;
+ }
+
+ double score2 = distance_masked_images(source, source_y, source_x, target, target_y, target_x, m_patch_size);
+ double score = score1 * m_weight + score2;
+ return int(score / (1 + m_weight));
+}
+
diff --git a/stablediffusion-infinity/PyPatchMatch/csrc/nnf.h b/stablediffusion-infinity/PyPatchMatch/csrc/nnf.h
new file mode 100644
index 0000000000000000000000000000000000000000..b5c144a4a58649906c9c87a40044b5118a00aa04
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/csrc/nnf.h
@@ -0,0 +1,133 @@
+#pragma once
+
+#include
+#include "masked_image.h"
+
+class PatchDistanceMetric {
+public:
+ PatchDistanceMetric(int patch_size) : m_patch_size(patch_size) {}
+ virtual ~PatchDistanceMetric() = default;
+
+ inline int patch_size() const { return m_patch_size; }
+ virtual int operator()(const MaskedImage &source, int source_y, int source_x, const MaskedImage &target, int target_y, int target_x) const = 0;
+ static const int kDistanceScale;
+
+protected:
+ int m_patch_size;
+};
+
+class NearestNeighborField {
+public:
+ NearestNeighborField() : m_source(), m_target(), m_field(), m_distance_metric(nullptr) {
+ // pass
+ }
+ NearestNeighborField(const MaskedImage &source, const MaskedImage &target, const PatchDistanceMetric *metric, int max_retry = 20)
+ : m_source(source), m_target(target), m_distance_metric(metric) {
+ m_field = cv::Mat(m_source.size(), CV_32SC3);
+ _randomize_field(max_retry);
+ }
+ NearestNeighborField(const MaskedImage &source, const MaskedImage &target, const PatchDistanceMetric *metric, const NearestNeighborField &other, int max_retry = 20)
+ : m_source(source), m_target(target), m_distance_metric(metric) {
+ m_field = cv::Mat(m_source.size(), CV_32SC3);
+ _initialize_field_from(other, max_retry);
+ }
+
+ const MaskedImage &source() const {
+ return m_source;
+ }
+ const MaskedImage &target() const {
+ return m_target;
+ }
+ inline cv::Size source_size() const {
+ return m_source.size();
+ }
+ inline cv::Size target_size() const {
+ return m_target.size();
+ }
+ inline void set_source(const MaskedImage &source) {
+ m_source = source;
+ }
+ inline void set_target(const MaskedImage &target) {
+ m_target = target;
+ }
+
+ inline int *mutable_ptr(int y, int x) {
+ return m_field.ptr(y, x);
+ }
+ inline const int *ptr(int y, int x) const {
+ return m_field.ptr(y, x);
+ }
+
+ inline int at(int y, int x, int c) const {
+ return m_field.ptr(y, x)[c];
+ }
+ inline int &at(int y, int x, int c) {
+ return m_field.ptr(y, x)[c];
+ }
+ inline void set_identity(int y, int x) {
+ auto ptr = mutable_ptr(y, x);
+ ptr[0] = y, ptr[1] = x, ptr[2] = 0;
+ }
+
+ void minimize(int nr_pass);
+
+private:
+ inline int _distance(int source_y, int source_x, int target_y, int target_x) {
+ return (*m_distance_metric)(m_source, source_y, source_x, m_target, target_y, target_x);
+ }
+
+ void _randomize_field(int max_retry = 20, bool reset = true);
+ void _initialize_field_from(const NearestNeighborField &other, int max_retry);
+ void _minimize_link(int y, int x, int direction);
+
+ MaskedImage m_source;
+ MaskedImage m_target;
+ cv::Mat m_field; // { y_target, x_target, distance_scaled }
+ const PatchDistanceMetric *m_distance_metric;
+};
+
+
+class PatchSSDDistanceMetric : public PatchDistanceMetric {
+public:
+ using PatchDistanceMetric::PatchDistanceMetric;
+ virtual int operator ()(const MaskedImage &source, int source_y, int source_x, const MaskedImage &target, int target_y, int target_x) const;
+ static const int kSSDScale;
+};
+
+class DebugPatchSSDDistanceMetric : public PatchDistanceMetric {
+public:
+ DebugPatchSSDDistanceMetric(int patch_size, int width, int height) : PatchDistanceMetric(patch_size), m_width(width), m_height(height) {}
+ virtual int operator ()(const MaskedImage &source, int source_y, int source_x, const MaskedImage &target, int target_y, int target_x) const;
+protected:
+ int m_width, m_height;
+};
+
+class RegularityGuidedPatchDistanceMetricV1 : public PatchDistanceMetric {
+public:
+ RegularityGuidedPatchDistanceMetricV1(int patch_size, double dx1, double dy1, double dx2, double dy2, double weight)
+ : PatchDistanceMetric(patch_size), m_dx1(dx1), m_dy1(dy1), m_dx2(dx2), m_dy2(dy2), m_weight(weight) {
+
+ assert(m_dy1 == 0);
+ assert(m_dx2 == 0);
+ m_scale = sqrt(m_dx1 * m_dx1 + m_dy2 * m_dy2) / 4;
+ }
+ virtual int operator ()(const MaskedImage &source, int source_y, int source_x, const MaskedImage &target, int target_y, int target_x) const;
+
+protected:
+ double m_dx1, m_dy1, m_dx2, m_dy2;
+ double m_scale, m_weight;
+};
+
+class RegularityGuidedPatchDistanceMetricV2 : public PatchDistanceMetric {
+public:
+ RegularityGuidedPatchDistanceMetricV2(int patch_size, cv::Mat ijmap, double weight)
+ : PatchDistanceMetric(patch_size), m_ijmap(ijmap), m_weight(weight) {
+
+ }
+ virtual int operator ()(const MaskedImage &source, int source_y, int source_x, const MaskedImage &target, int target_y, int target_x) const;
+
+protected:
+ cv::Mat m_ijmap;
+ double m_width, m_height, m_weight;
+};
+
diff --git a/stablediffusion-infinity/PyPatchMatch/csrc/pyinterface.cpp b/stablediffusion-infinity/PyPatchMatch/csrc/pyinterface.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..612ccba6544ff111a2da0dce9adc4019858ebded
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/csrc/pyinterface.cpp
@@ -0,0 +1,107 @@
+#include "pyinterface.h"
+#include "inpaint.h"
+
+static unsigned int PM_seed = 1212;
+static bool PM_verbose = false;
+
+int _dtype_py_to_cv(int dtype_py);
+int _dtype_cv_to_py(int dtype_cv);
+cv::Mat _py_to_cv2(PM_mat_t pymat);
+PM_mat_t _cv2_to_py(cv::Mat cvmat);
+
+void PM_set_random_seed(unsigned int seed) {
+ PM_seed = seed;
+}
+
+void PM_set_verbose(int value) {
+ PM_verbose = static_cast(value);
+}
+
+void PM_free_pymat(PM_mat_t pymat) {
+ free(pymat.data_ptr);
+}
+
+PM_mat_t PM_inpaint(PM_mat_t source_py, PM_mat_t mask_py, int patch_size) {
+ cv::Mat source = _py_to_cv2(source_py);
+ cv::Mat mask = _py_to_cv2(mask_py);
+ auto metric = PatchSSDDistanceMetric(patch_size);
+ cv::Mat result = Inpainting(source, mask, &metric).run(PM_verbose, false, PM_seed);
+ return _cv2_to_py(result);
+}
+
+PM_mat_t PM_inpaint_regularity(PM_mat_t source_py, PM_mat_t mask_py, PM_mat_t ijmap_py, int patch_size, float guide_weight) {
+ cv::Mat source = _py_to_cv2(source_py);
+ cv::Mat mask = _py_to_cv2(mask_py);
+ cv::Mat ijmap = _py_to_cv2(ijmap_py);
+
+ auto metric = RegularityGuidedPatchDistanceMetricV2(patch_size, ijmap, guide_weight);
+ cv::Mat result = Inpainting(source, mask, &metric).run(PM_verbose, false, PM_seed);
+ return _cv2_to_py(result);
+}
+
+PM_mat_t PM_inpaint2(PM_mat_t source_py, PM_mat_t mask_py, PM_mat_t global_mask_py, int patch_size) {
+ cv::Mat source = _py_to_cv2(source_py);
+ cv::Mat mask = _py_to_cv2(mask_py);
+ cv::Mat global_mask = _py_to_cv2(global_mask_py);
+
+ auto metric = PatchSSDDistanceMetric(patch_size);
+ cv::Mat result = Inpainting(source, mask, global_mask, &metric).run(PM_verbose, false, PM_seed);
+ return _cv2_to_py(result);
+}
+
+PM_mat_t PM_inpaint2_regularity(PM_mat_t source_py, PM_mat_t mask_py, PM_mat_t global_mask_py, PM_mat_t ijmap_py, int patch_size, float guide_weight) {
+ cv::Mat source = _py_to_cv2(source_py);
+ cv::Mat mask = _py_to_cv2(mask_py);
+ cv::Mat global_mask = _py_to_cv2(global_mask_py);
+ cv::Mat ijmap = _py_to_cv2(ijmap_py);
+
+ auto metric = RegularityGuidedPatchDistanceMetricV2(patch_size, ijmap, guide_weight);
+ cv::Mat result = Inpainting(source, mask, global_mask, &metric).run(PM_verbose, false, PM_seed);
+ return _cv2_to_py(result);
+}
+
+int _dtype_py_to_cv(int dtype_py) {
+ switch (dtype_py) {
+ case PM_UINT8: return CV_8U;
+ case PM_INT8: return CV_8S;
+ case PM_UINT16: return CV_16U;
+ case PM_INT16: return CV_16S;
+ case PM_INT32: return CV_32S;
+ case PM_FLOAT32: return CV_32F;
+ case PM_FLOAT64: return CV_64F;
+ }
+
+ return CV_8U;
+}
+
+int _dtype_cv_to_py(int dtype_cv) {
+ switch (dtype_cv) {
+ case CV_8U: return PM_UINT8;
+ case CV_8S: return PM_INT8;
+ case CV_16U: return PM_UINT16;
+ case CV_16S: return PM_INT16;
+ case CV_32S: return PM_INT32;
+ case CV_32F: return PM_FLOAT32;
+ case CV_64F: return PM_FLOAT64;
+ }
+
+ return PM_UINT8;
+}
+
+cv::Mat _py_to_cv2(PM_mat_t pymat) {
+ int dtype = _dtype_py_to_cv(pymat.dtype);
+ dtype = CV_MAKETYPE(pymat.dtype, pymat.shape.channels);
+ return cv::Mat(cv::Size(pymat.shape.width, pymat.shape.height), dtype, pymat.data_ptr).clone();
+}
+
+PM_mat_t _cv2_to_py(cv::Mat cvmat) {
+ PM_shape_t shape = {cvmat.size().width, cvmat.size().height, cvmat.channels()};
+ int dtype = _dtype_cv_to_py(cvmat.depth());
+ size_t dsize = cvmat.total() * cvmat.elemSize();
+
+ void *data_ptr = reinterpret_cast(malloc(dsize));
+ memcpy(data_ptr, reinterpret_cast(cvmat.data), dsize);
+
+ return PM_mat_t {data_ptr, shape, dtype};
+}
+
diff --git a/stablediffusion-infinity/PyPatchMatch/csrc/pyinterface.h b/stablediffusion-infinity/PyPatchMatch/csrc/pyinterface.h
new file mode 100644
index 0000000000000000000000000000000000000000..e53c88ae9dfcea7f9766828168d3ad35a404b699
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/csrc/pyinterface.h
@@ -0,0 +1,38 @@
+#include
+#include
+#include
+#include
+
+extern "C" {
+
+struct PM_shape_t {
+ int width, height, channels;
+};
+
+enum PM_dtype_e {
+ PM_UINT8,
+ PM_INT8,
+ PM_UINT16,
+ PM_INT16,
+ PM_INT32,
+ PM_FLOAT32,
+ PM_FLOAT64,
+};
+
+struct PM_mat_t {
+ void *data_ptr;
+ PM_shape_t shape;
+ int dtype;
+};
+
+void PM_set_random_seed(unsigned int seed);
+void PM_set_verbose(int value);
+
+void PM_free_pymat(PM_mat_t pymat);
+PM_mat_t PM_inpaint(PM_mat_t image, PM_mat_t mask, int patch_size);
+PM_mat_t PM_inpaint_regularity(PM_mat_t image, PM_mat_t mask, PM_mat_t ijmap, int patch_size, float guide_weight);
+PM_mat_t PM_inpaint2(PM_mat_t image, PM_mat_t mask, PM_mat_t global_mask, int patch_size);
+PM_mat_t PM_inpaint2_regularity(PM_mat_t image, PM_mat_t mask, PM_mat_t global_mask, PM_mat_t ijmap, int patch_size, float guide_weight);
+
+} /* extern "C" */
+
diff --git a/stablediffusion-infinity/PyPatchMatch/examples/.gitignore b/stablediffusion-infinity/PyPatchMatch/examples/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..11dce30641933a33fce2b5d5b1bc1d0fa12a3d4a
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/examples/.gitignore
@@ -0,0 +1,2 @@
+/cpp_example.exe
+/images/*recovered.bmp
diff --git a/stablediffusion-infinity/PyPatchMatch/examples/cpp_example.cpp b/stablediffusion-infinity/PyPatchMatch/examples/cpp_example.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8f3ff5c52783cf1e9d6ec6a8a6017f857c372c0e
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/examples/cpp_example.cpp
@@ -0,0 +1,31 @@
+#include
+#include
+#include
+
+#include "masked_image.h"
+#include "nnf.h"
+#include "inpaint.h"
+
+int main() {
+ auto source = cv::imread("./images/forest_pruned.bmp", cv::IMREAD_COLOR);
+
+ auto mask = cv::Mat(source.size(), CV_8UC1);
+ mask = cv::Scalar::all(0);
+ for (int i = 0; i < source.size().height; ++i) {
+ for (int j = 0; j < source.size().width; ++j) {
+ auto source_ptr = source.ptr(i, j);
+ if (source_ptr[0] == 255 && source_ptr[1] == 255 && source_ptr[2] == 255) {
+ mask.at(i, j) = 1;
+ }
+ }
+ }
+
+ auto metric = PatchSSDDistanceMetric(3);
+ auto result = Inpainting(source, mask, &metric).run(true, true);
+ // cv::imwrite("./images/forest_recovered.bmp", result);
+ // cv::imshow("Result", result);
+ // cv::waitKey();
+
+ return 0;
+}
+
diff --git a/stablediffusion-infinity/PyPatchMatch/examples/cpp_example_run.sh b/stablediffusion-infinity/PyPatchMatch/examples/cpp_example_run.sh
new file mode 100755
index 0000000000000000000000000000000000000000..cfb62557fe4a5bb0ee1aa48d7aa8582c23f4e6fc
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/examples/cpp_example_run.sh
@@ -0,0 +1,18 @@
+#! /bin/bash
+#
+# cpp_example_run.sh
+# Copyright (C) 2020 Jiayuan Mao
+#
+# Distributed under terms of the MIT license.
+#
+
+set -x
+
+CFLAGS="-std=c++14 -O2 $(pkg-config --cflags opencv)"
+LDFLAGS="$(pkg-config --libs opencv)"
+g++ $CFLAGS cpp_example.cpp -I../csrc/ -L../ -lpatchmatch $LDFLAGS -o cpp_example.exe
+
+export DYLD_LIBRARY_PATH=../:$DYLD_LIBRARY_PATH # For macOS
+export LD_LIBRARY_PATH=../:$LD_LIBRARY_PATH # For Linux
+time ./cpp_example.exe
+
diff --git a/stablediffusion-infinity/PyPatchMatch/examples/images/forest.bmp b/stablediffusion-infinity/PyPatchMatch/examples/images/forest.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..5246857e492d00390014e5c117d2c41675e039f7
Binary files /dev/null and b/stablediffusion-infinity/PyPatchMatch/examples/images/forest.bmp differ
diff --git a/stablediffusion-infinity/PyPatchMatch/examples/images/forest_pruned.bmp b/stablediffusion-infinity/PyPatchMatch/examples/images/forest_pruned.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..67adb12cc2c19d1bbdb25bed643ad24c5cd927d9
Binary files /dev/null and b/stablediffusion-infinity/PyPatchMatch/examples/images/forest_pruned.bmp differ
diff --git a/stablediffusion-infinity/PyPatchMatch/examples/py_example.py b/stablediffusion-infinity/PyPatchMatch/examples/py_example.py
new file mode 100644
index 0000000000000000000000000000000000000000..fa1b526f87b065a6acda35e06d563be134ffb27b
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/examples/py_example.py
@@ -0,0 +1,21 @@
+#! /usr/bin/env python3
+# -*- coding: utf-8 -*-
+# File : test.py
+# Author : Jiayuan Mao
+# Email : maojiayuan@gmail.com
+# Date : 01/09/2020
+#
+# Distributed under terms of the MIT license.
+
+from PIL import Image
+
+import sys
+sys.path.insert(0, '../')
+import patch_match
+
+
+if __name__ == '__main__':
+ source = Image.open('./images/forest_pruned.bmp')
+ result = patch_match.inpaint(source, patch_size=3)
+ Image.fromarray(result).save('./images/forest_recovered.bmp')
+
diff --git a/stablediffusion-infinity/PyPatchMatch/examples/py_example_global_mask.py b/stablediffusion-infinity/PyPatchMatch/examples/py_example_global_mask.py
new file mode 100644
index 0000000000000000000000000000000000000000..9025cc4230edcce7cbfa545f55600a240994edcf
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/examples/py_example_global_mask.py
@@ -0,0 +1,27 @@
+#! /usr/bin/env python3
+# -*- coding: utf-8 -*-
+# File : test.py
+# Author : Jiayuan Mao
+# Email : maojiayuan@gmail.com
+# Date : 01/09/2020
+#
+# Distributed under terms of the MIT license.
+
+import numpy as np
+from PIL import Image
+
+import sys
+sys.path.insert(0, '../')
+import patch_match
+
+
+if __name__ == '__main__':
+ patch_match.set_verbose(True)
+ source = Image.open('./images/forest_pruned.bmp')
+ source = np.array(source)
+ source[:100, :100] = 255
+ global_mask = np.zeros_like(source[..., 0])
+ global_mask[:100, :100] = 1
+ result = patch_match.inpaint(source, global_mask=global_mask, patch_size=3)
+ Image.fromarray(result).save('./images/forest_recovered.bmp')
+
diff --git a/stablediffusion-infinity/PyPatchMatch/opencv.pc b/stablediffusion-infinity/PyPatchMatch/opencv.pc
new file mode 100644
index 0000000000000000000000000000000000000000..1443d54f179f8fd6432bb38e6a5182d423a192fd
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/opencv.pc
@@ -0,0 +1,11 @@
+prefix=/usr
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+
+Name: opencv
+Description: The opencv library
+Version: 2.x.x
+Cflags: -I${includedir}/opencv4
+#Cflags: -I${includedir}/opencv -I${includedir}/opencv2
+Libs: -L${libdir} -lopencv_calib3d -lopencv_imgproc -lopencv_xobjdetect -lopencv_hdf -lopencv_flann -lopencv_core -lopencv_dpm -lopencv_videoio -lopencv_reg -lopencv_objdetect -lopencv_stitching -lopencv_saliency -lopencv_features2d -lopencv_text -lopencv_calib3d -lopencv_line_descriptor -lopencv_superres -lopencv_ml -lopencv_viz -lopencv_optflow -lopencv_videostab -lopencv_bioinspired -lopencv_highgui -lopencv_freetype -lopencv_imgcodecs -lopencv_video -lopencv_photo -lopencv_surface_matching -lopencv_rgbd -lopencv_datasets -lopencv_ximgproc -lopencv_plot -lopencv_face -lopencv_stereo -lopencv_aruco -lopencv_phase_unwrapping -lopencv_bgsegm -lopencv_ccalib -lopencv_imgproc -lopencv_shape -lopencv_xphoto -lopencv_structured_light -lopencv_fuzzy
\ No newline at end of file
diff --git a/stablediffusion-infinity/PyPatchMatch/patch_match.py b/stablediffusion-infinity/PyPatchMatch/patch_match.py
new file mode 100644
index 0000000000000000000000000000000000000000..ff49288a5ac459e644a4cf5be95bb27c94e9bcd8
--- /dev/null
+++ b/stablediffusion-infinity/PyPatchMatch/patch_match.py
@@ -0,0 +1,191 @@
+#! /usr/bin/env python3
+# -*- coding: utf-8 -*-
+# File : patch_match.py
+# Author : Jiayuan Mao
+# Email : maojiayuan@gmail.com
+# Date : 01/09/2020
+#
+# Distributed under terms of the MIT license.
+
+import ctypes
+import os.path as osp
+from typing import Optional, Union
+
+import numpy as np
+from PIL import Image
+
+
+__all__ = ['set_random_seed', 'set_verbose', 'inpaint', 'inpaint_regularity']
+
+
+class CShapeT(ctypes.Structure):
+ _fields_ = [
+ ('width', ctypes.c_int),
+ ('height', ctypes.c_int),
+ ('channels', ctypes.c_int),
+ ]
+
+
+class CMatT(ctypes.Structure):
+ _fields_ = [
+ ('data_ptr', ctypes.c_void_p),
+ ('shape', CShapeT),
+ ('dtype', ctypes.c_int)
+ ]
+
+
+PMLIB = ctypes.CDLL(osp.join(osp.dirname(__file__), 'libpatchmatch.so'))
+
+PMLIB.PM_set_random_seed.argtypes = [ctypes.c_uint]
+PMLIB.PM_set_verbose.argtypes = [ctypes.c_int]
+PMLIB.PM_free_pymat.argtypes = [CMatT]
+PMLIB.PM_inpaint.argtypes = [CMatT, CMatT, ctypes.c_int]
+PMLIB.PM_inpaint.restype = CMatT
+PMLIB.PM_inpaint_regularity.argtypes = [CMatT, CMatT, CMatT, ctypes.c_int, ctypes.c_float]
+PMLIB.PM_inpaint_regularity.restype = CMatT
+PMLIB.PM_inpaint2.argtypes = [CMatT, CMatT, CMatT, ctypes.c_int]
+PMLIB.PM_inpaint2.restype = CMatT
+PMLIB.PM_inpaint2_regularity.argtypes = [CMatT, CMatT, CMatT, CMatT, ctypes.c_int, ctypes.c_float]
+PMLIB.PM_inpaint2_regularity.restype = CMatT
+
+
+def set_random_seed(seed: int):
+ PMLIB.PM_set_random_seed(ctypes.c_uint(seed))
+
+
+def set_verbose(verbose: bool):
+ PMLIB.PM_set_verbose(ctypes.c_int(verbose))
+
+
+def inpaint(
+ image: Union[np.ndarray, Image.Image],
+ mask: Optional[Union[np.ndarray, Image.Image]] = None,
+ *,
+ global_mask: Optional[Union[np.ndarray, Image.Image]] = None,
+ patch_size: int = 15
+) -> np.ndarray:
+ """
+ PatchMatch based inpainting proposed in:
+
+ PatchMatch : A Randomized Correspondence Algorithm for Structural Image Editing
+ C.Barnes, E.Shechtman, A.Finkelstein and Dan B.Goldman
+ SIGGRAPH 2009
+
+ Args:
+ image (Union[np.ndarray, Image.Image]): the input image, should be 3-channel RGB/BGR.
+ mask (Union[np.array, Image.Image], optional): the mask of the hole(s) to be filled, should be 1-channel.
+ If not provided (None), the algorithm will treat all purely white pixels as the holes (255, 255, 255).
+ global_mask (Union[np.array, Image.Image], optional): the target mask of the output image.
+ patch_size (int): the patch size for the inpainting algorithm.
+
+ Return:
+ result (np.ndarray): the repaired image, of the same size as the input image.
+ """
+
+ if isinstance(image, Image.Image):
+ image = np.array(image)
+ image = np.ascontiguousarray(image)
+ assert image.ndim == 3 and image.shape[2] == 3 and image.dtype == 'uint8'
+
+ if mask is None:
+ mask = (image == (255, 255, 255)).all(axis=2, keepdims=True).astype('uint8')
+ mask = np.ascontiguousarray(mask)
+ else:
+ mask = _canonize_mask_array(mask)
+
+ if global_mask is None:
+ ret_pymat = PMLIB.PM_inpaint(np_to_pymat(image), np_to_pymat(mask), ctypes.c_int(patch_size))
+ else:
+ global_mask = _canonize_mask_array(global_mask)
+ ret_pymat = PMLIB.PM_inpaint2(np_to_pymat(image), np_to_pymat(mask), np_to_pymat(global_mask), ctypes.c_int(patch_size))
+
+ ret_npmat = pymat_to_np(ret_pymat)
+ PMLIB.PM_free_pymat(ret_pymat)
+
+ return ret_npmat
+
+
+def inpaint_regularity(
+ image: Union[np.ndarray, Image.Image],
+ mask: Optional[Union[np.ndarray, Image.Image]],
+ ijmap: np.ndarray,
+ *,
+ global_mask: Optional[Union[np.ndarray, Image.Image]] = None,
+ patch_size: int = 15, guide_weight: float = 0.25
+) -> np.ndarray:
+ if isinstance(image, Image.Image):
+ image = np.array(image)
+ image = np.ascontiguousarray(image)
+
+ assert isinstance(ijmap, np.ndarray) and ijmap.ndim == 3 and ijmap.shape[2] == 3 and ijmap.dtype == 'float32'
+ ijmap = np.ascontiguousarray(ijmap)
+
+ assert image.ndim == 3 and image.shape[2] == 3 and image.dtype == 'uint8'
+ if mask is None:
+ mask = (image == (255, 255, 255)).all(axis=2, keepdims=True).astype('uint8')
+ mask = np.ascontiguousarray(mask)
+ else:
+ mask = _canonize_mask_array(mask)
+
+
+ if global_mask is None:
+ ret_pymat = PMLIB.PM_inpaint_regularity(np_to_pymat(image), np_to_pymat(mask), np_to_pymat(ijmap), ctypes.c_int(patch_size), ctypes.c_float(guide_weight))
+ else:
+ global_mask = _canonize_mask_array(global_mask)
+ ret_pymat = PMLIB.PM_inpaint2_regularity(np_to_pymat(image), np_to_pymat(mask), np_to_pymat(global_mask), np_to_pymat(ijmap), ctypes.c_int(patch_size), ctypes.c_float(guide_weight))
+
+ ret_npmat = pymat_to_np(ret_pymat)
+ PMLIB.PM_free_pymat(ret_pymat)
+
+ return ret_npmat
+
+
+def _canonize_mask_array(mask):
+ if isinstance(mask, Image.Image):
+ mask = np.array(mask)
+ if mask.ndim == 2 and mask.dtype == 'uint8':
+ mask = mask[..., np.newaxis]
+ assert mask.ndim == 3 and mask.shape[2] == 1 and mask.dtype == 'uint8'
+ return np.ascontiguousarray(mask)
+
+
+dtype_pymat_to_ctypes = [
+ ctypes.c_uint8,
+ ctypes.c_int8,
+ ctypes.c_uint16,
+ ctypes.c_int16,
+ ctypes.c_int32,
+ ctypes.c_float,
+ ctypes.c_double,
+]
+
+
+dtype_np_to_pymat = {
+ 'uint8': 0,
+ 'int8': 1,
+ 'uint16': 2,
+ 'int16': 3,
+ 'int32': 4,
+ 'float32': 5,
+ 'float64': 6,
+}
+
+
+def np_to_pymat(npmat):
+ assert npmat.ndim == 3
+ return CMatT(
+ ctypes.cast(npmat.ctypes.data, ctypes.c_void_p),
+ CShapeT(npmat.shape[1], npmat.shape[0], npmat.shape[2]),
+ dtype_np_to_pymat[str(npmat.dtype)]
+ )
+
+
+def pymat_to_np(pymat):
+ npmat = np.ctypeslib.as_array(
+ ctypes.cast(pymat.data_ptr, ctypes.POINTER(dtype_pymat_to_ctypes[pymat.dtype])),
+ (pymat.shape.height, pymat.shape.width, pymat.shape.channels)
+ )
+ ret = np.empty(npmat.shape, npmat.dtype)
+ ret[:] = npmat
+ return ret
+
diff --git a/stablediffusion-infinity/app.py b/stablediffusion-infinity/app.py
new file mode 100644
index 0000000000000000000000000000000000000000..6f9f20e1a70fdf59daad84974303254b65920253
--- /dev/null
+++ b/stablediffusion-infinity/app.py
@@ -0,0 +1,427 @@
+import io
+import os
+
+from huggingface_hub import Repository
+
+from pathlib import Path
+import uvicorn
+from fastapi import FastAPI, HTTPException, UploadFile, Depends, status, Request
+from fastapi.staticfiles import StaticFiles
+from fastapi.middleware.cors import CORSMiddleware
+from fastapi_utils.tasks import repeat_every
+
+import numpy as np
+import torch
+from torch import autocast
+from diffusers import StableDiffusionInpaintPipeline
+from diffusers.models import AutoencoderKL
+
+from PIL import Image
+import gradio as gr
+import skimage
+import skimage.measure
+from utils import *
+import boto3
+import magic
+import sqlite3
+import requests
+import shortuuid
+import re
+import time
+import subprocess
+
+AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID')
+AWS_SECRET_KEY = os.getenv('AWS_SECRET_KEY')
+AWS_S3_BUCKET_NAME = os.getenv('AWS_S3_BUCKET_NAME')
+LIVEBLOCKS_SECRET = os.environ.get("LIVEBLOCKS_SECRET")
+HF_TOKEN = os.environ.get("API_TOKEN") or True
+
+FILE_TYPES = {
+ 'image/png': 'png',
+ 'image/jpeg': 'jpg',
+ 'imager/webp': 'webp',
+}
+S3_DATA_FOLDER = Path("sd-multiplayer-data")
+ROOMS_DATA_DB = S3_DATA_FOLDER / "rooms_data.db"
+ROOM_DB = Path("rooms.db")
+
+app = FastAPI()
+
+repo = Repository(
+ local_dir=S3_DATA_FOLDER,
+ repo_type="dataset",
+ clone_from="huggingface-projects/sd-multiplayer-data",
+ use_auth_token=True,
+)
+
+if not ROOM_DB.exists():
+ print("Creating database")
+ print("ROOM_DB", ROOM_DB)
+ db = sqlite3.connect(ROOM_DB)
+ with open(Path("schema.sql"), "r") as f:
+ db.executescript(f.read())
+ db.commit()
+ db.close()
+
+
+def get_room_db():
+ db = sqlite3.connect(ROOM_DB, check_same_thread=False)
+ db.row_factory = sqlite3.Row
+ try:
+ yield db
+ except Exception:
+ db.rollback()
+ finally:
+ db.close()
+
+
+def get_room_data_db():
+ db = sqlite3.connect(ROOMS_DATA_DB, check_same_thread=False)
+ db.row_factory = sqlite3.Row
+ try:
+ yield db
+ except Exception:
+ db.rollback()
+ finally:
+ db.close()
+
+
+s3 = boto3.client(service_name='s3',
+ aws_access_key_id=AWS_ACCESS_KEY_ID,
+ aws_secret_access_key=AWS_SECRET_KEY)
+try:
+ SAMPLING_MODE = Image.Resampling.LANCZOS
+except Exception as e:
+ SAMPLING_MODE = Image.LANCZOS
+
+
+blocks = gr.Blocks().queue()
+model = {}
+
+STATIC_MASK = Image.open("mask.png")
+
+
+def sync_rooms_data_repo():
+ subprocess.Popen("git fetch && git reset --hard origin/main",
+ cwd=S3_DATA_FOLDER, shell=True)
+
+
+def get_model():
+ if "inpaint" not in model:
+ vae = AutoencoderKL.from_pretrained(f"stabilityai/sd-vae-ft-ema")
+ inpaint = StableDiffusionInpaintPipeline.from_pretrained(
+ "radames/stable-diffusion-v2-inpainting",
+ torch_dtype=torch.float16,
+ vae=vae,
+ ).to("cuda")
+ model["inpaint"] = inpaint
+
+ return model["inpaint"]
+
+
+# init model on startup
+get_model()
+
+
+async def run_outpaint(
+ input_image,
+ prompt_text,
+ strength,
+ guidance,
+ step,
+ fill_mode,
+ room_id,
+ image_key
+):
+ inpaint = get_model()
+ sel_buffer = np.array(input_image)
+ img = sel_buffer[:, :, 0:3]
+ mask = sel_buffer[:, :, -1]
+ nmask = 255 - mask
+ process_size = 512
+
+ if nmask.sum() < 1:
+ print("inpaiting with fixed Mask")
+ mask = np.array(STATIC_MASK)[:, :, 0]
+ img, mask = functbl[fill_mode](img, mask)
+ init_image = Image.fromarray(img)
+ mask = 255 - mask
+ mask = skimage.measure.block_reduce(mask, (8, 8), np.max)
+ mask = mask.repeat(8, axis=0).repeat(8, axis=1)
+ mask_image = Image.fromarray(mask)
+ elif mask.sum() > 0:
+ print("inpainting")
+ img, mask = functbl[fill_mode](img, mask)
+ init_image = Image.fromarray(img)
+ mask = 255 - mask
+ mask = skimage.measure.block_reduce(mask, (8, 8), np.max)
+ mask = mask.repeat(8, axis=0).repeat(8, axis=1)
+ mask_image = Image.fromarray(mask)
+
+ # mask_image=mask_image.filter(ImageFilter.GaussianBlur(radius = 8))
+ else:
+ print("text2image")
+ print("inpainting")
+ img, mask = functbl[fill_mode](img, mask)
+ init_image = Image.fromarray(img)
+ mask = 255 - mask
+ mask = skimage.measure.block_reduce(mask, (8, 8), np.max)
+ mask = mask.repeat(8, axis=0).repeat(8, axis=1)
+ mask_image = Image.fromarray(mask)
+
+ # mask_image=mask_image.filter(ImageFilter.GaussianBlur(radius = 8))
+ with autocast("cuda"):
+ output = inpaint(
+ prompt=prompt_text,
+ image=init_image.resize(
+ (process_size, process_size), resample=SAMPLING_MODE
+ ),
+ mask_image=mask_image.resize((process_size, process_size)),
+ strength=strength,
+ num_inference_steps=step,
+ guidance_scale=guidance,
+ )
+ image = output["images"][0]
+ is_nsfw = output["nsfw_content_detected"][0]
+ image_url = {}
+
+ if not is_nsfw:
+ # print("not nsfw, uploading")
+ image_url = await upload_file(image, prompt_text, room_id, image_key)
+
+ params = {
+ "is_nsfw": is_nsfw,
+ "image": image_url
+ }
+ return params
+
+
+with blocks as demo:
+
+ with gr.Row():
+
+ with gr.Column(scale=3, min_width=270):
+ sd_prompt = gr.Textbox(
+ label="Prompt", placeholder="input your prompt here", lines=4
+ )
+ with gr.Column(scale=2, min_width=150):
+ sd_strength = gr.Slider(
+ label="Strength", minimum=0.0, maximum=1.0, value=0.75, step=0.01
+ )
+ with gr.Column(scale=1, min_width=150):
+ sd_step = gr.Number(label="Step", value=50, precision=0)
+ sd_guidance = gr.Number(label="Guidance", value=7.5)
+ with gr.Row():
+ with gr.Column(scale=4, min_width=600):
+ init_mode = gr.Radio(
+ label="Init mode",
+ choices=[
+ "patchmatch",
+ "edge_pad",
+ "cv2_ns",
+ "cv2_telea",
+ "gaussian",
+ "perlin",
+ ],
+ value="patchmatch",
+ type="value",
+ )
+
+ model_input = gr.Image(label="Input", type="pil", image_mode="RGBA")
+ room_id = gr.Textbox(label="Room ID")
+ image_key = gr.Textbox(label="image_key")
+ proceed_button = gr.Button("Proceed", elem_id="proceed")
+ params = gr.JSON()
+
+ proceed_button.click(
+ fn=run_outpaint,
+ inputs=[
+ model_input,
+ sd_prompt,
+ sd_strength,
+ sd_guidance,
+ sd_step,
+ init_mode,
+ room_id,
+ image_key
+ ],
+ outputs=[params],
+ )
+
+
+blocks.config['dev_mode'] = False
+
+app = gr.mount_gradio_app(app, blocks, "/gradio",
+ gradio_api_url="http://0.0.0.0:7860/gradio/")
+
+
+def generateAuthToken():
+ response = requests.get(f"https://liveblocks.io/api/authorize",
+ headers={"Authorization": f"Bearer {LIVEBLOCKS_SECRET}"})
+ if response.status_code == 200:
+ data = response.json()
+ return data["token"]
+ else:
+ raise Exception(response.status_code, response.text)
+
+
+def get_room_count(room_id: str):
+ response = requests.get(
+ f"https://api.liveblocks.io/v2/rooms/{room_id}/active_users",
+ headers={"Authorization": f"Bearer {LIVEBLOCKS_SECRET}", "Content-Type": "application/json"})
+ if response.status_code == 200:
+ res = response.json()
+ if "data" in res:
+ return len(res["data"])
+ else:
+ return 0
+ raise Exception("Error getting room count")
+
+
+@ app.on_event("startup")
+@ repeat_every(seconds=100)
+def sync_rooms():
+ print("Syncing rooms active users")
+ try:
+ for db in get_room_db():
+ rooms = db.execute("SELECT * FROM rooms").fetchall()
+ for row in rooms:
+ room_id = row["room_id"]
+ users_count = get_room_count(room_id)
+ cursor = db.cursor()
+ cursor.execute(
+ "UPDATE rooms SET users_count = ? WHERE room_id = ?", (users_count, room_id))
+ db.commit()
+ except Exception as e:
+ print(e)
+ print("Rooms update failed")
+
+
+@ app.on_event("startup")
+@ repeat_every(seconds=300)
+def sync_room_datq():
+ print("Sync rooms data")
+ sync_rooms_data_repo()
+
+
+@ app.get('/api/room_data/{room_id}')
+async def get_rooms_data(room_id: str, start: str = None, end: str = None, db: sqlite3.Connection = Depends(get_room_data_db)):
+ print("Getting rooms data", room_id, start, end)
+
+ if start is None and end is None:
+ rooms_rows = db.execute(
+ "SELECT key, prompt, time, x, y FROM rooms_data WHERE room_id = ? ORDER BY time", (room_id,)).fetchall()
+ elif end is None:
+ rooms_rows = db.execute("SELECT key, prompt, time, x, y FROM rooms_data WHERE room_id = ? AND time >= ? ORDER BY time",
+ (room_id, start)).fetchall()
+ elif start is None:
+ rooms_rows = db.execute("SELECT key, prompt, time, x, y FROM rooms_data WHERE room_id = ? AND time <= ? ORDER BY time",
+ (room_id, end)).fetchall()
+ else:
+ rooms_rows = db.execute("SELECT key, prompt, time, x, y FROM rooms_data WHERE room_id = ? AND time >= ? AND time <= ? ORDER BY time",
+ (room_id, start, end)).fetchall()
+ return rooms_rows
+
+
+@ app.get('/api/rooms')
+async def get_rooms(db: sqlite3.Connection = Depends(get_room_db)):
+ print("Getting rooms")
+ rooms = db.execute("SELECT * FROM rooms").fetchall()
+ return rooms
+
+
+@ app.post('/api/auth')
+async def autorize(request: Request):
+ data = await request.json()
+ room = data["room"]
+ payload = {
+ "userId": str(shortuuid.uuid()),
+ "userInfo": {
+ "name": "Anon"
+ }}
+
+ response = requests.post(f"https://api.liveblocks.io/v2/rooms/{room}/authorize",
+ headers={"Authorization": f"Bearer {LIVEBLOCKS_SECRET}"}, json=payload)
+ if response.status_code == 200:
+ # user in, incremente room count
+ # cursor = db.cursor()
+ # cursor.execute(
+ # "UPDATE rooms SET users_count = users_count + 1 WHERE room_id = ?", (room,))
+ # db.commit()
+ sync_rooms()
+ return response.json()
+ else:
+ raise Exception(response.status_code, response.text)
+
+
+def slugify(value):
+ value = re.sub(r'[^\w\s-]', '', value).strip().lower()
+ out = re.sub(r'[-\s]+', '-', value)
+ return out[:400]
+
+
+async def upload_file(image: Image.Image, prompt: str, room_id: str, image_key: str):
+ room_id = room_id.strip() or "uploads"
+ image_key = image_key.strip() or ""
+ image = image.convert('RGB')
+ # print("Uploading file from predict")
+ temp_file = io.BytesIO()
+ image.save(temp_file, format="WEBP")
+ temp_file.seek(0)
+ id = shortuuid.uuid()
+ date = int(time.time())
+ prompt_slug = slugify(prompt)
+ filename = f"{date}-{id}-{image_key}-{prompt_slug}.webp"
+ timelapse_name = f"{id}.webp"
+ key_name = f"{room_id}/{filename}"
+ s3.upload_fileobj(Fileobj=temp_file, Bucket=AWS_S3_BUCKET_NAME, Key=key_name, ExtraArgs={"ContentType": "image/webp", "CacheControl": "max-age=31536000"})
+ s3.copy_object(Bucket=AWS_S3_BUCKET_NAME, CopySource=f"{AWS_S3_BUCKET_NAME}/{key_name}", Key=f"timelapse/{room_id}/{timelapse_name}")
+
+ temp_file.close()
+
+ out = {"url": f'https://d26smi9133w0oo.cloudfront.net/{room_id}/{filename}',
+ "filename": filename}
+ return out
+
+
+@ app.post('/api/uploadfile')
+async def create_upload_file(file: UploadFile):
+ contents = await file.read()
+ file_size = len(contents)
+ if not 0 < file_size < 100E+06:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail='Supported file size is less than 2 MB'
+ )
+ file_type = magic.from_buffer(contents, mime=True)
+ if file_type.lower() not in FILE_TYPES:
+ raise HTTPException(
+ status_code=status.HTTP_400_BAD_REQUEST,
+ detail=f'Unsupported file type {file_type}. Supported types are {FILE_TYPES}'
+ )
+ temp_file = io.BytesIO()
+ temp_file.write(contents)
+ temp_file.seek(0)
+ s3.upload_fileobj(Fileobj=temp_file, Bucket=AWS_S3_BUCKET_NAME, Key="community/" +
+ file.filename, ExtraArgs={"ContentType": file.content_type, "CacheControl": "max-age=31536000"})
+ temp_file.close()
+
+ return {"url": f'https://d26smi9133w0oo.cloudfront.net/community/{file.filename}', "filename": file.filename}
+
+
+app.mount("/", StaticFiles(directory="../static", html=True), name="static")
+
+origins = ["*"]
+
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=origins,
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+
+
+if __name__ == "__main__":
+ uvicorn.run(app, host="0.0.0.0", port=7860,
+ log_level="debug", reload=False)
diff --git a/stablediffusion-infinity/createRooms.py b/stablediffusion-infinity/createRooms.py
new file mode 100644
index 0000000000000000000000000000000000000000..fec2d93e09ea0604d0d3b59324ecc08f9868cd3d
--- /dev/null
+++ b/stablediffusion-infinity/createRooms.py
@@ -0,0 +1,131 @@
+import os
+from fastapi import Depends, FastAPI
+import sqlite3
+import requests
+import uvicorn
+from pathlib import Path
+import json
+
+app = FastAPI()
+LIVEBLOCKS_SECRET = os.environ.get("LIVEBLOCKS_SECRET")
+
+DB_PATH = Path("rooms.db")
+if not DB_PATH.exists():
+ print("Creating database")
+ print("DB_PATH", DB_PATH)
+ db = sqlite3.connect(DB_PATH)
+ with open(Path("schema.sql"), "r") as f:
+ db.executescript(f.read())
+ db.commit()
+ db.close()
+
+
+def get_db():
+ db = sqlite3.connect(Path("./rooms.db"), check_same_thread=False)
+ print("Connected to database")
+ db.row_factory = sqlite3.Row
+ try:
+ yield db
+ except Exception:
+ db.rollback()
+ finally:
+ db.close()
+
+
+app = FastAPI()
+
+rooms = ["room-" + str(i) for i in range(0, 41)]
+
+
+@app.get("/")
+async def read_root(db: sqlite3.Connection = Depends(get_db)):
+ out = db.execute("SELECT * FROM rooms").fetchall()
+ print(out)
+ return out
+
+
+@app.get("/create-rooms")
+async def create_room(db: sqlite3.Connection = Depends(get_db)):
+ for room_id in rooms:
+ print(room_id)
+ createRoom(room_id, db)
+ all = db.execute("SELECT * FROM rooms").fetchall()
+ return all
+
+
+@app.get("/create-one-room/{room_id}")
+async def create_one_room(room_id: str):
+ payload = {"id": room_id, "defaultAccesses": ["room:write"]}
+
+ response = requests.post(f"https://api.liveblocks.io/v2/rooms",
+ headers={"Authorization": f"Bearer {LIVEBLOCKS_SECRET}"}, json=payload)
+ data = response.json()
+ return data
+
+
+def createRoom(room_id, db):
+ payload = {"id": room_id, "defaultAccesses": ["room:write"]}
+
+ response = requests.post(f"https://api.liveblocks.io/v2/rooms",
+ headers={"Authorization": f"Bearer {LIVEBLOCKS_SECRET}"}, json=payload)
+ # if response.status_code == 200:
+ data = response.json()
+ print(data)
+ if "error" in data and data["error"] == "ROOM_ALREADY_EXISTS":
+ print("Room already exists")
+
+ cursor = db.cursor()
+ cursor.execute("INSERT INTO rooms (room_id) VALUES (?)", (room_id,))
+ db.commit()
+ print("Room created")
+
+ print("Created room", room_id)
+ return True
+
+
+def generateAuthToken():
+ response = requests.get(f"https://liveblocks.io/api/authorize",
+ headers={"Authorization": f"Bearer {LIVEBLOCKS_SECRET}"})
+ if response.status_code == 200:
+ data = response.json()
+ return data["token"]
+ else:
+ raise Exception(response.status_code, response.text)
+
+
+def get_room_count(room_id: str, jwtToken: str = ''):
+ print("Getting room count" + room_id)
+ response = requests.get(
+ f"https://liveblocks.net/api/v1/room/{room_id}/users", headers={"Authorization": f"Bearer {jwtToken}", "Content-Type": "application/json"})
+ if response.status_code == 200:
+ res = response.json()
+ if "data" in res:
+ return len(res["data"])
+ else:
+ return 0
+ raise Exception("Error getting room count")
+
+
+@app.get("/sync-rooms")
+async def sync_rooms(db: sqlite3.Connection = Depends(get_db)):
+ try:
+ jwtToken = generateAuthToken()
+ rooms = db.execute("SELECT * FROM rooms").fetchall()
+ for row in rooms:
+ room_id = row["room_id"]
+ users_count = get_room_count(room_id, jwtToken)
+ print("Updating room", room_id, "with", users_count, "users")
+ cursor = db.cursor()
+ cursor.execute(
+ "UPDATE rooms SET users_count = ? WHERE room_id = ?", (users_count, room_id))
+ db.commit()
+ data = db.execute("SELECT * FROM rooms").fetchall()
+ return data
+ except Exception as e:
+ print(e)
+ return {"error": str(e)}
+
+
+if __name__ == "__main__":
+ uvicorn.run("createRooms:app", host="0.0.0.0",
+ log_level="debug", reload=True)
diff --git a/stablediffusion-infinity/mask.png b/stablediffusion-infinity/mask.png
new file mode 100644
index 0000000000000000000000000000000000000000..08f00b7707a8877a9b5359b45cdebc8952fceb7d
Binary files /dev/null and b/stablediffusion-infinity/mask.png differ
diff --git a/stablediffusion-infinity/perlin2d.py b/stablediffusion-infinity/perlin2d.py
new file mode 100644
index 0000000000000000000000000000000000000000..917c2c6511f5f1a75a284be9a9fef3248d82f2f9
--- /dev/null
+++ b/stablediffusion-infinity/perlin2d.py
@@ -0,0 +1,45 @@
+import numpy as np
+
+##########
+# https://stackoverflow.com/questions/42147776/producing-2d-perlin-noise-with-numpy/42154921#42154921
+def perlin(x, y, seed=0):
+ # permutation table
+ np.random.seed(seed)
+ p = np.arange(256, dtype=int)
+ np.random.shuffle(p)
+ p = np.stack([p, p]).flatten()
+ # coordinates of the top-left
+ xi, yi = x.astype(int), y.astype(int)
+ # internal coordinates
+ xf, yf = x - xi, y - yi
+ # fade factors
+ u, v = fade(xf), fade(yf)
+ # noise components
+ n00 = gradient(p[p[xi] + yi], xf, yf)
+ n01 = gradient(p[p[xi] + yi + 1], xf, yf - 1)
+ n11 = gradient(p[p[xi + 1] + yi + 1], xf - 1, yf - 1)
+ n10 = gradient(p[p[xi + 1] + yi], xf - 1, yf)
+ # combine noises
+ x1 = lerp(n00, n10, u)
+ x2 = lerp(n01, n11, u) # FIX1: I was using n10 instead of n01
+ return lerp(x1, x2, v) # FIX2: I also had to reverse x1 and x2 here
+
+
+def lerp(a, b, x):
+ "linear interpolation"
+ return a + x * (b - a)
+
+
+def fade(t):
+ "6t^5 - 15t^4 + 10t^3"
+ return 6 * t ** 5 - 15 * t ** 4 + 10 * t ** 3
+
+
+def gradient(h, x, y):
+ "grad converts h to the right gradient vector and return the dot product with (x,y)"
+ vectors = np.array([[0, 1], [0, -1], [1, 0], [-1, 0]])
+ g = vectors[h % 4]
+ return g[:, :, 0] * x + g[:, :, 1] * y
+
+
+##########
\ No newline at end of file
diff --git a/stablediffusion-infinity/readme.md b/stablediffusion-infinity/readme.md
new file mode 100644
index 0000000000000000000000000000000000000000..c6df1d3329a329e7cbefa70da6eb24b03b150aed
--- /dev/null
+++ b/stablediffusion-infinity/readme.md
@@ -0,0 +1,93 @@
+# stablediffusion-infinity
+
+Outpainting with Stable Diffusion on an infinite canvas.
+
+[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/lkwq007/stablediffusion-infinity/blob/master/stablediffusion_infinity_colab.ipynb)
+
+Start with init_image:
+
+
+
+https://user-images.githubusercontent.com/1665437/190231611-fc263115-0fb9-4f2d-a71b-7e500c1e311d.mp4
+
+
+Start with text2img:
+
+https://user-images.githubusercontent.com/1665437/190212025-f4a82c46-0ff1-4ca2-b79b-6c81601e3eed.mp4
+
+
+It is recommended to run the notebook on a local server for better interactive control.
+
+The notebook might work on Windows (see this issue https://github.com/lkwq007/stablediffusion-infinity/issues/12 for more information) and Apple Silicon devices (untested, check guide here: https://huggingface.co/docs/diffusers/optimization/mps).
+
+## Status
+
+This project mainly works as a proof of concept. In that case, the UI design is relatively weak, and the quality of results is not guaranteed.
+You may need to do prompt engineering or change the size of the selection box to get better outpainting results.
+
+Pull requests are welcome for better UI control, ideas to achieve better results, or any other improvements.
+
+## Setup environment
+setup with `environment.yml`
+```
+git clone --recurse-submodules https://github.com/lkwq007/stablediffusion-infinity
+cd stablediffusion-infinity
+conda env create -f environment.yml
+```
+
+if the `environment.yml` doesn't work for you, you may install dependencies manually:
+```
+conda create -n sd-inf python=3.10
+conda activate sd-inf
+conda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch
+conda install scipy scikit-image
+conda install -c conda-forge diffusers transformers ftfy
+pip install opencv-python
+pip install gradio==3.4
+```
+
+For windows, you may need to replace `pip install opencv-python` with `conda install -c conda-forge opencv`
+## CPP library (optional)
+
+Note that `opencv` library (e.g. `libopencv-dev`/`opencv-devel`, the package name may differ on different distributions) is required for `PyPatchMatch`. You may need to install `opencv` by yourself. If no `opencv` installed, the `patch_match` option (usually better quality) won't work.
+
+## How-to
+
+```
+conda activate sd-inf
+python app.py
+```
+
+## Running with Docker
+
+This should get you started without needing to manually install anything, except for having an environment with Docker installed and an Nvidia GPU.
+This has been tested on Docker Desktop on Windows 10 using the WSL2 backend.
+
+First, update the .env file with your Huggingface token from https://huggingface.co/settings/tokens
+
+Open your shell that has docker and run these commands
+
+```
+cd stablediffusion-infinity
+docker-compose build
+docker-compose up
+```
+
+Watch the log for the url to open in your browser. Choose the one that starts with http://127.0.0.1:8888/
+
+
+## FAQs
+
+- Troubleshooting on Windows:
+ - https://github.com/lkwq007/stablediffusion-infinity/issues/12
+- False positive rate of safety checker is quite high:
+ - https://github.com/lkwq007/stablediffusion-infinity/issues/8#issuecomment-1248448453
+- What is the init_mode
+ - init_mode indicates how to fill the empty/masked region, usually `patch_match` is better than others
+- The GUI is lagging on colab
+ - It is recommended to run the notebook on a local server since the interactions and canvas content updates are actually handled by the python backend on the serverside, and that's how `ipycanvas` works
+ - colab doesn't support the latest version of `ipycanvas`, which may have better performance
+
+## Credit
+
+The code of `perlin2d.py` is from https://stackoverflow.com/questions/42147776/producing-2d-perlin-noise-with-numpy/42154921#42154921 and is **not** included in the scope of LICENSE used in this repo.
diff --git a/stablediffusion-infinity/schema.sql b/stablediffusion-infinity/schema.sql
new file mode 100644
index 0000000000000000000000000000000000000000..667b3dd060d8b1b045d0ca38a5f4f298ba08aa04
--- /dev/null
+++ b/stablediffusion-infinity/schema.sql
@@ -0,0 +1,47 @@
+PRAGMA foreign_keys=OFF;
+BEGIN TRANSACTION;
+CREATE TABLE rooms (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, room_id TEXT NOT NULL, users_count INTEGER NOT NULL DEFAULT 0);
+INSERT INTO rooms VALUES(1,'room-0',0);
+INSERT INTO rooms VALUES(2,'room-1',0);
+INSERT INTO rooms VALUES(3,'room-2',0);
+INSERT INTO rooms VALUES(4,'room-3',0);
+INSERT INTO rooms VALUES(5,'room-4',0);
+INSERT INTO rooms VALUES(6,'room-5',0);
+INSERT INTO rooms VALUES(7,'room-6',0);
+INSERT INTO rooms VALUES(8,'room-7',0);
+INSERT INTO rooms VALUES(9,'room-8',0);
+INSERT INTO rooms VALUES(10,'room-9',0);
+INSERT INTO rooms VALUES(11,'room-10',0);
+INSERT INTO rooms VALUES(12,'room-11',0);
+INSERT INTO rooms VALUES(13,'room-12',0);
+INSERT INTO rooms VALUES(14,'room-13',0);
+INSERT INTO rooms VALUES(15,'room-14',0);
+INSERT INTO rooms VALUES(16,'room-15',0);
+INSERT INTO rooms VALUES(17,'room-16',0);
+INSERT INTO rooms VALUES(18,'room-17',0);
+INSERT INTO rooms VALUES(19,'room-18',0);
+INSERT INTO rooms VALUES(20,'room-19',0);
+INSERT INTO rooms VALUES(21,'room-20',0);
+INSERT INTO rooms VALUES(22,'room-21',0);
+INSERT INTO rooms VALUES(23,'room-22',0);
+INSERT INTO rooms VALUES(24,'room-23',0);
+INSERT INTO rooms VALUES(25,'room-24',0);
+INSERT INTO rooms VALUES(26,'room-25',0);
+INSERT INTO rooms VALUES(27,'room-26',0);
+INSERT INTO rooms VALUES(28,'room-27',0);
+INSERT INTO rooms VALUES(29,'room-28',0);
+INSERT INTO rooms VALUES(30,'room-29',0);
+INSERT INTO rooms VALUES(31,'room-30',0);
+INSERT INTO rooms VALUES(32,'room-31',0);
+INSERT INTO rooms VALUES(33,'room-32',0);
+INSERT INTO rooms VALUES(34,'room-33',0);
+INSERT INTO rooms VALUES(35,'room-34',0);
+INSERT INTO rooms VALUES(36,'room-35',0);
+INSERT INTO rooms VALUES(37,'room-36',0);
+INSERT INTO rooms VALUES(38,'room-37',0);
+INSERT INTO rooms VALUES(39,'room-38',0);
+INSERT INTO rooms VALUES(40,'room-39',0);
+INSERT INTO rooms VALUES(41,'room-40',0);
+DELETE FROM sqlite_sequence;
+INSERT INTO sqlite_sequence VALUES('rooms',41);
+COMMIT;
diff --git a/stablediffusion-infinity/utils.py b/stablediffusion-infinity/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..a9042cd597b9647b97be5baddd7abe0fe697c2da
--- /dev/null
+++ b/stablediffusion-infinity/utils.py
@@ -0,0 +1,140 @@
+from PIL import Image
+from PIL import ImageFilter
+import cv2
+import numpy as np
+import scipy
+import scipy.signal
+from scipy.spatial import cKDTree
+
+import os
+from perlin2d import *
+
+patch_match_compiled = True
+
+from PyPatchMatch import patch_match
+
+
+def edge_pad(img, mask, mode=1):
+ if mode == 0:
+ nmask = mask.copy()
+ nmask[nmask > 0] = 1
+ res0 = 1 - nmask
+ res1 = nmask
+ p0 = np.stack(res0.nonzero(), axis=0).transpose()
+ p1 = np.stack(res1.nonzero(), axis=0).transpose()
+ min_dists, min_dist_idx = cKDTree(p1).query(p0, 1)
+ loc = p1[min_dist_idx]
+ for (a, b), (c, d) in zip(p0, loc):
+ img[a, b] = img[c, d]
+ elif mode == 1:
+ record = {}
+ kernel = [[1] * 3 for _ in range(3)]
+ nmask = mask.copy()
+ nmask[nmask > 0] = 1
+ res = scipy.signal.convolve2d(
+ nmask, kernel, mode="same", boundary="fill", fillvalue=1
+ )
+ res[nmask < 1] = 0
+ res[res == 9] = 0
+ res[res > 0] = 1
+ ylst, xlst = res.nonzero()
+ queue = [(y, x) for y, x in zip(ylst, xlst)]
+ # bfs here
+ cnt = res.astype(np.float32)
+ acc = img.astype(np.float32)
+ step = 1
+ h = acc.shape[0]
+ w = acc.shape[1]
+ offset = [(1, 0), (-1, 0), (0, 1), (0, -1)]
+ while queue:
+ target = []
+ for y, x in queue:
+ val = acc[y][x]
+ for yo, xo in offset:
+ yn = y + yo
+ xn = x + xo
+ if 0 <= yn < h and 0 <= xn < w and nmask[yn][xn] < 1:
+ if record.get((yn, xn), step) == step:
+ acc[yn][xn] = acc[yn][xn] * cnt[yn][xn] + val
+ cnt[yn][xn] += 1
+ acc[yn][xn] /= cnt[yn][xn]
+ if (yn, xn) not in record:
+ record[(yn, xn)] = step
+ target.append((yn, xn))
+ step += 1
+ queue = target
+ img = acc.astype(np.uint8)
+ else:
+ nmask = mask.copy()
+ ylst, xlst = nmask.nonzero()
+ yt, xt = ylst.min(), xlst.min()
+ yb, xb = ylst.max(), xlst.max()
+ content = img[yt : yb + 1, xt : xb + 1]
+ img = np.pad(
+ content,
+ ((yt, mask.shape[0] - yb - 1), (xt, mask.shape[1] - xb - 1), (0, 0)),
+ mode="edge",
+ )
+ return img, mask
+
+
+def perlin_noise(img, mask):
+ lin = np.linspace(0, 5, mask.shape[0], endpoint=False)
+ x, y = np.meshgrid(lin, lin)
+ avg = img.mean(axis=0).mean(axis=0)
+ # noise=[((perlin(x, y)+1)*128+avg[i]).astype(np.uint8) for i in range(3)]
+ noise = [((perlin(x, y) + 1) * 0.5 * 255).astype(np.uint8) for i in range(3)]
+ noise = np.stack(noise, axis=-1)
+ # mask=skimage.measure.block_reduce(mask,(8,8),np.min)
+ # mask=mask.repeat(8, axis=0).repeat(8, axis=1)
+ # mask_image=Image.fromarray(mask)
+ # mask_image=mask_image.filter(ImageFilter.GaussianBlur(radius = 4))
+ # mask=np.array(mask_image)
+ nmask = mask.copy()
+ # nmask=nmask/255.0
+ nmask[mask > 0] = 1
+ img = nmask[:, :, np.newaxis] * img + (1 - nmask[:, :, np.newaxis]) * noise
+ # img=img.astype(np.uint8)
+ return img, mask
+
+
+def gaussian_noise(img, mask):
+ noise = np.random.randn(mask.shape[0], mask.shape[1], 3)
+ noise = (noise + 1) / 2 * 255
+ noise = noise.astype(np.uint8)
+ nmask = mask.copy()
+ nmask[mask > 0] = 1
+ img = nmask[:, :, np.newaxis] * img + (1 - nmask[:, :, np.newaxis]) * noise
+ return img, mask
+
+
+def cv2_telea(img, mask):
+ ret = cv2.inpaint(img, 255 - mask, 5, cv2.INPAINT_TELEA)
+ return ret, mask
+
+
+def cv2_ns(img, mask):
+ ret = cv2.inpaint(img, 255 - mask, 5, cv2.INPAINT_NS)
+ return ret, mask
+
+
+def patch_match_func(img, mask):
+ ret = patch_match.inpaint(img, mask=255 - mask, patch_size=3)
+ return ret, mask
+
+
+def mean_fill(img, mask):
+ avg = img.mean(axis=0).mean(axis=0)
+ img[mask < 1] = avg
+ return img, mask
+
+
+functbl = {
+ "gaussian": gaussian_noise,
+ "perlin": perlin_noise,
+ "edge_pad": edge_pad,
+ "patchmatch": patch_match_func if (os.name != "nt" and patch_match_compiled) else edge_pad,
+ "cv2_ns": cv2_ns,
+ "cv2_telea": cv2_telea,
+ "mean_fill": mean_fill,
+}
diff --git a/static/_app/immutable/assets/_layout-d90db7b5.css b/static/_app/immutable/assets/_layout-d90db7b5.css
new file mode 100644
index 0000000000000000000000000000000000000000..fa9a79575cf28cd11f483b563c61dda68adbf079
--- /dev/null
+++ b/static/_app/immutable/assets/_layout-d90db7b5.css
@@ -0,0 +1 @@
+*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,"Apple Color Emoji","Segoe UI Emoji",Segoe UI Symbol,"Noto Color Emoji"}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[type=text],[type=email],[type=url],[type=password],[type=number],[type=date],[type=datetime-local],[type=month],[type=search],[type=tel],[type=time],[type=week],[multiple],textarea,select{-webkit-appearance:none;-moz-appearance:none;appearance:none;background-color:#fff;border-color:#6b7280;border-width:1px;border-radius:0;padding:.5rem .75rem;font-size:1rem;line-height:1.5rem;--tw-shadow: 0 0 #0000}[type=text]:focus,[type=email]:focus,[type=url]:focus,[type=password]:focus,[type=number]:focus,[type=date]:focus,[type=datetime-local]:focus,[type=month]:focus,[type=search]:focus,[type=tel]:focus,[type=time]:focus,[type=week]:focus,[multiple]:focus,textarea:focus,select:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);border-color:#2563eb}input::-moz-placeholder,textarea::-moz-placeholder{color:#6b7280;opacity:1}input::placeholder,textarea::placeholder{color:#6b7280;opacity:1}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-date-and-time-value{min-height:1.5em}::-webkit-datetime-edit,::-webkit-datetime-edit-year-field,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute-field,::-webkit-datetime-edit-second-field,::-webkit-datetime-edit-millisecond-field,::-webkit-datetime-edit-meridiem-field{padding-top:0;padding-bottom:0}select{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");background-position:right .5rem center;background-repeat:no-repeat;background-size:1.5em 1.5em;padding-right:2.5rem;-webkit-print-color-adjust:exact;print-color-adjust:exact}[multiple]{background-image:initial;background-position:initial;background-repeat:unset;background-size:initial;padding-right:.75rem;-webkit-print-color-adjust:unset;print-color-adjust:unset}[type=checkbox],[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;padding:0;-webkit-print-color-adjust:exact;print-color-adjust:exact;display:inline-block;vertical-align:middle;background-origin:border-box;-webkit-user-select:none;-moz-user-select:none;user-select:none;flex-shrink:0;height:1rem;width:1rem;color:#2563eb;background-color:#fff;border-color:#6b7280;border-width:1px;--tw-shadow: 0 0 #0000}[type=checkbox]{border-radius:0}[type=radio]{border-radius:100%}[type=checkbox]:focus,[type=radio]:focus{outline:2px solid transparent;outline-offset:2px;--tw-ring-inset: var(--tw-empty, );--tw-ring-offset-width: 2px;--tw-ring-offset-color: #fff;--tw-ring-color: #2563eb;--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}[type=checkbox]:checked,[type=radio]:checked{border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e")}[type=radio]:checked{background-image:url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3ccircle cx='8' cy='8' r='3'/%3e%3c/svg%3e")}[type=checkbox]:checked:hover,[type=checkbox]:checked:focus,[type=radio]:checked:hover,[type=radio]:checked:focus{border-color:transparent;background-color:currentColor}[type=checkbox]:indeterminate{background-image:url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3e%3cpath stroke='white' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M4 8h8'/%3e%3c/svg%3e");border-color:transparent;background-color:currentColor;background-size:100% 100%;background-position:center;background-repeat:no-repeat}[type=checkbox]:indeterminate:hover,[type=checkbox]:indeterminate:focus{border-color:transparent;background-color:currentColor}[type=file]{background:unset;border-color:inherit;border-width:0;border-radius:0;padding:0;font-size:unset;line-height:inherit}[type=file]:focus{outline:1px solid ButtonText;outline:1px auto -webkit-focus-ring-color}*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.pointer-events-none{pointer-events:none}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.sticky{position:sticky}.inset-0{top:0px;right:0px;bottom:0px;left:0px}.top-0{top:0px}.left-0{left:0px}.bottom-0{bottom:0px}.right-0{right:0px}.left-full{left:100%}.bottom-full{bottom:100%}.z-50{z-index:50}.z-0{z-index:0}.z-10{z-index:10}.order-first{order:-9999}.order-last{order:9999}.col-span-2{grid-column:span 2 / span 2}.col-span-3{grid-column:span 3 / span 3}.col-start-2{grid-column-start:2}.row-span-2{grid-row:span 2 / span 2}.row-start-2{grid-row-start:2}.m-auto{margin:auto}.my-2{margin-top:.5rem;margin-bottom:.5rem}.mx-auto{margin-left:auto;margin-right:auto}.mx-4{margin-left:1rem;margin-right:1rem}.mb-8{margin-bottom:2rem}.mb-2{margin-bottom:.5rem}.ml-2{margin-left:.5rem}.mr-2{margin-right:.5rem}.mb-4{margin-bottom:1rem}.mr-3{margin-right:.75rem}.ml-4{margin-left:1rem}.mr-1\.5{margin-right:.375rem}.mr-1{margin-right:.25rem}.block{display:block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-screen{height:100vh}.h-10{height:2.5rem}.h-full{height:100%}.h-4{height:1rem}.max-h-72{max-height:18rem}.min-h-\[600px\]{min-height:600px}.w-screen{width:100vw}.w-10{width:2.5rem}.w-full{width:100%}.w-4{width:1rem}.min-w-\[25ch\]{min-width:25ch}.min-w-\[20ch\]{min-width:20ch}.max-w-md{max-width:28rem}.max-w-lg{max-width:32rem}.max-w-\[25px\]{max-width:25px}.flex-1{flex:1 1 0%}.origin-bottom-left{transform-origin:bottom left}.translate-y-\[2px\]{--tw-translate-y: 2px;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:spin 1s linear infinite}@keyframes pulse{50%{opacity:.5}}.animate-pulse{animation:pulse 2s cubic-bezier(.4,0,.6,1) infinite}.cursor-wait{cursor:wait}.cursor-pointer{cursor:pointer}.cursor-move{cursor:move}.touch-none{touch-action:none}.select-none{-webkit-user-select:none;-moz-user-select:none;user-select:none}.resize{resize:both}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.grid-rows-3{grid-template-rows:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-3{gap:.75rem}.gap-2{gap:.5rem}.gap-x-1{-moz-column-gap:.25rem;column-gap:.25rem}.self-center{align-self:center}.overflow-hidden{overflow:hidden}.overflow-y-scroll{overflow-y:scroll}.whitespace-nowrap{white-space:nowrap}.rounded-2xl{border-radius:1rem}.rounded-lg{border-radius:.5rem}.rounded-full{border-radius:9999px}.rounded-sm{border-radius:.125rem}.rounded-xl{border-radius:.75rem}.rounded-tr-xl{border-top-right-radius:.75rem}.border-8{border-width:8px}.border-2{border-width:2px}.border-l-2{border-left-width:2px}.border-t-2{border-top-width:2px}.border-dashed{border-style:dashed}.border-none{border-style:none}.border-black{--tw-border-opacity: 1;border-color:rgb(0 0 0 / var(--tw-border-opacity))}.border-violet-700{--tw-border-opacity: 1;border-color:rgb(109 40 217 / var(--tw-border-opacity))}.border-t-gray-400{--tw-border-opacity: 1;border-top-color:rgb(156 163 175 / var(--tw-border-opacity))}.border-opacity-50{--tw-border-opacity: .5}.bg-blue-200{--tw-bg-opacity: 1;background-color:rgb(191 219 254 / var(--tw-bg-opacity))}.bg-black{--tw-bg-opacity: 1;background-color:rgb(0 0 0 / var(--tw-bg-opacity))}.bg-black\/60{background-color:#0009}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity))}.bg-blue-800{--tw-bg-opacity: 1;background-color:rgb(30 64 175 / var(--tw-bg-opacity))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.bg-blue-700\/90{background-color:#1d4ed8e6}.bg-blue-700{--tw-bg-opacity: 1;background-color:rgb(29 78 216 / var(--tw-bg-opacity))}.bg-blue-300\/60{background-color:#93c5fd99}.bg-blue-100{--tw-bg-opacity: 1;background-color:rgb(219 234 254 / var(--tw-bg-opacity))}.bg-opacity-90{--tw-bg-opacity: .9}.bg-opacity-80{--tw-bg-opacity: .8}.bg-gradient-to-t{background-image:linear-gradient(to top,var(--tw-gradient-stops))}.bg-gradient-to-r{background-image:linear-gradient(to right,var(--tw-gradient-stops))}.from-blue-700\/40{--tw-gradient-from: rgb(29 78 216 / .4);--tw-gradient-to: rgb(29 78 216 / 0);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-blue-700\/90{--tw-gradient-from: rgb(29 78 216 / .9);--tw-gradient-to: rgb(29 78 216 / 0);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.from-transparent{--tw-gradient-from: transparent;--tw-gradient-to: rgb(0 0 0 / 0);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to)}.via-blue-900\/20{--tw-gradient-to: rgb(30 58 138 / 0);--tw-gradient-stops: var(--tw-gradient-from), rgb(30 58 138 / .2), var(--tw-gradient-to)}.to-blue-500\/10{--tw-gradient-to: rgb(59 130 246 / .1)}.to-transparent{--tw-gradient-to: transparent}.p-10{padding:2.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-0{padding-top:0;padding-bottom:0}.py-3{padding-top:.75rem;padding-bottom:.75rem}.px-5{padding-left:1.25rem;padding-right:1.25rem}.px-0\.5{padding-left:.125rem;padding-right:.125rem}.px-0{padding-left:0;padding-right:0}.py-2{padding-top:.5rem;padding-bottom:.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.pl-3{padding-left:.75rem}.pr-5{padding-right:1.25rem}.pb-2{padding-bottom:.5rem}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-base{font-size:1rem;line-height:1.5rem}.text-4xl{font-size:2.25rem;line-height:2.5rem}.text-8xl{font-size:6rem;line-height:1}.\!text-4xl{font-size:2.25rem!important;line-height:2.5rem!important}.text-sm{font-size:.875rem;line-height:1.25rem}.text-6xl{font-size:3.75rem;line-height:1}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-2xl{font-size:1.5rem;line-height:2rem}.text-3xl{font-size:1.875rem;line-height:2.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-normal{font-weight:400}.font-semibold{font-weight:600}.font-medium{font-weight:500}.italic{font-style:italic}.tracking-wide{letter-spacing:.025em}.tracking-tight{letter-spacing:-.025em}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity))}.text-blue-400{--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity))}.text-gray-300{--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity))}.text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}.text-\[\#387CFF\]{--tw-text-opacity: 1;color:rgb(56 124 255 / var(--tw-text-opacity))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity))}.text-blue-700{--tw-text-opacity: 1;color:rgb(29 78 216 / var(--tw-text-opacity))}.text-gray-800{--tw-text-opacity: 1;color:rgb(31 41 55 / var(--tw-text-opacity))}.text-blue-200{--tw-text-opacity: 1;color:rgb(191 219 254 / var(--tw-text-opacity))}.text-blue-900{--tw-text-opacity: 1;color:rgb(30 58 138 / var(--tw-text-opacity))}.underline{text-decoration-line:underline}.opacity-50{opacity:.5}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-lg{--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow: 0 1px 2px 0 rgb(0 0 0 / .05);--tw-shadow-colored: 0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-blue-500{--tw-shadow-color: #3b82f6;--tw-shadow: var(--tw-shadow-colored)}.shadow-blue-500\/20{--tw-shadow-color: rgb(59 130 246 / .2);--tw-shadow: var(--tw-shadow-colored)}.outline-none{outline:2px solid transparent;outline-offset:2px}.ring{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-8{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-0{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(0px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-1{--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000)}.ring-blue-500{--tw-ring-opacity: 1;--tw-ring-color: rgb(59 130 246 / var(--tw-ring-opacity))}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.line-clamp-4{overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:4}.x-scroll{scrollbar-width:thin;scrollbar-color:white #2F6DCB}.x-scroll::-webkit-scrollbar{width:4px}.x-scroll::-webkit-scrollbar-track{background:white;border-radius:100px}.x-scroll::-webkit-scrollbar-thumb{background-color:#2f6dcb;border-radius:100px;border:2px solid #2F6DCB}.hover\:bg-gray-300:hover{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity))}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity))}.hover\:saturate-150:hover{--tw-saturate: saturate(1.5);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.hover\:saturate-200:hover{--tw-saturate: saturate(2);filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.disabled\:opacity-50:disabled{opacity:.5}@media (prefers-color-scheme: dark){.dark\:bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity))}.dark\:text-black{--tw-text-opacity: 1;color:rgb(0 0 0 / var(--tw-text-opacity))}}@media (min-width: 640px){.sm\:flex{display:flex}}@media (min-width: 768px){.md\:bottom-16{bottom:4rem}.md\:order-none{order:0}.md\:flex{display:flex}.md\:hidden{display:none}.md\:w-\[210px\]{width:210px}.md\:flex-row{flex-direction:row}.md\:gap-0{gap:0px}.md\:px-12{padding-left:3rem;padding-right:3rem}.md\:px-6{padding-left:1.5rem;padding-right:1.5rem}.md\:py-2{padding-top:.5rem;padding-bottom:.5rem}.md\:text-3xl{font-size:1.875rem;line-height:2.25rem}.md\:text-sm{font-size:.875rem;line-height:1.25rem}}@media (min-width: 1280px){.xl\:text-2xl{font-size:1.5rem;line-height:2rem}}@media (min-width: 1536px){.\32xl\:max-w-xl{max-width:36rem}.\32xl\:text-2xl{font-size:1.5rem;line-height:2rem}}
diff --git a/static/_app/immutable/assets/_page-ff237a95.css b/static/_app/immutable/assets/_page-ff237a95.css
new file mode 100644
index 0000000000000000000000000000000000000000..603098fff1114044b5f884f8179dda966b5a20fb
--- /dev/null
+++ b/static/_app/immutable/assets/_page-ff237a95.css
@@ -0,0 +1 @@
+.cursor.svelte-14ka0w3{pointer-events:none;position:absolute;top:0px;left:0px;display:grid;touch-action:none;grid-template-columns:repeat(3,minmax(0,1fr));transform-origin:0 0}.frame.svelte-1wvt719{position:relative;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));grid-template-rows:repeat(3,minmax(0,1fr));--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(8px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow, 0 0 #0000);--tw-ring-opacity:1;--tw-ring-color:rgb(29 78 216 / var(--tw-ring-opacity)) }canvas.svelte-6dcxg7{transform-origin:0 0}.grid-row.svelte-tz2nn1.svelte-tz2nn1{display:grid;grid-template-columns:.5fr 2fr 1fr .5fr 2fr;align-items:center;justify-items:flex-start}.grid-row.svelte-tz2nn1 span.svelte-tz2nn1{white-space:nowrap}
diff --git a/static/_app/immutable/chunks/0-dd39116a.js b/static/_app/immutable/chunks/0-dd39116a.js
new file mode 100644
index 0000000000000000000000000000000000000000..d9deb06526ba476f0664940d0a9b433b783e49ea
--- /dev/null
+++ b/static/_app/immutable/chunks/0-dd39116a.js
@@ -0,0 +1 @@
+import{default as t}from"../components/pages/_layout.svelte-2e7ed5f6.js";export{t as component};
diff --git a/static/_app/immutable/chunks/1-bf704c85.js b/static/_app/immutable/chunks/1-bf704c85.js
new file mode 100644
index 0000000000000000000000000000000000000000..d779bb3107c7159e4e9ea4c555718eae17df5430
--- /dev/null
+++ b/static/_app/immutable/chunks/1-bf704c85.js
@@ -0,0 +1 @@
+import{default as t}from"../components/error.svelte-443b2358.js";export{t as component};
diff --git a/static/_app/immutable/chunks/2-9d823c2e.js b/static/_app/immutable/chunks/2-9d823c2e.js
new file mode 100644
index 0000000000000000000000000000000000000000..bd185bee2d6ad3f638a972f90af111ab3e85d977
--- /dev/null
+++ b/static/_app/immutable/chunks/2-9d823c2e.js
@@ -0,0 +1 @@
+import{_ as r}from"./_page-802cc2a3.js";import{default as t}from"../components/pages/_page.svelte-5ae30844.js";export{t as component,r as shared};
diff --git a/static/_app/immutable/chunks/_page-802cc2a3.js b/static/_app/immutable/chunks/_page-802cc2a3.js
new file mode 100644
index 0000000000000000000000000000000000000000..470b827d2ea3fc294e0b8a1ff4ca645db498ef5a
--- /dev/null
+++ b/static/_app/immutable/chunks/_page-802cc2a3.js
@@ -0,0 +1 @@
+const e=!0,r=Object.freeze(Object.defineProperty({__proto__:null,prerender:!0},Symbol.toStringTag,{value:"Module"}));export{r as _,e as p};
diff --git a/static/_app/immutable/chunks/index-4781a106.js b/static/_app/immutable/chunks/index-4781a106.js
new file mode 100644
index 0000000000000000000000000000000000000000..42aaf0960103b95b154d484d450593a5d5a0f224
--- /dev/null
+++ b/static/_app/immutable/chunks/index-4781a106.js
@@ -0,0 +1 @@
+function A(){}function Z(t,e){for(const n in e)t[n]=e[n];return t}function G(t){return t()}function H(){return Object.create(null)}function v(t){t.forEach(G)}function J(t){return typeof t=="function"}function xt(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function tt(t){return Object.keys(t).length===0}function et(t,...e){if(t==null)return A;const n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function bt(t,e,n){t.$$.on_destroy.push(et(e,n))}function $t(t,e,n,i){if(t){const r=K(t,e,n,i);return t[0](r)}}function K(t,e,n,i){return t[1]&&i?Z(n.ctx.slice(),t[1](i(e))):n.ctx}function wt(t,e,n,i){if(t[2]&&i){const r=t[2](i(n));if(e.dirty===void 0)return r;if(typeof r=="object"){const u=[],c=Math.max(e.dirty.length,r.length);for(let o=0;o32){const e=[],n=t.ctx.length/32;for(let i=0;i>1);n(r)<=i?t=r+1:e=r}return t}function ct(t){if(t.hydrate_init)return;t.hydrate_init=!0;let e=t.childNodes;if(t.nodeName==="HEAD"){const s=[];for(let l=0;l0&&e[n[r]].claim_order<=l?r+1:rt(1,r,_=>e[n[_]].claim_order,l))-1;i[s]=n[f]+1;const d=f+1;n[d]=s,r=Math.max(d,r)}const u=[],c=[];let o=e.length-1;for(let s=n[r]+1;s!=0;s=i[s-1]){for(u.push(e[s-1]);o>=s;o--)c.push(e[o]);o--}for(;o>=0;o--)c.push(e[o]);u.reverse(),c.sort((s,l)=>s.claim_order-l.claim_order);for(let s=0,l=0;s=u[l].claim_order;)l++;const f=lt.removeEventListener(e,n,i)}function jt(t){return function(e){return e.preventDefault(),t.call(this,e)}}function Pt(t){return function(e){return e.stopPropagation(),t.call(this,e)}}function Dt(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function at(t){return Array.from(t.childNodes)}function ft(t){t.claim_info===void 0&&(t.claim_info={last_index:0,total_claimed:0})}function Q(t,e,n,i,r=!1){ft(t);const u=(()=>{for(let c=t.claim_info.last_index;c=0;c--){const o=t[c];if(e(o)){const s=n(o);return s===void 0?t.splice(c,1):t[c]=s,r?s===void 0&&t.claim_info.last_index--:t.claim_info.last_index=c,o}}return i()})();return u.claim_order=t.claim_info.total_claimed,t.claim_info.total_claimed+=1,u}function R(t,e,n,i){return Q(t,r=>r.nodeName===e,r=>{const u=[];for(let c=0;cr.removeAttribute(c))},()=>i(e))}function Tt(t,e,n){return R(t,e,n,ot)}function Bt(t,e,n){return R(t,e,n,ut)}function _t(t,e){return Q(t,n=>n.nodeType===3,n=>{const i=""+e;if(n.data.startsWith(i)){if(n.data.length!==i.length)return n.splitText(i.length)}else n.data=i},()=>q(e),!0)}function Lt(t){return _t(t," ")}function Ot(t,e){e=""+e,t.wholeText!==e&&(t.data=e)}function qt(t,e,n,i){n===null?t.style.removeProperty(e):t.style.setProperty(e,n,i?"important":"")}function dt(t,e,{bubbles:n=!1,cancelable:i=!1}={}){const r=document.createEvent("CustomEvent");return r.initCustomEvent(t,n,i,e),r}function zt(t,e){return new t(e)}let w;function $(t){w=t}function x(){if(!w)throw new Error("Function called outside component initialization");return w}function Ft(t){x().$$.on_mount.push(t)}function Ht(t){x().$$.after_update.push(t)}function It(t){x().$$.on_destroy.push(t)}function Wt(){const t=x();return(e,n,{cancelable:i=!1}={})=>{const r=t.$$.callbacks[e];if(r){const u=dt(e,n,{cancelable:i});return r.slice().forEach(c=>{c.call(t,u)}),!u.defaultPrevented}return!0}}function Gt(t,e){return x().$$.context.set(t,e),e}function Jt(t){return x().$$.context.get(t)}function Kt(t,e){const n=t.$$.callbacks[e.type];n&&n.slice().forEach(i=>i.call(this,e))}const b=[],I=[],S=[],W=[],U=Promise.resolve();let L=!1;function V(){L||(L=!0,U.then(X))}function Qt(){return V(),U}function O(t){S.push(t)}const B=new Set;let N=0;function X(){const t=w;do{for(;N{C.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}else i&&i()}function Vt(t,e){mt(t,1,1,()=>{e.delete(t.key)})}function Xt(t,e,n,i,r,u,c,o,s,l,f,d){let _=t.length,m=u.length,h=_;const j={};for(;h--;)j[t[h].key]=h;const E=[],P=new Map,D=new Map;for(h=m;h--;){const a=d(r,u,h),p=n(a);let y=c.get(p);y?i&&y.p(a,e):(y=l(p,a),y.c()),P.set(p,E[h]=y),p in j&&D.set(p,Math.abs(h-j[p]))}const z=new Set,F=new Set;function T(a){Y(a,1),a.m(o,f),c.set(a.key,a),f=a.first,m--}for(;_&&m;){const a=E[m-1],p=t[_-1],y=a.key,k=p.key;a===p?(f=a.first,_--,m--):P.has(k)?!c.has(y)||z.has(y)?T(a):F.has(k)?_--:D.get(y)>D.get(k)?(F.add(y),T(a)):(z.add(k),_--):(s(p,c),_--)}for(;_--;){const a=t[_];P.has(a.key)||s(a,c)}for(;m;)T(E[m-1]);return E}function Yt(t){t&&t.c()}function Zt(t,e){t&&t.l(e)}function pt(t,e,n,i){const{fragment:r,after_update:u}=t.$$;r&&r.m(e,n),i||O(()=>{const c=t.$$.on_mount.map(G).filter(J);t.$$.on_destroy?t.$$.on_destroy.push(...c):v(c),t.$$.on_mount=[]}),u.forEach(O)}function yt(t,e){const n=t.$$;n.fragment!==null&&(v(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function gt(t,e){t.$$.dirty[0]===-1&&(b.push(t),V(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{const h=m.length?m[0]:_;return l.ctx&&r(l.ctx[d],l.ctx[d]=h)&&(!l.skip_bound&&l.bound[d]&&l.bound[d](h),f&>(t,d)),_}):[],l.update(),f=!0,v(l.before_update),l.fragment=i?i(l.ctx):!1,e.target){if(e.hydrate){nt();const d=at(e.target);l.fragment&&l.fragment.l(d),d.forEach(lt)}else l.fragment&&l.fragment.c();e.intro&&Y(t.$$.fragment),pt(t,e.target,e.anchor,e.customElement),it(),X()}$(s)}class ee{$destroy(){yt(this,1),this.$destroy=A}$on(e,n){if(!J(n))return A;const i=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return i.push(n),()=>{const r=i.indexOf(n);r!==-1&&i.splice(r,1)}}$set(e){this.$$set&&!tt(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}}export{Qt as A,A as B,$t as C,vt as D,Et as E,wt as F,st as G,bt as H,Gt as I,Jt as J,It as K,ut as L,Bt as M,Mt as N,Wt as O,v as P,I as Q,kt as R,ee as S,St as T,jt as U,Kt as V,Pt as W,Xt as X,Vt as Y,Ct as a,Nt as b,Lt as c,Ut as d,At as e,Y as f,Rt as g,lt as h,te as i,Ht as j,ot as k,Tt as l,at as m,Dt as n,Ft as o,qt as p,q,_t as r,xt as s,mt as t,Ot as u,zt as v,Yt as w,Zt as x,pt as y,yt as z};
diff --git a/static/_app/immutable/chunks/singletons-e8802a59.js b/static/_app/immutable/chunks/singletons-e8802a59.js
new file mode 100644
index 0000000000000000000000000000000000000000..8cf53c90713eda6159740048a2cb6d4fed10217a
--- /dev/null
+++ b/static/_app/immutable/chunks/singletons-e8802a59.js
@@ -0,0 +1 @@
+import{B as l,s as m}from"./index-4781a106.js";const f=[];function d(t,n=l){let e;const o=new Set;function r(i){if(m(t,i)&&(t=i,e)){const c=!f.length;for(const a of o)a[1](),f.push(a,t);if(c){for(let a=0;a{o.delete(a),o.size===0&&(e(),e=null)}}return{set:r,update:u,subscribe:s}}let p="",g="";function w(t){p=t.base,g=t.assets||p}function U(t){let n=t.baseURI;if(!n){const e=t.getElementsByTagName("base");n=e.length?e[0].href:t.URL}return n}function y(){return{x:pageXOffset,y:pageYOffset}}function R(t){let n,e=null,o=null,r=null;for(const s of t.composedPath())s instanceof Element&&(!n&&s.nodeName.toUpperCase()==="A"&&(n=s),e===null&&(e=b(s,"data-sveltekit-noscroll")),o===null&&(o=b(s,"data-sveltekit-prefetch")),r===null&&(r=b(s,"data-sveltekit-reload")));const u=n&&new URL(n instanceof SVGAElement?n.href.baseVal:n.href,document.baseURI);return{a:n,url:u,options:{noscroll:e,prefetch:o,reload:r}}}function b(t,n){const e=t.getAttribute(n);return e===null?e:e===""?!0:(e==="off",!1)}function h(t){const n=d(t);let e=!0;function o(){e=!0,n.update(s=>s)}function r(s){e=!1,n.set(s)}function u(s){let i;return n.subscribe(c=>{(i===void 0||e&&c!==i)&&s(i=c)})}return{notify:o,set:r,subscribe:u}}function _(){const{set:t,subscribe:n}=d(!1);let e;async function o(){clearTimeout(e);const r=await fetch(`${g}/_app/version.json`,{headers:{pragma:"no-cache","cache-control":"no-cache"}});if(r.ok){const{version:u}=await r.json(),s=u!=="1668020391802";return s&&(t(!0),clearTimeout(e)),s}else throw new Error(`Version check failed: ${r.status}`)}return{subscribe:n,check:o}}function E(t){t.client}const T={url:h({}),page:h({}),navigating:d(null),updated:_()};export{y as a,w as b,R as f,U as g,E as i,T as s,d as w};
diff --git a/static/_app/immutable/chunks/stores-36fae70e.js b/static/_app/immutable/chunks/stores-36fae70e.js
new file mode 100644
index 0000000000000000000000000000000000000000..df9de089c62ddb79fcdfc591d52d397e6bc518be
--- /dev/null
+++ b/static/_app/immutable/chunks/stores-36fae70e.js
@@ -0,0 +1 @@
+import"./index-4781a106.js";import{s as r}from"./singletons-e8802a59.js";const t=()=>{const e=r,s={page:{subscribe:e.page.subscribe},navigating:{subscribe:e.navigating.subscribe},updated:e.updated};return Object.defineProperties(s,{preloading:{get(){return console.error("stores.preloading is deprecated; use stores.navigating instead"),{subscribe:e.navigating.subscribe}},enumerable:!1},session:{get(){return o(),{}},enumerable:!1}}),s},a={subscribe(e){return t().page.subscribe(e)}};function o(){throw new Error("stores.session is no longer available. See https://github.com/sveltejs/kit/discussions/5883")}export{a as p};
diff --git a/static/_app/immutable/components/error.svelte-443b2358.js b/static/_app/immutable/components/error.svelte-443b2358.js
new file mode 100644
index 0000000000000000000000000000000000000000..0bd88baf199544e4a871a53ad6e39c535a03bde0
--- /dev/null
+++ b/static/_app/immutable/components/error.svelte-443b2358.js
@@ -0,0 +1 @@
+import{S as j,i as w,s as y,k as b,q as E,a as H,e as B,l as d,m as P,r as R,h as m,c as N,b as _,G as $,u as q,B as C,H as z}from"../chunks/index-4781a106.js";import{p as A}from"../chunks/stores-36fae70e.js";function G(p){let r,a=p[0].error.frame+"",f;return{c(){r=b("pre"),f=E(a)},l(l){r=d(l,"PRE",{});var s=P(r);f=R(s,a),s.forEach(m)},m(l,s){_(l,r,s),$(r,f)},p(l,s){s&1&&a!==(a=l[0].error.frame+"")&&q(f,a)},d(l){l&&m(r)}}}function h(p){let r,a=p[0].error.stack+"",f;return{c(){r=b("pre"),f=E(a)},l(l){r=d(l,"PRE",{});var s=P(r);f=R(s,a),s.forEach(m)},m(l,s){_(l,r,s),$(r,f)},p(l,s){s&1&&a!==(a=l[0].error.stack+"")&&q(f,a)},d(l){l&&m(r)}}}function D(p){let r,a=p[0].status+"",f,l,s,c=p[0].error.message+"",k,v,u,n,t=p[0].error.frame&&G(p),i=p[0].error.stack&&h(p);return{c(){r=b("h1"),f=E(a),l=H(),s=b("pre"),k=E(c),v=H(),t&&t.c(),u=H(),i&&i.c(),n=B()},l(e){r=d(e,"H1",{});var o=P(r);f=R(o,a),o.forEach(m),l=N(e),s=d(e,"PRE",{});var S=P(s);k=R(S,c),S.forEach(m),v=N(e),t&&t.l(e),u=N(e),i&&i.l(e),n=B()},m(e,o){_(e,r,o),$(r,f),_(e,l,o),_(e,s,o),$(s,k),_(e,v,o),t&&t.m(e,o),_(e,u,o),i&&i.m(e,o),_(e,n,o)},p(e,[o]){o&1&&a!==(a=e[0].status+"")&&q(f,a),o&1&&c!==(c=e[0].error.message+"")&&q(k,c),e[0].error.frame?t?t.p(e,o):(t=G(e),t.c(),t.m(u.parentNode,u)):t&&(t.d(1),t=null),e[0].error.stack?i?i.p(e,o):(i=h(e),i.c(),i.m(n.parentNode,n)):i&&(i.d(1),i=null)},i:C,o:C,d(e){e&&m(r),e&&m(l),e&&m(s),e&&m(v),t&&t.d(e),e&&m(u),i&&i.d(e),e&&m(n)}}}function F(p,r,a){let f;return z(p,A,l=>a(0,f=l)),[f]}class K extends j{constructor(r){super(),w(this,r,F,D,y,{})}}export{K as default};
diff --git a/static/_app/immutable/components/pages/_layout.svelte-2e7ed5f6.js b/static/_app/immutable/components/pages/_layout.svelte-2e7ed5f6.js
new file mode 100644
index 0000000000000000000000000000000000000000..b754c962f4eafebabb909a41cee779cbaa2e52b1
--- /dev/null
+++ b/static/_app/immutable/components/pages/_layout.svelte-2e7ed5f6.js
@@ -0,0 +1 @@
+import{S as l,i,s as r,C as u,D as f,E as _,F as c,f as p,t as d}from"../../chunks/index-4781a106.js";function m(n){let s;const o=n[1].default,e=u(o,n,n[0],null);return{c(){e&&e.c()},l(t){e&&e.l(t)},m(t,a){e&&e.m(t,a),s=!0},p(t,[a]){e&&e.p&&(!s||a&1)&&f(e,o,t,t[0],s?c(o,t[0],a,null):_(t[0]),null)},i(t){s||(p(e,t),s=!0)},o(t){d(e,t),s=!1},d(t){e&&e.d(t)}}}function $(n,s,o){let{$$slots:e={},$$scope:t}=s;return n.$$set=a=>{"$$scope"in a&&o(0,t=a.$$scope)},[t,e]}class h extends l{constructor(s){super(),i(this,s,$,m,r,{})}}export{h as default};
diff --git a/static/_app/immutable/components/pages/_page.svelte-5ae30844.js b/static/_app/immutable/components/pages/_page.svelte-5ae30844.js
new file mode 100644
index 0000000000000000000000000000000000000000..4c985dcaed0d8b00b5433596f02b5c3be922b347
--- /dev/null
+++ b/static/_app/immutable/components/pages/_page.svelte-5ae30844.js
@@ -0,0 +1,30 @@
+import{S as ke,i as xe,s as Ce,C as ir,D as sr,E as or,F as ar,f as J,t as q,I as vi,J as yi,K as Kt,L as Q,M as ee,m as k,h as _,n as c,b as re,G as m,B as de,k as D,w as pe,l as U,x as me,y as _e,z as ge,a as ie,c as se,g as Le,d as Te,q as te,r as ne,u as nt,N as Re,H as he,O as lr,o as Ot,P as ur,Q as _t,R as be,T as $s,U as Ms,V as cr,W as Rs,e as Xe,X as Ns,Y as Ds}from"../../chunks/index-4781a106.js";import{w as De}from"../../chunks/singletons-e8802a59.js";import{p as Us}from"../../chunks/stores-36fae70e.js";var Hs=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function zs(e){var t=e.default;if(typeof t=="function"){var n=function(){return t.apply(this,arguments)};n.prototype=t.prototype}else n={};return Object.defineProperty(n,"__esModule",{value:!0}),Object.keys(e).forEach(function(r){var i=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(n,r,i.get?i:{enumerable:!0,get:function(){return e[r]}})}),n}var Be={},Y={};Object.defineProperty(Y,"__esModule",{value:!0});var Vs=Object.defineProperty,Bs=Object.defineProperties,Ks=Object.getOwnPropertyDescriptors,fn=Object.getOwnPropertySymbols,wi=Object.prototype.hasOwnProperty,bi=Object.prototype.propertyIsEnumerable,Pr=(e,t,n)=>t in e?Vs(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n,rt=(e,t)=>{for(var n in t||(t={}))wi.call(t,n)&&Pr(e,n,t[n]);if(fn)for(var n of fn(t))bi.call(t,n)&&Pr(e,n,t[n]);return e},At=(e,t)=>Bs(e,Ks(t)),Fs=(e,t)=>{var n={};for(var r in e)wi.call(e,r)&&t.indexOf(r)<0&&(n[r]=e[r]);if(e!=null&&fn)for(var r of fn(e))t.indexOf(r)<0&&bi.call(e,r)&&(n[r]=e[r]);return n},fr=(e,t,n)=>new Promise((r,i)=>{var s=l=>{try{a(n.next(l))}catch(u){i(u)}},o=l=>{try{a(n.throw(l))}catch(u){i(u)}},a=l=>l.done?r(l.value):Promise.resolve(l.value).then(s,o);a((n=n.apply(e,t)).next())});function et(e,t){throw new Error(t)}function le(e,t="Expected value to be non-nullable"){return e}var Ei=(e=>(e[e.UPDATE_PRESENCE=100]="UPDATE_PRESENCE",e[e.BROADCAST_EVENT=103]="BROADCAST_EVENT",e[e.FETCH_STORAGE=200]="FETCH_STORAGE",e[e.UPDATE_STORAGE=201]="UPDATE_STORAGE",e))(Ei||{}),ki=(e=>(e[e.INIT=0]="INIT",e[e.SET_PARENT_KEY=1]="SET_PARENT_KEY",e[e.CREATE_LIST=2]="CREATE_LIST",e[e.UPDATE_OBJECT=3]="UPDATE_OBJECT",e[e.CREATE_OBJECT=4]="CREATE_OBJECT",e[e.DELETE_CRDT=5]="DELETE_CRDT",e[e.DELETE_OBJECT_KEY=6]="DELETE_OBJECT_KEY",e[e.CREATE_MAP=7]="CREATE_MAP",e[e.CREATE_REGISTER=8]="CREATE_REGISTER",e))(ki||{}),xi=(e=>(e[e.OBJECT=0]="OBJECT",e[e.LIST=1]="LIST",e[e.MAP=2]="MAP",e[e.REGISTER=3]="REGISTER",e))(xi||{});function Ci(e){return e.type===0&&!Ii(e)}function Ii(e){return e.parentId!==void 0&&e.parentKey!==void 0}var Si=(e=>(e[e.UPDATE_PRESENCE=100]="UPDATE_PRESENCE",e[e.USER_JOINED=101]="USER_JOINED",e[e.USER_LEFT=102]="USER_LEFT",e[e.BROADCASTED_EVENT=103]="BROADCASTED_EVENT",e[e.ROOM_STATE=104]="ROOM_STATE",e[e.INITIAL_STORAGE_STATE=200]="INITIAL_STORAGE_STATE",e[e.UPDATE_STORAGE=201]="UPDATE_STORAGE",e))(Si||{});function js(e){return e==="my-presence"||e==="others"||e==="event"||e==="error"||e==="connection"||e==="history"}var Oi=(e=>(e[e.CLOSE_ABNORMAL=1006]="CLOSE_ABNORMAL",e[e.INVALID_MESSAGE_FORMAT=4e3]="INVALID_MESSAGE_FORMAT",e[e.NOT_ALLOWED=4001]="NOT_ALLOWED",e[e.MAX_NUMBER_OF_MESSAGES_PER_SECONDS=4002]="MAX_NUMBER_OF_MESSAGES_PER_SECONDS",e[e.MAX_NUMBER_OF_CONCURRENT_CONNECTIONS=4003]="MAX_NUMBER_OF_CONCURRENT_CONNECTIONS",e[e.MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP=4004]="MAX_NUMBER_OF_MESSAGES_PER_DAY_PER_APP",e[e.MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM=4005]="MAX_NUMBER_OF_CONCURRENT_CONNECTIONS_PER_ROOM",e[e.CLOSE_WITHOUT_RETRY=4999]="CLOSE_WITHOUT_RETRY",e))(Oi||{});function Lr(e,t){return Object.freeze({type:"HasParent",node:e,key:t})}var Tr=Object.freeze({type:"NoParent"});function $r(e){return Object.freeze({type:"Orphaned",oldKey:e})}var En=class{constructor(){this._parent=Tr}_getParentKeyOrThrow(){switch(this.parent.type){case"HasParent":return this.parent.key;case"NoParent":throw new Error("Parent key is missing");case"Orphaned":return this.parent.oldKey;default:return et(this.parent,"Unknown state")}}get _pool(){return this.__pool}get roomId(){return this.__pool?this.__pool.roomId:null}get _id(){return this.__id}get parent(){return this._parent}get _parentNode(){switch(this.parent.type){case"HasParent":return this.parent.node;case"NoParent":return null;case"Orphaned":return null;default:return et(this.parent,"Unknown state")}}get _parentKey(){switch(this.parent.type){case"HasParent":return this.parent.key;case"NoParent":return null;case"Orphaned":return this.parent.oldKey;default:return et(this.parent,"Unknown state")}}_apply(e,t){switch(e.type){case 5:return this.parent.type==="HasParent"?this.parent.node._detachChild(this):{modified:!1}}return{modified:!1}}_setParentLink(e,t){switch(this.parent.type){case"HasParent":if(this.parent.node!==e)throw new Error("Cannot set parent: node already has a parent");this._parent=Lr(e,t);return;case"Orphaned":case"NoParent":{this._parent=Lr(e,t);return}default:return et(this.parent,"Unknown state")}}_attach(e,t){if(this.__id||this.__pool)throw new Error("Cannot attach node: already attached");t.addNode(e,this),this.__id=e,this.__pool=t}_detach(){switch(this.__pool&&this.__id&&this.__pool.deleteNode(this.__id),this.parent.type){case"HasParent":{this._parent=$r(this.parent.key);break}case"NoParent":{this._parent=Tr;break}case"Orphaned":{this._parent=$r(this.parent.oldKey);break}default:et(this.parent,"Unknown state")}this.__pool=void 0}invalidate(){this._cachedImmutable!==void 0&&(this._cachedImmutable=void 0,this.parent.type==="HasParent"&&this.parent.node.invalidate())}toImmutable(){return this._cachedImmutable===void 0&&(this._cachedImmutable=this._toImmutable()),this._cachedImmutable}},ot=class extends En{constructor(e){super(),this._data=e}get data(){return this._data}static _deserialize([e,t],n,r){const i=new ot(t.data);return i._attach(e,r),i}_toOps(e,t,n){if(this._id===void 0)throw new Error("Cannot serialize register if parentId or parentKey is undefined");return[{type:8,opId:n==null?void 0:n.generateOpId(),id:this._id,parentId:e,parentKey:t,data:this.data}]}_serialize(){if(this.parent.type!=="HasParent")throw new Error("Cannot serialize LiveRegister if parent is missing");return{type:3,parentId:le(this.parent.node._id,"Parent node expected to have ID"),parentKey:this.parent.key,data:this.data}}_attachChild(e){throw new Error("Method not implemented.")}_detachChild(e){throw new Error("Method not implemented.")}_apply(e,t){return super._apply(e,t)}_toImmutable(){return this._data}},gt=32,hr=126;function Ye(e,t){return e!==void 0&&t!==void 0?hn(Ai(xt(e),xt(t))):e!==void 0?Xs(e):t!==void 0?Ys(t):hn([gt+1])}function Ys(e){const t=[],n=xt(e);for(let r=0;rs)throw new Error(`Impossible to generate position between ${e} and ${t}`);if(i===s){r.push(i),n++;continue}if(s-i===1){r.push(i),r.push(...Ai(e.slice(n+1),[]));break}const o=s+i>>1;r.push(o);break}return r}function xt(e){const t=[];for(let n=0;nt._getParentKeyOrThrow()===e)}_attach(e,t){super._attach(e,t);for(const n of this._items)n._attach(t.generateId(),t)}_detach(){super._detach();for(const e of this._items)e._detach()}_applySetRemote(e){if(this._pool===void 0)throw new Error("Can't attach child if managed pool is not present");const{id:t,parentKey:n}=e,r=$t(e);r._attach(t,this._pool),r._setParentLink(this,n);const i=e.deletedId,s=this._indexOfPosition(n);if(s!==-1){const o=this._items[s];if(o._id===i)return o._detach(),this._items[s]=r,{modified:ye(this,[wt(s,r)]),reverse:[]};{this._implicitlyDeletedItems.add(o),this._items[s]=r;const a=[wt(s,r)],l=this._detachItemAssociatedToSetOperation(e.deletedId);return l&&a.push(l),{modified:ye(this,a),reverse:[]}}}else{const o=[],a=this._detachItemAssociatedToSetOperation(e.deletedId);return a&&o.push(a),this._insertAndSort(r),o.push(je(this._indexOfPosition(n),r)),{reverse:[],modified:ye(this,o)}}}_applySetAck(e){if(this._pool===void 0)throw new Error("Can't attach child if managed pool is not present");const t=[],n=this._detachItemAssociatedToSetOperation(e.deletedId);n&&t.push(n);const r=this._unacknowledgedSets.get(e.parentKey);if(r!==void 0){if(r!==e.opId)return t.length===0?{modified:!1}:{modified:ye(this,t),reverse:[]};this._unacknowledgedSets.delete(e.parentKey)}const i=this._indexOfPosition(e.parentKey),s=this._items.find(o=>o._id===e.id);if(s!==void 0){if(s._parentKey===e.parentKey)return{modified:t.length>0?ye(this,t):!1,reverse:[]};i!==-1&&(this._implicitlyDeletedItems.add(this._items[i]),this._items.splice(i,1),t.push(Zt(i)));const o=this._items.indexOf(s);s._setParentLink(this,e.parentKey),this._sortItems();const a=this._items.indexOf(s);return a!==o&&t.push(ft(o,a,s)),{modified:t.length>0?ye(this,t):!1,reverse:[]}}else{const o=this._pool.getNode(e.id);if(o&&this._implicitlyDeletedItems.has(o)){o._setParentLink(this,e.parentKey),this._implicitlyDeletedItems.delete(o),this._insertAndSort(o);const a=this._items.indexOf(o);return{modified:ye(this,[i===-1?je(a,o):wt(a,o),...t]),reverse:[]}}else{i!==-1&&this._items.splice(i,1);const{newItem:a,newIndex:l}=this._createAttachItemAndSort(e,e.parentKey);return{modified:ye(this,[i===-1?je(l,a):wt(l,a),...t]),reverse:[]}}}}_detachItemAssociatedToSetOperation(e){if(e===void 0||this._pool===void 0)return null;const t=this._pool.getNode(e);if(t===void 0)return null;const n=this._detachChild(t);return n.modified===!1?null:n.modified.updates[0]}_applyRemoteInsert(e){if(this._pool===void 0)throw new Error("Can't attach child if managed pool is not present");const t=e.parentKey,n=this._indexOfPosition(t);n!==-1&&this._shiftItemPosition(n,t);const{newItem:r,newIndex:i}=this._createAttachItemAndSort(e,t);return{modified:ye(this,[je(i,r)]),reverse:[]}}_applyInsertAck(e){const t=this._items.find(i=>i._id===e.id),n=e.parentKey,r=this._indexOfPosition(n);if(t){if(t._parentKey===n)return{modified:!1};{const i=this._items.indexOf(t);r!==-1&&this._shiftItemPosition(r,n),t._setParentLink(this,n),this._sortItems();const s=this._indexOfPosition(n);return s===i?{modified:!1}:{modified:ye(this,[ft(i,s,t)]),reverse:[]}}}else{const i=le(this._pool).getNode(e.id);if(i&&this._implicitlyDeletedItems.has(i)){i._setParentLink(this,n),this._implicitlyDeletedItems.delete(i),this._insertAndSort(i);const s=this._indexOfPosition(n);return{modified:ye(this,[je(s,i)]),reverse:[]}}else{r!==-1&&this._shiftItemPosition(r,n);const{newItem:s,newIndex:o}=this._createAttachItemAndSort(e,n);return{modified:ye(this,[je(o,s)]),reverse:[]}}}}_applyInsertUndoRedo(e){var t,n,r;const{id:i,parentKey:s}=e,o=$t(e);if(((t=this._pool)==null?void 0:t.getNode(i))!==void 0)return{modified:!1};o._attach(i,le(this._pool)),o._setParentLink(this,s);const a=this._indexOfPosition(s);let l=s;if(a!==-1){const f=(n=this._items[a])==null?void 0:n._getParentKeyOrThrow(),p=(r=this._items[a+1])==null?void 0:r._getParentKeyOrThrow();l=Ye(f,p),o._setParentLink(this,l)}this._insertAndSort(o);const u=this._indexOfPosition(l);return{modified:ye(this,[je(u,o)]),reverse:[{type:5,id:i}]}}_applySetUndoRedo(e){var t;const{id:n,parentKey:r}=e,i=$t(e);if(((t=this._pool)==null?void 0:t.getNode(n))!==void 0)return{modified:!1};this._unacknowledgedSets.set(r,le(e.opId));const s=this._indexOfPosition(r);i._attach(n,le(this._pool)),i._setParentLink(this,r);const o=r;if(s!==-1){const a=this._items[s];a._detach(),this._items[s]=i;const l=a._toOps(le(this._id),r,this._pool);Dn(l,e.id);const u=[wt(s,i)],f=this._detachItemAssociatedToSetOperation(e.deletedId);return f&&u.push(f),{modified:ye(this,u),reverse:l}}else{this._insertAndSort(i),this._detachItemAssociatedToSetOperation(e.deletedId);const a=this._indexOfPosition(o);return{reverse:[{type:5,id:n}],modified:ye(this,[je(a,i)])}}}_attachChild(e,t){if(this._pool===void 0)throw new Error("Can't attach child if managed pool is not present");let n;return e.intent==="set"?t===1?n=this._applySetRemote(e):t===2?n=this._applySetAck(e):n=this._applySetUndoRedo(e):t===1?n=this._applyRemoteInsert(e):t===2?n=this._applyInsertAck(e):n=this._applyInsertUndoRedo(e),n.modified!==!1&&this.invalidate(),n}_detachChild(e){if(e){const t=le(e._parentKey),n=e._toOps(le(this._id),t,this._pool),r=this._items.indexOf(e);return r===-1?{modified:!1}:(this._items.splice(r,1),this.invalidate(),e._detach(),{modified:ye(this,[Zt(r)]),reverse:n})}return{modified:!1}}_applySetChildKeyRemote(e,t){var n;if(this._implicitlyDeletedItems.has(t)){this._implicitlyDeletedItems.delete(t),t._setParentLink(this,e),this._insertAndSort(t);const s=this._items.indexOf(t);return{modified:ye(this,[je(s,t)]),reverse:[]}}const r=t._parentKey;if(e===r)return{modified:!1};const i=this._indexOfPosition(e);if(i===-1){const s=this._items.indexOf(t);t._setParentLink(this,e),this._sortItems();const o=this._items.indexOf(t);return o===s?{modified:!1}:{modified:ye(this,[ft(s,o,t)]),reverse:[]}}else{this._items[i]._setParentLink(this,Ye(e,(n=this._items[i+1])==null?void 0:n._getParentKeyOrThrow()));const s=this._items.indexOf(t);t._setParentLink(this,e),this._sortItems();const o=this._items.indexOf(t);return o===s?{modified:!1}:{modified:ye(this,[ft(s,o,t)]),reverse:[]}}}_applySetChildKeyAck(e,t){var n,r;const i=le(t._parentKey);if(this._implicitlyDeletedItems.has(t)){const s=this._indexOfPosition(e);return this._implicitlyDeletedItems.delete(t),s!==-1&&this._items[s]._setParentLink(this,Ye(e,(n=this._items[s+1])==null?void 0:n._getParentKeyOrThrow())),t._setParentLink(this,e),this._insertAndSort(t),{modified:!1}}else{if(e===i)return{modified:!1};const s=this._items.indexOf(t),o=this._indexOfPosition(e);o!==-1&&this._items[o]._setParentLink(this,Ye(e,(r=this._items[o+1])==null?void 0:r._getParentKeyOrThrow())),t._setParentLink(this,e),this._sortItems();const a=this._items.indexOf(t);return s===a?{modified:!1}:{modified:ye(this,[ft(s,a,t)]),reverse:[]}}}_applySetChildKeyUndoRedo(e,t){var n;const r=le(t._parentKey),i=this._items.indexOf(t),s=this._indexOfPosition(e);s!==-1&&this._items[s]._setParentLink(this,Ye(e,(n=this._items[s+1])==null?void 0:n._getParentKeyOrThrow())),t._setParentLink(this,e),this._sortItems();const o=this._items.indexOf(t);return i===o?{modified:!1}:{modified:ye(this,[ft(i,o,t)]),reverse:[{type:1,id:le(t._id),parentKey:r}]}}_setChildKey(e,t,n){return n===1?this._applySetChildKeyRemote(e,t):n===2?this._applySetChildKeyAck(e,t):this._applySetChildKeyUndoRedo(e,t)}_apply(e,t){return super._apply(e,t)}_serialize(){if(this.parent.type!=="HasParent")throw new Error("Cannot serialize LiveList if parent is missing");return{type:1,parentId:le(this.parent.node._id,"Parent node expected to have ID"),parentKey:this.parent.key}}get length(){return this._items.length}push(e){var t;return(t=this._pool)==null||t.assertStorageIsWritable(),this.insert(e,this.length)}insert(e,t){var n;if((n=this._pool)==null||n.assertStorageIsWritable(),t<0||t>this._items.length)throw new Error(`Cannot insert list item at index "${t}". index should be between 0 and ${this._items.length}`);const r=this._items[t-1]?this._items[t-1]._getParentKeyOrThrow():void 0,i=this._items[t]?this._items[t]._getParentKeyOrThrow():void 0,s=Ye(r,i),o=bt(e);if(o._setParentLink(this,s),this._insertAndSort(o),this._pool&&this._id){const a=this._pool.generateId();o._attach(a,this._pool),this._pool.dispatch(o._toOps(this._id,s,this._pool),[{type:5,id:a}],new Map([[this._id,ye(this,[je(t,o)])]]))}}move(e,t){var n;if((n=this._pool)==null||n.assertStorageIsWritable(),t<0)throw new Error("targetIndex cannot be less than 0");if(t>=this._items.length)throw new Error("targetIndex cannot be greater or equal than the list length");if(e<0)throw new Error("index cannot be less than 0");if(e>=this._items.length)throw new Error("index cannot be greater or equal than the list length");let r=null,i=null;e=this._items.length)throw new Error(`Cannot delete list item at index "${e}". index should be between 0 and ${this._items.length-1}`);const n=this._items[e];if(n._detach(),this._items.splice(e,1),this.invalidate(),this._pool){const r=n._id;if(r){const i=new Map;i.set(le(this._id),ye(this,[Zt(e)])),this._pool.dispatch([{id:r,opId:this._pool.generateOpId(),type:5}],n._toOps(le(this._id),n._getParentKeyOrThrow()),i)}}}clear(){var e;if((e=this._pool)==null||e.assertStorageIsWritable(),this._pool){const t=[],n=[],r=[];for(const s of this._items){s._detach();const o=s._id;o&&(t.push({type:5,id:o,opId:this._pool.generateOpId()}),n.push(...s._toOps(le(this._id),s._getParentKeyOrThrow())),r.push(Zt(0)))}this._items=[],this.invalidate();const i=new Map;i.set(le(this._id),ye(this,r)),this._pool.dispatch(t,n,i)}else{for(const t of this._items)t._detach();this._items=[],this.invalidate()}}set(e,t){var n;if((n=this._pool)==null||n.assertStorageIsWritable(),e<0||e>=this._items.length)throw new Error(`Cannot set list item at index "${e}". index should be between 0 and ${this._items.length-1}`);const r=this._items[e],i=r._getParentKeyOrThrow(),s=r._id;r._detach();const o=bt(t);if(o._setParentLink(this,i),this._items[e]=o,this.invalidate(),this._pool&&this._id){const a=this._pool.generateId();o._attach(a,this._pool);const l=new Map;l.set(this._id,ye(this,[wt(e,o)]));const u=o._toOps(this._id,i,this._pool);Dn(u,s),this._unacknowledgedSets.set(i,le(u[0].opId));const f=r._toOps(this._id,i,void 0);Dn(f,a),this._pool.dispatch(u,f,l)}}toArray(){return this._items.map(e=>dt(e))}every(e){return this.toArray().every(e)}filter(e){return this.toArray().filter(e)}find(e){return this.toArray().find(e)}findIndex(e){return this.toArray().findIndex(e)}forEach(e){return this.toArray().forEach(e)}get(e){if(!(e<0||e>=this._items.length))return dt(this._items[e])}indexOf(e,t){return this.toArray().indexOf(e,t)}lastIndexOf(e,t){return this.toArray().lastIndexOf(e,t)}map(e){return this._items.map((t,n)=>e(dt(t),n))}some(e){return this.toArray().some(e)}[Symbol.iterator](){return new Ws(this._items)}_createAttachItemAndSort(e,t){const n=$t(e);n._attach(e.id,le(this._pool)),n._setParentLink(this,t),this._insertAndSort(n);const r=this._indexOfPosition(t);return{newItem:n,newIndex:r}}_shiftItemPosition(e,t){var n;const r=Ye(t,this._items.length>e+1?(n=this._items[e+1])==null?void 0:n._getParentKeyOrThrow():void 0);this._items[e]._setParentLink(this,r)}toImmutable(){return super.toImmutable()}_toImmutable(){return this._items.map(t=>t.toImmutable())}},Ws=class{constructor(e){this._innerIterator=e[Symbol.iterator]()}[Symbol.iterator](){return this}next(){const e=this._innerIterator.next();return e.done?{done:!0,value:void 0}:{value:dt(e.value)}}};function ye(e,t){return{node:e,type:"LiveList",updates:t}}function wt(e,t){return{index:e,type:"set",item:t instanceof ot?t.data:t}}function Zt(e){return{index:e,type:"delete"}}function je(e,t){return{index:e,type:"insert",item:t instanceof ot?t.data:t}}function ft(e,t,n){return{index:t,type:"move",previousIndex:e,item:n instanceof ot?n.data:n}}function Dn(e,t){if(e.length===0)throw new Error("Internal error. Serialized LiveStructure should have at least 1 operation");const n=e[0];n.intent="set",n.deletedId=t}var at=class extends En{constructor(e){if(super(),this.unacknowledgedSet=new Map,e){const t=[];for(const n of e){const r=bt(n[1]);r._setParentLink(this,n[0]),t.push([n[0],r])}this._map=new Map(t)}else this._map=new Map}_toOps(e,t,n){if(this._id===void 0)throw new Error("Cannot serialize item is not attached");const r=[],i={id:this._id,opId:n==null?void 0:n.generateOpId(),type:7,parentId:e,parentKey:t};r.push(i);for(const[s,o]of this._map)r.push(...o._toOps(this._id,s,n));return r}static _deserialize([e,t],n,r){const i=new at;i._attach(e,r);const s=n.get(e);if(s===void 0)return i;for(const[o,a]of s){const l=$i([o,a],n,r);l._setParentLink(i,a.parentKey),i._map.set(a.parentKey,l),i.invalidate()}return i}_attach(e,t){super._attach(e,t);for(const[n,r]of this._map)Se(r)&&r._attach(t.generateId(),t)}_attachChild(e,t){if(this._pool===void 0)throw new Error("Can't attach child if managed pool is not present");const{id:n,parentKey:r,opId:i}=e,s=r,o=$t(e);if(this._pool.getNode(n)!==void 0)return{modified:!1};if(t===2){const u=this.unacknowledgedSet.get(s);if(u===i)return this.unacknowledgedSet.delete(s),{modified:!1};if(u!==void 0)return{modified:!1}}else t===1&&this.unacknowledgedSet.delete(s);const a=this._map.get(s);let l;if(a){const u=le(this._id);l=a._toOps(u,s),a._detach()}else l=[{type:5,id:n}];return o._setParentLink(this,s),o._attach(n,this._pool),this._map.set(s,o),this.invalidate(),{modified:{node:this,type:"LiveMap",updates:{[s]:{type:"update"}}},reverse:l}}_detach(){super._detach();for(const e of this._map.values())e._detach()}_detachChild(e){const t=le(this._id),n=le(e._parentKey),r=e._toOps(t,n,this._pool);for(const[s,o]of this._map)o===e&&(this._map.delete(s),this.invalidate());return e._detach(),{modified:{node:this,type:"LiveMap",updates:{[n]:{type:"delete"}}},reverse:r}}_serialize(){if(this.parent.type!=="HasParent")throw new Error("Cannot serialize LiveMap if parent is missing");return{type:2,parentId:le(this.parent.node._id,"Parent node expected to have ID"),parentKey:this.parent.key}}get(e){const t=this._map.get(e);if(t!==void 0)return dt(t)}set(e,t){var n;(n=this._pool)==null||n.assertStorageIsWritable();const r=this._map.get(e);r&&r._detach();const i=bt(t);if(i._setParentLink(this,e),this._map.set(e,i),this.invalidate(),this._pool&&this._id){const s=this._pool.generateId();i._attach(s,this._pool);const o=new Map;o.set(this._id,{node:this,type:"LiveMap",updates:{[e]:{type:"update"}}});const a=i._toOps(this._id,e,this._pool);this.unacknowledgedSet.set(e,le(a[0].opId)),this._pool.dispatch(i._toOps(this._id,e,this._pool),r?r._toOps(this._id,e):[{type:5,id:s}],o)}}get size(){return this._map.size}has(e){return this._map.has(e)}delete(e){var t;(t=this._pool)==null||t.assertStorageIsWritable();const n=this._map.get(e);if(n===void 0)return!1;if(n._detach(),this._map.delete(e),this.invalidate(),this._pool&&n._id){const r=le(this._id),i=new Map;i.set(r,{node:this,type:"LiveMap",updates:{[e]:{type:"delete"}}}),this._pool.dispatch([{type:5,id:n._id,opId:this._pool.generateOpId()}],n._toOps(r,e),i)}return!0}entries(){const e=this._map.entries();return{[Symbol.iterator](){return this},next(){const t=e.next();if(t.done)return{done:!0,value:void 0};const r=t.value[0],i=dt(t.value[1]);return{value:[r,i]}}}}[Symbol.iterator](){return this.entries()}keys(){return this._map.keys()}values(){const e=this._map.values();return{[Symbol.iterator](){return this},next(){const t=e.next();return t.done?{done:!0,value:void 0}:{value:dt(t.value)}}}}forEach(e){for(const t of this)e(t[1],t[0],this)}toImmutable(){return super.toImmutable()}_toImmutable(){const e=new Map;for(const[t,n]of this._map)e.set(t,n.toImmutable());return Ve(e)}},Ke=class extends En{constructor(e={}){super(),this._propToLastUpdate=new Map;for(const t in e){const n=e[t];n!==void 0&&Se(n)&&n._setParentLink(this,t)}this._map=new Map(Object.entries(e))}_toOps(e,t,n){if(this._id===void 0)throw new Error("Cannot serialize item is not attached");const r=n==null?void 0:n.generateOpId(),i=[],s=e!==void 0&&t!==void 0?{type:4,id:this._id,opId:r,parentId:e,parentKey:t,data:{}}:{type:4,id:this._id,opId:r,data:{}};i.push(s);for(const[o,a]of this._map)Se(a)?i.push(...a._toOps(this._id,o,n)):s.data[o]=a;return i}static _deserialize([e,t],n,r){const i=new Ke(t.data);return i._attach(e,r),this._deserializeChildren(i,n,r)}static _deserializeChildren(e,t,n){const r=t.get(le(e._id));if(r===void 0)return e;for(const[i,s]of r){const o=Zs([i,s],t,n);on(o)&&o._setParentLink(e,s.parentKey),e._map.set(s.parentKey,o),e.invalidate()}return e}_attach(e,t){super._attach(e,t);for(const[n,r]of this._map)Se(r)&&r._attach(t.generateId(),t)}_attachChild(e,t){if(this._pool===void 0)throw new Error("Can't attach child if managed pool is not present");const{id:n,opId:r,parentKey:i}=e,s=Li(e);if(this._pool.getNode(n)!==void 0)return this._propToLastUpdate.get(i)===r&&this._propToLastUpdate.delete(i),{modified:!1};if(t===0)this._propToLastUpdate.set(i,le(r));else if(this._propToLastUpdate.get(i)!==void 0)return this._propToLastUpdate.get(i)===r?(this._propToLastUpdate.delete(i),{modified:!1}):{modified:!1};const o=le(this._id),a=this._map.get(i);let l;return Se(a)?(l=a._toOps(o,i),a._detach()):a===void 0?l=[{type:6,id:o,key:i}]:l=[{type:3,id:o,data:{[i]:a}}],this._map.set(i,s),this.invalidate(),on(s)&&(s._setParentLink(this,i),s._attach(n,this._pool)),{reverse:l,modified:{node:this,type:"LiveObject",updates:{[i]:{type:"update"}}}}}_detachChild(e){if(e){const t=le(this._id),n=le(e._parentKey),r=e._toOps(t,n,this._pool);for(const[s,o]of this._map)o===e&&(this._map.delete(s),this.invalidate());return e._detach(),{modified:{node:this,type:"LiveObject",updates:{[n]:{type:"delete"}}},reverse:r}}return{modified:!1}}_detach(){super._detach();for(const e of this._map.values())Se(e)&&e._detach()}_apply(e,t){return e.type===3?this._applyUpdate(e,t):e.type===6?this._applyDeleteObjectKey(e):super._apply(e,t)}_serialize(){const e={};for(const[t,n]of this._map)Se(n)||(e[t]=n);return this.parent.type==="HasParent"&&this.parent.node._id?{type:0,parentId:this.parent.node._id,parentKey:this.parent.key,data:e}:{type:0,data:e}}_applyUpdate(e,t){let n=!1;const r=le(this._id),i=[],s={type:3,id:r,data:{}};i.push(s);for(const a in e.data){const l=this._map.get(a);Se(l)?(i.push(...l._toOps(r,a)),l._detach()):l!==void 0?s.data[a]=l:l===void 0&&i.push({type:6,id:r,key:a})}const o={};for(const a in e.data){const l=e.data[a];if(l===void 0)continue;if(t)this._propToLastUpdate.set(a,le(e.opId));else if(this._propToLastUpdate.get(a)===void 0)n=!0;else if(this._propToLastUpdate.get(a)===e.opId){this._propToLastUpdate.delete(a);continue}else continue;const u=this._map.get(a);Se(u)&&u._detach(),n=!0,o[a]={type:"update"},this._map.set(a,l),this.invalidate()}return Object.keys(s.data).length!==0&&i.unshift(s),n?{modified:{node:this,type:"LiveObject",updates:o},reverse:i}:{modified:!1}}_applyDeleteObjectKey(e){const t=e.key;if(this._map.has(t)===!1)return{modified:!1};if(this._propToLastUpdate.get(t)!==void 0)return{modified:!1};const n=this._map.get(t),r=le(this._id);let i=[];return Se(n)?(i=n._toOps(r,e.key),n._detach()):n!==void 0&&(i=[{type:3,id:r,data:{[t]:n}}]),this._map.delete(t),this.invalidate(),{modified:{node:this,type:"LiveObject",updates:{[e.key]:{type:"delete"}}},reverse:i}}toObject(){return ro(this._map)}set(e,t){var n;(n=this._pool)==null||n.assertStorageIsWritable(),this.update({[e]:t})}get(e){return this._map.get(e)}delete(e){var t;(t=this._pool)==null||t.assertStorageIsWritable();const n=e,r=this._map.get(n);if(r===void 0)return;if(this._pool===void 0||this._id===void 0){Se(r)&&r._detach(),this._map.delete(n),this.invalidate();return}let i;Se(r)?(r._detach(),i=r._toOps(this._id,n)):i=[{type:3,data:{[n]:r},id:this._id}],this._map.delete(n),this.invalidate();const s=new Map;s.set(this._id,{node:this,type:"LiveObject",updates:{[e]:{type:"delete"}}}),this._pool.dispatch([{type:6,key:n,id:this._id,opId:this._pool.generateOpId()}],i,s)}update(e){var t;if((t=this._pool)==null||t.assertStorageIsWritable(),this._pool===void 0||this._id===void 0){for(const u in e){const f=e[u];if(f===void 0)continue;const p=this._map.get(u);Se(p)&&p._detach(),Se(f)&&f._setParentLink(this,u),this._map.set(u,f),this.invalidate()}return}const n=[],r=[],i=this._pool.generateOpId(),s={},o={id:this._id,type:3,data:{}},a={};for(const u in e){const f=e[u];if(f===void 0)continue;const p=this._map.get(u);if(Se(p)?(r.push(...p._toOps(this._id,u)),p._detach()):p===void 0?r.push({type:6,id:this._id,key:u}):o.data[u]=p,Se(f)){f._setParentLink(this,u),f._attach(this._pool.generateId(),this._pool);const h=f._toOps(this._id,u,this._pool),d=h.find(y=>y.parentId===this._id);d&&this._propToLastUpdate.set(u,le(d.opId)),n.push(...h)}else s[u]=f,this._propToLastUpdate.set(u,i);this._map.set(u,f),this.invalidate(),a[u]={type:"update"}}Object.keys(o.data).length!==0&&r.unshift(o),Object.keys(s).length!==0&&n.unshift({opId:i,id:this._id,type:3,data:s});const l=new Map;l.set(this._id,{node:this,type:"LiveObject",updates:a}),this._pool.dispatch(n,r,l)}toImmutable(){return super.toImmutable()}_toImmutable(){const e={};for(const[t,n]of this._map)e[t]=on(n)?n.toImmutable():n;return e}},Ve=e=>e;function Yn(e){return e.filter(t=>t!=null)}function kn(e){const t=rt({},e);return Object.keys(e).forEach(n=>{const r=n;t[r]===void 0&&delete t[r]}),t}function $t(e){return bt(Li(e))}function Li(e){switch(e.type){case 8:return e.data;case 4:return new Ke(e.data);case 7:return new at;case 2:return new We;default:return et(e,"Unknown creation Op")}}function Ti(e,t){return e===t?!0:e.parent.type==="HasParent"?Ti(e.parent.node,t):!1}function $i([e,t],n,r){switch(t.type){case 0:return Ke._deserialize([e,t],n,r);case 1:return We._deserialize([e,t],n,r);case 2:return at._deserialize([e,t],n,r);case 3:return ot._deserialize([e,t],n,r);default:throw new Error("Unexpected CRDT type")}}function Zs([e,t],n,r){switch(t.type){case 0:return Ke._deserialize([e,t],n,r);case 1:return We._deserialize([e,t],n,r);case 2:return at._deserialize([e,t],n,r);case 3:return t.data;default:throw new Error("Unexpected CRDT type")}}function on(e){return xn(e)||qs(e)||dr(e)}function Se(e){return on(e)||Gs(e)}function xn(e){return e instanceof We}function qs(e){return e instanceof at}function dr(e){return e instanceof Ke}function Gs(e){return e instanceof ot}function dt(e){return e instanceof ot?e.data:e instanceof We||e instanceof at||e instanceof Ke?e:et(e,"Unknown AbstractCrdt")}function bt(e){return e instanceof Ke||e instanceof at||e instanceof We?e:new ot(e)}function Qs(e,t){const n=[];return e.forEach((r,i)=>{t.get(i)||n.push({type:5,id:i})}),t.forEach((r,i)=>{const s=e.get(i);if(s)r.type===0&&(s.type!==0||JSON.stringify(r.data)!==JSON.stringify(s.data))&&n.push({type:3,id:i,data:r.data}),r.parentKey!==s.parentKey&&n.push({type:1,id:i,parentKey:le(r.parentKey,"Parent key must not be missing")});else switch(r.type){case 3:n.push({type:8,id:i,parentId:r.parentId,parentKey:r.parentKey,data:r.data});break;case 1:n.push({type:2,id:i,parentId:r.parentId,parentKey:r.parentKey});break;case 0:n.push(r.parentId?{type:4,id:i,parentId:r.parentId,parentKey:r.parentKey,data:r.data}:{type:4,id:i,data:r.data});break;case 2:n.push({type:7,id:i,parentId:r.parentId,parentKey:r.parentKey});break}}),n}function eo(e,t){const n=e.updates;for(const[r,i]of Mi(t.updates))n[r]=i;return At(rt({},t),{updates:n})}function to(e,t){const n=e.updates;for(const[r,i]of Mi(t.updates))n[r]=i;return At(rt({},t),{updates:n})}function no(e,t){const n=e.updates;return At(rt({},t),{updates:n.concat(t.updates)})}function Un(e,t){return e?e.type==="LiveObject"&&t.type==="LiveObject"?eo(e,t):e.type==="LiveMap"&&t.type==="LiveMap"?to(e,t):e.type==="LiveList"&&t.type==="LiveList"?no(e,t):t:t}function it(e){return e!==null&&typeof e=="object"&&Object.prototype.toString.call(e)==="[object Object]"}function ro(e){const t={};for(const[n,r]of e)t[n]=r;return t}function Mi(e){return Object.entries(e)}function pr(e){try{return JSON.parse(e)}catch{return}}function Ri(e){try{const t=e.replace(/-/g,"+").replace(/_/g,"/");return decodeURIComponent(atob(t).split("").map(function(r){return"%"+("00"+r.charCodeAt(0).toString(16)).slice(-2)}).join(""))}catch{return atob(e)}}function io(e){if(!it(e))return!1;const{iat:t,exp:n}=e;return typeof t=="number"&&typeof n=="number"}function so(e){const t=Date.now()/1e3;return t>e.exp-300||ttypeof t=="string")}function Di(e){return typeof e.appId=="string"&&e.roomId===void 0&&Ni(e.scopes)}function mr(e){return typeof e.appId=="string"&&typeof e.roomId=="string"&&typeof e.actor=="number"&&(e.id===void 0||typeof e.id=="string")&&Ni(e.scopes)&&(e.maxConnectionsPerRoom===void 0||typeof e.maxConnectionsPerRoom=="number")}function oo(e){return Di(e)||mr(e)}function ao(e){const t=e.split(".");if(t.length!==3)throw new Error("Authentication error: invalid JWT token");const n=pr(Ri(t[1]));if(n&&io(n))return n;throw new Error("Authentication error: missing JWT metadata")}function Mr(e){const t=ao(e);if(t&&mr(t))return Fs(t,["maxConnections"]);throw new Error("Authentication error: we expected a room token but did not get one. Hint: if you are using a callback, ensure the room is passed when creating the token. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientCallback")}function lo(e,t=e){}function uo(e,t,n=t){}function co(e){}function fo(e,t){}function Ge(){const e=new Set,t=new Set;function n(o){return t.add(o),()=>t.delete(o)}function r(o){return e.add(o),()=>e.delete(o)}function i(o){e.forEach(a=>a(o)),e.clear(),t.forEach(a=>a(o))}function s(){e.clear(),t.clear()}return{notify:i,subscribe:n,subscribeOnce:r,clear:s,observable:{subscribe:n,subscribeOnce:r}}}function Ui(e,t){let n=!1;const r=rt({},e);return Object.keys(t).forEach(i=>{const s=i,o=t[s];r[s]!==o&&(o===void 0?delete r[s]:r[s]=o,n=!0)}),n?r:e}var Cn=class{constructor(){this._ev=Ge()}get didInvalidate(){return this._ev.observable}invalidate(){this._cache!==void 0&&(this._cache=void 0,this._ev.notify())}get current(){var e;return(e=this._cache)!=null?e:this._cache=this._toImmutable()}},ho=class extends Cn{constructor(e){super(),this._me=Ve(kn(e))}_toImmutable(){return this._me}patch(e){const t=this._me,n=Ui(t,e);t!==n&&(this._me=Ve(n),this.invalidate())}};function Hi(e){return Object.defineProperty(e,"count",{value:e.length,enumerable:!1}),Object.defineProperty(e,"toArray",{value:()=>e,enumerable:!1}),Ve(e)}function po(e,t){return Ve(kn(At(rt({},e),{presence:t})))}var mo=class extends Cn{constructor(){super(),this._connections={},this._presences={},this._users={}}_toImmutable(){const e=Yn(Object.keys(this._presences).map(t=>this.getUser(Number(t))));return Hi(e)}clearOthers(){this._connections={},this._presences={},this._users={},this.invalidate()}_getUser(e){const t=this._connections[e],n=this._presences[e];if(t!==void 0&&n!==void 0)return po(t,n)}getUser(e){const t=this._users[e];if(t)return t;const n=this._getUser(e);if(n)return this._users[e]=n,n}_invalidateUser(e){this._users[e]!==void 0&&delete this._users[e],this.invalidate()}setConnection(e,t,n,r){this._connections[e]=Ve({connectionId:e,id:t,info:n,isReadOnly:r}),this._presences[e]!==void 0&&this._invalidateUser(e)}removeConnection(e){delete this._connections[e],delete this._presences[e],this._invalidateUser(e)}setOther(e,t){this._presences[e]=Ve(kn(t)),this._connections[e]!==void 0&&this._invalidateUser(e)}patchOther(e,t){const n=this._presences[e];if(n===void 0)return;const r=Ui(n,t);n!==r&&(this._presences[e]=Ve(r),this._invalidateUser(e))}};function zi(e){return e===null||typeof e=="string"||typeof e=="number"||typeof e=="boolean"}function _r(e){return Array.isArray(e)}function Vi(e){return!zi(e)&&!_r(e)}var _o=class extends Cn{constructor(e){super(),this._value=Ve(kn(e))}_toImmutable(){return this._value}set(e){this._value=Ve(e),this.invalidate()}},go=class extends Cn{constructor(e,t){super(),this._refs=e,this._refs.forEach(n=>{n.didInvalidate.subscribe(()=>this.invalidate())}),this._transform=t}_toImmutable(){return this._transform(this._refs[0].current,this._refs[1].current)}},Hn=[250,500,1e3,2e3,4e3,8e3,1e4],zn=[2e3,3e4,6e4,3e5],vo=3e4,yo=2e3;function wo(e){let t=0;return()=>`${e}:${t++}`}function qt(e){return e.state==="open"||e.state==="connecting"}function bo(e,t,n){var r;const i=b=>b(),s=(r=t.unstable_batchedUpdates)!=null?r:i,o={roomId:t.roomId,getNode:b=>e.nodes.get(b),addNode:(b,R)=>void e.nodes.set(b,R),deleteNode:b=>void e.nodes.delete(b),generateId:()=>`${w()}:${e.clock++}`,generateOpId:()=>`${w()}:${e.opClock++}`,dispatch(b,R,H){const j=e.activeBatch;j?(j.ops.push(...b),H.forEach((Z,we)=>{j.updates.storageUpdates.set(we,Un(j.updates.storageUpdates.get(we),Z))}),j.reverseOps.push(...R)):s(()=>{g(R,i),e.redoStack=[],Ir(b),x({storageUpdates:H},i)})},assertStorageIsWritable:()=>{if(qt(e.connection.current)&&e.connection.current.isReadOnly)throw new Error("Cannot write to storage with a read only user, please ensure the user has write permissions")}},a={customEvent:Ge(),me:Ge(),others:Ge(),error:Ge(),connection:Ge(),storage:Ge(),history:Ge(),storageDidLoad:Ge()},l=n||{authenticate(b,R){const H=e.token,j=H!==null&&Mr(H);if(j&&!so(j)){const Z=R(H);M(j,Z);return}else return b(t.roomId).then(({token:Z})=>{if(e.connection.current.state!=="authenticating")return;const we=Mr(Z),ve=R(Z);M(we,ve),e.token=Z}).catch(Z=>F())},send(b){if(e.socket===null)throw new Error("Can't send message if socket is null");e.socket.send(JSON.stringify(b))},delayFlush(b){return setTimeout($e,b)},startHeartbeatInterval(){return setInterval(Oe,vo)},schedulePongTimeout(){return setTimeout(lt,yo)},scheduleReconnect(b){return setTimeout(z,b)}},u=new go([e.connection,e.me],(b,R)=>qt(b)?{connectionId:b.id,id:b.userId,info:b.userInfo,presence:R,isReadOnly:b.isReadOnly}:null);function f(b,R){if(b.items.length===0)throw new Error("Internal error: cannot load storage without items");e.root?h(b.items,R):e.root=d(b.items);for(const H in e.initialStorage)e.root.get(H)===void 0&&e.root.set(H,e.initialStorage[H])}function p(b){const R=new Map;let H=null;for(const[j,Z]of b)if(Ci(Z))H=[j,Z];else{const we=[j,Z],ve=R.get(Z.parentId);ve!==void 0?ve.push(we):R.set(Z.parentId,[we])}if(H===null)throw new Error("Root can't be null");return[H,R]}function h(b,R){if(!e.root)return;const H=new Map;e.nodes.forEach((we,ve)=>{H.set(ve,we._serialize())});const j=Qs(H,new Map(b)),Z=C(j,!1);x(Z.updates,R)}function d(b){const[R,H]=p(b);return Ke._deserialize(R,H,o)}function y(b,R){e.undoStack.length>=50&&e.undoStack.shift(),e.undoStack.push(b),A(R)}function g(b,R){e.pausedHistory!==null?e.pausedHistory.unshift(...b):y(b,R)}function x({storageUpdates:b=new Map,presence:R=!1,others:H=[]},j){j(()=>{if(H.length>0){const Z=e.others.current;for(const we of H)a.others.notify({others:Z,event:we})}if(R&&a.me.notify(e.me.current),b.size>0){const Z=Array.from(b.values());a.storage.notify(Z)}})}function w(){const b=e.connection.current;if(qt(b))return b.id;if(e.lastConnectionId!==null)return e.lastConnectionId;throw new Error("Internal. Tried to get connection id but connection was never open")}function C(b,R){const H={reverse:[],updates:{storageUpdates:new Map,presence:!1}},j=new Set;for(const Z of b)if(Z.type==="presence"){const we={type:"presence",data:{}};for(const ve in Z.data)we.data[ve]=e.me.current[ve];if(e.me.patch(Z.data),e.buffer.me===null)e.buffer.me={type:"partial",data:Z.data};else for(const ve in Z.data)e.buffer.me.data[ve]=Z.data[ve];H.reverse.unshift(we),H.updates.presence=!0}else{let we;Z.opId||(Z.opId=o.generateOpId()),R?we=0:we=e.offlineOperations.delete(le(Z.opId))?2:1;const ve=T(Z,we);if(ve.modified){const Nn=ve.modified.node.parent.type==="HasParent"?le(ve.modified.node.parent.node._id,"Expected parent node to have an ID"):void 0;(!Nn||!j.has(Nn))&&(H.updates.storageUpdates.set(le(ve.modified.node._id),Un(H.updates.storageUpdates.get(le(ve.modified.node._id)),ve.modified)),H.reverse.unshift(...ve.reverse)),(Z.type===2||Z.type===7||Z.type===4)&&j.add(le(ve.modified.node._id))}}return H}function T(b,R){switch(b.type){case 6:case 3:case 5:{const H=e.nodes.get(b.id);return H===void 0?{modified:!1}:H._apply(b,R===0)}case 1:{const H=e.nodes.get(b.id);return H===void 0?{modified:!1}:H.parent.type==="HasParent"&&xn(H.parent.node)?H.parent.node._setChildKey(b.parentKey,H,R):{modified:!1}}case 4:case 2:case 7:case 8:{if(b.parentId===void 0)return{modified:!1};const H=e.nodes.get(b.parentId);return H===void 0?{modified:!1}:H._attachChild(b,R)}}}function E(b,R){return a.storage.subscribe(H=>{const j=H.filter(Z=>Ti(Z.node,b));j.length>0&&R(j)})}function S(b,R){return a.storage.subscribe(H=>{for(const j of H)j.node._id===b._id&&R(j.node)})}function P(b,R,H){if(typeof b=="string"&&js(b)){if(typeof R!="function")throw new Error("Second argument must be a callback function");const j=R;switch(b){case"event":return a.customEvent.subscribe(j);case"my-presence":return a.me.subscribe(j);case"others":{const Z=j;return a.others.subscribe(({others:we,event:ve})=>Z(we,ve))}case"error":return a.error.subscribe(j);case"connection":return a.connection.subscribe(j);case"storage":return a.storage.subscribe(j);case"history":return a.history.subscribe(j);default:return et(b,"Unknown event")}}if(R===void 0||typeof b=="function")if(typeof b=="function"){const j=b;return a.storage.subscribe(j)}else throw new Error("Please specify a listener callback");if(Se(b)){const j=b;return H!=null&&H.isDeep?E(j,R):S(j,R)}throw new Error(`"${b}" is not a valid event name`)}function O(){return e.connection.current.state}function z(){var b,R,H,j;if(e.connection.current.state!=="closed"&&e.connection.current.state!=="unavailable")return;const Z=Io(t.authentication,(R=(b=t.polyfills)==null?void 0:b.fetch)!=null?R:t.fetchPolyfill),we=Co(t.liveblocksServer,(j=(H=t.polyfills)==null?void 0:H.WebSocket)!=null?j:t.WebSocketPolyfill);G({state:"authenticating"},s),l.authenticate(Z,we)}function X(b,R){const H={};e.buffer.me===null&&(e.buffer.me={type:"partial",data:{}});for(const j in b){const Z=b[j];Z!==void 0&&(e.buffer.me.data[j]=Z,H[j]=e.me.current[j])}e.me.patch(b),e.activeBatch?(R!=null&&R.addToHistory&&e.activeBatch.reverseOps.push({type:"presence",data:H}),e.activeBatch.updates.presence=!0):($e(),s(()=>{R!=null&&R.addToHistory&&g([{type:"presence",data:H}],i),x({presence:!0},i)}))}function K(b){return b.includes("room:read")&&b.includes("room:presence:write")&&!b.includes("room:write")}function M(b,R){R.addEventListener("message",oe),R.addEventListener("open",Ie),R.addEventListener("close",ae),R.addEventListener("error",Ee),G({state:"connecting",id:b.actor,userInfo:b.info,userId:b.id,isReadOnly:K(b.scopes)},s),e.idFactory=wo(b.actor),e.socket=R}function F(b){e.token=null,G({state:"unavailable"},s),e.numberOfRetry++,e.timeoutHandles.reconnect=l.scheduleReconnect(ue())}function B(b){b==="visible"&&e.connection.current.state==="open"&&Oe()}function v(b){if(b.targetActor!==void 0){const H=e.others.getUser(b.actor);e.others.setOther(b.actor,b.data);const j=e.others.getUser(b.actor);if(H===void 0&&j!==void 0)return{type:"enter",user:j}}else e.others.patchOther(b.actor,b.data);const R=e.others.getUser(b.actor);if(R)return{type:"update",updates:b.data,user:R}}function $(b){const R=e.others.getUser(b.actor);return R?(e.others.removeConnection(b.actor),{type:"leave",user:R}):null}function I(b){for(const R in b.users){const H=b.users[R],j=Number(R);e.others.setConnection(j,H.id,H.info,K(H.scopes))}return{type:"reset"}}function N(){e.connection.current.state==="unavailable"&&ut()}function A(b){b(()=>{a.history.notify({canUndo:Or(),canRedo:Ar()})})}function V(b){e.others.setConnection(b.actor,b.id,b.info,K(b.scopes)),e.buffer.messages.push({type:100,data:e.me.current,targetActor:b.actor}),$e();const R=e.others.getUser(b.actor);return R?{type:"enter",user:R}:void 0}function L(b){return Vi(b)?b:null}function W(b){const R=pr(b);return R===void 0?null:_r(R)?Yn(R.map(H=>L(H))):Yn([L(R)])}function oe(b){if(b.data==="pong"){clearTimeout(e.timeoutHandles.pongTimeout);return}const R=W(b.data);if(R===null||R.length===0)return;const H={storageUpdates:new Map,others:[]};s(()=>{for(const j of R)switch(j.type){case 101:{const Z=V(j);Z&&H.others.push(Z);break}case 100:{const Z=v(j);Z&&H.others.push(Z);break}case 103:{a.customEvent.notify({connectionId:j.actor,event:j.event});break}case 102:{const Z=$(j);Z&&H.others.push(Z);break}case 104:{H.others.push(I(j));break}case 200:{const Z=new Map(e.offlineOperations);f(j,i),Xt(Z,i),Rn==null||Rn(),a.storageDidLoad.notify();break}case 201:{C(j.ops,!1).updates.storageUpdates.forEach((we,ve)=>{H.storageUpdates.set(ve,Un(H.storageUpdates.get(ve),we))});break}}x(H,i)})}function ae(b){e.socket=null,clearTimeout(e.timeoutHandles.pongTimeout),clearInterval(e.intervalHandles.heartbeat),e.timeoutHandles.flush&&clearTimeout(e.timeoutHandles.flush),clearTimeout(e.timeoutHandles.reconnect),e.others.clearOthers(),s(()=>{if(x({others:[{type:"reset"}]},i),b.code>=4e3&&b.code<=4100){G({state:"failed"},i);const R=new xo(b.reason,b.code);a.error.notify(R);const H=ue(!0);e.numberOfRetry++,G({state:"unavailable"},i),e.timeoutHandles.reconnect=l.scheduleReconnect(H)}else if(b.code===4999)G({state:"closed"},i);else{const R=ue();e.numberOfRetry++,G({state:"unavailable"},i),e.timeoutHandles.reconnect=l.scheduleReconnect(R)}})}function G(b,R){e.connection.set(b),R(()=>{a.connection.notify(b.state)})}function ue(b=!1){return b?zn[e.numberOfRetry0&&b.forEach(j=>{e.offlineOperations.set(le(j.opId),j)}),e.socket===null||e.socket.readyState!==e.socket.OPEN){e.buffer.storageOperations=[];return}const R=Date.now();if(R-e.lastFlushTime>t.throttleDelay){const j=Jt(e);if(j.length===0)return;l.send(j),e.buffer={messages:[],storageOperations:[],me:null},e.lastFlushTime=R}else e.timeoutHandles.flush!==null&&clearTimeout(e.timeoutHandles.flush),e.timeoutHandles.flush=l.delayFlush(t.throttleDelay-(R-e.lastFlushTime))}function Jt(b){const R=[];b.buffer.me&&R.push(b.buffer.me.type==="full"?{type:100,targetActor:-1,data:b.buffer.me.data}:{type:100,data:b.buffer.me.data});for(const H of b.buffer.messages)R.push(H);return b.buffer.storageOperations.length>0&&R.push({type:201,ops:b.buffer.storageOperations}),R}function Pt(){e.socket&&(e.socket.removeEventListener("open",Ie),e.socket.removeEventListener("message",oe),e.socket.removeEventListener("close",ae),e.socket.removeEventListener("error",Ee),e.socket.close(),e.socket=null),s(()=>{G({state:"closed"},i),e.timeoutHandles.flush&&clearTimeout(e.timeoutHandles.flush),clearTimeout(e.timeoutHandles.reconnect),clearTimeout(e.timeoutHandles.pongTimeout),clearInterval(e.intervalHandles.heartbeat),e.others.clearOthers(),x({others:[{type:"reset"}]},i),Object.values(a).forEach(b=>b.clear())})}function Wt(){return e.me.current}function Es(){return e.others.current}function ks(b,R={shouldQueueEventIfNotReady:!1}){e.socket===null&&!R.shouldQueueEventIfNotReady||(e.buffer.messages.push({type:103,event:b}),$e())}function Ir(b){e.buffer.storageOperations.push(...b),$e()}let Mn=null,Rn=null;function Sr(){return Mn===null&&(e.buffer.messages.push({type:200}),$e(),Mn=new Promise(b=>Rn=b)),Mn}function xs(){const b=e.root;return b!==void 0?b:(Sr(),null)}function Cs(){return fr(this,null,function*(){return e.root?Promise.resolve({root:e.root}):(yield Sr(),{root:le(e.root)})})}function Is(){if(e.activeBatch)throw new Error("undo is not allowed during a batch");const b=e.undoStack.pop();if(b===void 0)return;e.pausedHistory=null;const R=C(b,!0);s(()=>{x(R.updates,i),e.redoStack.push(R.reverse),A(i)});for(const H of b)H.type!=="presence"&&e.buffer.storageOperations.push(H);$e()}function Or(){return e.undoStack.length>0}function Ss(){if(e.activeBatch)throw new Error("redo is not allowed during a batch");const b=e.redoStack.pop();if(b===void 0)return;e.pausedHistory=null;const R=C(b,!0);s(()=>{x(R.updates,i),e.undoStack.push(R.reverse),A(i)});for(const H of b)H.type!=="presence"&&e.buffer.storageOperations.push(H);$e()}function Ar(){return e.redoStack.length>0}function Os(b){if(e.activeBatch)return b();let R;return s(()=>{e.activeBatch={ops:[],updates:{storageUpdates:new Map,presence:!1,others:[]},reverseOps:[]};try{R=b()}finally{const H=e.activeBatch;e.activeBatch=null,H.reverseOps.length>0&&g(H.reverseOps,i),H.ops.length>0&&(e.redoStack=[]),H.ops.length>0&&Ir(H.ops),x(H.updates,i),$e()}}),R}function As(){e.pausedHistory=[]}function Ps(){const b=e.pausedHistory;e.pausedHistory=null,b!==null&&b.length>0&&y(b,s)}function Ls(){e.socket&&(e.socket=null)}function Ts(b){ae(b)}return{onClose:ae,onMessage:oe,authenticationSuccess:M,heartbeat:Oe,onNavigatorOnline:N,simulateSocketClose:Ls,simulateSendCloseEvent:Ts,onVisibilityChange:B,getUndoStack:()=>e.undoStack,getItemsCount:()=>e.nodes.size,connect:z,disconnect:Pt,subscribe:P,updatePresence:X,broadcastEvent:ks,batch:Os,undo:Is,redo:Ss,canUndo:Or,canRedo:Ar,pauseHistory:As,resumeHistory:Ps,getStorage:Cs,getStorageSnapshot:xs,events:{customEvent:a.customEvent.observable,others:a.others.observable,me:a.me.observable,error:a.error.observable,connection:a.connection.observable,storage:a.storage.observable,history:a.history.observable,storageDidLoad:a.storageDidLoad.observable},getConnectionState:O,isSelfAware:()=>qt(e.connection.current),getSelf:()=>u.current,getPresence:Wt,getOthers:Es}}function Eo(e,t){const n=new mo,r=new _o({state:"closed"});return{token:null,lastConnectionId:null,socket:null,numberOfRetry:0,lastFlushTime:0,timeoutHandles:{flush:null,reconnect:0,pongTimeout:0},buffer:{me:{type:"full",data:e},messages:[],storageOperations:[]},intervalHandles:{heartbeat:0},connection:r,me:new ho(e),others:n,initialStorage:t,idFactory:null,clock:0,opClock:0,nodes:new Map,root:void 0,undoStack:[],redoStack:[],pausedHistory:null,activeBatch:null,offlineOperations:new Map}}function ko(e,t){const{initialPresence:n,initialStorage:r}=e,i=Eo(typeof n=="function"?n(t.roomId):n,typeof r=="function"?r(t.roomId):r),s=bo(i,t),o={id:t.roomId,getConnectionState:s.getConnectionState,isSelfAware:s.isSelfAware,getSelf:s.getSelf,subscribe:s.subscribe,getPresence:s.getPresence,updatePresence:s.updatePresence,getOthers:s.getOthers,broadcastEvent:s.broadcastEvent,getStorage:s.getStorage,getStorageSnapshot:s.getStorageSnapshot,events:s.events,batch:s.batch,history:{undo:s.undo,redo:s.redo,canUndo:s.canUndo,canRedo:s.canRedo,pause:s.pauseHistory,resume:s.resumeHistory},__INTERNAL_DO_NOT_USE:{simulateCloseWebsocket:s.simulateSocketClose,simulateSendCloseEvent:s.simulateSendCloseEvent}};return{connect:s.connect,disconnect:s.disconnect,onNavigatorOnline:s.onNavigatorOnline,onVisibilityChange:s.onVisibilityChange,room:o}}var xo=class extends Error{constructor(e,t){super(e),this.code=t}};function Co(e,t){if(typeof window>"u"&&t===void 0)throw new Error("To use Liveblocks client in a non-dom environment, you need to provide a WebSocket polyfill.");const n=t||WebSocket;return r=>new n(`${e}/?token=${r}&version=0.18.5`)}function Io(e,t){if(e.type==="public"){if(typeof window>"u"&&t===void 0)throw new Error("To use Liveblocks client in a non-dom environment with a publicApiKey, you need to provide a fetch polyfill.");return n=>Rr(t||fetch,e.url,{room:n,publicApiKey:e.publicApiKey})}if(e.type==="private"){if(typeof window>"u"&&t===void 0)throw new Error("To use Liveblocks client in a non-dom environment with a url as auth endpoint, you need to provide a fetch polyfill.");return n=>Rr(t||fetch,e.url,{room:n})}if(e.type==="custom")return n=>fr(this,null,function*(){const r=yield e.callback(n);if(!r||!r.token)throw new Error('Authentication error. We expect the authentication callback to return a token, but it does not. Hint: the return value should look like: { token: "..." }');return r});throw new Error("Internal error. Unexpected authentication type")}function Rr(e,t,n){return fr(this,null,function*(){const r=yield e(t,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(!r.ok)throw new Vn(`Expected a status 200 but got ${r.status} when doing a POST request on "${t}"`);let i;try{i=yield r.json()}catch(o){throw new Vn(`Expected a JSON response when doing a POST request on "${t}". ${o}`)}if(!it(i)||typeof i.token!="string")throw new Vn(`Expected a JSON response of the form \`{ token: "..." }\` when doing a POST request on "${t}", but got ${JSON.stringify(i)}`);const{token:s}=i;return{token:s}})}var Vn=class extends Error{constructor(e){super(e)}};function So(e){const t=e,n=Oo(e),r=new Map;function i(a){const l=r.get(a);return l?l.room:null}function s(a,l){var u,f;const p=l.shouldInitiallyConnect===void 0?!0:l.shouldInitiallyConnect;let h=r.get(a);if(h)return h.room;if(l.initialPresence===null||l.initialPresence,h=ko({initialPresence:(u=l.initialPresence)!=null?u:{},initialStorage:l.initialStorage},{roomId:a,throttleDelay:n,polyfills:t.polyfills,WebSocketPolyfill:t.WebSocketPolyfill,fetchPolyfill:t.fetchPolyfill,unstable_batchedUpdates:l==null?void 0:l.unstable_batchedUpdates,liveblocksServer:(t==null?void 0:t.liveblocksServer)||"wss://api.liveblocks.io/v6",authentication:Ao(t,a)}),r.set(a,h),p){if(typeof atob>"u"){if(((f=t.polyfills)==null?void 0:f.atob)===void 0)throw new Error("You need to polyfill atob to use the client in your environment. Please follow the instructions at https://liveblocks.io/docs/errors/liveblocks-client/atob-polyfill");Hs.atob=t.polyfills.atob}h.connect()}return h.room}function o(a){const l=r.get(a);l&&(l.disconnect(),r.delete(a))}return typeof window<"u"&&typeof window.addEventListener<"u"&&window.addEventListener("online",()=>{for(const[,a]of r)a.onNavigatorOnline()}),typeof document<"u"&&document.addEventListener("visibilitychange",()=>{for(const[,a]of r)a.onVisibilityChange(document.visibilityState)}),{getRoom:i,enter:s,leave:o}}function Oo(e){if(e.throttle===void 0)return 100;if(typeof e.throttle!="number"||e.throttle<80||e.throttle>1e3)throw new Error("throttle should be a number between 80 and 1000.");return e.throttle}function Ao(e,t){const{publicApiKey:n,authEndpoint:r}=e;if(r!==void 0&&n!==void 0)throw new Error("You cannot use both publicApiKey and authEndpoint. Please use either publicApiKey or authEndpoint, but not both. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient");if(typeof n=="string"){if(n.startsWith("sk_"))throw new Error("Invalid publicApiKey. You are using the secret key which is not supported. Please use the public key instead. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientPublicKey");if(!n.startsWith("pk_"))throw new Error("Invalid key. Please use the public key format: pk_. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientPublicKey");return{type:"public",publicApiKey:n,url:Po(e,t)}}if(typeof r=="string")return{type:"private",url:r};if(typeof r=="function")return{type:"custom",callback:r};throw r!==void 0?new Error("authEndpoint must be a string or a function. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClientAuthEndpoint"):new Error("Invalid Liveblocks client options. For more information: https://liveblocks.io/docs/api-reference/liveblocks-client#createClient")}function Po(e,t){return e.publicAuthorizeEndpoint?e.publicAuthorizeEndpoint.replace("{roomId}",t):`https://api.liveblocks.io/v2/rooms/${encodeURIComponent(t)}/public/authorize`}function Bi(e){const t={};for(const n in e){const r=e[n];r!==void 0&&(t[n]=He(r))}return t}function Lo(e){return Bi(e.toObject())}function To(e){const t={};for(const[n,r]of e.entries())t[n]=He(r);return t}function Ki(e){return e.map(He)}function $o(e){return Ki(e.toArray())}function He(e){return e instanceof Ke?Lo(e):e instanceof We?$o(e):e instanceof at?To(e):e instanceof ot?e.data:Array.isArray(e)?Ki(e):it(e)?Bi(e):e}function pt(e){if(Array.isArray(e))return new We(e.map(pt));if(it(e)){const t={};for(const n in e){const r=e[n];r!==void 0&&(t[n]=pt(r))}return new Ke(t)}else return e}function Mo(e,t,n){let r=0,i=t.length-1,s=n.length-1,o=t[0],a=n[0];e:{for(;o===a;){if(++r,r>i||r>s)break e;o=t[r],a=n[r]}for(o=t[i],a=n[s];o===a;){if(i--,s--,r>i||r>s)break e;o=t[i],a=n[s]}}if(r>i){if(r<=s)for(;r<=s;)e.insert(pt(n[r]),r),r++}else if(r>s){let l=r;for(;l<=i;)e.delete(r),l++}else{for(;r<=i&&r<=s;){o=t[r],a=n[r];const u=e.get(r);dr(u)&&it(o)&&it(a)?ji(u,o,a):e.set(r,pt(a)),r++}for(;r<=s;)e.insert(pt(n[r]),r),r++;let l=r;for(;l<=i;)e.delete(r),l++}}function Fi(e,t,n,r){const i=e.get(t);if(r===void 0)e.delete(t);else if(i===void 0)e.set(t,pt(r));else{if(n===r)return;xn(i)&&Array.isArray(n)&&Array.isArray(r)?Mo(i,n,r):dr(i)&&it(n)&&it(r)?ji(i,n,r):e.set(t,pt(r))}}function ji(e,t,n){const r={};for(const i in n)Fi(e,i,t[i],n[i]);for(const i in t)n[i]===void 0&&e.delete(i);Object.keys(r).length>0&&e.update(r)}function Ro(e){const t=[];for(;e.parent.type==="HasParent";)xn(e.parent.node)?t.push(e.parent.node._indexOfPosition(e.parent.key)):t.push(e.parent.key),e=e.parent.node;return t}function No(e,t){return t.reduce((n,r)=>Do(n,r),e)}function Do(e,t){const n=Ro(t.node);return Xn(e,n,t)}function Xn(e,t,n){var r,i,s,o;const a=t.pop();if(a===void 0)switch(n.type){case"LiveObject":{if(e===null||typeof e!="object"||Array.isArray(e))throw new Error("Internal: received update on LiveObject but state was not an object");const l=Object.assign({},e);for(const u in n.updates)if(((r=n.updates[u])==null?void 0:r.type)==="update"){const f=n.node.get(u);f!==void 0&&(l[u]=He(f))}else((i=n.updates[u])==null?void 0:i.type)==="delete"&&delete l[u];return l}case"LiveList":{if(!Array.isArray(e))throw new Error("Internal: received update on LiveList but state was not an array");let l=e.map(u=>u);for(const u of n.updates)u.type==="set"?l=l.map((f,p)=>p===u.index?He(u.item):f):u.type==="insert"?u.index===l.length?l.push(He(u.item)):l=[...l.slice(0,u.index),He(u.item),...l.slice(u.index)]:u.type==="delete"?l.splice(u.index,1):u.type==="move"&&(u.previousIndex>u.index?l=[...l.slice(0,u.index),He(u.item),...l.slice(u.index,u.previousIndex),...l.slice(u.previousIndex+1)]:l=[...l.slice(0,u.previousIndex),...l.slice(u.previousIndex+1,u.index+1),He(u.item),...l.slice(u.index+1)]);return l}case"LiveMap":{if(e===null||typeof e!="object"||Array.isArray(e))throw new Error("Internal: received update on LiveMap but state was not an object");const l=Object.assign({},e);for(const u in n.updates)if(((s=n.updates[u])==null?void 0:s.type)==="update"){const f=n.node.get(u);f!==void 0&&(l[u]=He(f))}else((o=n.updates[u])==null?void 0:o.type)==="delete"&&delete l[u];return l}}if(Array.isArray(e)){const l=[...e];return l[a]=Xn(e[a],t,n),l}else if(e!==null&&typeof e=="object"){const l=e[a];return l===void 0?e:At(rt({},e),{[a]:Xn(l,t,n)})}else return e}function Uo(e,t){if(e.length!==t.length)return!1;for(let n=0;nObject.prototype.hasOwnProperty.call(t,r)&&Object.is(e[r],t[r]))}function zo(e,t){if(Object.is(e,t))return!0;const n=Array.isArray(e),r=Array.isArray(t);return n||r?!n||!r?!1:Uo(e,t):Ho(e,t)}Y.ClientMsgCode=Ei;Y.CrdtType=xi;Y.LiveList=We;Y.LiveMap=at;Y.LiveObject=Ke;Y.OpCode=ki;Y.ServerMsgCode=Si;Y.WebsocketCloseCodes=Oi;Y.asArrayWithLegacyMethods=Hi;Y.assertNever=et;Y.b64decode=Ri;Y.comparePosition=Pi;Y.createClient=So;Y.deprecate=lo;Y.deprecateIf=uo;Y.errorIf=fo;Y.freeze=Ve;Y.isAppOnlyAuthToken=Di;Y.isAuthToken=oo;Y.isChildCrdt=Ii;Y.isJsonArray=_r;Y.isJsonObject=Vi;Y.isJsonScalar=zi;Y.isPlainObject=it;Y.isRoomAuthToken=mr;Y.isRootCrdt=Ci;Y.legacy_patchImmutableObject=No;Y.lsonToJson=He;Y.makePosition=Ye;Y.nn=le;Y.patchLiveObjectKey=Fi;Y.shallow=zo;Y.throwUsageError=co;Y.tryParseJson=pr;const Vo=Y.ClientMsgCode,Bo=Y.CrdtType,Ko=Y.LiveList,Fo=Y.LiveMap,jo=Y.LiveObject,Yo=Y.OpCode,Xo=Y.ServerMsgCode,Jo=Y.WebsocketCloseCodes,Wo=Y.asArrayWithLegacyMethods,Zo=Y.assertNever,qo=Y.b64decode,Go=Y.comparePosition,Qo=Y.createClient,ea=Y.deprecate,ta=Y.deprecateIf,na=Y.errorIf,ra=Y.freeze,ia=Y.isAppOnlyAuthToken,sa=Y.isAuthToken,oa=Y.isChildCrdt,aa=Y.isJsonArray,la=Y.isJsonObject,ua=Y.isJsonScalar,ca=Y.isPlainObject,fa=Y.isRoomAuthToken,ha=Y.isRootCrdt,da=Y.legacy_patchImmutableObject,pa=Y.lsonToJson,ma=Y.makePosition,_a=Y.nn,ga=Y.patchLiveObjectKey,va=Y.shallow,ya=Y.throwUsageError,wa=Y.tryParseJson,ba=Object.freeze(Object.defineProperty({__proto__:null,default:Y,ClientMsgCode:Vo,CrdtType:Bo,LiveList:Ko,LiveMap:Fo,LiveObject:jo,OpCode:Yo,ServerMsgCode:Xo,WebsocketCloseCodes:Jo,asArrayWithLegacyMethods:Wo,assertNever:Zo,b64decode:qo,comparePosition:Go,createClient:Qo,deprecate:ea,deprecateIf:ta,errorIf:na,freeze:ra,isAppOnlyAuthToken:ia,isAuthToken:sa,isChildCrdt:oa,isJsonArray:aa,isJsonObject:la,isJsonScalar:ua,isPlainObject:ca,isRoomAuthToken:fa,isRootCrdt:ha,legacy_patchImmutableObject:da,lsonToJson:pa,makePosition:ma,nn:_a,patchLiveObjectKey:ga,shallow:va,throwUsageError:ya,tryParseJson:wa},Symbol.toStringTag,{value:"Module"})),Ea=zs(ba);Object.defineProperty(Be,"__esModule",{value:!0});var Ft=Ea;Be.LiveList=Ft.LiveList;Be.LiveMap=Ft.LiveMap;Be.LiveObject=Ft.LiveObject;Be.createClient=Ft.createClient;Be.shallow=Ft.shallow;Be.LiveList;Be.LiveMap;const gr=Be.LiveObject,ka=Be.createClient;Be.shallow;const Yi=Symbol(),Xi=Symbol();function xa(e){let t;const n=e[2].default,r=ir(n,e,e[1],null);return{c(){r&&r.c()},l(i){r&&r.l(i)},m(i,s){r&&r.m(i,s),t=!0},p(i,[s]){r&&r.p&&(!t||s&2)&&sr(r,n,i,i[1],t?ar(n,i[1],s,null):or(i[1]),null)},i(i){t||(J(r,i),t=!0)},o(i){q(r,i),t=!1},d(i){r&&r.d(i)}}}function Ca(e,t,n){let{$$slots:r={},$$scope:i}=t,{client:s}=t;if(!s)throw new Error("LiveblocksProvider requires a client");return vi(Yi,s),e.$$set=o=>{"client"in o&&n(0,s=o.client),"$$scope"in o&&n(1,i=o.$$scope)},[s,i,r]}class Ia extends ke{constructor(t){super(),xe(this,t,Ca,xa,Ce,{client:0})}}function Sa(e){let t;const n=e[3].default,r=ir(n,e,e[2],null);return{c(){r&&r.c()},l(i){r&&r.l(i)},m(i,s){r&&r.m(i,s),t=!0},p(i,[s]){r&&r.p&&(!t||s&4)&&sr(r,n,i,i[2],t?ar(n,i[2],s,null):or(i[2]),null)},i(i){t||(J(r,i),t=!0)},o(i){q(r,i),t=!1},d(i){r&&r.d(i)}}}function Oa(e,t,n){let{$$slots:r={},$$scope:i}=t,{id:s}=t,{initialPresence:o={}}=t;if(!s)throw new Error("RoomProvider requires an id");const a=yi(Yi);if(a){const l=a.enter(s,{initialPresence:o});vi(Xi,l),Kt(()=>{a.leave(s)})}return e.$$set=l=>{"id"in l&&n(0,s=l.id),"initialPresence"in l&&n(1,o=l.initialPresence),"$$scope"in l&&n(2,i=l.$$scope)},[s,o,i,r]}class Aa extends ke{constructor(t){super(),xe(this,t,Oa,Sa,Ce,{id:0,initialPresence:1})}}function Pa(e){let t,n,r;return{c(){t=Q("svg"),n=Q("path"),r=Q("path"),this.h()},l(i){t=ee(i,"svg",{class:!0,width:!0,height:!0,viewBox:!0,xmlns:!0});var s=k(t);n=ee(s,"path",{d:!0,fill:!0}),k(n).forEach(_),r=ee(s,"path",{"fill-rule":!0,"clip-rule":!0,d:!0,fill:!0,"fill-opacity":!0}),k(r).forEach(_),s.forEach(_),this.h()},h(){c(n,"d","M3.09022 1.77278C2.25499 1.40456 1.40358 2.25597 1.7718 3.0912L4.57875 9.45818C4.95365 10.3086 6.18455 10.2323 6.4516 9.34213L6.9637 7.63515C7.06029 7.31317 7.31219 7.06126 7.63417 6.96467L9.34117 6.45258C10.2313 6.18552 10.3076 4.95463 9.45722 4.57972L3.09022 1.77278Z"),c(n,"fill",e[1]),c(r,"fill-rule","evenodd"),c(r,"clip-rule","evenodd"),c(r,"d","M3.66305 9.86091L0.856101 3.49392C0.119663 1.82347 1.82248 0.120639 3.49294 0.857077L9.85994 3.66402C11.5607 4.41383 11.4082 6.87562 9.62784 7.40973L7.92085 7.92182L7.40875 9.62881C6.87465 11.4092 4.41286 11.5617 3.66305 9.86091ZM1.77113 3.09053C1.40291 2.2553 2.25432 1.40388 3.08955 1.7721L9.45654 4.57905C10.3069 4.95395 10.2307 6.18485 9.34049 6.4519L7.6335 6.964C7.31152 7.06059 7.05961 7.3125 6.96302 7.63448L6.45093 9.34146C6.18387 10.2316 4.95298 10.3079 4.57807 9.45751L1.77113 3.09053Z"),c(r,"fill","white"),c(r,"fill-opacity","0.8"),c(t,"class",e[0]),c(t,"width","1em"),c(t,"height","1em"),c(t,"viewBox","0 0 12 12"),c(t,"xmlns","http://www.w3.org/2000/svg")},m(i,s){re(i,t,s),m(t,n),m(t,r)},p(i,[s]){s&2&&c(n,"fill",i[1]),s&1&&c(t,"class",i[0])},i:de,o:de,d(i){i&&_(t)}}}function La(e,t,n){let{classList:r=""}=t,{fill:i=""}=t;return e.$$set=s=>{"classList"in s&&n(0,r=s.classList),"fill"in s&&n(1,i=s.fill)},[r,i]}class Ta extends ke{constructor(t){super(),xe(this,t,La,Pa,Ce,{classList:0,fill:1})}}function $a(e){let t,n,r,i;return n=new Ta({props:{classList:"block z-0 col-span-2 row-span-2 text-8xl",fill:e[1]}}),{c(){t=D("div"),pe(n.$$.fragment),this.h()},l(s){t=U(s,"DIV",{class:!0,style:!0});var o=k(t);me(n.$$.fragment,o),o.forEach(_),this.h()},h(){c(t,"class","cursor text-4xl svelte-14ka0w3"),c(t,"style",r=`transform: translateX(${e[2].x}px) translateY(${e[2].y}px) scale(${e[0].k});`)},m(s,o){re(s,t,o),_e(n,t,null),i=!0},p(s,[o]){const a={};o&2&&(a.fill=s[1]),n.$set(a),(!i||o&5&&r!==(r=`transform: translateX(${s[2].x}px) translateY(${s[2].y}px) scale(${s[0].k});`))&&c(t,"style",r)},i(s){i||(J(n.$$.fragment,s),i=!0)},o(s){q(n.$$.fragment,s),i=!1},d(s){s&&_(t),ge(n)}}}function Ma(e,t,n){let r,{transform:i}=t,{color:s=""}=t,{position:o={x:0,y:0}}=t;return e.$$set=a=>{"transform"in a&&n(0,i=a.transform),"color"in a&&n(1,s=a.color),"position"in a&&n(3,o=a.position)},e.$$.update=()=>{e.$$.dirty&9&&n(2,r={x:i.applyX(o.x),y:i.applyY(o.y)})},[i,s,r,o]}class Ra extends ke{constructor(t){super(),xe(this,t,Ma,$a,Ce,{transform:0,color:1,position:3})}}function Na(e){let t,n,r;return{c(){t=Q("svg"),n=Q("circle"),r=Q("path"),this.h()},l(i){t=ee(i,"svg",{class:!0,xmlns:!0,"xmlns:xlink":!0,"aria-hidden":!0,fill:!0,focusable:!0,role:!0,width:!0,height:!0,preserveAspectRatio:!0,viewBox:!0});var s=k(t);n=ee(s,"circle",{class:!0,cx:!0,cy:!0,r:!0,stroke:!0,"stroke-width":!0}),k(n).forEach(_),r=ee(s,"path",{fill:!0,d:!0}),k(r).forEach(_),s.forEach(_),this.h()},h(){c(n,"class","opacity-50"),c(n,"cx","12"),c(n,"cy","12"),c(n,"r","10"),c(n,"stroke","currentColor"),c(n,"stroke-width","4"),c(r,"fill","currentColor"),c(r,"d","M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"),c(t,"class",e[0]),c(t,"xmlns","http://www.w3.org/2000/svg"),c(t,"xmlns:xlink","http://www.w3.org/1999/xlink"),c(t,"aria-hidden","true"),c(t,"fill","none"),c(t,"focusable","false"),c(t,"role","img"),c(t,"width","1em"),c(t,"height","1em"),c(t,"preserveAspectRatio","xMidYMid meet"),c(t,"viewBox","0 0 24 24")},m(i,s){re(i,t,s),m(t,n),m(t,r)},p(i,[s]){s&1&&c(t,"class",i[0])},i:de,o:de,d(i){i&&_(t)}}}function Da(e,t,n){let{classList:r=""}=t;return e.$$set=i=>{"classList"in i&&n(0,r=i.classList)},[r]}class In extends ke{constructor(t){super(),xe(this,t,Da,Na,Ce,{classList:0})}}const Gt=["#505669","#414AA6","#1C5B92","#216B44","#893301","#912728","#98184D","#743095","#5F4199","#8f3f94"],Ct=50,Pe=32,ce=512;var fe=(e=>(e.ready="ready",e.loading="loading",e.prompting="prompting",e.processing="processing",e.dragging="dragging",e.masking="masking",e))(fe||{});function Ua(e){let t,n;return{c(){t=D("p"),n=te("Someone is typing:"),this.h()},l(r){t=U(r,"P",{class:!0});var i=k(t);n=ne(i,"Someone is typing:"),i.forEach(_),this.h()},h(){c(t,"class","text-4xl")},m(r,i){re(r,t,i),m(t,n)},i:de,o:de,d(r){r&&_(t)}}}function Ha(e){let t,n;return{c(){t=D("p"),n=te("Someone is masking"),this.h()},l(r){t=U(r,"P",{class:!0});var i=k(t);n=ne(i,"Someone is masking"),i.forEach(_),this.h()},h(){c(t,"class","text-4xl")},m(r,i){re(r,t,i),m(t,n)},i:de,o:de,d(r){r&&_(t)}}}function za(e){let t,n,r,i,s;return t=new In({props:{classList:"animate-spin text-4xl inline mr-2 mx-auto text-white mb-4"}}),{c(){pe(t.$$.fragment),n=ie(),r=D("p"),i=te("Someone is painting:"),this.h()},l(o){me(t.$$.fragment,o),n=se(o),r=U(o,"P",{class:!0});var a=k(r);i=ne(a,"Someone is painting:"),a.forEach(_),this.h()},h(){c(r,"class","text-4xl")},m(o,a){_e(t,o,a),re(o,n,a),re(o,r,a),m(r,i),s=!0},i(o){s||(J(t.$$.fragment,o),s=!0)},o(o){q(t.$$.fragment,o),s=!1},d(o){ge(t,o),o&&_(n),o&&_(r)}}}function Nr(e){let t,n,r,i;return{c(){t=D("span"),n=te('"'),r=te(e[1]),i=te('"'),this.h()},l(s){t=U(s,"SPAN",{class:!0});var o=k(t);n=ne(o,'"'),r=ne(o,e[1]),i=ne(o,'"'),o.forEach(_),this.h()},h(){c(t,"class","italic font-normal line-clamp-4")},m(s,o){re(s,t,o),m(t,n),m(t,r),m(t,i)},p(s,o){o&2&&nt(r,s[1])},d(s){s&&_(t)}}}function Va(e){let t,n,r,i,s,o,a,l;const u=[za,Ha,Ua],f=[];function p(d,y){return d[2]===fe.loading||d[2]===fe.processing?0:d[2]===fe.masking?1:d[2]===fe.prompting?2:-1}~(i=p(e))&&(s=f[i]=u[i](e));let h=e[1]&&Nr(e);return{c(){t=D("div"),n=D("div"),r=D("div"),s&&s.c(),o=ie(),h&&h.c(),this.h()},l(d){t=U(d,"DIV",{class:!0,style:!0});var y=k(t);n=U(y,"DIV",{class:!0});var g=k(n);r=U(g,"DIV",{class:!0});var x=k(r);s&&s.l(x),o=se(x),h&&h.l(x),x.forEach(_),g.forEach(_),y.forEach(_),this.h()},h(){c(r,"class","font-bold !text-4xl text-white rounded-2xl text-center p-10"),c(n,"class","pointer-events-none touch-none"),c(t,"class","absolute top-0 left-0 border-8 border-dashed border-black flex items-center justify-center bg-black/60"),c(t,"style",a=`width: ${ce}px;
+ height: ${ce}px;
+ transform: translateX(${e[3].x}px) translateY(${e[3].y}px) scale(${e[0].k}); transform-origin: 0 0;`)},m(d,y){re(d,t,y),m(t,n),m(n,r),~i&&f[i].m(r,null),m(r,o),h&&h.m(r,null),l=!0},p(d,[y]){let g=i;i=p(d),i!==g&&(s&&(Le(),q(f[g],1,1,()=>{f[g]=null}),Te()),~i?(s=f[i],s||(s=f[i]=u[i](d),s.c()),J(s,1),s.m(r,o)):s=null),d[1]?h?h.p(d,y):(h=Nr(d),h.c(),h.m(r,null)):h&&(h.d(1),h=null),(!l||y&9&&a!==(a=`width: ${ce}px;
+ height: ${ce}px;
+ transform: translateX(${d[3].x}px) translateY(${d[3].y}px) scale(${d[0].k}); transform-origin: 0 0;`))&&c(t,"style",a)},i(d){l||(J(s),l=!0)},o(d){q(s),l=!1},d(d){d&&_(t),~i&&f[i].d(),h&&h.d()}}}function Ba(e,t,n){let r,{transform:i}=t,{position:s={x:0,y:0}}=t,{prompt:o=""}=t,{status:a}=t;return e.$$set=l=>{"transform"in l&&n(0,i=l.transform),"position"in l&&n(4,s=l.position),"prompt"in l&&n(1,o=l.prompt),"status"in l&&n(2,a=l.status)},e.$$.update=()=>{e.$$.dirty&17&&n(3,r={x:i.applyX(s.x),y:i.applyY(s.y)})},[i,o,a,r,s]}class Ka extends ke{constructor(t){super(),xe(this,t,Ba,Va,Ce,{transform:0,position:4,prompt:1,status:2})}}var Fa={value:()=>{}};function Sn(){for(var e=0,t=arguments.length,n={},r;e=0&&(r=n.slice(i+1),n=n.slice(0,i)),n&&!t.hasOwnProperty(n))throw new Error("unknown type: "+n);return{type:n,name:r}})}an.prototype=Sn.prototype={constructor:an,on:function(e,t){var n=this._,r=ja(e+"",n),i,s=-1,o=r.length;if(arguments.length<2){for(;++s0)for(var n=new Array(i),r=0,i,s;r=0&&(t=e.slice(0,n))!=="xmlns"&&(e=e.slice(n+1)),Ur.hasOwnProperty(t)?{space:Ur[t],local:e}:e}function Xa(e){return function(){var t=this.ownerDocument,n=this.namespaceURI;return n===Jn&&t.documentElement.namespaceURI===Jn?t.createElement(e):t.createElementNS(n,e)}}function Ja(e){return function(){return this.ownerDocument.createElementNS(e.space,e.local)}}function Ji(e){var t=On(e);return(t.local?Ja:Xa)(t)}function Wa(){}function vr(e){return e==null?Wa:function(){return this.querySelector(e)}}function Za(e){typeof e!="function"&&(e=vr(e));for(var t=this._groups,n=t.length,r=new Array(n),i=0;i=T&&(T=C+1);!(S=x[T])&&++T=0;)(o=r[i])&&(s&&o.compareDocumentPosition(s)^4&&s.parentNode.insertBefore(o,s),s=o);return this}function bl(e){e||(e=El);function t(p,h){return p&&h?e(p.__data__,h.__data__):!p-!h}for(var n=this._groups,r=n.length,i=new Array(r),s=0;st?1:e>=t?0:NaN}function kl(){var e=arguments[0];return arguments[0]=this,e.apply(null,arguments),this}function xl(){return Array.from(this)}function Cl(){for(var e=this._groups,t=0,n=e.length;t1?this.each((t==null?Nl:typeof t=="function"?Ul:Dl)(e,t,n==null?"":n)):It(this.node(),e)}function It(e,t){return e.style.getPropertyValue(t)||Qi(e).getComputedStyle(e,null).getPropertyValue(t)}function zl(e){return function(){delete this[e]}}function Vl(e,t){return function(){this[e]=t}}function Bl(e,t){return function(){var n=t.apply(this,arguments);n==null?delete this[e]:this[e]=n}}function Kl(e,t){return arguments.length>1?this.each((t==null?zl:typeof t=="function"?Bl:Vl)(e,t)):this.node()[e]}function es(e){return e.trim().split(/^|\s+/)}function yr(e){return e.classList||new ts(e)}function ts(e){this._node=e,this._names=es(e.getAttribute("class")||"")}ts.prototype={add:function(e){var t=this._names.indexOf(e);t<0&&(this._names.push(e),this._node.setAttribute("class",this._names.join(" ")))},remove:function(e){var t=this._names.indexOf(e);t>=0&&(this._names.splice(t,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(e){return this._names.indexOf(e)>=0}};function ns(e,t){for(var n=yr(e),r=-1,i=t.length;++r=0&&(n=t.slice(r+1),t=t.slice(0,r)),{type:t,name:n}})}function gu(e){return function(){var t=this.__on;if(!!t){for(var n=0,r=-1,i=t.length,s;n()=>e;function Wn(e,{sourceEvent:t,subject:n,target:r,identifier:i,active:s,x:o,y:a,dx:l,dy:u,dispatch:f}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},subject:{value:n,enumerable:!0,configurable:!0},target:{value:r,enumerable:!0,configurable:!0},identifier:{value:i,enumerable:!0,configurable:!0},active:{value:s,enumerable:!0,configurable:!0},x:{value:o,enumerable:!0,configurable:!0},y:{value:a,enumerable:!0,configurable:!0},dx:{value:l,enumerable:!0,configurable:!0},dy:{value:u,enumerable:!0,configurable:!0},_:{value:f}})}Wn.prototype.on=function(){var e=this._.on.apply(this._,arguments);return e===this._?this:e};function Su(e){return!e.ctrlKey&&!e.button}function Ou(){return this.parentNode}function Au(e,t){return t==null?{x:e.x,y:e.y}:t}function Pu(){return navigator.maxTouchPoints||"ontouchstart"in this}function Hr(){var e=Su,t=Ou,n=Au,r=Pu,i={},s=Sn("start","drag","end"),o=0,a,l,u,f,p=0;function h(E){E.on("mousedown.drag",d).filter(r).on("touchstart.drag",x).on("touchmove.drag",w,Iu).on("touchend.drag touchcancel.drag",C).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function d(E,S){if(!(f||!e.call(this,E,S))){var P=T(this,t.call(this,E,S),E,S,"mouse");!P||(Ue(E.view).on("mousemove.drag",y,Ut).on("mouseup.drag",g,Ut),os(E.view),Bn(E),u=!1,a=E.clientX,l=E.clientY,P("start",E))}}function y(E){if(Et(E),!u){var S=E.clientX-a,P=E.clientY-l;u=S*S+P*P>p}i.mouse("drag",E)}function g(E){Ue(E.view).on("mousemove.drag mouseup.drag",null),as(E.view,u),Et(E),i.mouse("end",E)}function x(E,S){if(!!e.call(this,E,S)){var P=E.changedTouches,O=t.call(this,E,S),z=P.length,X,K;for(X=0;X{r(o)});return Kt(()=>{s()}),{subscribe:n,update:i}}function Ru(){const e=An(),t=De(),n=e.subscribe("others",r=>{t.set(r)});return Kt(n),t}function Nu(){const e=An(),t=De();async function n(){const{root:r}=await e.getStorage();t.set(r)}return n(),t}function ls(e,t){const n=An(),r=Nu(),i=De();let s=()=>{};const o=r.subscribe(a=>{!a||(a.get(e)||a.set(e,new gr(t)),i.set(a.get(e)),s(),s=n.subscribe(a.get(e),l=>{i.set(l)}))});return Kt(o),i}const Du=1e4;function Uu(){const e=De([]),t=setInterval(()=>{zr().then(n=>e.set(n))},Du);return zr().then(n=>e.set(n)),Kt(()=>{clearInterval(t)}),e}async function zr(){return fetch(pn+"/rooms").then(e=>e.json())}function wr(e,t,n){e.prototype=t.prototype=n,n.constructor=e}function us(e,t){var n=Object.create(e.prototype);for(var r in t)n[r]=t[r];return n}function Yt(){}var Ht=.7,mn=1/Ht,kt="\\s*([+-]?\\d+)\\s*",zt="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)\\s*",Je="\\s*([+-]?(?:\\d*\\.)?\\d+(?:[eE][+-]?\\d+)?)%\\s*",Hu=/^#([0-9a-f]{3,8})$/,zu=new RegExp(`^rgb\\(${kt},${kt},${kt}\\)$`),Vu=new RegExp(`^rgb\\(${Je},${Je},${Je}\\)$`),Bu=new RegExp(`^rgba\\(${kt},${kt},${kt},${zt}\\)$`),Ku=new RegExp(`^rgba\\(${Je},${Je},${Je},${zt}\\)$`),Fu=new RegExp(`^hsl\\(${zt},${Je},${Je}\\)$`),ju=new RegExp(`^hsla\\(${zt},${Je},${Je},${zt}\\)$`),Vr={aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074};wr(Yt,Vt,{copy(e){return Object.assign(new this.constructor,this,e)},displayable(){return this.rgb().displayable()},hex:Br,formatHex:Br,formatHex8:Yu,formatHsl:Xu,formatRgb:Kr,toString:Kr});function Br(){return this.rgb().formatHex()}function Yu(){return this.rgb().formatHex8()}function Xu(){return cs(this).formatHsl()}function Kr(){return this.rgb().formatRgb()}function Vt(e){var t,n;return e=(e+"").trim().toLowerCase(),(t=Hu.exec(e))?(n=t[1].length,t=parseInt(t[1],16),n===6?Fr(t):n===3?new Me(t>>8&15|t>>4&240,t>>4&15|t&240,(t&15)<<4|t&15,1):n===8?tn(t>>24&255,t>>16&255,t>>8&255,(t&255)/255):n===4?tn(t>>12&15|t>>8&240,t>>8&15|t>>4&240,t>>4&15|t&240,((t&15)<<4|t&15)/255):null):(t=zu.exec(e))?new Me(t[1],t[2],t[3],1):(t=Vu.exec(e))?new Me(t[1]*255/100,t[2]*255/100,t[3]*255/100,1):(t=Bu.exec(e))?tn(t[1],t[2],t[3],t[4]):(t=Ku.exec(e))?tn(t[1]*255/100,t[2]*255/100,t[3]*255/100,t[4]):(t=Fu.exec(e))?Xr(t[1],t[2]/100,t[3]/100,1):(t=ju.exec(e))?Xr(t[1],t[2]/100,t[3]/100,t[4]):Vr.hasOwnProperty(e)?Fr(Vr[e]):e==="transparent"?new Me(NaN,NaN,NaN,0):null}function Fr(e){return new Me(e>>16&255,e>>8&255,e&255,1)}function tn(e,t,n,r){return r<=0&&(e=t=n=NaN),new Me(e,t,n,r)}function Ju(e){return e instanceof Yt||(e=Vt(e)),e?(e=e.rgb(),new Me(e.r,e.g,e.b,e.opacity)):new Me}function Zn(e,t,n,r){return arguments.length===1?Ju(e):new Me(e,t,n,r==null?1:r)}function Me(e,t,n,r){this.r=+e,this.g=+t,this.b=+n,this.opacity=+r}wr(Me,Zn,us(Yt,{brighter(e){return e=e==null?mn:Math.pow(mn,e),new Me(this.r*e,this.g*e,this.b*e,this.opacity)},darker(e){return e=e==null?Ht:Math.pow(Ht,e),new Me(this.r*e,this.g*e,this.b*e,this.opacity)},rgb(){return this},clamp(){return new Me(mt(this.r),mt(this.g),mt(this.b),_n(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:jr,formatHex:jr,formatHex8:Wu,formatRgb:Yr,toString:Yr}));function jr(){return`#${ht(this.r)}${ht(this.g)}${ht(this.b)}`}function Wu(){return`#${ht(this.r)}${ht(this.g)}${ht(this.b)}${ht((isNaN(this.opacity)?1:this.opacity)*255)}`}function Yr(){const e=_n(this.opacity);return`${e===1?"rgb(":"rgba("}${mt(this.r)}, ${mt(this.g)}, ${mt(this.b)}${e===1?")":`, ${e})`}`}function _n(e){return isNaN(e)?1:Math.max(0,Math.min(1,e))}function mt(e){return Math.max(0,Math.min(255,Math.round(e)||0))}function ht(e){return e=mt(e),(e<16?"0":"")+e.toString(16)}function Xr(e,t,n,r){return r<=0?e=t=n=NaN:n<=0||n>=1?e=t=NaN:t<=0&&(e=NaN),new ze(e,t,n,r)}function cs(e){if(e instanceof ze)return new ze(e.h,e.s,e.l,e.opacity);if(e instanceof Yt||(e=Vt(e)),!e)return new ze;if(e instanceof ze)return e;e=e.rgb();var t=e.r/255,n=e.g/255,r=e.b/255,i=Math.min(t,n,r),s=Math.max(t,n,r),o=NaN,a=s-i,l=(s+i)/2;return a?(t===s?o=(n-r)/a+(n0&&l<1?0:o,new ze(o,a,l,e.opacity)}function Zu(e,t,n,r){return arguments.length===1?cs(e):new ze(e,t,n,r==null?1:r)}function ze(e,t,n,r){this.h=+e,this.s=+t,this.l=+n,this.opacity=+r}wr(ze,Zu,us(Yt,{brighter(e){return e=e==null?mn:Math.pow(mn,e),new ze(this.h,this.s,this.l*e,this.opacity)},darker(e){return e=e==null?Ht:Math.pow(Ht,e),new ze(this.h,this.s,this.l*e,this.opacity)},rgb(){var e=this.h%360+(this.h<0)*360,t=isNaN(e)||isNaN(this.s)?0:this.s,n=this.l,r=n+(n<.5?n:1-n)*t,i=2*n-r;return new Me(Kn(e>=240?e-240:e+120,i,r),Kn(e,i,r),Kn(e<120?e+240:e-120,i,r),this.opacity)},clamp(){return new ze(Jr(this.h),nn(this.s),nn(this.l),_n(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const e=_n(this.opacity);return`${e===1?"hsl(":"hsla("}${Jr(this.h)}, ${nn(this.s)*100}%, ${nn(this.l)*100}%${e===1?")":`, ${e})`}`}}));function Jr(e){return e=(e||0)%360,e<0?e+360:e}function nn(e){return Math.max(0,Math.min(1,e||0))}function Kn(e,t,n){return(e<60?t+(n-t)*e/60:e<180?n:e<240?t+(n-t)*(240-e)/60:t)*255}const fs=e=>()=>e;function qu(e,t){return function(n){return e+n*t}}function Gu(e,t,n){return e=Math.pow(e,n),t=Math.pow(t,n)-e,n=1/n,function(r){return Math.pow(e+r*t,n)}}function Qu(e){return(e=+e)==1?hs:function(t,n){return n-t?Gu(t,n,e):fs(isNaN(t)?n:t)}}function hs(e,t){var n=t-e;return n?qu(e,n):fs(isNaN(e)?t:e)}const Wr=function e(t){var n=Qu(t);function r(i,s){var o=n((i=Zn(i)).r,(s=Zn(s)).r),a=n(i.g,s.g),l=n(i.b,s.b),u=hs(i.opacity,s.opacity);return function(f){return i.r=o(f),i.g=a(f),i.b=l(f),i.opacity=u(f),i+""}}return r.gamma=e,r}(1);function ct(e,t){return e=+e,t=+t,function(n){return e*(1-n)+t*n}}var qn=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,Fn=new RegExp(qn.source,"g");function ec(e){return function(){return e}}function tc(e){return function(t){return e(t)+""}}function nc(e,t){var n=qn.lastIndex=Fn.lastIndex=0,r,i,s,o=-1,a=[],l=[];for(e=e+"",t=t+"";(r=qn.exec(e))&&(i=Fn.exec(t));)(s=i.index)>n&&(s=t.slice(n,s),a[o]?a[o]+=s:a[++o]=s),(r=r[0])===(i=i[0])?a[o]?a[o]+=i:a[++o]=i:(a[++o]=null,l.push({i:o,x:ct(r,i)})),n=Fn.lastIndex;return n180?f+=360:f-u>180&&(u+=360),h.push({i:p.push(i(p)+"rotate(",null,r)-2,x:ct(u,f)})):f&&p.push(i(p)+"rotate("+f+r)}function a(u,f,p,h){u!==f?h.push({i:p.push(i(p)+"skewX(",null,r)-2,x:ct(u,f)}):f&&p.push(i(p)+"skewX("+f+r)}function l(u,f,p,h,d,y){if(u!==p||f!==h){var g=d.push(i(d)+"scale(",null,",",null,")");y.push({i:g-4,x:ct(u,p)},{i:g-2,x:ct(f,h)})}else(p!==1||h!==1)&&d.push(i(d)+"scale("+p+","+h+")")}return function(u,f){var p=[],h=[];return u=e(u),f=e(f),s(u.translateX,u.translateY,f.translateX,f.translateY,p,h),o(u.rotate,f.rotate,p,h),a(u.skewX,f.skewX,p,h),l(u.scaleX,u.scaleY,f.scaleX,f.scaleY,p,h),u=f=null,function(d){for(var y=-1,g=h.length,x;++y=0&&e._call.call(void 0,t),e=e._next;--St}function Gr(){vt=(vn=Bt.now())+Ln,St=Mt=0;try{hc()}finally{St=0,pc(),vt=0}}function dc(){var e=Bt.now(),t=e-vn;t>ms&&(Ln-=t,vn=e)}function pc(){for(var e,t=gn,n,r=1/0;t;)t._call?(r>t._time&&(r=t._time),e=t,t=t._next):(n=t._next,t._next=null,t=e?e._next=n:gn=n);Rt=e,Qn(r)}function Qn(e){if(!St){Mt&&(Mt=clearTimeout(Mt));var t=e-vt;t>24?(e<1/0&&(Mt=setTimeout(Gr,e-Bt.now()-Ln)),Lt&&(Lt=clearInterval(Lt))):(Lt||(vn=Bt.now(),Lt=setInterval(dc,ms)),St=1,_s(Gr))}}function Qr(e,t,n){var r=new yn;return t=t==null?0:+t,r.restart(i=>{r.stop(),e(i+t)},t,n),r}var mc=Sn("start","end","cancel","interrupt"),_c=[],vs=0,ei=1,er=2,ln=3,ti=4,tr=5,un=6;function Tn(e,t,n,r,i,s){var o=e.__transition;if(!o)e.__transition={};else if(n in o)return;gc(e,n,{name:t,index:r,group:i,on:mc,tween:_c,time:s.time,delay:s.delay,duration:s.duration,ease:s.ease,timer:null,state:vs})}function Er(e,t){var n=Fe(e,t);if(n.state>vs)throw new Error("too late; already scheduled");return n}function Ze(e,t){var n=Fe(e,t);if(n.state>ln)throw new Error("too late; already running");return n}function Fe(e,t){var n=e.__transition;if(!n||!(n=n[t]))throw new Error("transition not found");return n}function gc(e,t,n){var r=e.__transition,i;r[t]=n,n.timer=gs(s,0,n.time);function s(u){n.state=ei,n.timer.restart(o,n.delay,n.time),n.delay<=u&&o(u-n.delay)}function o(u){var f,p,h,d;if(n.state!==ei)return l();for(f in r)if(d=r[f],d.name===n.name){if(d.state===ln)return Qr(o);d.state===ti?(d.state=un,d.timer.stop(),d.on.call("interrupt",e,e.__data__,d.index,d.group),delete r[f]):+fer&&r.state=0&&(t=t.slice(0,n)),!t||t==="start"})}function Xc(e,t,n){var r,i,s=Yc(t)?Er:Ze;return function(){var o=s(this,e),a=o.on;a!==r&&(i=(r=a).copy()).on(t,n),o.on=i}}function Jc(e,t){var n=this._id;return arguments.length<2?Fe(this.node(),n).on.on(e):this.each(Xc(n,e,t))}function Wc(e){return function(){var t=this.parentNode;for(var n in this.__transition)if(+n!==e)return;t&&t.removeChild(this)}}function Zc(){return this.on("end.remove",Wc(this._id))}function qc(e){var t=this._name,n=this._id;typeof e!="function"&&(e=vr(e));for(var r=this._groups,i=r.length,s=new Array(i),o=0;o()=>e;function kf(e,{sourceEvent:t,target:n,transform:r,dispatch:i}){Object.defineProperties(this,{type:{value:e,enumerable:!0,configurable:!0},sourceEvent:{value:t,enumerable:!0,configurable:!0},target:{value:n,enumerable:!0,configurable:!0},transform:{value:r,enumerable:!0,configurable:!0},_:{value:i}})}function tt(e,t,n){this.k=e,this.x=t,this.y=n}tt.prototype={constructor:tt,scale:function(e){return e===1?this:new tt(this.k*e,this.x,this.y)},translate:function(e,t){return e===0&t===0?this:new tt(this.k,this.x+this.k*e,this.y+this.k*t)},apply:function(e){return[e[0]*this.k+this.x,e[1]*this.k+this.y]},applyX:function(e){return e*this.k+this.x},applyY:function(e){return e*this.k+this.y},invert:function(e){return[(e[0]-this.x)/this.k,(e[1]-this.y)/this.k]},invertX:function(e){return(e-this.x)/this.k},invertY:function(e){return(e-this.y)/this.k},rescaleX:function(e){return e.copy().domain(e.range().map(this.invertX,this).map(e.invert,e))},rescaleY:function(e){return e.copy().domain(e.range().map(this.invertY,this).map(e.invert,e))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var $n=new tt(1,0,0);tt.prototype;function jn(e){e.stopImmediatePropagation()}function Tt(e){e.preventDefault(),e.stopImmediatePropagation()}function xf(e){return(!e.ctrlKey||e.type==="wheel")&&!e.button}function Cf(){var e=this;return e instanceof SVGElement?(e=e.ownerSVGElement||e,e.hasAttribute("viewBox")?(e=e.viewBox.baseVal,[[e.x,e.y],[e.x+e.width,e.y+e.height]]):[[0,0],[e.width.baseVal.value,e.height.baseVal.value]]):[[0,0],[e.clientWidth,e.clientHeight]]}function ni(){return this.__zoom||$n}function If(e){return-e.deltaY*(e.deltaMode===1?.05:e.deltaMode?1:.002)*(e.ctrlKey?10:1)}function Sf(){return navigator.maxTouchPoints||"ontouchstart"in this}function Of(e,t,n){var r=e.invertX(t[0][0])-n[0][0],i=e.invertX(t[1][0])-n[1][0],s=e.invertY(t[0][1])-n[0][1],o=e.invertY(t[1][1])-n[1][1];return e.translate(i>r?(r+i)/2:Math.min(0,r)||Math.max(0,i),o>s?(s+o)/2:Math.min(0,s)||Math.max(0,o))}function Af(){var e=xf,t=Cf,n=Of,r=If,i=Sf,s=[0,1/0],o=[[-1/0,-1/0],[1/0,1/0]],a=250,l=cc,u=Sn("start","zoom","end"),f,p,h,d=500,y=150,g=0,x=10;function w(v){v.property("__zoom",ni).on("wheel.zoom",z,{passive:!1}).on("mousedown.zoom",X).on("dblclick.zoom",K).filter(i).on("touchstart.zoom",M).on("touchmove.zoom",F).on("touchend.zoom touchcancel.zoom",B).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}w.transform=function(v,$,I,N){var A=v.selection?v.selection():v;A.property("__zoom",ni),v!==A?S(v,$,I,N):A.interrupt().each(function(){P(this,arguments).event(N).start().zoom(null,typeof $=="function"?$.apply(this,arguments):$).end()})},w.scaleBy=function(v,$,I,N){w.scaleTo(v,function(){var A=this.__zoom.k,V=typeof $=="function"?$.apply(this,arguments):$;return A*V},I,N)},w.scaleTo=function(v,$,I,N){w.transform(v,function(){var A=t.apply(this,arguments),V=this.__zoom,L=I==null?E(A):typeof I=="function"?I.apply(this,arguments):I,W=V.invert(L),oe=typeof $=="function"?$.apply(this,arguments):$;return n(T(C(V,oe),L,W),A,o)},I,N)},w.translateBy=function(v,$,I,N){w.transform(v,function(){return n(this.__zoom.translate(typeof $=="function"?$.apply(this,arguments):$,typeof I=="function"?I.apply(this,arguments):I),t.apply(this,arguments),o)},null,N)},w.translateTo=function(v,$,I,N,A){w.transform(v,function(){var V=t.apply(this,arguments),L=this.__zoom,W=N==null?E(V):typeof N=="function"?N.apply(this,arguments):N;return n($n.translate(W[0],W[1]).scale(L.k).translate(typeof $=="function"?-$.apply(this,arguments):-$,typeof I=="function"?-I.apply(this,arguments):-I),V,o)},N,A)};function C(v,$){return $=Math.max(s[0],Math.min(s[1],$)),$===v.k?v:new tt($,v.x,v.y)}function T(v,$,I){var N=$[0]-I[0]*v.k,A=$[1]-I[1]*v.k;return N===v.x&&A===v.y?v:new tt(v.k,N,A)}function E(v){return[(+v[0][0]+ +v[1][0])/2,(+v[0][1]+ +v[1][1])/2]}function S(v,$,I,N){v.on("start.zoom",function(){P(this,arguments).event(N).start()}).on("interrupt.zoom end.zoom",function(){P(this,arguments).event(N).end()}).tween("zoom",function(){var A=this,V=arguments,L=P(A,V).event(N),W=t.apply(A,V),oe=I==null?E(W):typeof I=="function"?I.apply(A,V):I,ae=Math.max(W[1][0]-W[0][0],W[1][1]-W[0][1]),G=A.__zoom,ue=typeof $=="function"?$.apply(A,V):$,Ee=l(G.invert(oe).concat(ae/G.k),ue.invert(oe).concat(ae/ue.k));return function(Ie){if(Ie===1)Ie=ue;else{var Oe=Ee(Ie),lt=ae/Oe[2];Ie=new tt(lt,oe[0]-Oe[0]*lt,oe[1]-Oe[1]*lt)}L.zoom(null,Ie)}})}function P(v,$,I){return!I&&v.__zooming||new O(v,$)}function O(v,$){this.that=v,this.args=$,this.active=0,this.sourceEvent=null,this.extent=t.apply(v,$),this.taps=0}O.prototype={event:function(v){return v&&(this.sourceEvent=v),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(v,$){return this.mouse&&v!=="mouse"&&(this.mouse[1]=$.invert(this.mouse[0])),this.touch0&&v!=="touch"&&(this.touch0[1]=$.invert(this.touch0[0])),this.touch1&&v!=="touch"&&(this.touch1[1]=$.invert(this.touch1[0])),this.that.__zoom=$,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(v){var $=Ue(this.that).datum();u.call(v,this.that,new kf(v,{sourceEvent:this.sourceEvent,target:w,type:v,transform:this.that.__zoom,dispatch:u}),$)}};function z(v,...$){if(!e.apply(this,arguments))return;var I=P(this,$).event(v),N=this.__zoom,A=Math.max(s[0],Math.min(s[1],N.k*Math.pow(2,r.apply(this,arguments)))),V=Qe(v);if(I.wheel)(I.mouse[0][0]!==V[0]||I.mouse[0][1]!==V[1])&&(I.mouse[1]=N.invert(I.mouse[0]=V)),clearTimeout(I.wheel);else{if(N.k===A)return;I.mouse=[V,N.invert(V)],cn(this),I.start()}Tt(v),I.wheel=setTimeout(L,y),I.zoom("mouse",n(T(C(N,A),I.mouse[0],I.mouse[1]),I.extent,o));function L(){I.wheel=null,I.end()}}function X(v,...$){if(h||!e.apply(this,arguments))return;var I=v.currentTarget,N=P(this,$,!0).event(v),A=Ue(v.view).on("mousemove.zoom",oe,!0).on("mouseup.zoom",ae,!0),V=Qe(v,I),L=v.clientX,W=v.clientY;os(v.view),jn(v),N.mouse=[V,this.__zoom.invert(V)],cn(this),N.start();function oe(G){if(Tt(G),!N.moved){var ue=G.clientX-L,Ee=G.clientY-W;N.moved=ue*ue+Ee*Ee>g}N.event(G).zoom("mouse",n(T(N.that.__zoom,N.mouse[0]=Qe(G,I),N.mouse[1]),N.extent,o))}function ae(G){A.on("mousemove.zoom mouseup.zoom",null),as(G.view,N.moved),Tt(G),N.event(G).end()}}function K(v,...$){if(!!e.apply(this,arguments)){var I=this.__zoom,N=Qe(v.changedTouches?v.changedTouches[0]:v,this),A=I.invert(N),V=I.k*(v.shiftKey?.5:2),L=n(T(C(I,V),N,A),t.apply(this,$),o);Tt(v),a>0?Ue(this).transition().duration(a).call(S,L,N,v):Ue(this).call(w.transform,L,N,v)}}function M(v,...$){if(!!e.apply(this,arguments)){var I=v.touches,N=I.length,A=P(this,$,v.changedTouches.length===N).event(v),V,L,W,oe;for(jn(v),L=0;L{K=null}),Te()),((L=A[3])==null?void 0:L.status)!=="masking"?M?M.p(A,V):(M=ii(A),M.c(),M.m(r,s)):M&&(M.d(1),M=null),(!O||V[0]&2&&a!==(a=(A[1]?"hidden":"bg-white block")+" absolute top-0 left-0 z-0"))&&c(o,"class",a),A[8]?F?F.p(A,V):(F=si(A),F.c(),F.m(u,null)):F&&(F.d(1),F=null),v===(v=B(A))&&$?$.p(A,V):($.d(1),$=v(A),$&&($.c(),$.m(h,null))),(!O||V[0]&1&&d!==(d=`transform: scale(${Math.max(2.5-A[0].k,1)});`))&&c(p,"style",d),A[6]?I&&(I.d(1),I=null):I?I.p(A,V):(I=ai(A),I.c(),I.m(g,null)),(!O||V[0]&1&&x!==(x=`transform: scale(${Math.max(2.5-A[0].k,1)}); transform-origin: 0 0;`))&&c(g,"style",x),(!O||V[0]&129&&w!==(w=`transform: translateX(${A[7].x}px) translateY(${A[7].y}px) scale(${A[0].k}); transform-origin: 0 0;`))&&c(n,"style",w),(!O||V[0]&2&&E!==(E=A[1]?"Drag the frame around, prompt, and paint":"Enable dragging"))&&c(T,"title",E),(!O||V[0]&66&&S!==(S="absolute top-0 left-0 ring-8 hand "+(A[1]?"block":"hidden")+" "+(A[6]?"cursor-wait":A[1]?"block cursor-move":"hidden cursor-pointer")))&&c(T,"class",S),(!O||V[0]&129&&P!==(P=`width: ${ce}px;height: ${ce}px;transform: translateX(${A[7].x}px) translateY(${A[7].y}px) scale(${A[0].k}); transform-origin: 0 0;`))&&c(T,"style",P)},i(A){O||(J(K),O=!0)},o(A){q(K),O=!1},d(A){A&&_(t),K&&K.d(),M&&M.d(),e[17](null),F&&F.d(),$.d(),I&&I.d(),e[20](null),z=!1,X()}}}function $f(e,t,n){let r,i,s,o,a,l,u,f,p;he(e,bn,L=>n(24,o=L)),he(e,Nt,L=>n(25,a=L)),he(e,rr,L=>n(9,l=L)),he(e,Ae,L=>n(2,u=L)),he(e,Dt,L=>n(16,f=L));const h=Pn();he(e,h,L=>n(3,p=L));const d=lr();let{transform:y}=t,g,x={x:o.width/2-ce/2,y:o.height/2-ce/2},w,C=!0,T=!1,E=null,S=0,P=0;function O(L){g.save(),g.clearRect(0,0,ce,ce),g.globalCompositeOperation="source-over",g.drawImage(a,L.x,L.y,ce,ce,0,0,ce,ce),g.restore()}function z(L){g.save(),g.globalCompositeOperation="destination-out",g.beginPath(),g.moveTo(L.lastx,L.lasty),g.lineTo(L.x,L.y),g.lineWidth=50,g.lineCap="round",g.strokeStyle="black",g.stroke(),g.restore()}Ot(()=>{g=l.getContext("2d"),Ue(w).on("wheel",L=>{a.dispatchEvent(new WheelEvent("wheel",L))}).call(F()).call(X),Ue(l).on("wheel",L=>{a.dispatchEvent(new WheelEvent("wheel",L))}).call(M()).call(X),n(15,E=!0)});function X(L){function W(ae){h.update({cursor:{x:y.invertX(ae.clientX),y:y.invertY(ae.clientY)}})}function oe(){h.update({cursor:null})}return L.on("pointermove",W).on("pointerleave",oe)}function K(L){return Math.min(Math.max(L,Pe),ce-Pe)}function M(){let L,W;function oe(G){if(i)return;const ue=K(G.x/y.k),Ee=K(G.y/y.k);L=ue,W=Ee}function ae(G){if(i)return;const ue=K(G.x/y.k),Ee=K(G.y/y.k);z({x:ue,y:Ee,lastx:L,lasty:W}),L=ue,W=Ee}return Hr().on("start",oe).on("drag",ae)}function F(){function L(ae){if(i)return;const G=ae.sourceEvent.target.getBoundingClientRect();typeof TouchEvent<"u"&&ae.sourceEvent instanceof TouchEvent?(S=ae.sourceEvent.targetTouches[0].pageX-G.left,P=ae.sourceEvent.targetTouches[0].pageY-G.top):ae.sourceEvent instanceof MouseEvent&&(S=ae.sourceEvent.pageX-G.left,P=ae.sourceEvent.pageY-G.top),n(5,T=!0)}function W(ae){if(i)return;const G=en(y.invertX(ae.x-S),o),ue=en(y.invertY(ae.y-P),o);n(14,x={x:G,y:ue}),h.update({cursor:{x:y.invertX(ae.x),y:y.invertY(ae.y)}}),O({x:G,y:ue})}function oe(ae){if(i)return;n(5,T=!1);const G=en(y.invertX(ae.x-S),o),ue=en(y.invertY(ae.y-P),o);O({x:G,y:ue}),h.update({frame:{x:G,y:ue}})}return Hr().on("start",L).on("drag",W).on("end",oe)}function B(){n(1,C=!0),h.update({status:fe.dragging})}function v(){n(1,C=!1),O(x),h.update({status:fe.masking})}function $(){O(x)}function I(L){_t[L?"unshift":"push"](()=>{l=L,rr.set(l)})}const N=()=>B(),A=()=>d("showModal",{showModal:!0});function V(L){_t[L?"unshift":"push"](()=>{w=L,n(4,w)})}return e.$$set=L=>{"transform"in L&&n(0,y=L.transform)},e.$$.update=()=>{e.$$.dirty[0]&8&&n(8,r=p==null?void 0:p.currentPrompt),e.$$.dirty[0]&8&&n(6,i=(p==null?void 0:p.status)===fe.loading||(p==null?void 0:p.status)===fe.prompting||!1),e.$$.dirty[0]&16385&&n(7,s={x:y.applyX(x.x),y:y.applyY(x.y)}),e.$$.dirty[0]&98304&&E!==null&&!f&&E&&($(),n(15,E=!1)),e.$$.dirty[0]&6&&u==="Complete"&&!C&&($(),B())},[y,C,u,p,w,T,i,s,r,l,h,d,B,v,x,E,f,I,N,A,V]}class Mf extends ke{constructor(t){super(),xe(this,t,$f,Tf,Ce,{transform:0},null,[-1,-1])}}function Rf(e,t){let n;if(t===void 0)for(const r of e)r!=null&&(n>r||n===void 0&&r>=r)&&(n=r);else{let r=-1;for(let i of e)(i=t(i,++r,e))!=null&&(n>i||n===void 0&&i>=i)&&(n=i)}return n}function Nf(e){let t,n,r,i;const s=e[8].default,o=ir(s,e,e[7],null);return{c(){t=D("div"),n=D("canvas"),r=ie(),o&&o.c(),this.h()},l(a){t=U(a,"DIV",{class:!0});var l=k(t);n=U(l,"CANVAS",{width:!0,height:!0,class:!0}),k(n).forEach(_),r=se(l),o&&o.l(l),l.forEach(_),this.h()},h(){c(n,"width",e[4]),c(n,"height",e[3]),c(n,"class","absolute top-0 left-0 bg-white shadow-2xl shadow-blue-500/20 svelte-6dcxg7"),c(t,"class","absolute top-0 left-0 right-0 bottom-0 overflow-hidden z-0 bg-blue-200")},m(a,l){re(a,t,l),m(t,n),e[9](n),m(t,r),o&&o.m(t,null),e[10](t),i=!0},p(a,[l]){o&&o.p&&(!i||l&128)&&sr(o,s,a,a[7],i?ar(s,a[7],l,null):or(a[7]),null)},i(a){i||(J(o,a),i=!0)},o(a){q(o,a),i=!1},d(a){a&&_(t),e[9](null),o&&o.d(a),e[10](null)}}}function Df(e,t,n){let r,i,s,o,a,l;he(e,nr,M=>n(12,r=M)),he(e,Nt,M=>n(1,i=M)),he(e,Dt,M=>n(13,s=M)),he(e,yt,M=>n(14,a=M)),he(e,bn,M=>n(15,l=M));let{$$slots:u={},$$scope:f}=t;const p=Pn(),h=ls("promptImgStorage");he(e,h,M=>n(6,o=M));const d=l.height,y=l.width;let g,x;const w=new Set;function C(M){if(M){const F=a||"",B=new Map;for(const N of Array.from(Array(y/Pe).keys()))for(const A of Array.from(Array(d/Pe).keys()))B.set(`${N*Pe}_${A*Pe}`,null);const v=Object.values(M).map(N=>N instanceof gr?N.toObject():N).map(N=>{const A=N.imgURL.split(/-|.jpg|.webp/),V=parseInt(A[0]),L=A[1],[W,oe]=A[2].split("_"),ae=A.slice(3).join(" ");return{id:L,date:V,position:{x:parseInt(W),y:parseInt(oe)},imgURL:N.imgURL,prompt:ae,room:F}}).sort((N,A)=>A.date-N.date);for(const N of v){const A=N.position.x,V=N.position.y;for(const L of[...Array(ce/Pe).keys()])for(const W of[...Array(ce/Pe).keys()]){const oe=`${A+L*Pe}_${V+W*Pe}`;B.get(oe)||B.set(oe,N.id)}}const $=new Set([...B.values()]),I=v.filter(N=>$.has(N.id));return v.filter(N=>!$.has(N.id)).map(N=>{const A=`${N.position.x}_${N.position.y}`;o.delete(A),console.log("deleted",A)}),I.reverse().filter(N=>!w.has(N.id))}return[]}let T=[];function E(M,F,B,v,$,I){const N=(M-I)/v,A=(F-I)/$,V=Rf([N,A])||1,L=M/2-B.x*V,W=F/2-B.y*V;return $n.translate(L,W).scale(V)}Ot(()=>{const F=(y+100)/(g.clientHeight>g.clientWidth?g.clientWidth:g.clientHeight),B=Af().scaleExtent([1/F/2,3]).tapDistance(10).on("zoom",P),v=Ue(i.parentElement).call(B).call(B.transform,E(g.clientWidth,g.clientHeight,{x:y/2,y:d/2},y,d,50)).on("pointermove",O).on("pointerleave",z);x=i.getContext("2d");function $(){const I=(y+100)/(g.clientHeight>g.clientWidth?g.clientWidth:g.clientHeight);B.scaleExtent([1/I/2,3]),v.call(B.transform,E(g.clientWidth,g.clientHeight,{x:y/2,y:d/2},y,d,50))}return window.addEventListener("resize",$),()=>{window.removeEventListener("resize",$)}});async function S(M){M.length!==0&&(be(Dt,s=!0,s),await Promise.allSettled(M.map(({imgURL:F,position:B,id:v,room:$})=>new Promise((I,N)=>{const A=new Image;A.crossOrigin="anonymous",A.onload=()=>{const V={img:A,position:B,id:v};x.drawImage(A,B.x,B.y,A.width,A.height),I(V)},A.onerror=V=>{N(V)},A.src=`${Tu}/${$}/${F}`}))).then(F=>{F.filter(v=>v.status==="fulfilled").map(v=>v.value).forEach(({img:v,position:$,id:I})=>{w.add(I),x.drawImage(v,$.x,$.y,v.width,v.height)})}),be(Dt,s=!1,s))}function P(M){const F=be(nr,r=M.transform,r);be(Nt,i.style.transform=`translate(${F.x}px, ${F.y}px) scale(${F.k})`,i)}function O(M){M.preventDefault();const F=r.invertX(M.clientX),B=r.invertY(M.clientY);p.update({cursor:{x:F,y:B}})}function z(){p.update({cursor:null})}function X(M){_t[M?"unshift":"push"](()=>{i=M,Nt.set(i)})}function K(M){_t[M?"unshift":"push"](()=>{g=M,n(0,g)})}return e.$$set=M=>{"$$scope"in M&&n(7,f=M.$$scope)},e.$$.update=()=>{e.$$.dirty&64&&n(5,T=C(o==null?void 0:o.toObject())),e.$$.dirty&32&&T&&S(T)},[g,i,h,d,y,T,o,f,u,X,K]}class Uf extends ke{constructor(t){super(),xe(this,t,Df,Nf,Ce,{})}}function Hf(e){let t,n,r;return{c(){t=Q("svg"),n=Q("rect"),r=Q("rect"),this.h()},l(i){t=ee(i,"svg",{class:!0,height:!0,viewBox:!0,fill:!0,xmlns:!0});var s=k(t);n=ee(s,"rect",{x:!0,y:!0,width:!0,height:!0,rx:!0,stroke:!0}),k(n).forEach(_),r=ee(s,"rect",{x:!0,y:!0,width:!0,height:!0,rx:!0,fill:!0,stroke:!0}),k(r).forEach(_),s.forEach(_),this.h()},h(){c(n,"x","1"),c(n,"y","1"),c(n,"width","7"),c(n,"height","7"),c(n,"rx","1"),c(n,"stroke","#2F6DCB"),c(r,"x","3.05566"),c(r,"y","3.05566"),c(r,"width","2.88889"),c(r,"height","2.88889"),c(r,"rx","0.5"),c(r,"fill","#2F6DCB"),c(r,"stroke","#2F6DCB"),c(t,"class",e[0]),c(t,"height","1em"),c(t,"viewBox","0 0 9 9"),c(t,"fill","none"),c(t,"xmlns","http://www.w3.org/2000/svg")},m(i,s){re(i,t,s),m(t,n),m(t,r)},p(i,[s]){s&1&&c(t,"class",i[0])},i:de,o:de,d(i){i&&_(t)}}}function zf(e,t,n){let{classList:r=""}=t;return e.$$set=i=>{"classList"in i&&n(0,r=i.classList)},[r]}class xr extends ke{constructor(t){super(),xe(this,t,zf,Hf,Ce,{classList:0})}}function Vf(e){let t,n;return{c(){t=Q("svg"),n=Q("path"),this.h()},l(r){t=ee(r,"svg",{class:!0,height:!0,viewBox:!0,fill:!0,xmlns:!0});var i=k(t);n=ee(i,"path",{d:!0,fill:!0}),k(n).forEach(_),i.forEach(_),this.h()},h(){c(n,"d","M3.5 4.58599C3.74063 4.58599 3.94669 4.4961 4.11819 4.31633C4.2894 4.13687 4.375 3.92102 4.375 3.66879C4.375 3.41656 4.2894 3.20056 4.11819 3.02079C3.94669 2.84132 3.74063 2.75159 3.5 2.75159C3.25937 2.75159 3.05346 2.84132 2.88225 3.02079C2.71075 3.20056 2.625 3.41656 2.625 3.66879C2.625 3.92102 2.71075 4.13687 2.88225 4.31633C3.05346 4.4961 3.25937 4.58599 3.5 4.58599ZM3.5 7.95669C4.38958 7.10064 5.04948 6.32285 5.47969 5.62334C5.9099 4.92413 6.125 4.30318 6.125 3.76051C6.125 2.92739 5.87154 2.24515 5.36462 1.71378C4.858 1.18273 4.23646 0.917197 3.5 0.917197C2.76354 0.917197 2.14185 1.18273 1.63494 1.71378C1.12831 2.24515 0.875 2.92739 0.875 3.76051C0.875 4.30318 1.0901 4.92413 1.52031 5.62334C1.95052 6.32285 2.61042 7.10064 3.5 7.95669ZM3.5 9C3.44167 9 3.38333 8.98853 3.325 8.9656C3.26667 8.94267 3.21562 8.9121 3.17188 8.87389C2.10729 7.8879 1.3125 6.97269 0.7875 6.12825C0.2625 5.28352 0 4.49427 0 3.76051C0 2.61401 0.351896 1.70064 1.05569 1.02038C1.75919 0.340127 2.57396 0 3.5 0C4.42604 0 5.24081 0.340127 5.94431 1.02038C6.6481 1.70064 7 2.61401 7 3.76051C7 4.49427 6.7375 5.28352 6.2125 6.12825C5.6875 6.97269 4.89271 7.8879 3.82812 8.87389C3.78438 8.9121 3.73333 8.94267 3.675 8.9656C3.61667 8.98853 3.55833 9 3.5 9Z"),c(n,"fill","white"),c(t,"class",e[0]),c(t,"height","1em"),c(t,"viewBox","0 0 7 9"),c(t,"fill","none"),c(t,"xmlns","http://www.w3.org/2000/svg")},m(r,i){re(r,t,i),m(t,n)},p(r,[i]){i&1&&c(t,"class",r[0])},i:de,o:de,d(r){r&&_(t)}}}function Bf(e,t,n){let{classList:r=""}=t;return e.$$set=i=>{"classList"in i&&n(0,r=i.classList)},[r]}class Kf extends ke{constructor(t){super(),xe(this,t,Bf,Vf,Ce,{classList:0})}}function Ff(e){let t,n,r,i;return{c(){t=Q("svg"),n=Q("path"),r=Q("path"),i=Q("path"),this.h()},l(s){t=ee(s,"svg",{class:!0,height:!0,width:!0,viewBox:!0,fill:!0,xmlns:!0});var o=k(t);n=ee(o,"path",{"fill-rule":!0,"clip-rule":!0,d:!0,fill:!0}),k(n).forEach(_),r=ee(o,"path",{d:!0,fill:!0}),k(r).forEach(_),i=ee(o,"path",{"fill-rule":!0,"clip-rule":!0,d:!0,fill:!0}),k(i).forEach(_),o.forEach(_),this.h()},h(){c(n,"fill-rule","evenodd"),c(n,"clip-rule","evenodd"),c(n,"d","M6.41113 3.73486C6.97158 4.11531 7.3643 4.63076 7.3643 5.31801V6.54526H8.59155C8.81654 6.54526 9.00063 6.36118 9.00063 6.13618V5.31801C9.00063 4.42621 7.5402 3.8985 6.41113 3.73486Z"),c(n,"fill","currentColor"),c(r,"d","M3.27305 3.27266C4.17677 3.27266 4.90938 2.54005 4.90938 1.63633C4.90938 0.732611 4.17677 0 3.27305 0C2.36933 0 1.63672 0.732611 1.63672 1.63633C1.63672 2.54005 2.36933 3.27266 3.27305 3.27266Z"),c(r,"fill","currentColor"),c(i,"fill-rule","evenodd"),c(i,"clip-rule","evenodd"),c(i,"d","M5.72716 3.27266C6.63124 3.27266 7.36349 2.54041 7.36349 1.63633C7.36349 0.732258 6.63124 0 5.72716 0C5.53489 0 5.3549 0.0409082 5.18308 0.0981798C5.53511 0.533533 5.72715 1.07646 5.72715 1.63633C5.72715 2.1962 5.53511 2.73913 5.18308 3.17448C5.3549 3.23176 5.53489 3.27266 5.72716 3.27266ZM3.27266 3.68175C2.18041 3.68175 0 4.22992 0 5.31808V6.13624C0 6.36124 0.184087 6.54533 0.409083 6.54533H6.13625C6.36124 6.54533 6.54533 6.36124 6.54533 6.13624V5.31808C6.54533 4.22992 4.36492 3.68175 3.27266 3.68175Z"),c(i,"fill","currentColor"),c(t,"class",e[0]),c(t,"height","1em"),c(t,"width","1em"),c(t,"viewBox","0 0 9 7"),c(t,"fill","none"),c(t,"xmlns","http://www.w3.org/2000/svg")},m(s,o){re(s,t,o),m(t,n),m(t,r),m(t,i)},p(s,[o]){o&1&&c(t,"class",s[0])},i:de,o:de,d(s){s&&_(t)}}}function jf(e,t,n){let{classList:r=""}=t;return e.$$set=i=>{"classList"in i&&n(0,r=i.classList)},[r]}class Cr extends ke{constructor(t){super(),xe(this,t,jf,Ff,Ce,{classList:0})}}function li(e,t,n){const r=e.slice();return r[14]=t[n],r}function Yf(e){let t,n,r,i;return n=new In({props:{classList:"animate-spin mr-2 text-sm"}}),{c(){t=D("div"),pe(n.$$.fragment),r=te(" loading rooms"),this.h()},l(s){t=U(s,"DIV",{class:!0});var o=k(t);me(n.$$.fragment,o),r=ne(o," loading rooms"),o.forEach(_),this.h()},h(){c(t,"class","bg-gradient-to-r from-transparent via-blue-900/20 to-transparent py-1.5 text-blue-700 rounded-full flex justify-center items-center")},m(s,o){re(s,t,o),_e(n,t,null),m(t,r),i=!0},p:de,i(s){i||(J(n.$$.fragment,s),i=!0)},o(s){q(n.$$.fragment,s),i=!1},d(s){s&&_(t),ge(n)}}}function Xf(e){let t,n,r,i,s,o,a,l,u,f=!e[4]&&ui(e);const p=[Wf,Jf],h=[];function d(y,g){return y[6]?0:1}return i=d(e),s=h[i]=p[i](e),{c(){t=D("div"),f&&f.c(),n=ie(),r=D("div"),s.c(),this.h()},l(y){t=U(y,"DIV",{class:!0,title:!0});var g=k(t);f&&f.l(g),n=se(g),r=U(g,"DIV",{class:!0});var x=k(r);s.l(x),x.forEach(_),g.forEach(_),this.h()},h(){c(r,"class",o=e[0]?"cursor-wait":"cursor-pointer"),c(t,"class","text-sm rounded-2xl md:text-smtext-gray-700 py-1 font-medium tracking-tight relative ring-1 ring-blue-500 px-2"),c(t,"title","Choose a different room")},m(y,g){re(y,t,g),f&&f.m(t,null),m(t,n),m(t,r),h[i].m(r,null),e[11](t),a=!0,l||(u=Re(r,"click",e[10]),l=!0)},p(y,g){y[4]?f&&(Le(),q(f,1,1,()=>{f=null}),Te()):f?(f.p(y,g),g&16&&J(f,1)):(f=ui(y),f.c(),J(f,1),f.m(t,n));let x=i;i=d(y),i===x?h[i].p(y,g):(Le(),q(h[x],1,1,()=>{h[x]=null}),Te(),s=h[i],s?s.p(y,g):(s=h[i]=p[i](y),s.c()),J(s,1),s.m(r,null)),(!a||g&1&&o!==(o=y[0]?"cursor-wait":"cursor-pointer"))&&c(r,"class",o)},i(y){a||(J(f),J(s),a=!0)},o(y){q(f),q(s),a=!1},d(y){y&&_(t),f&&f.d(),h[i].d(),e[11](null),l=!1,u()}}}function ui(e){let t,n,r,i,s,o,a,l,u,f,p,h,d,y,g,x,w,C;i=new xr({}),p=new Cr({});let T=e[2],E=[];for(let P=0;Pq(E[P],1,1,()=>{E[P]=null});return{c(){t=D("div"),n=D("ul"),r=D("li"),pe(i.$$.fragment),s=ie(),o=D("span"),a=te("room"),l=ie(),u=D("span"),f=ie(),pe(p.$$.fragment),h=ie(),d=D("span"),y=te("players"),g=ie();for(let P=0;P{O=null}),Te()),(!E||K&4)&&o!==(o=e[14].room_id+"")&&nt(a,o),(!E||K&4)&&y!==(y=e[14].users_count+"")&&nt(g,y),(!E||K&6&&C!==(C="grid-row gap-2 hover:bg-gray-300 "+(e[14].room_id===e[1]?"text-black":"")+" svelte-tz2nn1"))&&c(n,"class",C)},i(X){E||(J(O),E=!0)},o(X){q(O),E=!1},d(X){X&&_(t),O&&O.d(),S=!1,P()}}}function Jf(e){let t,n,r,i,s,o,a,l,u,f;return n=new xr({}),o=new Cr({}),{c(){t=D("div"),pe(n.$$.fragment),r=ie(),i=D("span"),s=te(`Loading...
+ `),pe(o.$$.fragment),a=ie(),l=D("span"),u=te("... / ..."),this.h()},l(p){t=U(p,"DIV",{class:!0});var h=k(t);me(n.$$.fragment,h),r=se(h),i=U(h,"SPAN",{class:!0});var d=k(i);s=ne(d,`Loading...
+ `),me(o.$$.fragment,d),a=se(d),l=U(d,"SPAN",{class:!0});var y=k(l);u=ne(y,"... / ..."),y.forEach(_),d.forEach(_),h.forEach(_),this.h()},h(){c(l,"class","svelte-tz2nn1"),c(i,"class","svelte-tz2nn1"),c(t,"class","grid-row gap-2 svelte-tz2nn1")},m(p,h){re(p,t,h),_e(n,t,null),m(t,r),m(t,i),m(i,s),_e(o,i,null),m(i,a),m(i,l),m(l,u),f=!0},p:de,i(p){f||(J(n.$$.fragment,p),J(o.$$.fragment,p),f=!0)},o(p){q(n.$$.fragment,p),q(o.$$.fragment,p),f=!1},d(p){p&&_(t),ge(n),ge(o)}}}function Wf(e){var C,T;let t,n,r,i,s=((C=e[6])==null?void 0:C.room_id)+"",o,a,l,u,f,p,h,d=((T=e[6])==null?void 0:T.users_count)+"",y,g,x,w;return n=new xr({}),f=new Cr({}),{c(){t=D("div"),pe(n.$$.fragment),r=ie(),i=D("span"),o=te(s),a=ie(),l=D("span"),u=ie(),pe(f.$$.fragment),p=ie(),h=D("span"),y=te(d),g=te(" / "),x=te(Ct),this.h()},l(E){t=U(E,"DIV",{class:!0});var S=k(t);me(n.$$.fragment,S),r=se(S),i=U(S,"SPAN",{class:!0});var P=k(i);o=ne(P,s),P.forEach(_),a=se(S),l=U(S,"SPAN",{class:!0}),k(l).forEach(_),u=se(S),me(f.$$.fragment,S),p=se(S),h=U(S,"SPAN",{class:!0});var O=k(h);y=ne(O,d),g=ne(O," / "),x=ne(O,Ct),O.forEach(_),S.forEach(_),this.h()},h(){c(i,"class","svelte-tz2nn1"),c(l,"class","svelte-tz2nn1"),c(h,"class","svelte-tz2nn1"),c(t,"class","grid-row gap-2 svelte-tz2nn1")},m(E,S){re(E,t,S),_e(n,t,null),m(t,r),m(t,i),m(i,o),m(t,a),m(t,l),m(t,u),_e(f,t,null),m(t,p),m(t,h),m(h,y),m(h,g),m(h,x),w=!0},p(E,S){var P,O;(!w||S&64)&&s!==(s=((P=E[6])==null?void 0:P.room_id)+"")&&nt(o,s),(!w||S&64)&&d!==(d=((O=E[6])==null?void 0:O.users_count)+"")&&nt(y,d)},i(E){w||(J(n.$$.fragment,E),J(f.$$.fragment,E),w=!0)},o(E){q(n.$$.fragment,E),q(f.$$.fragment,E),w=!1},d(E){E&&_(t),ge(n),ge(f)}}}function Zf(e){let t,n,r,i;const s=[Xf,Yf],o=[];function a(l,u){return l[5]&&l[6]?0:1}return n=a(e),r=o[n]=s[n](e),{c(){t=D("div"),r.c(),this.h()},l(l){t=U(l,"DIV",{class:!0});var u=k(t);r.l(u),u.forEach(_),this.h()},h(){c(t,"class","min-w-[20ch]")},m(l,u){re(l,t,u),o[n].m(t,null),i=!0},p(l,[u]){let f=n;n=a(l),n===f?o[n].p(l,u):(Le(),q(o[f],1,1,()=>{o[f]=null}),Te(),r=o[n],r?r.p(l,u):(r=o[n]=s[n](l),r.c()),J(r,1),r.m(t,null))},i(l){i||(J(r),i=!0)},o(l){q(r),i=!1},d(l){l&&_(t),o[n].d()}}}function qf(e,t,n){let r,i,s,o,a;he(e,Us,w=>n(12,s=w)),he(e,yt,w=>n(1,o=w));let{isLoading:l=!1}=t,u;const f=Uu();he(e,f,w=>n(2,a=w));let p=!0;function h(w){u&&!u.contains(w.target)&&n(4,p=!0)}Ot(()=>(window.addEventListener("pointerdown",h,!0),()=>{window.removeEventListener("pointerdown",h,!0)}));function d(w){be(yt,o=w.room_id,o),n(4,p=!0),s.url.searchParams.set("roomid",w.room_id),window.location.search=`?${s.url.searchParams.toString()}`,window.parent.postMessage({queryString:`?${s.url.searchParams.toString()}`},"*")}const y=w=>d(w),g=()=>l?null:n(4,p=!p);function x(w){_t[w?"unshift":"push"](()=>{u=w,n(3,u)})}return e.$$set=w=>{"isLoading"in w&&n(0,l=w.isLoading)},e.$$.update=()=>{e.$$.dirty&6&&n(6,r=a.find(w=>w.room_id===o)),e.$$.dirty&4&&n(5,i=a.length>0)},[l,o,a,u,p,i,r,f,d,y,g,x]}class Gf extends ke{constructor(t){super(),xe(this,t,qf,Zf,Ce,{isLoading:0})}}function Qf(e){let t,n,r;return{c(){t=Q("svg"),n=Q("path"),r=Q("path"),this.h()},l(i){t=ee(i,"svg",{class:!0,xmlns:!0,"xmlns:xlink":!0,"aria-hidden":!0,focusable:!0,role:!0,width:!0,height:!0,preserveAspectRatio:!0,viewBox:!0});var s=k(t);n=ee(s,"path",{d:!0,fill:!0}),k(n).forEach(_),r=ee(s,"path",{d:!0,fill:!0}),k(r).forEach(_),s.forEach(_),this.h()},h(){c(n,"d","M20.6081 3C21.7684 3 22.8053 3.49196 23.5284 4.38415C23.9756 4.93678 24.4428 5.82749 24.4808 7.16133C24.9674 7.01707 25.4353 6.93643 25.8725 6.93643C26.9833 6.93643 27.9865 7.37587 28.696 8.17411C29.6075 9.19872 30.0124 10.4579 29.8361 11.7177C29.7523 12.3177 29.5581 12.8555 29.2678 13.3534C29.8798 13.8646 30.3306 14.5763 30.5485 15.4322C30.719 16.1032 30.8939 17.5006 29.9808 18.9403C30.0389 19.0342 30.0934 19.1319 30.1442 19.2318C30.6932 20.3074 30.7283 21.5229 30.2439 22.6548C29.5093 24.3704 27.6841 25.7219 24.1397 27.1727C21.9347 28.0753 19.9174 28.6523 19.8994 28.6575C16.9842 29.4379 14.3477 29.8345 12.0653 29.8345C7.87017 29.8345 4.8668 28.508 3.13831 25.8921C0.356375 21.6797 0.754104 17.8269 4.35369 14.1131C6.34591 12.058 7.67023 9.02782 7.94613 8.36275C8.50224 6.39343 9.97271 4.20438 12.4172 4.20438H12.4179C12.6236 4.20438 12.8314 4.2214 13.0364 4.25468C14.107 4.42854 15.0428 5.06476 15.7115 6.02205C16.4331 5.09583 17.134 4.359 17.7682 3.94323C18.7242 3.31737 19.6794 3 20.6081 3ZM20.6081 5.95917C20.2427 5.95917 19.7963 6.1197 19.3039 6.44225C17.7754 7.44319 14.8258 12.6772 13.7458 14.7131C13.3839 15.3952 12.7655 15.6837 12.2086 15.6837C11.1036 15.6837 10.2408 14.5497 12.1076 13.1085C14.9146 10.9402 13.9299 7.39584 12.5898 7.1776C12.5311 7.16799 12.4731 7.16355 12.4172 7.16355C11.1989 7.16355 10.6615 9.33114 10.6615 9.33114C10.6615 9.33114 9.0863 13.4148 6.38031 16.206C3.67434 18.998 3.5346 21.2388 5.50675 24.2246C6.85185 26.2606 9.42666 26.8753 12.0653 26.8753C14.8021 26.8753 17.6077 26.2139 19.1799 25.793C19.2574 25.7723 28.8193 22.984 27.6081 20.6107C27.4046 20.212 27.0693 20.0522 26.6471 20.0522C24.9416 20.0522 21.8393 22.6726 20.5057 22.6726C20.2076 22.6726 19.9976 22.5416 19.9116 22.222C19.3433 20.1173 28.552 19.2325 27.7758 16.1839C27.639 15.6445 27.2677 15.4256 26.746 15.4263C24.4923 15.4263 19.4358 19.5181 18.3759 19.5181C18.2949 19.5181 18.2368 19.4937 18.2053 19.4419C17.6743 18.557 17.9653 17.9394 21.7082 15.6009C25.4511 13.2617 28.0783 11.8545 26.5841 10.1752C26.4121 9.98141 26.1684 9.8956 25.8725 9.8956C23.6001 9.89634 18.2311 14.9403 18.2311 14.9403C18.2311 14.9403 16.7821 16.496 15.9057 16.496C15.7043 16.496 15.533 16.4139 15.4169 16.2112C14.7956 15.1296 21.1879 10.1286 21.5484 8.06535C21.7928 6.66715 21.3771 5.95917 20.6081 5.95917Z"),c(n,"fill","#FF9D00"),c(r,"d","M5.50686 24.2246C3.53472 21.2387 3.67446 18.9979 6.38043 16.206C9.08641 13.4147 10.6615 9.33111 10.6615 9.33111C10.6615 9.33111 11.2499 6.95933 12.59 7.17757C13.93 7.39581 14.9139 10.9401 12.1069 13.1084C9.29997 15.276 12.6659 16.7489 13.7459 14.713C14.8258 12.6772 17.7747 7.44316 19.304 6.44221C20.8326 5.44128 21.9089 6.00204 21.5484 8.06532C21.188 10.1286 14.795 15.1295 15.4171 16.2118C16.0391 17.2934 18.2312 14.9402 18.2312 14.9402C18.2312 14.9402 25.0907 8.49588 26.5842 10.1752C28.0776 11.8545 25.4512 13.2616 21.7082 15.6008C17.9646 17.9393 17.6744 18.557 18.2054 19.4418C18.7372 20.3266 26.9998 13.1351 27.7759 16.1838C28.5513 19.2324 19.3434 20.1173 19.9117 22.2219C20.48 24.3274 26.3979 18.2382 27.6082 20.6107C28.8193 22.9839 19.2574 25.7722 19.18 25.7929C16.0914 26.62 8.24723 28.3726 5.50686 24.2246Z"),c(r,"fill","#FFD21E"),c(t,"class",e[0]),c(t,"xmlns","http://www.w3.org/2000/svg"),c(t,"xmlns:xlink","http://www.w3.org/1999/xlink"),c(t,"aria-hidden","true"),c(t,"focusable","false"),c(t,"role","img"),c(t,"width","1em"),c(t,"height","1em"),c(t,"preserveAspectRatio","xMidYMid meet"),c(t,"viewBox","0 0 32 32")},m(i,s){re(i,t,s),m(t,n),m(t,r)},p(i,[s]){s&1&&c(t,"class",i[0])},i:de,o:de,d(i){i&&_(t)}}}function eh(e,t,n){let{classNames:r=""}=t;return e.$$set=i=>{"classNames"in i&&n(0,r=i.classNames)},[r]}class th extends ke{constructor(t){super(),xe(this,t,eh,Qf,Ce,{classNames:0})}}let nh=(e=21)=>crypto.getRandomValues(new Uint8Array(e)).reduce((t,n)=>(n&=63,n<36?t+=n.toString(36):n<62?t+=(n-26).toString(36).toUpperCase():n>62?t+="-":t+="_",t),"");function rh(e){let t,n;return t=new th({}),{c(){pe(t.$$.fragment)},l(r){me(t.$$.fragment,r)},m(r,i){_e(t,r,i),n=!0},i(r){n||(J(t.$$.fragment,r),n=!0)},o(r){q(t.$$.fragment,r),n=!1},d(r){ge(t,r)}}}function ih(e){let t,n;return t=new In({props:{classList:"animate-spin max-w-[25px] text-white"}}),{c(){pe(t.$$.fragment)},l(r){me(t.$$.fragment,r)},m(r,i){_e(t,r,i),n=!0},i(r){n||(J(t.$$.fragment,r),n=!0)},o(r){q(t.$$.fragment,r),n=!1},d(r){ge(t,r)}}}function sh(e){let t,n,r,i,s,o,a,l,u,f,p;const h=[ih,rh],d=[];function y(g,x){return g[1]?0:1}return n=y(e),r=d[n]=h[n](e),{c(){t=D("button"),r.c(),i=ie(),s=D("p"),o=te("Share to community"),this.h()},l(g){t=U(g,"BUTTON",{class:!0,title:!0});var x=k(t);r.l(x),i=se(x),s=U(x,"P",{class:!0});var w=k(s);o=ne(w,"Share to community"),w.forEach(_),x.forEach(_),this.h()},h(){c(s,"class","text-white font-semibold"),c(t,"class",a=(e[0]||e[1]?"cursor-wait":"cursor-pointer")+" text-xs font-mono flex items-center justify-center bg-black gap-x-1 rounded-xl px-2 py-1 whitespace-nowrap"),t.disabled=l=e[1]||e[0],c(t,"title","Share with community")},m(g,x){re(g,t,x),d[n].m(t,null),m(t,i),m(t,s),m(s,o),u=!0,f||(p=Re(t,"click",e[2]),f=!0)},p(g,[x]){let w=n;n=y(g),n!==w&&(Le(),q(d[w],1,1,()=>{d[w]=null}),Te(),r=d[n],r||(r=d[n]=h[n](g),r.c()),J(r,1),r.m(t,i)),(!u||x&3&&a!==(a=(g[0]||g[1]?"cursor-wait":"cursor-pointer")+" text-xs font-mono flex items-center justify-center bg-black gap-x-1 rounded-xl px-2 py-1 whitespace-nowrap"))&&c(t,"class",a),(!u||x&3&&l!==(l=g[1]||g[0]))&&(t.disabled=l)},i(g){u||(J(r),u=!0)},o(g){q(r),u=!1},d(g){g&&_(t),d[n].d(),f=!1,p()}}}function oh(e,t,n){let r,i;he(e,yt,u=>n(3,r=u)),he(e,Nt,u=>n(4,i=u));let{isLoading:s=!1}=t,o=!1;async function a(){if(o)return;const u=await new Promise(f=>{i.toBlob(f,"image/jpeg",.95)});n(1,o=!0),await l(u),n(1,o=!1)}async function l(u){let f=null;try{f=await $u(u,{prompt:"canvas",position:{x:0,y:0},date:new Date().getTime(),id:nh(),room:r||"default"})}catch(g){console.error(g)}if(!f){console.error("Failed to upload image");return}const p=``,h=`#### Stable Diffusion Multiplayer:
+### [${r}](https://huggingface.co/spaces/huggingface-projects/stable-diffusion-multiplayer?roomid=${r})
+
+
+${p}
+
`,y=new URLSearchParams({title:`Room ${r}`,description:h}).toString();window.open(`https://huggingface.co/spaces/huggingface-projects/stable-diffusion-multiplayer/discussions/new?${y}`,"_blank")}return e.$$set=u=>{"isLoading"in u&&n(0,s=u.isLoading)},[s,o,a]}class ah extends ke{constructor(t){super(),xe(this,t,oh,sh,Ce,{isLoading:0})}}function lh(e){let t,n,r,i,s,o,a,l,u,f,p,h,d,y,g,x,w,C,T,E,S;return C=new ah({props:{isLoading:e[0]}}),{c(){t=D("div"),n=D("details"),r=D("summary"),i=te("More"),s=ie(),o=D("p"),a=te("Instructions: move the "),l=D("span"),u=te("blue square"),f=te(`,
+ click "\u{1F58D} Paint".`),p=ie(),h=D("div"),d=D("button"),y=Q("svg"),g=Q("path"),x=te(`
+ About`),w=ie(),pe(C.$$.fragment),this.h()},l(P){t=U(P,"DIV",{class:!0});var O=k(t);n=U(O,"DETAILS",{});var z=k(n);r=U(z,"SUMMARY",{class:!0});var X=k(r);i=ne(X,"More"),X.forEach(_),s=se(z),o=U(z,"P",{class:!0});var K=k(o);a=ne(K,"Instructions: move the "),l=U(K,"SPAN",{class:!0});var M=k(l);u=ne(M,"blue square"),M.forEach(_),f=ne(K,`,
+ click "\u{1F58D} Paint".`),K.forEach(_),p=se(z),h=U(z,"DIV",{class:!0});var F=k(h);d=U(F,"BUTTON",{class:!0});var B=k(d);y=ee(B,"svg",{width:!0,height:!0,viewBox:!0,class:!0});var v=k(y);g=ee(v,"path",{fill:!0,"fill-rule":!0,d:!0,"clip-rule":!0}),k(g).forEach(_),v.forEach(_),x=ne(B,`
+ About`),B.forEach(_),w=se(F),me(C.$$.fragment,F),F.forEach(_),z.forEach(_),O.forEach(_),this.h()},h(){c(r,"class","md:hidden"),c(l,"class","text-blue-700 bg-blue-300/60 px-0.5"),c(o,"class","inline"),c(g,"fill","currentColor"),c(g,"fill-rule","evenodd"),c(g,"d","M12 2C6.477 2 2 6.477 2 12s4.477 10 10 10s10-4.477 10-10S17.523 2 12 2zm0 7a1 1 0 0 0-1 1a1 1 0 1 1-2 0a3 3 0 1 1 4.44 2.633a1.404 1.404 0 0 0-.383.288a.303.303 0 0 0-.057.085v.494a1 1 0 1 1-2 0V13c0-.58.253-1.047.539-1.38c.281-.33.63-.572.94-.742A1 1 0 0 0 12 9zm.999 4.011v-.004v.005zM12 15a1 1 0 1 0 0 2h.01a1 1 0 1 0 0-2H12z"),c(g,"clip-rule","evenodd"),c(y,"width",".9em"),c(y,"height",".9em"),c(y,"viewBox","0 0 24 24"),c(y,"class","mr-1"),c(d,"class","items-center inline-flex"),c(h,"class","flex justify-between py-2 gap-3"),n.open=e[1],c(t,"class","md:w-[210px] text-sm md:flex flex-col order-last md:order-none")},m(P,O){re(P,t,O),m(t,n),m(n,r),m(r,i),m(n,s),m(n,o),m(o,a),m(o,l),m(l,u),m(o,f),m(n,p),m(n,h),m(h,d),m(d,y),m(y,g),m(d,x),m(h,w),_e(C,h,null),T=!0,E||(S=Re(d,"click",e[2]),E=!0)},p(P,[O]){const z={};O&1&&(z.isLoading=P[0]),C.$set(z),(!T||O&2)&&(n.open=P[1])},i(P){T||(J(C.$$.fragment,P),T=!0)},o(P){q(C.$$.fragment,P),T=!1},d(P){P&&_(t),ge(C),E=!1,S()}}}function uh(e,t,n){let{isLoading:r=!1}=t,i=!0;Ot(()=>(s(),window.addEventListener("resize",s),()=>{window.removeEventListener("resize",s)}));function s(){n(1,i=window.innerWidth>768)}function o(a){cr.call(this,e,a)}return e.$$set=a=>{"isLoading"in a&&n(0,r=a.isLoading)},[r,i,o]}class ch extends ke{constructor(t){super(),xe(this,t,uh,lh,Ce,{isLoading:0})}}function fh(e){let t,n,r,i,s,o,a,l,u,f,p,h,d,y,g,x,w;return n=new ch({props:{isLoading:e[0]}}),n.$on("click",e[4]),y=new Gf({props:{isLoading:e[0]}}),{c(){t=D("div"),pe(n.$$.fragment),r=ie(),i=D("button"),s=D("span"),o=te("\u{1F58D}"),a=te(`Paint
+ `),l=D("span"),u=Q("svg"),f=Q("path"),p=te(`
+ Enter`),d=ie(),pe(y.$$.fragment),this.h()},l(C){t=U(C,"DIV",{class:!0});var T=k(t);me(n.$$.fragment,T),r=se(T),i=U(T,"BUTTON",{title:!0,class:!0});var E=k(i);s=U(E,"SPAN",{class:!0});var S=k(s);o=ne(S,"\u{1F58D}"),S.forEach(_),a=ne(E,`Paint
+ `),l=U(E,"SPAN",{class:!0});var P=k(l);u=ee(P,"svg",{class:!0,width:!0,height:!0,viewBox:!0,fill:!0,xmlns:!0});var O=k(u);f=ee(O,"path",{"fill-rule":!0,"clip-rule":!0,d:!0,fill:!0}),k(f).forEach(_),O.forEach(_),p=ne(P,`
+ Enter`),P.forEach(_),E.forEach(_),d=se(T),me(y.$$.fragment,T),T.forEach(_),this.h()},h(){c(s,"class","mr-3"),c(f,"fill-rule","evenodd"),c(f,"clip-rule","evenodd"),c(f,"d","M8.5 8.5V0H9.5V9.5H1.70711L4.03553 11.8284C4.2308 12.0237 4.2308 12.3403 4.03553 12.5355C3.84027 12.7308 3.52369 12.7308 3.32843 12.5355L0.146447 9.35355C-0.0488155 9.15829 -0.0488155 8.84171 0.146447 8.64645L3.32843 5.46447C3.52369 5.2692 3.84027 5.2692 4.03553 5.46447C4.2308 5.65973 4.2308 5.97631 4.03553 6.17157L1.70711 8.5H8.5Z"),c(f,"fill","currentColor"),c(u,"class","text-sm mr-1.5"),c(u,"width","1em"),c(u,"height","1em"),c(u,"viewBox","0 0 10 13"),c(u,"fill","currentColor"),c(u,"xmlns","http://www.w3.org/2000/svg"),c(l,"class","bg-blue-800 text-gray-300 rounded-lg px-2 py-0.5 text-base ml-4 hidden sm:flex items-center translate-y-[2px]"),c(i,"title","Click to prompt, and paint. The generated image will show up in the frame."),i.disabled=e[0],c(i,"class",h=(e[0]?"cursor-wait":"cursor-pointer")+" order-first md:order-none text-xl md:text-3xl bg-blue-600 text-white px-4 py-1 md:px-6 md:py-2 rounded-2xl ring ring-blue-500 font-semibold shadow-2xl shadow-blue-500 self-center flex items-center hover:saturate-150"),c(t,"class","flex flex-col md:flex-row items-center justify-between px-4 md:px-12 gap-3 md:gap-0")},m(C,T){re(C,t,T),_e(n,t,null),m(t,r),m(t,i),m(i,s),m(s,o),m(i,a),m(i,l),m(l,u),m(u,f),m(l,p),m(t,d),_e(y,t,null),g=!0,x||(w=[Re(window,"keypress",e[3]),Re(i,"click",e[5])],x=!0)},p(C,[T]){const E={};T&1&&(E.isLoading=C[0]),n.$set(E),(!g||T&1)&&(i.disabled=C[0]),(!g||T&1&&h!==(h=(C[0]?"cursor-wait":"cursor-pointer")+" order-first md:order-none text-xl md:text-3xl bg-blue-600 text-white px-4 py-1 md:px-6 md:py-2 rounded-2xl ring ring-blue-500 font-semibold shadow-2xl shadow-blue-500 self-center flex items-center hover:saturate-150"))&&c(i,"class",h);const S={};T&1&&(S.isLoading=C[0]),y.$set(S)},i(C){g||(J(n.$$.fragment,C),J(y.$$.fragment,C),g=!0)},o(C){q(n.$$.fragment,C),q(y.$$.fragment,C),g=!1},d(C){C&&_(t),ge(n),ge(y),x=!1,ur(w)}}}function hh(e,t,n){let r;he(e,wn,u=>n(1,r=u));const i=lr();let{isLoading:s=!1}=t;const o=u=>{u.key==="Enter"&&i("showModal",{showModal:!0})},a=()=>{be(wn,r=!r,r)},l=()=>i("showModal",{showModal:!0});return e.$$set=u=>{"isLoading"in u&&n(0,s=u.isLoading)},[s,r,i,o,a,l]}class dh extends ke{constructor(t){super(),xe(this,t,hh,fh,Ce,{isLoading:0})}}function ph(e){let t,n,r,i,s,o,a,l,u,f;return{c(){t=D("form"),n=D("div"),r=D("input"),i=ie(),s=D("button"),o=D("span"),a=te("\u{1F58D}"),l=te(" Paint"),this.h()},l(p){t=U(p,"FORM",{class:!0});var h=k(t);n=U(h,"DIV",{class:!0});var d=k(n);r=U(d,"INPUT",{class:!0,placeholder:!0,title:!0,type:!0,name:!0}),i=se(d),s=U(d,"BUTTON",{class:!0,type:!0});var y=k(s);o=U(y,"SPAN",{class:!0});var g=k(o);a=ne(g,"\u{1F58D}"),g.forEach(_),l=ne(y," Paint"),y.forEach(_),d.forEach(_),h.forEach(_),this.h()},h(){r.value=e[0],c(r,"class","flex-1 outline-none ring-0 border-none text-xl 2xl:text-2xl py-3 px-3"),c(r,"placeholder","Describe your prompt"),c(r,"title","Input prompt to generate image and obtain palette"),c(r,"type","text"),c(r,"name","prompt"),c(o,"class","mr-2"),c(s,"class","font-semibold bg-blue-700 text-white border-l-2 px-5 text-xl 2xl:text-2xl spacing tracking-wide hover:saturate-150"),c(s,"type","submit"),c(n,"class","flex bg-white overflow-hidden rounded-2xl w-full max-w-lg 2xl:max-w-xl"),c(t,"class","fixed w-screen top-0 left-0 bottom-0 right-0 h-screen z-50 flex items-center justify-center bg-black bg-opacity-80")},m(p,h){re(p,t,h),m(t,n),m(n,r),e[7](r),m(n,i),m(n,s),m(s,o),m(o,a),m(s,l),e[8](n),u||(f=[Re(r,"click",Rs(e[6])),Re(r,"input",e[4]),Re(t,"submit",e[3])],u=!0)},p(p,[h]){h&1&&r.value!==p[0]&&(r.value=p[0])},i:de,o:de,d(p){p&&_(t),e[7](null),e[8](null),u=!1,ur(f)}}}function mh(e,t,n){const r=lr();let{initPrompt:i=""}=t,s,o,a;const l=Pn(),u=C=>{C.key==="Escape"&&r("showModal",{showModal:!1})};Ot(()=>(o.focus(),n(0,s=i),window.addEventListener("keyup",u),window.addEventListener("pointerdown",y,!0),()=>{window.removeEventListener("keyup",u),window.removeEventListener("pointerdown",y,!0)}));let f;function p(C){clearTimeout(f),f=setTimeout(()=>{n(0,s=C),l.update({currentPrompt:s,status:fe.prompting})},100)}function h(C){C.stopPropagation(),C.preventDefault(),C.stopImmediatePropagation(),s.trim()!==""&&r("paint")}function d(C){const T=C.target;p(T.value)}function y(C){a.contains(C.target)||(l.update({status:fe.ready}),r("showModal",{showModal:!1}))}function g(C){cr.call(this,e,C)}function x(C){_t[C?"unshift":"push"](()=>{o=C,n(1,o)})}function w(C){_t[C?"unshift":"push"](()=>{a=C,n(2,a)})}return e.$$set=C=>{"initPrompt"in C&&n(5,i=C.initPrompt)},[s,o,a,h,d,i,g,x,w]}class _h extends ke{constructor(t){super(),xe(this,t,mh,ph,Ce,{initPrompt:5})}}function hi(e,t,n){const r=e.slice();return r[18]=t[n].connectionId,r[19]=t[n].presence,r}function di(e){var r;let t,n;return t=new _h({props:{initPrompt:(r=e[0])==null?void 0:r.currentPrompt}}),t.$on("paint",e[10]),t.$on("showModal",e[9]),{c(){pe(t.$$.fragment)},l(i){me(t.$$.fragment,i)},m(i,s){_e(t,i,s),n=!0},p(i,s){var a;const o={};s&1&&(o.initPrompt=(a=i[0])==null?void 0:a.currentPrompt),t.$set(o)},i(i){n||(J(t.$$.fragment,i),n=!0)},o(i){q(t.$$.fragment,i),n=!1},d(i){ge(t,i)}}}function pi(e){let t=[],n=new Map,r,i,s=[...e[4]];const o=a=>a[18];for(let a=0;a{o=null}),Te()),(T=t[19])!=null&&T.cursor?a?(a.p(t,y),y&16&&J(a,1)):(a=_i(t),a.c(),J(a,1),a.m(i.parentNode,i)):a&&(Le(),q(a,1,1,()=>{a=null}),Te())},i(d){s||(J(o),J(a),s=!0)},o(d){q(o),q(a),s=!1},d(d){d&&_(n),o&&o.d(d),d&&_(r),a&&a.d(d),d&&_(i)}}}function gh(e){let t,n,r,i,s,o,a,l,u,f,p,h,d,y,g=e[1]&&di(e);o=new Uf({});let x=e[4]&&pi(e);return f=new Mf({props:{transform:e[5]}}),f.$on("showModal",e[9]),d=new dh({props:{isLoading:e[2]}}),d.$on("showModal",e[9]),{c(){t=D("div"),n=te(e[3]),r=ie(),g&&g.c(),i=ie(),s=D("div"),pe(o.$$.fragment),a=ie(),l=D("main"),x&&x.c(),u=ie(),pe(f.$$.fragment),p=ie(),h=D("div"),pe(d.$$.fragment),this.h()},l(w){t=U(w,"DIV",{class:!0});var C=k(t);n=ne(C,e[3]),C.forEach(_),r=se(w),g&&g.l(w),i=se(w),s=U(w,"DIV",{class:!0});var T=k(s);me(o.$$.fragment,T),a=se(T),l=U(T,"MAIN",{class:!0});var E=k(l);x&&x.l(E),u=se(E),me(f.$$.fragment,E),E.forEach(_),T.forEach(_),p=se(w),h=U(w,"DIV",{class:!0});var S=k(h);me(d.$$.fragment,S),S.forEach(_),this.h()},h(){c(t,"class","text touch-none pointer-events-none"),c(l,"class","z-10 relative"),c(s,"class","fixed top-0 left-0 z-0 w-screen h-screen min-h-[600px]"),c(h,"class","fixed bottom-0 md:bottom-16 left-0 right-0 z-10 my-2")},m(w,C){re(w,t,C),m(t,n),re(w,r,C),g&&g.m(w,C),re(w,i,C),re(w,s,C),_e(o,s,null),m(s,a),m(s,l),x&&x.m(l,null),m(l,u),_e(f,l,null),re(w,p,C),re(w,h,C),_e(d,h,null),y=!0},p(w,[C]){(!y||C&8)&&nt(n,w[3]),w[1]?g?(g.p(w,C),C&2&&J(g,1)):(g=di(w),g.c(),J(g,1),g.m(i.parentNode,i)):g&&(Le(),q(g,1,1,()=>{g=null}),Te()),w[4]?x?(x.p(w,C),C&16&&J(x,1)):(x=pi(w),x.c(),J(x,1),x.m(l,u)):x&&(Le(),q(x,1,1,()=>{x=null}),Te());const T={};C&32&&(T.transform=w[5]),f.$set(T);const E={};C&4&&(E.isLoading=w[2]),d.$set(E)},i(w){y||(J(g),J(o.$$.fragment,w),J(x),J(f.$$.fragment,w),J(d.$$.fragment,w),y=!0)},o(w){q(g),q(o.$$.fragment,w),q(x),q(f.$$.fragment,w),q(d.$$.fragment,w),y=!1},d(w){w&&_(t),w&&_(r),g&&g.d(w),w&&_(i),w&&_(s),ge(o),x&&x.d(),ge(f),w&&_(p),w&&_(h),ge(d)}}}function vh(e){return`${e.x}_${e.y}`}function yh(e,t,n){let r,i,s,o,a,l,u,f,p;he(e,Ae,S=>n(3,i=S)),he(e,rr,S=>n(13,o=S)),he(e,yt,S=>n(14,a=S)),he(e,Dt,S=>n(11,f=S)),he(e,nr,S=>n(5,p=S));const h=Pn();he(e,h,S=>n(0,l=S));const d=Ru();he(e,d,S=>n(4,u=S));let y=!1;const g=ls("promptImgStorage");he(e,g,S=>n(12,s=S));function x(S){r||(n(1,y=S.detail.showModal),y?h.update({status:fe.prompting}):h.update({status:fe.ready}))}function w(){n(1,y=!1),E()}function C(S){if(!u)return!0;let P=!0;for(const{presence:O}of u)if(S.xO.frame.x&&S.yO.frame.y){if(O.status===fe.ready||O.status===fe.dragging){P=!0;continue}P=!1;break}return P}function T(S=5e3){setTimeout(()=>{be(Ae,i="",i)},S)}async function E(){if(r)return;const S=l.currentPrompt,P=l.frame;if(be(Ae,i="Pending",i),!C(P)){be(Ae,i="Someone is already painting here",i),h.update({status:fe.ready}),T();return}const O=vh(P),z=a||"default";console.log("Generating...",S,P),h.update({status:fe.loading});const X=crypto.randomUUID(),K=o.toDataURL("image/webp"),M={fn_index:0,session_hash:X},F={data:[K,S,.75,7.5,40,"patchmatch",z,O]},B=new WebSocket(Lu);B.onclose=v=>{v.wasClean||(be(Ae,i="Error",i),h.update({status:fe.ready}))},B.onmessage=async function(v){try{const $=JSON.parse(v.data);switch(be(Ae,i="",i),$.msg){case"send_hash":B.send(JSON.stringify(M));break;case"send_data":be(Ae,i="Sending Data",i),B.send(JSON.stringify({...M,...F}));break;case"queue_full":be(Ae,i="Queue full",i),B.close(),h.update({status:fe.ready});return;case"estimation":const{rank:I,queue_size:N}=$;be(Ae,i=`On queue ${I}/${N}`,i);break;case"process_generating":be(Ae,i=$.success?"Generating":"Error",i);break;case"process_completed":try{const A=$.output.data[0];if(A.is_nsfw)throw new Error("NFSW");const L={imgURL:A.image.filename};s.set(O,new gr(L)),console.log(A.image.url),be(Ae,i=$.success?"Complete":"Error",i),T(),h.update({status:fe.ready,currentPrompt:""})}catch(A){const V=A;be(Ae,i=V==null?void 0:V.message,i),h.update({status:fe.ready}),T(1e4)}B.close();return;case"process_starts":be(Ae,i="Processing",i);break}}catch($){console.error($),be(Ae,i="Error",i)}}}return e.$$.update=()=>{e.$$.dirty&2049&&n(2,r=(l==null?void 0:l.status)===fe.loading||f||!1)},[l,y,r,i,u,p,h,d,g,x,w,f]}class wh extends ke{constructor(t){super(),xe(this,t,yh,gh,Ce,{})}}function bh(e){let t,n,r,i,s,o,a,l,u,f,p,h,d,y,g,x,w,C,T,E,S,P,O,z,X,K,M;return{c(){t=Q("svg"),n=Q("rect"),r=Q("path"),i=Q("path"),s=Q("path"),o=Q("path"),a=Q("path"),l=Q("path"),u=Q("path"),f=Q("path"),p=Q("path"),h=Q("path"),d=Q("path"),y=Q("path"),g=Q("path"),x=Q("path"),w=Q("path"),C=Q("path"),T=Q("path"),E=Q("path"),S=Q("path"),P=Q("path"),O=Q("path"),z=Q("defs"),X=Q("radialGradient"),K=Q("stop"),M=Q("stop"),this.h()},l(F){t=ee(F,"svg",{class:!0,width:!0,height:!0,viewBox:!0,fill:!0,xmlns:!0});var B=k(t);n=ee(B,"rect",{opacity:!0,x:!0,y:!0,width:!0,height:!0,rx:!0,fill:!0,stroke:!0,"stroke-width":!0}),k(n).forEach(_),r=ee(B,"path",{d:!0,fill:!0}),k(r).forEach(_),i=ee(B,"path",{d:!0,fill:!0}),k(i).forEach(_),s=ee(B,"path",{d:!0,fill:!0}),k(s).forEach(_),o=ee(B,"path",{d:!0,fill:!0}),k(o).forEach(_),a=ee(B,"path",{d:!0,fill:!0}),k(a).forEach(_),l=ee(B,"path",{d:!0,fill:!0}),k(l).forEach(_),u=ee(B,"path",{d:!0,fill:!0}),k(u).forEach(_),f=ee(B,"path",{d:!0,fill:!0}),k(f).forEach(_),p=ee(B,"path",{d:!0,fill:!0}),k(p).forEach(_),h=ee(B,"path",{d:!0,fill:!0}),k(h).forEach(_),d=ee(B,"path",{d:!0,fill:!0}),k(d).forEach(_),y=ee(B,"path",{d:!0,fill:!0}),k(y).forEach(_),g=ee(B,"path",{d:!0,fill:!0}),k(g).forEach(_),x=ee(B,"path",{d:!0,fill:!0}),k(x).forEach(_),w=ee(B,"path",{d:!0,fill:!0}),k(w).forEach(_),C=ee(B,"path",{d:!0,fill:!0}),k(C).forEach(_),T=ee(B,"path",{d:!0,fill:!0}),k(T).forEach(_),E=ee(B,"path",{d:!0,fill:!0}),k(E).forEach(_),S=ee(B,"path",{d:!0,fill:!0}),k(S).forEach(_),P=ee(B,"path",{d:!0,fill:!0}),k(P).forEach(_),O=ee(B,"path",{"fill-rule":!0,"clip-rule":!0,d:!0,fill:!0}),k(O).forEach(_),z=ee(B,"defs",{});var v=k(z);X=ee(v,"radialGradient",{id:!0,cx:!0,cy:!0,r:!0,gradientUnits:!0,gradientTransform:!0});var $=k(X);K=ee($,"stop",{"stop-color":!0}),k(K).forEach(_),M=ee($,"stop",{offset:!0,"stop-color":!0}),k(M).forEach(_),$.forEach(_),v.forEach(_),B.forEach(_),this.h()},h(){c(n,"opacity","0.5"),c(n,"x","0.25"),c(n,"y","0.25"),c(n,"width","122.5"),c(n,"height","43.5"),c(n,"rx","6.75"),c(n,"fill","#1F2937"),c(n,"stroke","#3A4C64"),c(n,"stroke-width","0.5"),c(r,"d","M44.9102 16.8569H45.8514V14.778H47.1691C48.364 14.778 49.1497 14.0577 49.1497 12.9528C49.1497 11.8397 48.364 11.1277 47.1691 11.1277H44.9102V16.8569ZM47.0954 11.9461C47.7666 11.9461 48.1921 12.3308 48.1921 12.9528C48.1921 13.5667 47.7584 13.9595 47.0872 13.9595H45.8514V11.9461H47.0954Z"),c(r,"fill","#A3BAD9"),c(i,"d","M51.5649 16.9059C52.8417 16.9059 53.701 16.0465 53.701 14.7615C53.701 13.4847 52.8417 12.6172 51.5649 12.6172C50.2881 12.6172 49.4287 13.4847 49.4287 14.7615C49.4287 16.0465 50.2881 16.9059 51.5649 16.9059ZM51.5649 16.1529C50.8201 16.1529 50.3372 15.5718 50.3372 14.7615C50.3372 13.9513 50.8201 13.3702 51.5649 13.3702C52.3097 13.3702 52.8007 13.9513 52.8007 14.7615C52.8007 15.5718 52.3097 16.1529 51.5649 16.1529Z"),c(i,"fill","#A3BAD9"),c(s,"d","M55.233 16.857H56.1906L57.1073 14.0088L57.9912 16.857H58.9406L60.332 12.6665H59.4317L58.4414 15.8748L57.5247 12.6665H56.7144L55.7568 15.8748L54.7992 12.6665H53.8662L55.233 16.857Z"),c(s,"fill","#A3BAD9"),c(o,"d","M62.6424 16.9059C63.6818 16.9059 64.3857 16.2757 64.533 15.449H63.6491C63.5263 15.9156 63.1335 16.1856 62.5933 16.1856C61.8976 16.1856 61.4475 15.7191 61.4229 15.0071V14.9498H64.5821C64.5985 14.8352 64.6067 14.7206 64.6067 14.6142C64.5821 13.3865 63.7719 12.6172 62.5605 12.6172C61.3247 12.6172 60.498 13.4766 60.498 14.7697C60.498 16.0547 61.3247 16.9059 62.6424 16.9059ZM61.4556 14.3032C61.5211 13.7057 62.004 13.3292 62.5687 13.3292C63.1826 13.3292 63.6164 13.6812 63.69 14.3032H61.4556Z"),c(o,"fill","#A3BAD9"),c(a,"d","M67.4411 12.6665C66.7536 12.6665 66.418 12.9448 66.2052 13.2967L66.107 12.6665H65.3213V16.857H66.2052V14.7536C66.2052 14.107 66.4589 13.4931 67.2447 13.4931H67.6375V12.6665H67.4411Z"),c(a,"fill","#A3BAD9"),c(l,"d","M69.9725 16.9059C71.0119 16.9059 71.7158 16.2757 71.8631 15.449H70.9792C70.8564 15.9156 70.4635 16.1856 69.9234 16.1856C69.2277 16.1856 68.7775 15.7191 68.753 15.0071V14.9498H71.9122C71.9286 14.8352 71.9368 14.7206 71.9368 14.6142C71.9122 13.3865 71.1019 12.6172 69.8906 12.6172C68.6548 12.6172 67.8281 13.4766 67.8281 14.7697C67.8281 16.0547 68.6548 16.9059 69.9725 16.9059ZM68.7857 14.3032C68.8512 13.7057 69.3341 13.3292 69.8988 13.3292C70.5127 13.3292 70.9464 13.6812 71.0201 14.3032H68.7857Z"),c(l,"fill","#A3BAD9"),c(u,"d","M75.8352 13.2475C75.5651 12.8792 75.1149 12.6173 74.4765 12.6173C73.3391 12.6173 72.4961 13.4685 72.4961 14.7616C72.4961 16.1039 73.3391 16.906 74.4765 16.906C75.1395 16.906 75.5733 16.5949 75.8433 16.2266L75.9497 16.8569H76.7191V11.1277H75.8352V13.2475ZM74.6238 16.1612C73.8875 16.1612 73.4046 15.5883 73.4046 14.7616C73.4046 13.9432 73.8875 13.3702 74.6238 13.3702C75.3605 13.3702 75.8433 13.9432 75.8433 14.778C75.8433 15.5883 75.3605 16.1612 74.6238 16.1612Z"),c(u,"fill","#A3BAD9"),c(f,"d","M81.9193 12.6173C81.2727 12.6173 80.839 12.9119 80.5607 13.2884V11.1277H79.6768V16.8569H80.4461L80.5525 16.2512C80.8144 16.6277 81.2646 16.906 81.9193 16.906C83.0652 16.906 83.9 16.0466 83.9 14.7616C83.9 13.4112 83.0652 12.6173 81.9193 12.6173ZM81.772 16.1612C81.0354 16.1612 80.5525 15.5801 80.5525 14.7534C80.5525 13.9432 81.0354 13.3702 81.772 13.3702C82.5086 13.3702 82.9997 13.9432 82.9997 14.7616C82.9997 15.5883 82.5086 16.1612 81.772 16.1612Z"),c(f,"fill","#A3BAD9"),c(p,"d","M85.6277 16.8815L85.4641 17.2908C85.3331 17.6345 85.2513 17.7164 84.9075 17.7164H84.2855V18.4939H85.2349C85.8487 18.4939 86.0288 18.1911 86.2907 17.5117L88.1895 12.6665H87.2483L86.1106 15.8503L84.9402 12.6665H83.999L85.6277 16.8815Z"),c(p,"fill","#A3BAD9"),c(h,"d","M45.1162 32.4821H47.2144V22.0654H45.1162V32.4821Z"),c(h,"fill","#A3BAD9"),c(d,"d","M49.7329 24.0148C50.4175 24.0148 50.9532 23.5088 50.9532 22.8392C50.9532 22.1546 50.4175 21.6487 49.7329 21.6487C49.0484 21.6487 48.5127 22.1546 48.5127 22.8392C48.5127 23.5088 49.0484 24.0148 49.7329 24.0148ZM48.6764 32.482H50.7895V24.8332H48.6764V32.482Z"),c(d,"fill","#A3BAD9"),c(y,"d","M54.2461 32.4823H56.8503L59.6033 24.8335H57.4009L55.5854 30.3394L53.7402 24.8335H51.4932L54.2461 32.4823Z"),c(y,"fill","#A3BAD9"),c(g,"d","M63.718 32.5713C65.7567 32.5713 67.0811 31.3808 67.3192 29.8927H65.2507C65.0722 30.607 64.4769 30.979 63.6287 30.979C62.5722 30.979 61.8728 30.3243 61.8281 29.2379V29.1338H67.3787C67.4234 28.8957 67.4382 28.6427 67.4382 28.4195C67.4085 26.1725 65.8609 24.7439 63.5692 24.7439C61.2031 24.7439 59.6406 26.2915 59.6406 28.6725C59.6406 31.0385 61.1734 32.5713 63.718 32.5713ZM61.8728 27.7647C61.9918 26.857 62.6763 26.3064 63.5841 26.3064C64.5365 26.3064 65.1763 26.8272 65.3251 27.7647H61.8728Z"),c(g,"fill","#A3BAD9"),c(x,"d","M72.9898 24.744C71.9332 24.744 71.1891 25.1904 70.6832 25.8005V22.0654H68.585V32.4821H70.4153L70.6237 31.4404C71.1148 32.0952 71.8737 32.5714 72.9749 32.5714C75.0434 32.5714 76.5315 31.0089 76.5315 28.6428C76.5315 26.2172 75.0434 24.744 72.9898 24.744ZM72.5136 30.8601C71.3678 30.8601 70.6534 29.9523 70.6534 28.6428C70.6534 27.3482 71.3678 26.4553 72.5136 26.4553C73.6594 26.4553 74.4035 27.3482 74.4035 28.6577C74.4035 29.9672 73.6594 30.8601 72.5136 30.8601Z"),c(x,"fill","#A3BAD9"),c(w,"d","M77.6973 32.4821H79.7955V22.0654H77.6973V32.4821Z"),c(w,"fill","#A3BAD9"),c(C,"d","M84.9927 32.5713C87.4332 32.5713 89.0254 31.0237 89.0254 28.6576C89.0254 26.3064 87.4332 24.7439 84.9927 24.7439C82.5522 24.7439 80.96 26.3064 80.96 28.6576C80.96 31.0088 82.5522 32.5713 84.9927 32.5713ZM84.9927 30.86C83.8171 30.86 83.1028 29.9522 83.1028 28.6576C83.1028 27.3629 83.8171 26.4552 84.9927 26.4552C86.1683 26.4552 86.8975 27.3629 86.8975 28.6576C86.8975 29.9522 86.1683 30.86 84.9927 30.86Z"),c(C,"fill","#A3BAD9"),c(T,"d","M93.7816 32.5713C95.865 32.5713 97.2489 31.4254 97.5465 29.5951H95.3441C95.1953 30.3689 94.6447 30.86 93.8263 30.86C92.7251 30.86 92.0257 29.9671 92.0257 28.6576C92.0257 27.3629 92.7251 26.4552 93.8263 26.4552C94.6447 26.4552 95.1655 26.9314 95.3441 27.6903H97.5316C97.234 25.8748 95.9394 24.7439 93.856 24.7439C91.4304 24.7439 89.8828 26.2915 89.8828 28.6576C89.8828 31.0683 91.356 32.5713 93.7816 32.5713Z"),c(T,"fill","#A3BAD9"),c(E,"d","M98.6514 32.4821H100.75V30.622L101.895 29.3869L103.83 32.4821H106.256L103.354 27.8392L106.107 24.8333H103.741L100.75 28.0773V22.0654H98.6514V32.4821Z"),c(E,"fill","#A3BAD9"),c(S,"d","M106.188 29.9375C106.277 31.5744 107.72 32.5714 109.848 32.5714C111.902 32.5714 113.33 31.6042 113.33 30.0863C113.33 28.3601 111.872 27.9583 110.116 27.7798C109.015 27.6458 108.36 27.5863 108.36 27.006C108.36 26.5149 108.896 26.2173 109.714 26.2173C110.562 26.2173 111.143 26.5893 111.202 27.1994H113.211C113.107 25.6369 111.693 24.7292 109.64 24.7292C107.676 24.7143 106.351 25.7113 106.351 27.2292C106.351 28.8065 107.735 29.2083 109.521 29.4167C110.756 29.5804 111.277 29.625 111.277 30.25C111.277 30.7857 110.741 31.0685 109.863 31.0685C108.836 31.0685 108.256 30.6071 108.182 29.9375H106.188Z"),c(S,"fill","#A3BAD9"),c(P,"d","M32.4824 8.67236H11.649C10.0053 8.67236 8.67285 10.0048 8.67285 11.6486V32.4819C8.67285 34.1256 10.0053 35.4581 11.649 35.4581H32.4824C34.1261 35.4581 35.4586 34.1256 35.4586 32.4819V11.6486C35.4586 10.0048 34.1261 8.67236 32.4824 8.67236Z"),c(P,"fill","url(#paint0_radial_253_107)"),c(O,"fill-rule","evenodd"),c(O,"clip-rule","evenodd"),c(O,"d","M24.8953 17.78H15.0332L17.8712 20.7599V24.875L24.8953 17.78ZM19.2193 26.294H29.0814L26.2434 23.3141V19.199L19.2193 26.294Z"),c(O,"fill","white"),c(K,"stop-color","#FF0099"),c(M,"offset","1"),c(M,"stop-color","#FF7A00"),c(X,"id","paint0_radial_253_107"),c(X,"cx","0"),c(X,"cy","0"),c(X,"r","1"),c(X,"gradientUnits","userSpaceOnUse"),c(X,"gradientTransform","translate(4.7524 1.97593) rotate(45.3703) scale(40.7748 35.4976)"),c(t,"class",e[0]),c(t,"width","123"),c(t,"height","44"),c(t,"viewBox","0 0 123 44"),c(t,"fill","none"),c(t,"xmlns","http://www.w3.org/2000/svg")},m(F,B){re(F,t,B),m(t,n),m(t,r),m(t,i),m(t,s),m(t,o),m(t,a),m(t,l),m(t,u),m(t,f),m(t,p),m(t,h),m(t,d),m(t,y),m(t,g),m(t,x),m(t,w),m(t,C),m(t,T),m(t,E),m(t,S),m(t,P),m(t,O),m(t,z),m(z,X),m(X,K),m(X,M)},p(F,[B]){B&1&&c(t,"class",F[0])},i:de,o:de,d(F){F&&_(t)}}}function Eh(e,t,n){let{classList:r=""}=t;return e.$$set=i=>{"classList"in i&&n(0,r=i.classList)},[r]}class kh extends ke{constructor(t){super(),xe(this,t,Eh,bh,Ce,{classList:0})}}function xh(e){let t,n,r,i,s,o,a,l,u,f,p,h,d,y,g,x,w,C,T,E,S,P,O,z,X,K,M,F,B,v,$,I,N,A,V;return $=new kh({props:{classList:"ml-2"}}),{c(){t=D("div"),n=D("div"),r=D("h2"),i=te("Stable Difussion Multiplayer"),s=ie(),o=D("ul"),a=D("li"),l=te("Powered by "),u=D("a"),f=te("Hugging Face GPU Spaces"),p=ie(),h=D("li"),d=D("a"),y=te("Diffusers"),g=te(`
+ and
+ `),x=D("a"),w=te("Runwayml Inpainting Stable Diffusion"),C=ie(),T=D("li"),E=te("Thanks to "),S=D("a"),P=te("Lnyan"),O=te(`
+ for the original outpainting technique implemented on
+ `),z=D("a"),X=te("Stable Diffusion Infinity"),K=ie(),M=D("li"),F=D("p"),B=te(`Multiplayer API by
+ `),v=D("a"),pe($.$$.fragment),this.h()},l(L){t=U(L,"DIV",{class:!0});var W=k(t);n=U(W,"DIV",{class:!0});var oe=k(n);r=U(oe,"H2",{class:!0});var ae=k(r);i=ne(ae,"Stable Difussion Multiplayer"),ae.forEach(_),s=se(oe),o=U(oe,"UL",{});var G=k(o);a=U(G,"LI",{class:!0});var ue=k(a);l=ne(ue,"Powered by "),u=U(ue,"A",{href:!0,class:!0});var Ee=k(u);f=ne(Ee,"Hugging Face GPU Spaces"),Ee.forEach(_),ue.forEach(_),p=se(G),h=U(G,"LI",{class:!0});var Ie=k(h);d=U(Ie,"A",{href:!0,class:!0});var Oe=k(d);y=ne(Oe,"Diffusers"),Oe.forEach(_),g=ne(Ie,`
+ and
+ `),x=U(Ie,"A",{href:!0,target:!0,class:!0,rel:!0});var lt=k(x);w=ne(lt,"Runwayml Inpainting Stable Diffusion"),lt.forEach(_),Ie.forEach(_),C=se(G),T=U(G,"LI",{class:!0});var ut=k(T);E=ne(ut,"Thanks to "),S=U(ut,"A",{href:!0,target:!0,rel:!0,class:!0});var Xt=k(S);P=ne(Xt,"Lnyan"),Xt.forEach(_),O=ne(ut,`
+ for the original outpainting technique implemented on
+ `),z=U(ut,"A",{href:!0,target:!0,rel:!0,class:!0});var $e=k(z);X=ne($e,"Stable Diffusion Infinity"),$e.forEach(_),ut.forEach(_),K=se(G),M=U(G,"LI",{class:!0});var Jt=k(M);F=U(Jt,"P",{class:!0});var Pt=k(F);B=ne(Pt,`Multiplayer API by
+ `),v=U(Pt,"A",{href:!0,target:!0,rel:!0});var Wt=k(v);me($.$$.fragment,Wt),Wt.forEach(_),Pt.forEach(_),Jt.forEach(_),G.forEach(_),oe.forEach(_),W.forEach(_),this.h()},h(){c(r,"class","font-bold text-xl font-mono mb-8"),c(u,"href","https://huggingface.co/docs/hub/spaces-gpus"),c(u,"class","text-blue-400 hover:text-blue-600 underline"),c(a,"class","mb-2"),c(d,"href","https://huggingface.co/docs/diffusers/index"),c(d,"class","text-blue-400 hover:text-blue-600 underline"),c(x,"href","https://github.com/runwayml/stable-diffusion"),c(x,"target","_blank"),c(x,"class","text-blue-400 hover:text-blue-600 underline"),c(x,"rel","noopener noreferrer"),c(h,"class","mb-2"),c(S,"href","https://twitter.com/lkwq007"),c(S,"target","_blank"),c(S,"rel","noopener noreferrer"),c(S,"class","text-blue-400 hover:text-blue-600 underline"),c(z,"href","https://github.com/lkwq007/stablediffusion-infinity"),c(z,"target","_blank"),c(z,"rel","noopener noreferrer"),c(z,"class","text-blue-400 hover:text-blue-600 underline"),c(T,"class","mb-2"),c(v,"href","https://liveblocks.io"),c(v,"target","_blank"),c(v,"rel","noopener noreferrer"),c(F,"class","text-base flex items-center"),c(M,"class","mb-2"),c(n,"class","max-w-md"),c(t,"class",I="fixed "+e[0]+" w-screen h-screen top-0 left-0 bottom-0 right-0 z-50 items-center justify-center bg-black text-white bg-opacity-90 px-3")},m(L,W){re(L,t,W),m(t,n),m(n,r),m(r,i),m(n,s),m(n,o),m(o,a),m(a,l),m(a,u),m(u,f),m(o,p),m(o,h),m(h,d),m(d,y),m(h,g),m(h,x),m(x,w),m(o,C),m(o,T),m(T,E),m(T,S),m(S,P),m(T,O),m(T,z),m(z,X),m(o,K),m(o,M),m(M,F),m(F,B),m(F,v),_e($,v,null),N=!0,A||(V=Re(t,"click",e[1]),A=!0)},p(L,[W]){(!N||W&1&&I!==(I="fixed "+L[0]+" w-screen h-screen top-0 left-0 bottom-0 right-0 z-50 items-center justify-center bg-black text-white bg-opacity-90 px-3"))&&c(t,"class",I)},i(L){N||(J($.$$.fragment,L),N=!0)},o(L){q($.$$.fragment,L),N=!1},d(L){L&&_(t),ge($),A=!1,V()}}}function Ch(e,t,n){let{classList:r=""}=t;function i(s){cr.call(this,e,s)}return e.$$set=s=>{"classList"in s&&n(0,r=s.classList)},[r,i]}class Ih extends ke{constructor(t){super(),xe(this,t,Ch,xh,Ce,{classList:0})}}function Sh(e){let t,n;return t=new Ia({props:{client:e[1],$$slots:{default:[Th]},$$scope:{ctx:e}}}),{c(){pe(t.$$.fragment)},l(r){me(t.$$.fragment,r)},m(r,i){_e(t,r,i),n=!0},p(r,i){const s={};i&2&&(s.client=r[1]),i&516&&(s.$$scope={dirty:i,ctx:r}),t.$set(s)},i(r){n||(J(t.$$.fragment,r),n=!0)},o(r){q(t.$$.fragment,r),n=!1},d(r){ge(t,r)}}}function Oh(e){let t;return{c(){t=D("div"),this.h()},l(n){t=U(n,"DIV",{class:!0}),k(t).forEach(_),this.h()},h(){c(t,"class","inset-0 fixed bg-white animate-pulse")},m(n,r){re(n,t,r)},p:de,i:de,o:de,d(n){n&&_(t)}}}function Ah(e){let t,n,r,i,s,o;return{c(){t=D("div"),n=D("h1"),r=te("No room selected"),i=ie(),s=D("p"),o=te("Please select a room in the URL"),this.h()},l(a){t=U(a,"DIV",{class:!0});var l=k(t);n=U(l,"H1",{class:!0});var u=k(n);r=ne(u,"No room selected"),u.forEach(_),i=se(l),s=U(l,"P",{class:!0});var f=k(s);o=ne(f,"Please select a room in the URL"),f.forEach(_),l.forEach(_),this.h()},h(){c(n,"class","text-2xl font-bold"),c(s,"class","text-gray-500"),c(t,"class","flex flex-col items-center justify-center h-full")},m(a,l){re(a,t,l),m(t,n),m(n,r),m(t,i),m(t,s),m(s,o)},p:de,i:de,o:de,d(a){a&&_(t)}}}function Ph(e){let t,n;return t=new Aa({props:{id:e[2],initialPresence:e[4],$$slots:{default:[Lh]},$$scope:{ctx:e}}}),{c(){pe(t.$$.fragment)},l(r){me(t.$$.fragment,r)},m(r,i){_e(t,r,i),n=!0},p(r,i){const s={};i&4&&(s.id=r[2]),i&512&&(s.$$scope={dirty:i,ctx:r}),t.$set(s)},i(r){n||(J(t.$$.fragment,r),n=!0)},o(r){q(t.$$.fragment,r),n=!1},d(r){ge(t,r)}}}function Lh(e){let t,n;return t=new wh({}),{c(){pe(t.$$.fragment)},l(r){me(t.$$.fragment,r)},m(r,i){_e(t,r,i),n=!0},i(r){n||(J(t.$$.fragment,r),n=!0)},o(r){q(t.$$.fragment,r),n=!1},d(r){ge(t,r)}}}function Th(e){let t,n,r,i;const s=[Ph,Ah],o=[];function a(l,u){return l[2]?0:1}return t=a(e),n=o[t]=s[t](e),{c(){n.c(),r=Xe()},l(l){n.l(l),r=Xe()},m(l,u){o[t].m(l,u),re(l,r,u),i=!0},p(l,u){let f=t;t=a(l),t===f?o[t].p(l,u):(Le(),q(o[f],1,1,()=>{o[f]=null}),Te(),n=o[t],n?n.p(l,u):(n=o[t]=s[t](l),n.c()),J(n,1),n.m(r.parentNode,r))},i(l){i||(J(n),i=!0)},o(l){q(n),i=!1},d(l){o[t].d(l),l&&_(r)}}}function $h(e){let t,n,r,i,s,o;t=new Ih({props:{classList:e[3]?"flex":"hidden"}}),t.$on("click",e[6]);const a=[Oh,Sh],l=[];function u(f,p){return f[0]?0:1}return r=u(e),i=l[r]=a[r](e),{c(){pe(t.$$.fragment),n=ie(),i.c(),s=Xe()},l(f){me(t.$$.fragment,f),n=se(f),i.l(f),s=Xe()},m(f,p){_e(t,f,p),re(f,n,p),l[r].m(f,p),re(f,s,p),o=!0},p(f,[p]){const h={};p&8&&(h.classList=f[3]?"flex":"hidden"),t.$set(h);let d=r;r=u(f),r===d?l[r].p(f,p):(Le(),q(l[d],1,1,()=>{l[d]=null}),Te(),i=l[r],i?i.p(f,p):(i=l[r]=a[r](f),i.c()),J(i,1),i.m(s.parentNode,s))},i(f){o||(J(t.$$.fragment,f),J(i),o=!0)},o(f){q(t.$$.fragment,f),q(i),o=!1},d(f){ge(t,f),f&&_(n),l[r].d(f),f&&_(s)}}}function Mh(e,t,n){let r,i,s,o;he(e,bn,h=>n(7,i=h)),he(e,yt,h=>n(5,s=h)),he(e,wn,h=>n(3,o=h));let a=!0,l;Ot(()=>{/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)&&be(bn,i={width:512*8,height:512*8},i),n(1,l=ka({authEndpoint:pn+"/auth"})),u()});async function u(){n(0,a=!0);const h=new URLSearchParams(window.location.search).get("roomid"),y=await(await fetch(pn+"/rooms")).json(),g=y.find(w=>w.users_countC.room_id===h)||null;x=w&&w.users_countbe(wn,o=!1,o);return e.$$.update=()=>{e.$$.dirty&32&&n(2,r=s)},[a,l,r,o,f,s,p]}class Uh extends ke{constructor(t){super(),xe(this,t,Mh,$h,Ce,{})}}export{Uh as default};
diff --git a/static/_app/immutable/modules/pages/_page.ts-e9fa0128.js b/static/_app/immutable/modules/pages/_page.ts-e9fa0128.js
new file mode 100644
index 0000000000000000000000000000000000000000..e23d26c658fd3513b3ed3386f8f9baafdc416e73
--- /dev/null
+++ b/static/_app/immutable/modules/pages/_page.ts-e9fa0128.js
@@ -0,0 +1 @@
+import{p}from"../../chunks/_page-802cc2a3.js";export{p as prerender};
diff --git a/static/_app/immutable/start-01a14595.js b/static/_app/immutable/start-01a14595.js
new file mode 100644
index 0000000000000000000000000000000000000000..fe90900a34389df9abeeaf33de6b79bb9dfee103
--- /dev/null
+++ b/static/_app/immutable/start-01a14595.js
@@ -0,0 +1 @@
+import{S as Ye,i as Xe,s as Ze,a as Qe,e as B,c as xe,b as z,g as le,t as F,d as ce,f as J,h as G,j as et,o as ve,k as tt,l as nt,m as rt,n as ye,p as C,q as at,r as st,u as ot,v as H,w as W,x as Oe,y as Y,z as X,A as Be}from"./chunks/index-4781a106.js";import{g as Fe,f as Je,s as K,a as Ee,b as it,i as lt}from"./chunks/singletons-e8802a59.js";function ct(r,e){return r==="/"||e==="ignore"?r:e==="never"?r.endsWith("/")?r.slice(0,-1):r:e==="always"&&!r.endsWith("/")?r+"/":r}function ft(r){for(const e in r)r[e]=r[e].replace(/%23/g,"#").replace(/%3[Bb]/g,";").replace(/%2[Cc]/g,",").replace(/%2[Ff]/g,"/").replace(/%3[Ff]/g,"?").replace(/%3[Aa]/g,":").replace(/%40/g,"@").replace(/%26/g,"&").replace(/%3[Dd]/g,"=").replace(/%2[Bb]/g,"+").replace(/%24/g,"$");return r}const ut=["href","pathname","search","searchParams","toString","toJSON"];function pt(r,e){const t=new URL(r);for(const o of ut){let s=t[o];Object.defineProperty(t,o,{get(){return e(),s},enumerable:!0,configurable:!0})}return t[Symbol.for("nodejs.util.inspect.custom")]=(o,s,l)=>l(r,s),dt(t),t}function dt(r){Object.defineProperty(r,"hash",{get(){throw new Error("Cannot access event.url.hash. Consider using `$page.url.hash` inside a component instead")}})}function ht(r){let e=5381;if(typeof r=="string"){let t=r.length;for(;t;)e=e*33^r.charCodeAt(--t)}else if(ArrayBuffer.isView(r)){const t=new Uint8Array(r.buffer,r.byteOffset,r.byteLength);let o=t.length;for(;o;)e=e*33^t[--o]}else throw new TypeError("value must be a string or TypedArray");return(e>>>0).toString(36)}const fe=window.fetch;window.fetch=(r,e)=>{if((r instanceof Request?r.method:(e==null?void 0:e.method)||"GET")!=="GET"){const o=new URL(r instanceof Request?r.url:r.toString(),document.baseURI).href;ie.delete(o)}return fe(r,e)};const ie=new Map;function mt(r,e,t){let s=`script[data-sveltekit-fetched][data-url=${JSON.stringify(r instanceof Request?r.url:r)}]`;(t==null?void 0:t.body)&&(typeof t.body=="string"||ArrayBuffer.isView(t.body))&&(s+=`[data-hash="${ht(t.body)}"]`);const l=document.querySelector(s);if(l!=null&&l.textContent){const{body:n,...f}=JSON.parse(l.textContent),h=l.getAttribute("data-ttl");return h&&ie.set(e,{body:n,init:f,ttl:1e3*Number(h)}),Promise.resolve(new Response(n,f))}return fe(r,t)}function gt(r,e){const t=ie.get(r);if(t){if(performance.now(){const h=decodeURIComponent(l),d=/^\[\.\.\.(\w+)(?:=(\w+))?\]$/.exec(h);if(d)return e.push(d[1]),t.push(d[2]),"(?:/(.*))?";const _=n===f.length-1;return h&&"/"+h.split(/\[(.+?)\]/).map((w,R)=>{if(R%2){const U=_t.exec(w);if(!U)throw new Error(`Invalid param: ${w}. Params and matcher names can only have underscores and alphanumeric characters.`);const[,D,q,T]=U;return e.push(q),t.push(T),D?"(.*?)":"([^/]+?)"}return _&&w.includes(".")&&(o=!1),w.normalize().replace(/%5[Bb]/g,"[").replace(/%5[Dd]/g,"]").replace(/#/g,"%23").replace(/\?/g,"%3F").replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}).join("")}).join("")}${o?"/?":""}$`),names:e,types:t}}function wt(r){return!/^\([^)]+\)$/.test(r)}function bt(r,e,t,o){const s={};for(let l=0;l{const{pattern:w,names:R,types:U}=yt(f),D={id:f,exec:q=>{const T=w.exec(q);if(T)return bt(T,R,U,o)},errors:[1,..._||[]].map(q=>r[q]),layouts:[0,...d||[]].map(n),leaf:l(h)};return D.errors.length=D.layouts.length=Math.max(D.errors.length,D.layouts.length),D});function l(f){const h=f<0;return h&&(f=~f),[h,r[f]]}function n(f){return f===void 0?f:[s.has(f),r[f]]}}function Et(r){let e,t,o;var s=r[0][0];function l(n){return{props:{data:n[2],form:n[1]}}}return s&&(e=H(s,l(r))),{c(){e&&W(e.$$.fragment),t=B()},l(n){e&&Oe(e.$$.fragment,n),t=B()},m(n,f){e&&Y(e,n,f),z(n,t,f),o=!0},p(n,f){const h={};if(f&4&&(h.data=n[2]),f&2&&(h.form=n[1]),s!==(s=n[0][0])){if(e){le();const d=e;F(d.$$.fragment,1,0,()=>{X(d,1)}),ce()}s?(e=H(s,l(n)),W(e.$$.fragment),J(e.$$.fragment,1),Y(e,t.parentNode,t)):e=null}else s&&e.$set(h)},i(n){o||(e&&J(e.$$.fragment,n),o=!0)},o(n){e&&F(e.$$.fragment,n),o=!1},d(n){n&&G(t),e&&X(e,n)}}}function kt(r){let e,t,o;var s=r[0][0];function l(n){return{props:{data:n[2],$$slots:{default:[St]},$$scope:{ctx:n}}}}return s&&(e=H(s,l(r))),{c(){e&&W(e.$$.fragment),t=B()},l(n){e&&Oe(e.$$.fragment,n),t=B()},m(n,f){e&&Y(e,n,f),z(n,t,f),o=!0},p(n,f){const h={};if(f&4&&(h.data=n[2]),f&523&&(h.$$scope={dirty:f,ctx:n}),s!==(s=n[0][0])){if(e){le();const d=e;F(d.$$.fragment,1,0,()=>{X(d,1)}),ce()}s?(e=H(s,l(n)),W(e.$$.fragment),J(e.$$.fragment,1),Y(e,t.parentNode,t)):e=null}else s&&e.$set(h)},i(n){o||(e&&J(e.$$.fragment,n),o=!0)},o(n){e&&F(e.$$.fragment,n),o=!1},d(n){n&&G(t),e&&X(e,n)}}}function St(r){let e,t,o;var s=r[0][1];function l(n){return{props:{data:n[3],form:n[1]}}}return s&&(e=H(s,l(r))),{c(){e&&W(e.$$.fragment),t=B()},l(n){e&&Oe(e.$$.fragment,n),t=B()},m(n,f){e&&Y(e,n,f),z(n,t,f),o=!0},p(n,f){const h={};if(f&8&&(h.data=n[3]),f&2&&(h.form=n[1]),s!==(s=n[0][1])){if(e){le();const d=e;F(d.$$.fragment,1,0,()=>{X(d,1)}),ce()}s?(e=H(s,l(n)),W(e.$$.fragment),J(e.$$.fragment,1),Y(e,t.parentNode,t)):e=null}else s&&e.$set(h)},i(n){o||(e&&J(e.$$.fragment,n),o=!0)},o(n){e&&F(e.$$.fragment,n),o=!1},d(n){n&&G(t),e&&X(e,n)}}}function Ge(r){let e,t=r[5]&&Ke(r);return{c(){e=tt("div"),t&&t.c(),this.h()},l(o){e=nt(o,"DIV",{id:!0,"aria-live":!0,"aria-atomic":!0,style:!0});var s=rt(e);t&&t.l(s),s.forEach(G),this.h()},h(){ye(e,"id","svelte-announcer"),ye(e,"aria-live","assertive"),ye(e,"aria-atomic","true"),C(e,"position","absolute"),C(e,"left","0"),C(e,"top","0"),C(e,"clip","rect(0 0 0 0)"),C(e,"clip-path","inset(50%)"),C(e,"overflow","hidden"),C(e,"white-space","nowrap"),C(e,"width","1px"),C(e,"height","1px")},m(o,s){z(o,e,s),t&&t.m(e,null)},p(o,s){o[5]?t?t.p(o,s):(t=Ke(o),t.c(),t.m(e,null)):t&&(t.d(1),t=null)},d(o){o&&G(e),t&&t.d()}}}function Ke(r){let e;return{c(){e=at(r[6])},l(t){e=st(t,r[6])},m(t,o){z(t,e,o)},p(t,o){o&64&&ot(e,t[6])},d(t){t&&G(e)}}}function Rt(r){let e,t,o,s,l;const n=[kt,Et],f=[];function h(_,w){return _[0][1]?0:1}e=h(r),t=f[e]=n[e](r);let d=r[4]&&Ge(r);return{c(){t.c(),o=Qe(),d&&d.c(),s=B()},l(_){t.l(_),o=xe(_),d&&d.l(_),s=B()},m(_,w){f[e].m(_,w),z(_,o,w),d&&d.m(_,w),z(_,s,w),l=!0},p(_,[w]){let R=e;e=h(_),e===R?f[e].p(_,w):(le(),F(f[R],1,1,()=>{f[R]=null}),ce(),t=f[e],t?t.p(_,w):(t=f[e]=n[e](_),t.c()),J(t,1),t.m(o.parentNode,o)),_[4]?d?d.p(_,w):(d=Ge(_),d.c(),d.m(s.parentNode,s)):d&&(d.d(1),d=null)},i(_){l||(J(t),l=!0)},o(_){F(t),l=!1},d(_){f[e].d(_),_&&G(o),d&&d.d(_),_&&G(s)}}}function Ot(r,e,t){let{stores:o}=e,{page:s}=e,{components:l}=e,{form:n}=e,{data_0:f=null}=e,{data_1:h=null}=e;et(o.page.notify);let d=!1,_=!1,w=null;return ve(()=>{const R=o.page.subscribe(()=>{d&&(t(5,_=!0),t(6,w=document.title||"untitled page"))});return t(4,d=!0),R}),r.$$set=R=>{"stores"in R&&t(7,o=R.stores),"page"in R&&t(8,s=R.page),"components"in R&&t(0,l=R.components),"form"in R&&t(1,n=R.form),"data_0"in R&&t(2,f=R.data_0),"data_1"in R&&t(3,h=R.data_1)},r.$$.update=()=>{r.$$.dirty&384&&o.page.set(s)},[l,n,f,h,d,_,w,o,s]}class $t extends Ye{constructor(e){super(),Xe(this,e,Ot,Rt,Ze,{stores:7,page:8,components:0,form:1,data_0:2,data_1:3})}}const Lt=function(){const e=document.createElement("link").relList;return e&&e.supports&&e.supports("modulepreload")?"modulepreload":"preload"}(),It=function(r,e){return new URL(r,e).href},ze={},we=function(e,t,o){return!t||t.length===0?e():Promise.all(t.map(s=>{if(s=It(s,o),s in ze)return;ze[s]=!0;const l=s.endsWith(".css"),n=l?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${s}"]${n}`))return;const f=document.createElement("link");if(f.rel=l?"stylesheet":Lt,l||(f.as="script",f.crossOrigin=""),f.href=s,document.head.appendChild(f),l)return new Promise((h,d)=>{f.addEventListener("load",h),f.addEventListener("error",()=>d(new Error(`Unable to preload CSS for ${s}`)))})})).then(()=>e())},jt={},ue=[()=>we(()=>import("./chunks/0-dd39116a.js"),["chunks/0-dd39116a.js","components/pages/_layout.svelte-2e7ed5f6.js","assets/_layout-d90db7b5.css","chunks/index-4781a106.js"],import.meta.url),()=>we(()=>import("./chunks/1-bf704c85.js"),["chunks/1-bf704c85.js","components/error.svelte-443b2358.js","chunks/index-4781a106.js","chunks/stores-36fae70e.js","chunks/singletons-e8802a59.js"],import.meta.url),()=>we(()=>import("./chunks/2-9d823c2e.js"),["chunks/2-9d823c2e.js","chunks/_page-802cc2a3.js","components/pages/_page.svelte-5ae30844.js","assets/_page-ff237a95.css","chunks/index-4781a106.js","chunks/singletons-e8802a59.js","chunks/stores-36fae70e.js"],import.meta.url)],At=[],Nt={"":[2]},Pt={handleError:({error:r})=>{console.error(r)}};class ke{constructor(e,t){this.status=e,typeof t=="string"?this.body={message:t}:t?this.body=t:this.body={message:`Error: ${e}`}}toString(){return JSON.stringify(this.body)}}class Me{constructor(e,t){this.status=e,this.location=t}}const Ut="/__data.json";async function Tt(r){var e;for(const t in r)if(typeof((e=r[t])==null?void 0:e.then)=="function")return Object.fromEntries(await Promise.all(Object.entries(r).map(async([o,s])=>[o,await s])));return r}Object.getOwnPropertyNames(Object.prototype).sort().join("\0");Object.getOwnPropertyNames(Object.prototype).sort().join("\0");const Dt=-1,qt=-2,Ct=-3,Vt=-4,Bt=-5,Ft=-6;function Jt(r){const e=JSON.parse(r);if(typeof e=="number")return s(e);const t=e,o=Array(t.length);function s(l){if(l===Dt)return;if(l===Ct)return NaN;if(l===Vt)return 1/0;if(l===Bt)return-1/0;if(l===Ft)return-0;if(l in o)return o[l];const n=t[l];if(!n||typeof n!="object")o[l]=n;else if(Array.isArray(n))if(typeof n[0]=="string")switch(n[0]){case"Date":o[l]=new Date(n[1]);break;case"Set":const h=new Set;o[l]=h;for(let w=1;w{},blocked:()=>{},type:"goto"})}async function Ie(a){const u=me(a,!1);if(!u)throw new Error("Attempted to prefetch a URL that does not belong to this app");return s={id:u.id,promise:Pe(u)},s.promise}async function je(a,u,p,i,c={},m){var k,E;$e=c;let g=a&&await Pe(a);if(g||(g=await De(u,null,x(new Error(`Not found: ${u.pathname}`),{url:u,params:{},routeId:null}),404)),u=(a==null?void 0:a.url)||u,$e!==c)return!1;if(g.type==="redirect")if(p.length>10||p.includes(u.pathname))g=await ne({status:500,error:x(new Error("Redirect loop"),{url:u,params:{},routeId:null}),url:u,routeId:null});else return pe(new URL(g.location,u).href,{},[...p,u.pathname],c),!1;else((E=(k=g.props)==null?void 0:k.page)==null?void 0:E.status)>=400&&await K.updated.check()&&await re(u);if(o.length=0,w=!1,_=!0,i&&i.details){const{details:b}=i,v=b.replaceState?0:1;b.state[V]=U+=v,history[b.replaceState?"replaceState":"pushState"](b.state,"",u)}if(s=null,h){n=g.state,g.props.page&&(g.props.page.url=u);const b=oe();R.$set(g.props),b()}else Ae(g);if(i){const{scroll:b,keepfocus:v}=i;if(!v){const O=document.body,L=O.getAttribute("tabindex");O.tabIndex=-1,O.focus({preventScroll:!0}),setTimeout(()=>{var I;(I=getSelection())==null||I.removeAllRanges()}),L!==null?O.setAttribute("tabindex",L):O.removeAttribute("tabindex")}if(await Be(),d){const O=u.hash&&document.getElementById(u.hash.slice(1));b?scrollTo(b.x,b.y):O?O.scrollIntoView():scrollTo(0,0)}}else await Be();d=!0,g.props.page&&(T=g.props.page),m&&m(),_=!1}function Ae(a){var c,m;n=a.state;const u=document.querySelector("style[data-sveltekit]");u&&u.remove(),T=a.props.page;const p=oe();R=new $t({target:r,props:{...a.props,stores:K},hydrate:!0}),p();const i={from:null,to:se("to",{params:n.params,routeId:(m=(c=n.route)==null?void 0:c.id)!=null?m:null,url:new URL(location.href)}),type:"load"};l.after_navigate.forEach(g=>g(i)),h=!0}async function Z({url:a,params:u,branch:p,status:i,error:c,route:m,form:g}){var L;const k=p.filter(Boolean),E={type:"loaded",state:{url:a,params:u,branch:p,error:c,route:m},props:{components:k.map(I=>I.node.component)}};g!==void 0&&(E.props.form=g);let b={},v=!T;for(let I=0;IP===N))&&(E.props[`data_${I}`]=b,v=v||Object.keys((L=N.data)!=null?L:{}).length>0)}if(v||(v=Object.keys(T.data).length!==Object.keys(b).length),!n.url||a.href!==n.url.href||n.error!==c||g!==void 0||v){E.props.page={error:c,params:u,routeId:m&&m.id,status:i,url:a,form:g,data:v?b:T.data};const I=(N,P)=>{Object.defineProperty(E.props.page,N,{get:()=>{throw new Error(`$page.${N} has been replaced by $page.url.${P}`)}})};I("origin","origin"),I("path","pathname"),I("query","searchParams")}return E}async function de({loader:a,parent:u,url:p,params:i,routeId:c,server_data_node:m}){var b,v,O,L,I;let g=null;const k={dependencies:new Set,params:new Set,parent:!1,url:!1},E=await a();if((b=E.shared)!=null&&b.load){let N=function(...$){for(const y of $){const{href:S}=new URL(y,p);k.dependencies.add(S)}};const P={routeId:c,params:new Proxy(i,{get:($,y)=>(k.params.add(y),$[y])}),data:(v=m==null?void 0:m.data)!=null?v:null,url:pt(p,()=>{k.url=!0}),async fetch($,y){let S;$ instanceof Request?(S=$.url,y={body:$.method==="GET"||$.method==="HEAD"?void 0:await $.blob(),cache:$.cache,credentials:$.credentials,headers:$.headers,integrity:$.integrity,keepalive:$.keepalive,method:$.method,mode:$.mode,redirect:$.redirect,referrer:$.referrer,referrerPolicy:$.referrerPolicy,signal:$.signal,...y}):S=$;const A=new URL(S,p).href;return N(A),h?gt(A,y):mt(S,A,y)},setHeaders:()=>{},depends:N,parent(){return k.parent=!0,u()}};Object.defineProperties(P,{props:{get(){throw new Error("@migration task: Replace `props` with `data` stuff https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292693")},enumerable:!1},session:{get(){throw new Error("session is no longer available. See https://github.com/sveltejs/kit/discussions/5883")},enumerable:!1},stuff:{get(){throw new Error("@migration task: Remove stuff https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3292693")},enumerable:!1}}),g=(O=await E.shared.load.call(null,P))!=null?O:null,g=g?await Tt(g):null}return{node:E,loader:a,server:m,shared:(L=E.shared)!=null&&L.load?{type:"data",data:g,uses:k}:null,data:(I=g!=null?g:m==null?void 0:m.data)!=null?I:null}}function Ne(a,u,p,i){if(w)return!0;if(!p)return!1;if(p.parent&&u||p.url&&a)return!0;for(const c of p.params)if(i[c]!==n.params[c])return!0;for(const c of p.dependencies)if(o.some(m=>m(new URL(c))))return!0;return!1}function he(a,u){var p,i;return(a==null?void 0:a.type)==="data"?{type:"data",data:a.data,uses:{dependencies:new Set((p=a.uses.dependencies)!=null?p:[]),params:new Set((i=a.uses.params)!=null?i:[]),parent:!!a.uses.parent,url:!!a.uses.url}}:(a==null?void 0:a.type)==="skip"&&u!=null?u:null}async function Pe({id:a,invalidating:u,url:p,params:i,route:c}){var $;if((s==null?void 0:s.id)===a)return s.promise;const{errors:m,layouts:g,leaf:k}=c,E=[...g,k];m.forEach(y=>y==null?void 0:y().catch(()=>{})),E.forEach(y=>y==null?void 0:y[1]().catch(()=>{}));let b=null;const v=n.url?a!==n.url.pathname+n.url.search:!1,O=E.reduce((y,S,A)=>{var Q;const j=n.branch[A],M=!!(S!=null&&S[0])&&((j==null?void 0:j.loader)!==S[1]||Ne(v,y.some(Boolean),(Q=j.server)==null?void 0:Q.uses,i));return y.push(M),y},[]);if(O.some(Boolean)){try{b=await He(p,O)}catch(y){return ne({status:500,error:x(y,{url:p,params:i,routeId:c.id}),url:p,routeId:c.id})}if(b.type==="redirect")return b}const L=b==null?void 0:b.nodes;let I=!1;const N=E.map(async(y,S)=>{var Q;if(!y)return;const A=n.branch[S],j=L==null?void 0:L[S];if((!j||j.type==="skip")&&y[1]===(A==null?void 0:A.loader)&&!Ne(v,I,(Q=A.shared)==null?void 0:Q.uses,i))return A;if(I=!0,(j==null?void 0:j.type)==="error")throw j;return de({loader:y[1],url:p,params:i,routeId:c.id,parent:async()=>{var Ve;const Ce={};for(let _e=0;_e{});const P=[];for(let y=0;yPromise.resolve({}),server_data_node:he(g)}),E={node:await Re(),loader:Re,shared:null,server:null,data:null};return await Z({url:p,params:c,branch:[k,E],status:a,error:u,route:null})}function me(a,u){if(Te(a))return;const p=decodeURI(a.pathname.slice(e.length)||"/");for(const i of ae){const c=i.exec(p);if(c){const m=new URL(a.origin+ct(a.pathname,t)+a.search+a.hash);return{id:m.pathname+m.search,invalidating:u,route:i,params:ft(c),url:m}}}}function Te(a){return a.origin!==location.origin||!a.pathname.startsWith(e)}async function ge({url:a,scroll:u,keepfocus:p,redirect_chain:i,details:c,type:m,delta:g,nav_token:k,accepted:E,blocked:b}){var N,P,$,y;let v=!1;const O=me(a,!1),L={from:se("from",{params:n.params,routeId:(P=(N=n.route)==null?void 0:N.id)!=null?P:null,url:n.url}),to:se("to",{params:($=O==null?void 0:O.params)!=null?$:null,routeId:(y=O==null?void 0:O.route.id)!=null?y:null,url:a}),type:m};g!==void 0&&(L.delta=g);const I={...L,cancel:()=>{v=!0}};if(l.before_navigate.forEach(S=>S(I)),v){b();return}be(U),E(),h&&K.navigating.set(L),await je(O,a,i,{scroll:u,keepfocus:p,details:c},k,()=>{l.after_navigate.forEach(S=>S(L)),K.navigating.set(null)})}async function De(a,u,p,i){return a.origin===location.origin&&a.pathname===location.pathname&&!f?await ne({status:i,error:p,url:a,routeId:u}):await re(a)}function re(a){return location.href=a.href,new Promise(()=>{})}return{after_navigate:a=>{ve(()=>(l.after_navigate.push(a),()=>{const u=l.after_navigate.indexOf(a);l.after_navigate.splice(u,1)}))},before_navigate:a=>{ve(()=>(l.before_navigate.push(a),()=>{const u=l.before_navigate.indexOf(a);l.before_navigate.splice(u,1)}))},disable_scroll_handling:()=>{(_||!h)&&(d=!1)},goto:(a,u={})=>pe(a,u,[]),invalidate:a=>{if(a===void 0)throw new Error("`invalidate()` (with no arguments) has been replaced by `invalidateAll()`");if(typeof a=="function")o.push(a);else{const{href:u}=new URL(a,location.href);o.push(p=>p.href===u)}return Le()},invalidateAll:()=>(w=!0,Le()),prefetch:async a=>{const u=new URL(a,Fe(document));await Ie(u)},prefetch_routes:async a=>{const p=(a?ae.filter(i=>a.some(c=>i.exec(c))):ae).map(i=>Promise.all([...i.layouts,i.leaf].map(c=>c==null?void 0:c[1]())));await Promise.all(p)},apply_action:async a=>{if(a.type==="error"){const u=new URL(location.href),{branch:p,route:i}=n;if(!i)return;const c=await Ue(n.branch.length,p,i.errors);if(c){const m=await Z({url:u,params:n.params,branch:p.slice(0,c.idx).concat(c.node),status:500,error:a.error,route:i});n=m.state;const g=oe();R.$set(m.props),g()}}else if(a.type==="redirect")pe(a.location,{},[]);else{const u={form:a.data,page:{...T,form:a.data,status:a.status}},p=oe();R.$set(u),p()}},_start_router:()=>{history.scrollRestoration="manual",addEventListener("beforeunload",i=>{var g,k;let c=!1;const m={from:se("from",{params:n.params,routeId:(k=(g=n.route)==null?void 0:g.id)!=null?k:null,url:n.url}),to:null,type:"unload",cancel:()=>c=!0};l.before_navigate.forEach(E=>E(m)),c?(i.preventDefault(),i.returnValue=""):history.scrollRestoration="auto"}),addEventListener("visibilitychange",()=>{if(document.visibilityState==="hidden"){be(U);try{sessionStorage[We]=JSON.stringify(ee)}catch{}}});const a=i=>{const{url:c,options:m}=Je(i);if(c&&m.prefetch){if(Te(c))return;Ie(c)}};let u;const p=i=>{clearTimeout(u),u=setTimeout(()=>{var c;(c=i.target)==null||c.dispatchEvent(new CustomEvent("sveltekit:trigger_prefetch",{bubbles:!0}))},20)};addEventListener("touchstart",a),addEventListener("mousemove",p),addEventListener("sveltekit:trigger_prefetch",a),addEventListener("click",i=>{if(i.button||i.which!==1||i.metaKey||i.ctrlKey||i.shiftKey||i.altKey||i.defaultPrevented)return;const{a:c,url:m,options:g}=Je(i);if(!c||!m)return;const k=c instanceof SVGAElement;if(!k&&m.protocol!==location.protocol&&!(m.protocol==="https:"||m.protocol==="http:"))return;const E=(c.getAttribute("rel")||"").split(/\s+/);if(c.hasAttribute("download")||E.includes("external")||g.reload||(k?c.target.baseVal:c.target))return;const[b,v]=m.href.split("#");if(v!==void 0&&b===location.href.split("#")[0]){q=!0,be(U),n.url=m,K.page.set({...T,url:m}),K.page.notify();return}ge({url:m,scroll:g.noscroll?Ee():null,keepfocus:!1,redirect_chain:[],details:{state:{},replaceState:m.href===location.href},accepted:()=>i.preventDefault(),blocked:()=>i.preventDefault(),type:"link"})}),addEventListener("popstate",i=>{if(i.state){if(i.state[V]===U)return;const c=i.state[V]-U;ge({url:new URL(location.href),scroll:ee[i.state[V]],keepfocus:!1,redirect_chain:[],details:null,accepted:()=>{U=i.state[V]},blocked:()=>{history.go(-c)},type:"popstate",delta:c})}}),addEventListener("hashchange",()=>{q&&(q=!1,history.replaceState({...history.state,[V]:++U},"",location.href))});for(const i of document.querySelectorAll("link"))i.rel==="icon"&&(i.href=i.href);addEventListener("pageshow",i=>{i.persisted&&K.navigating.set(null)})},_hydrate:async({status:a,error:u,node_ids:p,params:i,routeId:c,data:m,form:g})=>{var b;f=!0;const k=new URL(location.href);let E;try{const v=p.map(async(O,L)=>{const I=m[L];return de({loader:ue[O],url:k,params:i,routeId:c,parent:async()=>{const N={};for(let P=0;PO.id===c))!=null?b:null})}catch(v){if(v instanceof Me){await re(new URL(v.location,location.href));return}E=await ne({status:v instanceof ke?v.status:500,error:x(v,{url:k,params:i,routeId:c}),url:k,routeId:c})}Ae(E)}}}async function He(r,e){const t=new URL(r);t.pathname=r.pathname.replace(/\/$/,"")+Ut;const o=await fe(t.href,{headers:{"x-sveltekit-invalidated":e.map(l=>l?"1":"").join(",")}}),s=await o.text();if(!o.ok)throw new Error(JSON.parse(s));return Jt(s)}function x(r,e){var t;return r instanceof ke?r.body:(t=Pt.handleError({error:r,event:e}))!=null?t:{message:e.routeId!=null?"Internal Error":"Not Found"}}const Kt=["hash","href","host","hostname","origin","pathname","port","protocol","search","searchParams","toString","toJSON"];function se(r,e){for(const t of Kt)Object.defineProperty(e,t,{get(){throw new Error(`The navigation shape changed - ${r}.${t} should now be ${r}.url.${t}`)},enumerable:!1});return e}function oe(){return()=>{}}async function Ht({env:r,hydrate:e,paths:t,target:o,trailing_slash:s}){it(t);const l=Gt({target:o,base:t.base,trailing_slash:s});lt({client:l}),e?await l._hydrate(e):l.goto(location.href,{replaceState:!0}),l._start_router()}export{Ht as start};
diff --git a/static/_app/version.json b/static/_app/version.json
new file mode 100644
index 0000000000000000000000000000000000000000..be8de5e136604b1e4910a4fb152c2427b8705fd5
--- /dev/null
+++ b/static/_app/version.json
@@ -0,0 +1 @@
+{"version":"1668020391802"}
\ No newline at end of file
diff --git a/static/favicon.png b/static/favicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..825b9e65af7c104cfb07089bb28659393b4f2097
Binary files /dev/null and b/static/favicon.png differ
diff --git a/static/index.html b/static/index.html
new file mode 100644
index 0000000000000000000000000000000000000000..24d4a91b9b2454ea508e2482b2f13b5f11960901
--- /dev/null
+++ b/static/index.html
@@ -0,0 +1,66 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Stable Difussion Multiplayer
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/static/robots.txt b/static/robots.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e9e57dc4d41b9b46e05112e9f45b7ea6ac0ba15e
--- /dev/null
+++ b/static/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/static/vite-manifest.json b/static/vite-manifest.json
new file mode 100644
index 0000000000000000000000000000000000000000..0221113e3323a6e9c2cdcbdeafd39f089a90afc7
--- /dev/null
+++ b/static/vite-manifest.json
@@ -0,0 +1,109 @@
+{
+ "node_modules/@sveltejs/kit/src/runtime/client/start.js": {
+ "file": "_app/immutable/start-01a14595.js",
+ "src": "node_modules/@sveltejs/kit/src/runtime/client/start.js",
+ "isEntry": true,
+ "imports": [
+ "_index-4781a106.js",
+ "_singletons-e8802a59.js"
+ ],
+ "dynamicImports": [
+ ".svelte-kit/generated/nodes/0.js",
+ ".svelte-kit/generated/nodes/1.js",
+ ".svelte-kit/generated/nodes/2.js"
+ ]
+ },
+ "src/routes/+layout.svelte": {
+ "file": "_app/immutable/components/pages/_layout.svelte-2e7ed5f6.js",
+ "src": "src/routes/+layout.svelte",
+ "isEntry": true,
+ "imports": [
+ "_index-4781a106.js"
+ ],
+ "css": [
+ "_app/immutable/assets/_layout-d90db7b5.css"
+ ]
+ },
+ "node_modules/@sveltejs/kit/src/runtime/components/error.svelte": {
+ "file": "_app/immutable/components/error.svelte-443b2358.js",
+ "src": "node_modules/@sveltejs/kit/src/runtime/components/error.svelte",
+ "isEntry": true,
+ "imports": [
+ "_index-4781a106.js",
+ "_stores-36fae70e.js"
+ ]
+ },
+ "src/routes/+page.svelte": {
+ "file": "_app/immutable/components/pages/_page.svelte-5ae30844.js",
+ "src": "src/routes/+page.svelte",
+ "isEntry": true,
+ "imports": [
+ "_index-4781a106.js",
+ "_singletons-e8802a59.js",
+ "_stores-36fae70e.js"
+ ],
+ "css": [
+ "_app/immutable/assets/_page-ff237a95.css"
+ ]
+ },
+ "src/routes/+page.ts": {
+ "file": "_app/immutable/modules/pages/_page.ts-e9fa0128.js",
+ "src": "src/routes/+page.ts",
+ "isEntry": true,
+ "imports": [
+ "__page-802cc2a3.js"
+ ]
+ },
+ "_singletons-e8802a59.js": {
+ "file": "_app/immutable/chunks/singletons-e8802a59.js",
+ "imports": [
+ "_index-4781a106.js"
+ ]
+ },
+ "_index-4781a106.js": {
+ "file": "_app/immutable/chunks/index-4781a106.js"
+ },
+ "_stores-36fae70e.js": {
+ "file": "_app/immutable/chunks/stores-36fae70e.js",
+ "imports": [
+ "_index-4781a106.js",
+ "_singletons-e8802a59.js"
+ ]
+ },
+ "__page-802cc2a3.js": {
+ "file": "_app/immutable/chunks/_page-802cc2a3.js"
+ },
+ ".svelte-kit/generated/nodes/0.js": {
+ "file": "_app/immutable/chunks/0-dd39116a.js",
+ "src": ".svelte-kit/generated/nodes/0.js",
+ "isDynamicEntry": true,
+ "imports": [
+ "src/routes/+layout.svelte"
+ ]
+ },
+ ".svelte-kit/generated/nodes/1.js": {
+ "file": "_app/immutable/chunks/1-bf704c85.js",
+ "src": ".svelte-kit/generated/nodes/1.js",
+ "isDynamicEntry": true,
+ "imports": [
+ "node_modules/@sveltejs/kit/src/runtime/components/error.svelte"
+ ]
+ },
+ ".svelte-kit/generated/nodes/2.js": {
+ "file": "_app/immutable/chunks/2-9d823c2e.js",
+ "src": ".svelte-kit/generated/nodes/2.js",
+ "isDynamicEntry": true,
+ "imports": [
+ "__page-802cc2a3.js",
+ "src/routes/+page.svelte"
+ ]
+ },
+ "src/routes/+page.css": {
+ "file": "_app/immutable/assets/_page-ff237a95.css",
+ "src": "src/routes/+page.css"
+ },
+ "src/routes/+layout.css": {
+ "file": "_app/immutable/assets/_layout-d90db7b5.css",
+ "src": "src/routes/+layout.css"
+ }
+}
\ No newline at end of file