9 Commits

Author SHA1 Message Date
kaj
62c9d968d6 Merge branch 'main' into better-plugin-dx 2023-05-24 10:13:05 -08:00
kaj
aeea895bba fix releases 2023-05-20 11:58:00 -08:00
kaj
6d2045ed15 readme & github action build pipeline 2023-05-19 19:42:54 -08:00
kaj
8fa9ec5fb7 basic readme stub 2023-05-19 18:59:28 -08:00
kaj
3a70bbed29 make yarn happy 2023-05-19 16:20:06 -08:00
kaj
3d30ade50f .gitignore 2023-05-19 16:18:44 -08:00
kaj
d4c0af7273 switch package names 2023-05-19 16:16:18 -08:00
kaj
054a2b9175 CRLF fix 2023-05-19 16:15:09 -08:00
kaj
b6b6ed4c84 initial move of example into create-stablestudio-plugin 2023-05-19 16:02:36 -08:00
39 changed files with 3477 additions and 949 deletions

File diff suppressed because one or more lines are too long

873
.yarn/releases/yarn-3.5.1.cjs vendored Normal file

File diff suppressed because one or more lines are too long

View File

@@ -4,4 +4,4 @@ plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
yarnPath: .yarn/releases/yarn-3.3.0.cjs
yarnPath: .yarn/releases/yarn-3.5.1.cjs

View File

@@ -1,6 +1,6 @@
{
"license": "MIT",
"packageManager": "yarn@3.3.0",
"packageManager": "yarn@3.5.1",
"workspaces": {
"packages": [
"packages/*"
@@ -9,13 +9,10 @@
"scripts": {
"postinstall": "node -e \"try { require('husky').install() } catch (e) {if (e.code !== 'MODULE_NOT_FOUND') throw e}\" && yarn build",
"stablestudio-plugin": "yarn workspace @stability/stablestudio-plugin",
"stablestudio-plugin-example": "yarn workspace @stability/stablestudio-plugin-example",
"stablestudio-plugin-stability": "yarn workspace @stability/stablestudio-plugin-stability",
"stablestudio-plugin-webgpu": "yarn workspace @stability/stablestudio-plugin-webgpu",
"stablestudio-plugin-webui": "yarn workspace @stability/stablestudio-plugin-webui",
"stablestudio-ui": "yarn workspace @stability/stablestudio-ui",
"dev:use-example-plugin": "cross-env VITE_USE_EXAMPLE_PLUGIN=true yarn dev",
"dev:use-webui-plugin": "cross-env VITE_USE_WEBUI_PLUGIN=true yarn dev",
"dev": "yarn workspaces foreach --all --interlaced --verbose --parallel --jobs unlimited run dev",
"build": "yarn workspaces foreach --all --interlaced --verbose --jobs unlimited run build",
"clean": "yarn workspaces foreach --all --interlaced --verbose --parallel --jobs unlimited run clean && rimraf node_modules"

View File

@@ -0,0 +1 @@
dist

View File

@@ -0,0 +1 @@
# create-stablestudio-plugin

View File

@@ -0,0 +1,64 @@
/* eslint-disable import/no-extraneous-dependencies */
import path from "path";
import chalk from "chalk";
import type { PackageManager } from "./helpers/get-pkg-manager";
import { tryGitInit } from "./helpers/git";
import { isFolderEmpty } from "./helpers/is-folder-empty";
import { isWriteable } from "./helpers/is-writeable";
import { makeDir } from "./helpers/make-dir";
import { installTemplate, TemplateType } from "./templates";
export async function createPlugin({
pluginName,
pluginPath,
packageManager,
template = "default",
}: {
pluginName: string;
pluginPath: string;
packageManager: PackageManager;
example?: string;
examplePath?: string;
template?: TemplateType;
}): Promise<void> {
const root = path.resolve(pluginPath);
if (!(await isWriteable(path.dirname(root)))) {
console.error(
"The plugin path is not writable, please check folder permissions and try again."
);
console.error(
"It is likely you do not have write permissions for this folder."
);
process.exit(1);
}
const appName = path.basename(root);
await makeDir(root);
if (!isFolderEmpty(root, appName)) {
process.exit(1);
}
console.log(`Creating a new StableStudio plugin in ${chalk.green(root)}.`);
console.log();
process.chdir(root);
await installTemplate({
pluginName,
root,
packageManager,
template,
});
if (tryGitInit(root)) {
console.log("Initialized a git repository.");
console.log();
}
console.log();
}

View File

@@ -0,0 +1,17 @@
export type PackageManager = "npm" | "pnpm" | "yarn";
export function getPkgManager(): PackageManager {
const userAgent = process.env.npm_config_user_agent;
if (userAgent) {
if (userAgent.startsWith("yarn")) {
return "yarn";
} else if (userAgent.startsWith("pnpm")) {
return "pnpm";
} else {
return "npm";
}
} else {
return "npm";
}
}

View File

@@ -0,0 +1,48 @@
/* eslint-disable import/no-extraneous-dependencies */
import { execSync } from "child_process";
import fs from "fs";
import path from "path";
function isInGitRepository(): boolean {
try {
execSync("git rev-parse --is-inside-work-tree", { stdio: "ignore" });
return true;
} catch (_) {}
return false;
}
function isInMercurialRepository(): boolean {
try {
execSync("hg --cwd . root", { stdio: "ignore" });
return true;
} catch (_) {}
return false;
}
export function tryGitInit(root: string): boolean {
let didInit = false;
try {
execSync("git --version", { stdio: "ignore" });
if (isInGitRepository() || isInMercurialRepository()) {
return false;
}
execSync("git init", { stdio: "ignore" });
didInit = true;
execSync("git checkout -b main", { stdio: "ignore" });
execSync("git add -A", { stdio: "ignore" });
execSync('git commit -m "Initial commit from Create StableStudio Plugin"', {
stdio: "ignore",
});
return true;
} catch (e) {
if (didInit) {
try {
fs.rmSync(path.join(root, ".git"), { recursive: true, force: true });
} catch (_) {}
}
return false;
}
}

View File

@@ -0,0 +1,76 @@
/* eslint-disable import/no-extraneous-dependencies */
import chalk from 'chalk'
import spawn from 'cross-spawn'
import type { PackageManager } from './get-pkg-manager'
interface InstallArgs {
/**
* Indicate whether to install packages using npm, pnpm or Yarn.
*/
packageManager: PackageManager
/**
* Indicate whether the given dependencies are devDependencies.
*/
devDependencies?: boolean
}
/**
* Spawn a package manager installation with either Yarn or NPM.
*
* @returns A Promise that resolves once the installation is finished.
*/
export function install(
root: string,
{ packageManager, devDependencies }: InstallArgs
): Promise<void> {
/**
* (p)npm-specific command-line flags.
*/
const npmFlags: string[] = []
/**
* Yarn-specific command-line flags.
*/
const yarnFlags: string[] = []
/**
* Return a Promise that resolves once the installation is finished.
*/
return new Promise((resolve, reject) => {
let args: string[]
let command = packageManager
const useYarn = packageManager === 'yarn'
args = ['install'];
/**
* Add any package manager-specific flags.
*/
if (useYarn) {
args.push(...yarnFlags)
} else {
args.push(...npmFlags)
}
/**
* Spawn the installation process.
*/
const child = spawn(command, args, {
stdio: 'inherit',
env: {
...process.env,
ADBLOCK: '1',
// we set NODE_ENV to development as pnpm skips dev
// dependencies when production
NODE_ENV: 'development',
DISABLE_OPENCOLLECTIVE: '1',
},
})
child.on('close', (code) => {
if (code !== 0) {
reject({ command: `${command} ${args.join(' ')}` })
return
}
resolve()
})
})
}

View File

@@ -0,0 +1,63 @@
/* eslint-disable import/no-extraneous-dependencies */
import fs from "fs";
import path from "path";
import chalk from "chalk";
export function isFolderEmpty(root: string, name: string): boolean {
const validFiles = [
".DS_Store",
".git",
".gitattributes",
".gitignore",
".gitlab-ci.yml",
".hg",
".hgcheck",
".hgignore",
".idea",
".npmignore",
".travis.yml",
"LICENSE",
"Thumbs.db",
"docs",
"mkdocs.yml",
"npm-debug.log",
"yarn-debug.log",
"yarn-error.log",
"yarnrc.yml",
".yarn",
];
const conflicts = fs
.readdirSync(root)
.filter((file) => !validFiles.includes(file))
// Support IntelliJ IDEA-based editors
.filter((file) => !/\.iml$/.test(file));
if (conflicts.length > 0) {
console.log(
`The directory ${chalk.green(name)} contains files that could conflict:`
);
console.log();
for (const file of conflicts) {
try {
const stats = fs.lstatSync(path.join(root, file));
if (stats.isDirectory()) {
console.log(` ${chalk.blue(file)}/`);
} else {
console.log(` ${file}`);
}
} catch {
console.log(` ${file}`);
}
}
console.log();
console.log(
"Either try using a new directory name, or remove the files listed above."
);
console.log();
return false;
}
return true;
}

View File

@@ -0,0 +1,10 @@
import fs from "fs";
export async function isWriteable(directory: string): Promise<boolean> {
try {
await fs.promises.access(directory, (fs.constants || fs).W_OK);
return true;
} catch (err) {
return false;
}
}

View File

@@ -0,0 +1,8 @@
import fs from "fs";
export function makeDir(
root: string,
options = { recursive: true }
): Promise<string | undefined> {
return fs.promises.mkdir(root, options);
}

View File

@@ -0,0 +1,20 @@
// eslint-disable-next-line import/no-extraneous-dependencies
import validateProjectName from "validate-npm-package-name";
export function validateNpmName(name: string): {
valid: boolean;
problems?: string[];
} {
const nameValidation = validateProjectName(name);
if (nameValidation.validForNewPackages) {
return { valid: true };
}
return {
valid: false,
problems: [
...(nameValidation.errors || []),
...(nameValidation.warnings || []),
],
};
}

View File

@@ -0,0 +1,204 @@
#!/usr/bin/env node
/* eslint-disable import/no-extraneous-dependencies */
import fs from "fs";
import path from "path";
import chalk from "chalk";
import Commander from "commander";
import Conf from "conf";
import prompts from "prompts";
import checkForUpdate from "update-check";
import { createPlugin } from "./create-plugin";
import { getPkgManager } from "./helpers/get-pkg-manager";
import { isFolderEmpty } from "./helpers/is-folder-empty";
import { validateNpmName } from "./helpers/validate-pkg";
import packageJson from "./package.json";
let projectPath = "";
const handleSigTerm = () => process.exit(0);
process.on("SIGINT", handleSigTerm);
process.on("SIGTERM", handleSigTerm);
const onPromptState = (state: any) => {
if (state.aborted) {
// If we don't re-enable the terminal cursor before exiting
// the program, the cursor will remain hidden
process.stdout.write("\x1B[?25h");
process.stdout.write("\n");
process.exit(1);
}
};
const program = new Commander.Command(packageJson.name)
.version(packageJson.version)
.arguments("<project-directory>")
.usage(`${chalk.green("<project-directory>")} [options]`)
.action((name) => {
projectPath = name;
})
.option(
"--use-npm",
`
Explicitly tell the CLI to bootstrap the application using npm
`
)
.option(
"--use-pnpm",
`
Explicitly tell the CLI to bootstrap the application using pnpm
`
)
.option(
"--use-yarn",
`
Explicitly tell the CLI to bootstrap the application using Yarn
`
)
.allowUnknownOption()
.parse(process.argv);
const packageManager = !!program.useNpm
? "npm"
: !!program.usePnpm
? "pnpm"
: !!program.useYarn
? "yarn"
: getPkgManager();
async function run(): Promise<void> {
const conf = new Conf({ projectName: "create-stablestudio-plugin" });
if (typeof projectPath === "string") {
projectPath = projectPath.trim();
}
if (!projectPath) {
const res = await prompts({
onState: onPromptState,
type: "text",
name: "path",
message: "What is your plugin called?",
initial: "my-plugin",
validate: (name) => {
const validation = validateNpmName(path.basename(path.resolve(name)));
if (validation.valid) {
return true;
}
return "Invalid plugin name: " + validation.problems?.[0];
},
});
if (typeof res.path === "string") {
projectPath = res.path.trim();
}
}
if (!projectPath) {
console.log(
"\nPlease specify the plugin directory:\n" +
` ${chalk.cyan(program.name())} ${chalk.green(
"<project-directory>"
)}\n` +
"For example:\n" +
` ${chalk.cyan(program.name())} ${chalk.green(
"my-stablestudio-plugin"
)}\n\n` +
`Run ${chalk.cyan(`${program.name()} --help`)} to see all options.`
);
process.exit(1);
}
const resolvedProjectPath = path.resolve(projectPath);
const projectName = path.basename(resolvedProjectPath);
const { valid, problems } = validateNpmName(projectName);
if (!valid) {
console.error(
`Could not create a plugin called ${chalk.red(
`"${projectName}"`
)} because of npm naming restrictions:`
);
problems?.forEach((p) => console.error(` ${chalk.red.bold("*")} ${p}`));
process.exit(1);
}
/**
* Verify the project dir is empty or doesn't exist
*/
const root = path.resolve(resolvedProjectPath);
const appName = path.basename(root);
const folderExists = fs.existsSync(root);
if (folderExists && !isFolderEmpty(root, appName)) {
process.exit(1);
}
const preferences = (conf.get("preferences") || {}) as Record<
string,
boolean | string
>;
await createPlugin({
pluginName: projectName,
pluginPath: resolvedProjectPath,
packageManager,
});
conf.set("preferences", preferences);
}
const update = checkForUpdate(packageJson).catch(() => null);
async function notifyUpdate(): Promise<void> {
try {
const res = await update;
if (res?.latest) {
const updateMessage =
packageManager === "yarn"
? "yarn global add create-stablestudio-plugin"
: packageManager === "pnpm"
? "pnpm add -g create-stablestudio-plugin"
: "npm i -g create-stablestudio-plugin";
console.log(
chalk.yellow.bold(
"A new version of `create-stablestudio-plugin` is available!"
) +
"\n" +
"You can update by running: " +
chalk.cyan(updateMessage) +
"\n"
);
}
process.exit();
} catch {
// ignore error
}
}
run()
.then(notifyUpdate)
.catch(async (reason) => {
console.log();
console.log("Aborting installation.");
if (reason.command) {
console.log(` ${chalk.cyan(reason.command)} has failed.`);
} else {
console.log(
chalk.red("Unexpected error. Please report it as a bug:") + "\n",
reason
);
}
console.log();
await notifyUpdate();
process.exit(1);
});

View File

@@ -0,0 +1,53 @@
{
"name": "@stability/create-stablestudio-plugin",
"version": "1.0.3",
"keywords": [
"stablestudio",
"react"
],
"description": "Create a StableStudio plugin",
"repository": {
"type": "git",
"url": "https://github.com/Stability-AI/stablestudio",
"directory": "packages/create-stablestudio-plugin"
},
"author": "Stability AI",
"license": "MIT",
"bin": "./dist/index.js",
"files": [
"dist"
],
"scripts": {
"clean": "rimraf lib && rimraf node_modules",
"release": "ncc build ./index.ts -o ./dist/ --minify --no-cache --no-source-map-register",
"prepublishOnly": "yarn release",
"start": "ts-node index.ts"
},
"devDependencies": {
"@types/async-retry": "1.4.2",
"@types/ci-info": "2.0.0",
"@types/cross-spawn": "6.0.0",
"@types/glob": "7.1.1",
"@types/node": "^16.8.0",
"@types/prompts": "2.0.1",
"@types/tar": "4.0.3",
"@types/validate-npm-package-name": "3.0.0",
"async-retry": "1.3.1",
"chalk": "2.4.2",
"ci-info": "watson/ci-info#f43f6a1cefff47fb361c88cf4b943fdbcaafe540",
"commander": "2.20.0",
"conf": "10.2.0",
"cpy": "7.3.0",
"cross-spawn": "6.0.5",
"glob": "8.0.3",
"got": "10.7.0",
"prompts": "2.1.0",
"tar": "4.4.10",
"ts-node": "10.9.1",
"update-check": "1.5.4",
"validate-npm-package-name": "3.0.0"
},
"engines": {
"node": ">=16.8.0"
}
}

View File

@@ -0,0 +1,29 @@
name: release
on:
push:
branches:
- main
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 16
- name: Install Dependencies
run: yarn install
- name: Build
run: yarn build
- name: Upload Release Asset
uses: svenstaro/upload-release-action@v2
with:
file: ./lib/index.js
asset_name: plugin.js
overwrite: true
release_name: "Release ${{ github.ref }}"

View File

@@ -0,0 +1,26 @@
This is a [StableStudio plugin](https://github.com/Stability-AI/StableStudio) bootstrapped with [`create-stablestudio-plugin`](https://github.com/stability-ai/stablestudio/tree/packages/create-stablestudio-plugin)
## Getting Started
- explain how to get a plugin built
```
yarn build
npm run build
```
- explain basic outline of functions
## Learn more
- link to possible reference docs
## Deploying
- explain pushing to github to make CI build and create artifacts stablestudio can import
> you have to grant "Read and write permissions" in the "workflow permissions" section in repository actions settings for the action to work.
```
git push
```

View File

@@ -1,5 +1,4 @@
{
"name": "@stability/stablestudio-plugin-example",
"version": "0.0.0",
"license": "MIT",
"main": "./lib/index.js",
@@ -9,13 +8,13 @@
],
"scripts": {
"clean": "rimraf lib && rimraf node_modules",
"build:types": "ttsc --project tsconfig.json",
"build:types": "ttsc",
"build:javascript": "tsx scripts/Build.ts",
"build": "yarn build:types && yarn build:javascript",
"dev": "nodemon --watch src --ext ts,tsx,json --exec \"yarn build\""
},
"dependencies": {
"@stability/stablestudio-plugin": "workspace:^"
"@stability/stablestudio-plugin": "^0.0.0"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.33.1",

View File

@@ -0,0 +1,29 @@
{
"include": [
"src/**/*"
],
"exclude": [
"node_modules"
],
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"noUncheckedIndexedAccess": false,
"outDir": "./lib",
"baseUrl": "./",
"paths": {
"~/*": [
"./src/*"
]
},
"plugins": [
{
"transform": "typescript-transform-paths"
},
{
"transform": "typescript-transform-paths",
"afterDeclarations": true
}
]
}
}

View File

@@ -0,0 +1,92 @@
import fs from "fs";
import path from "path";
import chalk from "chalk";
import cpy from "cpy";
import { install } from "../helpers/install";
import { GetTemplateFileArgs, InstallTemplateArgs } from "./types";
/**
* Get the file path for a given file in a template, e.g. "next.config.js".
*/
export const getTemplateFile = ({
template,
file,
}: GetTemplateFileArgs): string => {
return path.join(__dirname, "tenplates", template, file);
};
/**
* Install a Next.js internal template to a given `root` directory.
*/
export const installTemplate = async ({
pluginName,
root,
packageManager,
template,
}: InstallTemplateArgs) => {
console.log(chalk.bold(`Using ${packageManager}.`));
/**
* Copy the template files to the target directory.
*/
console.log("\nInitializing plugin with template:", template, "\n");
const templatePath = path.join(__dirname, "templates", template);
const copySource = ["**"];
await cpy(copySource, root, {
parents: true,
cwd: templatePath,
rename: (name) => {
switch (name) {
case "gitignore":
case "eslintrc.json": {
return ".".concat(name);
}
default: {
return name;
}
}
},
});
/**
* pull out package.json and add the plugin name
*/
const packagejson = JSON.parse(
fs.readFileSync(path.join(root, "packagejson"), "utf8")
);
fs.writeFileSync(
path.join(root, "package.json"),
JSON.stringify(
{
name: pluginName,
...packagejson,
},
null,
2
)
);
fs.unlinkSync(path.join(root, "packagejson"));
/**
* These flags will be passed to `install()`, which calls the package manager
* install process.
*/
const installFlags = { packageManager };
/**
* Install package.json dependencies if they exist.
*/
const pkgPath = path.join(root, "package.json");
if (fs.existsSync(pkgPath)) {
console.log("Installing dependencies...");
await install(root, installFlags);
}
};
export * from "./types";

View File

@@ -0,0 +1,15 @@
import { PackageManager } from "../helpers/get-pkg-manager";
export type TemplateType = "default";
export interface GetTemplateFileArgs {
template: TemplateType;
file: string;
}
export interface InstallTemplateArgs {
pluginName: string;
root: string;
packageManager: PackageManager;
template: TemplateType;
}

View File

@@ -0,0 +1,14 @@
{
"compilerOptions": {
"target": "es2019",
"moduleResolution": "node",
"strict": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"skipLibCheck": false
},
"exclude": [
"templates",
"dist"
]
}

View File

@@ -1,21 +0,0 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*"],
"exclude": ["node_modules"],
"compilerOptions": {
"emitDeclarationOnly": true,
"declaration": true,
"noUncheckedIndexedAccess": false,
"outDir": "./lib",
"baseUrl": "./",
"paths": {
"~/*": ["./src/*"]
},
"plugins": [
{ "transform": "typescript-transform-paths" },
{ "transform": "typescript-transform-paths", "afterDeclarations": true }
]
}
}

View File

@@ -41,7 +41,7 @@ export async function setOptions(baseUrl: string | undefined, options: any) {
}
export async function getImageInfo(
baseUrl: string | null,
baseUrl: string | undefined,
base64image: any
) {
const imageInfoResponse = await fetch(`${baseUrl}/sdapi/v1/png-info`, {

View File

@@ -94,6 +94,7 @@ export const createPlugin = StableStudio.createPlugin<{
| "getStableDiffusionDefaultInput"
| "getStableDiffusionExistingImages"
> => {
webuiHostUrl = webuiHostUrl ?? "http://127.0.0.1:7861";
return {
createStableDiffusionImages: async (options) => {
@@ -243,11 +244,8 @@ export const createPlugin = StableStudio.createPlugin<{
};
};
let webuiHostUrl = localStorage.getItem("webui-host-url");
if (!webuiHostUrl || webuiHostUrl === "") {
webuiHostUrl = "http://127.0.0.1:7861";
}
const webuiHostUrl =
localStorage.getItem("webui-host-url") ?? "http://127.0.0.1:7861";
return {
...webuiLoad(webuiHostUrl),

View File

@@ -1,6 +1,6 @@
{
"name": "@stability/stablestudio-plugin",
"version": "0.0.0",
"version": "0.0.1",
"license": "MIT",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
@@ -12,7 +12,8 @@
"build:types": "ttsc --project tsconfig.json",
"build:javascript": "tsx scripts/Build.ts",
"build": "yarn build:types && yarn build:javascript",
"dev": "nodemon --watch src --ext ts,tsx,json --exec \"yarn build\""
"dev": "nodemon --watch src --ext ts,tsx,json --exec \"yarn build\"",
"prepublish": "yarn build"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.33.1",

View File

@@ -191,11 +191,6 @@ export type Plugin<P extends PluginTypeHelper = PluginTypeHelperDefault> = {
StableDiffusionStyle[] | undefined
>;
/** If you want to provide a list of resolutions in pixels to choose from, you can return them via this function and they will be presented as a slider in the UI */
getStableDiffusionAllowedResolutions?: (
model?: ID
) => MaybePromise<{ width: number; height: number }[] | undefined>;
/** Determines the default count passed to `createStableDiffusionImages` */
getStableDiffusionDefaultCount?: () => number | undefined;

View File

@@ -21,7 +21,6 @@
"@react-hook/resize-observer": "^1.2.6",
"@reecelucas/react-use-hotkeys": "^2.0.0",
"@stability/stablestudio-plugin": "workspace:^",
"@stability/stablestudio-plugin-example": "workspace:^",
"@stability/stablestudio-plugin-stability": "workspace:^",
"@tanstack/react-query": "^4.22.0",
"@tanstack/react-query-devtools": "^4.22.0",

View File

@@ -1,8 +1,5 @@
import * as ReactQuery from "@tanstack/react-query";
import { Generation } from "~/Generation";
import { Size } from "~/Geometry";
import { Plugin } from "~/Plugin";
import { Theme } from "~/Theme";
export type Ratio = Size & { label?: string };
@@ -154,30 +151,8 @@ export namespace Ratios {
{ width: 4, height: 1 },
] as const;
const gcd = (a: number, b: number): number => (b ? gcd(b, a % b) : a);
const simplifyAspectRatio = (width: number, height: number) => {
const divisor = gcd(width, height);
return { width: width / divisor, height: height / divisor } as Ratio;
};
export const usePluginResolutions = (model?: ID) => {
const getStableDiffusionAllowedResolutions = Plugin.use(
({ getStableDiffusionAllowedResolutions }) =>
getStableDiffusionAllowedResolutions
);
return ReactQuery.useQuery({
enabled: !!getStableDiffusionAllowedResolutions,
queryKey: ["Generation.Image.Ratio.PluginResolutions.use"],
queryFn: async () =>
(await getStableDiffusionAllowedResolutions?.(model)) ?? [],
});
};
export const use = (id?: ID, fullControl = false) => {
const { input } = Generation.Image.Input.use(id);
const { data: pluginResolutions } = usePluginResolutions(input?.model);
const bounds = Generation.Image.Size.Bounds.use(id);
const ratios = useMemo(() => {
if (!input?.width || !input?.height || !bounds) return [];
@@ -193,19 +168,9 @@ export namespace Ratios {
};
};
const ratios = pluginResolutions
? pluginResolutions.map(({ width, height }) => ({
...simplifyAspectRatio(width, height),
input: {
width,
height,
},
}))
: (fullControl ? presets : presets.slice(0, -2))
.map(sizing)
.filter(
({ input }) => input.width * input.height <= bounds.area.max
);
const ratios = (fullControl ? presets : presets.slice(0, -2))
.map(sizing)
.filter(({ input }) => input.width * input.height <= bounds.area.max);
const flipped = ratios.map(({ width, height, input }) => ({
width: height,

View File

@@ -1,5 +1,4 @@
import * as StableStudio from "@stability/stablestudio-plugin";
import * as StableStudioPluginExample from "@stability/stablestudio-plugin-example";
import * as StableStudioPluginStability from "@stability/stablestudio-plugin-stability";
import * as StableStudioPluginWebUI from "@stability/stablestudio-plugin-webui";
@@ -113,12 +112,7 @@ namespace State {
};
export const use = GlobalState.create<State>((set) => {
const { createPlugin: createRootPlugin } =
Environment.get("USE_EXAMPLE_PLUGIN") === "true"
? StableStudioPluginExample
: Environment.get("USE_WEBUI_PLUGIN") === "true"
? StableStudioPluginWebUI
: StableStudioPluginStability;
const { createPlugin: createRootPlugin } = StableStudioPluginStability;
return {
rootPlugin: createRootPlugin({

View File

@@ -98,7 +98,7 @@ function Open({
return (
<motion.div
className={classes(
"fixed top-0 left-0 z-[1000] flex h-full w-full bg-black/75 sm:h-screen sm:w-screen sm:items-center sm:justify-center",
"fixed left-0 top-0 z-[1000] flex h-full w-full bg-black/75 sm:h-screen sm:w-screen sm:items-center sm:justify-center",
!open && "pointer-events-none"
)}
variants={outSideVariants}

1871
yarn.lock

File diff suppressed because it is too large Load Diff