Julian Bilcke
commited on
Commit
·
932a7fd
1
Parent(s):
624088c
fixed various issues
Browse files- package-lock.json +73 -76
- package.json +3 -4
- src/app/engine/presets.ts +2 -2
- src/app/engine/render.ts +5 -0
- src/app/interface/panel/index.tsx +42 -22
- src/app/interface/progress/index.tsx +2 -2
- src/app/interface/top-menu/index.tsx +25 -22
- src/app/layouts/index.tsx +160 -0
- src/app/main.tsx +48 -84
- src/app/store/index.ts +57 -0
- src/lib/fonts.ts +2 -0
- src/types.ts +8 -0
package-lock.json
CHANGED
|
@@ -9,7 +9,6 @@
|
|
| 9 |
"version": "0.0.0",
|
| 10 |
"dependencies": {
|
| 11 |
"@huggingface/inference": "^2.6.1",
|
| 12 |
-
"@photo-sphere-viewer/core": "^5.1.7",
|
| 13 |
"@radix-ui/react-accordion": "^1.1.2",
|
| 14 |
"@radix-ui/react-avatar": "^1.0.3",
|
| 15 |
"@radix-ui/react-checkbox": "^1.0.4",
|
|
@@ -45,17 +44,17 @@
|
|
| 45 |
"react": "18.2.0",
|
| 46 |
"react-circular-progressbar": "^2.1.0",
|
| 47 |
"react-dom": "18.2.0",
|
| 48 |
-
"react-virtualized": "^
|
| 49 |
"sbd": "^1.0.19",
|
| 50 |
"styled-components": "^6.0.7",
|
| 51 |
"tailwind-merge": "^1.13.2",
|
| 52 |
"tailwindcss": "3.3.3",
|
| 53 |
"tailwindcss-animate": "^1.0.6",
|
| 54 |
-
"temp-dir": "^3.0.0",
|
| 55 |
"ts-node": "^10.9.1",
|
| 56 |
"typescript": "5.1.6",
|
| 57 |
"usehooks-ts": "^2.9.1",
|
| 58 |
-
"uuid": "^9.0.0"
|
|
|
|
| 59 |
},
|
| 60 |
"devDependencies": {
|
| 61 |
"@types/qs": "^6.9.7",
|
|
@@ -2459,14 +2458,6 @@
|
|
| 2459 |
"node": ">= 8"
|
| 2460 |
}
|
| 2461 |
},
|
| 2462 |
-
"node_modules/@photo-sphere-viewer/core": {
|
| 2463 |
-
"version": "5.3.0",
|
| 2464 |
-
"resolved": "https://registry.npmjs.org/@photo-sphere-viewer/core/-/core-5.3.0.tgz",
|
| 2465 |
-
"integrity": "sha512-gIRJ/ODTVkiYKUoWPg2zThNYbf4RiwJfw0h302lRjaLsmFK20RaXknmHdtQsfNp5DU2J/tBZ5NOnXfMNr3GmlQ==",
|
| 2466 |
-
"dependencies": {
|
| 2467 |
-
"three": "^0.155.0"
|
| 2468 |
-
}
|
| 2469 |
-
},
|
| 2470 |
"node_modules/@radix-ui/number": {
|
| 2471 |
"version": "1.0.1",
|
| 2472 |
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz",
|
|
@@ -4282,9 +4273,9 @@
|
|
| 4282 |
}
|
| 4283 |
},
|
| 4284 |
"node_modules/caniuse-lite": {
|
| 4285 |
-
"version": "1.0.
|
| 4286 |
-
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.
|
| 4287 |
-
"integrity": "sha512-
|
| 4288 |
"funding": [
|
| 4289 |
{
|
| 4290 |
"type": "opencollective",
|
|
@@ -4908,15 +4899,6 @@
|
|
| 4908 |
"node": ">=6.0.0"
|
| 4909 |
}
|
| 4910 |
},
|
| 4911 |
-
"node_modules/dom-helpers": {
|
| 4912 |
-
"version": "5.2.1",
|
| 4913 |
-
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
|
| 4914 |
-
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
|
| 4915 |
-
"dependencies": {
|
| 4916 |
-
"@babel/runtime": "^7.8.7",
|
| 4917 |
-
"csstype": "^3.0.2"
|
| 4918 |
-
}
|
| 4919 |
-
},
|
| 4920 |
"node_modules/dom-serializer": {
|
| 4921 |
"version": "2.0.0",
|
| 4922 |
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
|
@@ -4969,9 +4951,9 @@
|
|
| 4969 |
}
|
| 4970 |
},
|
| 4971 |
"node_modules/electron-to-chromium": {
|
| 4972 |
-
"version": "1.4.
|
| 4973 |
-
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.
|
| 4974 |
-
"integrity": "sha512-
|
| 4975 |
},
|
| 4976 |
"node_modules/emoji-regex": {
|
| 4977 |
"version": "10.2.1",
|
|
@@ -5054,14 +5036,14 @@
|
|
| 5054 |
}
|
| 5055 |
},
|
| 5056 |
"node_modules/es-iterator-helpers": {
|
| 5057 |
-
"version": "1.0.
|
| 5058 |
-
"resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.
|
| 5059 |
-
"integrity": "sha512-
|
| 5060 |
"dependencies": {
|
| 5061 |
"asynciterator.prototype": "^1.0.0",
|
| 5062 |
"call-bind": "^1.0.2",
|
| 5063 |
"define-properties": "^1.2.0",
|
| 5064 |
-
"es-abstract": "^1.
|
| 5065 |
"es-set-tostringtag": "^2.0.1",
|
| 5066 |
"function-bind": "^1.1.1",
|
| 5067 |
"get-intrinsic": "^1.2.1",
|
|
@@ -5623,15 +5605,16 @@
|
|
| 5623 |
}
|
| 5624 |
},
|
| 5625 |
"node_modules/flat-cache": {
|
| 5626 |
-
"version": "3.0
|
| 5627 |
-
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.
|
| 5628 |
-
"integrity": "sha512-
|
| 5629 |
"dependencies": {
|
| 5630 |
-
"flatted": "^3.
|
|
|
|
| 5631 |
"rimraf": "^3.0.2"
|
| 5632 |
},
|
| 5633 |
"engines": {
|
| 5634 |
-
"node": "
|
| 5635 |
}
|
| 5636 |
},
|
| 5637 |
"node_modules/flatted": {
|
|
@@ -6438,6 +6421,11 @@
|
|
| 6438 |
"node": ">=4"
|
| 6439 |
}
|
| 6440 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6441 |
"node_modules/json-schema-traverse": {
|
| 6442 |
"version": "0.4.1",
|
| 6443 |
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
|
@@ -6473,6 +6461,14 @@
|
|
| 6473 |
"node": ">=4.0"
|
| 6474 |
}
|
| 6475 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6476 |
"node_modules/language-subtag-registry": {
|
| 6477 |
"version": "0.3.22",
|
| 6478 |
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
|
|
@@ -7302,11 +7298,6 @@
|
|
| 7302 |
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
| 7303 |
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
| 7304 |
},
|
| 7305 |
-
"node_modules/react-lifecycles-compat": {
|
| 7306 |
-
"version": "3.0.4",
|
| 7307 |
-
"resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
|
| 7308 |
-
"integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
|
| 7309 |
-
},
|
| 7310 |
"node_modules/react-remove-scroll": {
|
| 7311 |
"version": "2.5.5",
|
| 7312 |
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz",
|
|
@@ -7374,29 +7365,13 @@
|
|
| 7374 |
}
|
| 7375 |
}
|
| 7376 |
},
|
| 7377 |
-
"node_modules/react-virtualized": {
|
| 7378 |
-
"version": "
|
| 7379 |
-
"resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-
|
| 7380 |
-
"integrity": "sha512-
|
| 7381 |
-
"dependencies": {
|
| 7382 |
-
"@babel/runtime": "^7.7.2",
|
| 7383 |
-
"clsx": "^1.0.4",
|
| 7384 |
-
"dom-helpers": "^5.1.3",
|
| 7385 |
-
"loose-envify": "^1.4.0",
|
| 7386 |
-
"prop-types": "^15.7.2",
|
| 7387 |
-
"react-lifecycles-compat": "^3.0.4"
|
| 7388 |
-
},
|
| 7389 |
"peerDependencies": {
|
| 7390 |
-
"react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0",
|
| 7391 |
-
"react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0"
|
| 7392 |
-
}
|
| 7393 |
-
},
|
| 7394 |
-
"node_modules/react-virtualized/node_modules/clsx": {
|
| 7395 |
-
"version": "1.2.1",
|
| 7396 |
-
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
| 7397 |
-
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
| 7398 |
-
"engines": {
|
| 7399 |
-
"node": ">=6"
|
| 7400 |
}
|
| 7401 |
},
|
| 7402 |
"node_modules/read-cache": {
|
|
@@ -8065,14 +8040,6 @@
|
|
| 8065 |
"node": ">=6"
|
| 8066 |
}
|
| 8067 |
},
|
| 8068 |
-
"node_modules/temp-dir": {
|
| 8069 |
-
"version": "3.0.0",
|
| 8070 |
-
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz",
|
| 8071 |
-
"integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==",
|
| 8072 |
-
"engines": {
|
| 8073 |
-
"node": ">=14.16"
|
| 8074 |
-
}
|
| 8075 |
-
},
|
| 8076 |
"node_modules/text-table": {
|
| 8077 |
"version": "0.2.0",
|
| 8078 |
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
|
@@ -8097,11 +8064,6 @@
|
|
| 8097 |
"node": ">=0.8"
|
| 8098 |
}
|
| 8099 |
},
|
| 8100 |
-
"node_modules/three": {
|
| 8101 |
-
"version": "0.155.0",
|
| 8102 |
-
"resolved": "https://registry.npmjs.org/three/-/three-0.155.0.tgz",
|
| 8103 |
-
"integrity": "sha512-sNgCYmDijnIqkD/bMfk+1pHg3YzsxW7V2ChpuP6HCQ8NiZr3RufsXQr8M3SSUMjW4hG+sUk7YbyuY0DncaDTJQ=="
|
| 8104 |
-
},
|
| 8105 |
"node_modules/tiny-inflate": {
|
| 8106 |
"version": "1.0.3",
|
| 8107 |
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
|
|
@@ -8475,6 +8437,14 @@
|
|
| 8475 |
}
|
| 8476 |
}
|
| 8477 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8478 |
"node_modules/usehooks-ts": {
|
| 8479 |
"version": "2.9.1",
|
| 8480 |
"resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.9.1.tgz",
|
|
@@ -8675,6 +8645,33 @@
|
|
| 8675 |
"funding": {
|
| 8676 |
"url": "https://github.com/sponsors/colinhacks"
|
| 8677 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8678 |
}
|
| 8679 |
}
|
| 8680 |
}
|
|
|
|
| 9 |
"version": "0.0.0",
|
| 10 |
"dependencies": {
|
| 11 |
"@huggingface/inference": "^2.6.1",
|
|
|
|
| 12 |
"@radix-ui/react-accordion": "^1.1.2",
|
| 13 |
"@radix-ui/react-avatar": "^1.0.3",
|
| 14 |
"@radix-ui/react-checkbox": "^1.0.4",
|
|
|
|
| 44 |
"react": "18.2.0",
|
| 45 |
"react-circular-progressbar": "^2.1.0",
|
| 46 |
"react-dom": "18.2.0",
|
| 47 |
+
"react-virtualized-auto-sizer": "^1.0.20",
|
| 48 |
"sbd": "^1.0.19",
|
| 49 |
"styled-components": "^6.0.7",
|
| 50 |
"tailwind-merge": "^1.13.2",
|
| 51 |
"tailwindcss": "3.3.3",
|
| 52 |
"tailwindcss-animate": "^1.0.6",
|
|
|
|
| 53 |
"ts-node": "^10.9.1",
|
| 54 |
"typescript": "5.1.6",
|
| 55 |
"usehooks-ts": "^2.9.1",
|
| 56 |
+
"uuid": "^9.0.0",
|
| 57 |
+
"zustand": "^4.4.1"
|
| 58 |
},
|
| 59 |
"devDependencies": {
|
| 60 |
"@types/qs": "^6.9.7",
|
|
|
|
| 2458 |
"node": ">= 8"
|
| 2459 |
}
|
| 2460 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2461 |
"node_modules/@radix-ui/number": {
|
| 2462 |
"version": "1.0.1",
|
| 2463 |
"resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.0.1.tgz",
|
|
|
|
| 4273 |
}
|
| 4274 |
},
|
| 4275 |
"node_modules/caniuse-lite": {
|
| 4276 |
+
"version": "1.0.30001524",
|
| 4277 |
+
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001524.tgz",
|
| 4278 |
+
"integrity": "sha512-Jj917pJtYg9HSJBF95HVX3Cdr89JUyLT4IZ8SvM5aDRni95swKgYi3TgYLH5hnGfPE/U1dg6IfZ50UsIlLkwSA==",
|
| 4279 |
"funding": [
|
| 4280 |
{
|
| 4281 |
"type": "opencollective",
|
|
|
|
| 4899 |
"node": ">=6.0.0"
|
| 4900 |
}
|
| 4901 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4902 |
"node_modules/dom-serializer": {
|
| 4903 |
"version": "2.0.0",
|
| 4904 |
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
|
|
|
|
| 4951 |
}
|
| 4952 |
},
|
| 4953 |
"node_modules/electron-to-chromium": {
|
| 4954 |
+
"version": "1.4.503",
|
| 4955 |
+
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.503.tgz",
|
| 4956 |
+
"integrity": "sha512-LF2IQit4B0VrUHFeQkWhZm97KuJSGF2WJqq1InpY+ECpFRkXd8yTIaTtJxsO0OKDmiBYwWqcrNaXOurn2T2wiA=="
|
| 4957 |
},
|
| 4958 |
"node_modules/emoji-regex": {
|
| 4959 |
"version": "10.2.1",
|
|
|
|
| 5036 |
}
|
| 5037 |
},
|
| 5038 |
"node_modules/es-iterator-helpers": {
|
| 5039 |
+
"version": "1.0.14",
|
| 5040 |
+
"resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.14.tgz",
|
| 5041 |
+
"integrity": "sha512-JgtVnwiuoRuzLvqelrvN3Xu7H9bu2ap/kQ2CrM62iidP8SKuD99rWU3CJy++s7IVL2qb/AjXPGR/E7i9ngd/Cw==",
|
| 5042 |
"dependencies": {
|
| 5043 |
"asynciterator.prototype": "^1.0.0",
|
| 5044 |
"call-bind": "^1.0.2",
|
| 5045 |
"define-properties": "^1.2.0",
|
| 5046 |
+
"es-abstract": "^1.22.1",
|
| 5047 |
"es-set-tostringtag": "^2.0.1",
|
| 5048 |
"function-bind": "^1.1.1",
|
| 5049 |
"get-intrinsic": "^1.2.1",
|
|
|
|
| 5605 |
}
|
| 5606 |
},
|
| 5607 |
"node_modules/flat-cache": {
|
| 5608 |
+
"version": "3.1.0",
|
| 5609 |
+
"resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz",
|
| 5610 |
+
"integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==",
|
| 5611 |
"dependencies": {
|
| 5612 |
+
"flatted": "^3.2.7",
|
| 5613 |
+
"keyv": "^4.5.3",
|
| 5614 |
"rimraf": "^3.0.2"
|
| 5615 |
},
|
| 5616 |
"engines": {
|
| 5617 |
+
"node": ">=12.0.0"
|
| 5618 |
}
|
| 5619 |
},
|
| 5620 |
"node_modules/flatted": {
|
|
|
|
| 6421 |
"node": ">=4"
|
| 6422 |
}
|
| 6423 |
},
|
| 6424 |
+
"node_modules/json-buffer": {
|
| 6425 |
+
"version": "3.0.1",
|
| 6426 |
+
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
|
| 6427 |
+
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="
|
| 6428 |
+
},
|
| 6429 |
"node_modules/json-schema-traverse": {
|
| 6430 |
"version": "0.4.1",
|
| 6431 |
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
|
|
|
| 6461 |
"node": ">=4.0"
|
| 6462 |
}
|
| 6463 |
},
|
| 6464 |
+
"node_modules/keyv": {
|
| 6465 |
+
"version": "4.5.3",
|
| 6466 |
+
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz",
|
| 6467 |
+
"integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==",
|
| 6468 |
+
"dependencies": {
|
| 6469 |
+
"json-buffer": "3.0.1"
|
| 6470 |
+
}
|
| 6471 |
+
},
|
| 6472 |
"node_modules/language-subtag-registry": {
|
| 6473 |
"version": "0.3.22",
|
| 6474 |
"resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz",
|
|
|
|
| 7298 |
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
| 7299 |
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
|
| 7300 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7301 |
"node_modules/react-remove-scroll": {
|
| 7302 |
"version": "2.5.5",
|
| 7303 |
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz",
|
|
|
|
| 7365 |
}
|
| 7366 |
}
|
| 7367 |
},
|
| 7368 |
+
"node_modules/react-virtualized-auto-sizer": {
|
| 7369 |
+
"version": "1.0.20",
|
| 7370 |
+
"resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.20.tgz",
|
| 7371 |
+
"integrity": "sha512-OdIyHwj4S4wyhbKHOKM1wLSj/UDXm839Z3Cvfg2a9j+He6yDa6i5p0qQvEiCnyQlGO/HyfSnigQwuxvYalaAXA==",
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7372 |
"peerDependencies": {
|
| 7373 |
+
"react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc",
|
| 7374 |
+
"react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0-rc"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7375 |
}
|
| 7376 |
},
|
| 7377 |
"node_modules/read-cache": {
|
|
|
|
| 8040 |
"node": ">=6"
|
| 8041 |
}
|
| 8042 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8043 |
"node_modules/text-table": {
|
| 8044 |
"version": "0.2.0",
|
| 8045 |
"resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
|
|
|
|
| 8064 |
"node": ">=0.8"
|
| 8065 |
}
|
| 8066 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8067 |
"node_modules/tiny-inflate": {
|
| 8068 |
"version": "1.0.3",
|
| 8069 |
"resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
|
|
|
|
| 8437 |
}
|
| 8438 |
}
|
| 8439 |
},
|
| 8440 |
+
"node_modules/use-sync-external-store": {
|
| 8441 |
+
"version": "1.2.0",
|
| 8442 |
+
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
| 8443 |
+
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
| 8444 |
+
"peerDependencies": {
|
| 8445 |
+
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
| 8446 |
+
}
|
| 8447 |
+
},
|
| 8448 |
"node_modules/usehooks-ts": {
|
| 8449 |
"version": "2.9.1",
|
| 8450 |
"resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-2.9.1.tgz",
|
|
|
|
| 8645 |
"funding": {
|
| 8646 |
"url": "https://github.com/sponsors/colinhacks"
|
| 8647 |
}
|
| 8648 |
+
},
|
| 8649 |
+
"node_modules/zustand": {
|
| 8650 |
+
"version": "4.4.1",
|
| 8651 |
+
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.4.1.tgz",
|
| 8652 |
+
"integrity": "sha512-QCPfstAS4EBiTQzlaGP1gmorkh/UL1Leaj2tdj+zZCZ/9bm0WS7sI2wnfD5lpOszFqWJ1DcPnGoY8RDL61uokw==",
|
| 8653 |
+
"dependencies": {
|
| 8654 |
+
"use-sync-external-store": "1.2.0"
|
| 8655 |
+
},
|
| 8656 |
+
"engines": {
|
| 8657 |
+
"node": ">=12.7.0"
|
| 8658 |
+
},
|
| 8659 |
+
"peerDependencies": {
|
| 8660 |
+
"@types/react": ">=16.8",
|
| 8661 |
+
"immer": ">=9.0",
|
| 8662 |
+
"react": ">=16.8"
|
| 8663 |
+
},
|
| 8664 |
+
"peerDependenciesMeta": {
|
| 8665 |
+
"@types/react": {
|
| 8666 |
+
"optional": true
|
| 8667 |
+
},
|
| 8668 |
+
"immer": {
|
| 8669 |
+
"optional": true
|
| 8670 |
+
},
|
| 8671 |
+
"react": {
|
| 8672 |
+
"optional": true
|
| 8673 |
+
}
|
| 8674 |
+
}
|
| 8675 |
}
|
| 8676 |
}
|
| 8677 |
}
|
package.json
CHANGED
|
@@ -10,7 +10,6 @@
|
|
| 10 |
},
|
| 11 |
"dependencies": {
|
| 12 |
"@huggingface/inference": "^2.6.1",
|
| 13 |
-
"@photo-sphere-viewer/core": "^5.1.7",
|
| 14 |
"@radix-ui/react-accordion": "^1.1.2",
|
| 15 |
"@radix-ui/react-avatar": "^1.0.3",
|
| 16 |
"@radix-ui/react-checkbox": "^1.0.4",
|
|
@@ -46,17 +45,17 @@
|
|
| 46 |
"react": "18.2.0",
|
| 47 |
"react-circular-progressbar": "^2.1.0",
|
| 48 |
"react-dom": "18.2.0",
|
| 49 |
-
"react-virtualized": "^
|
| 50 |
"sbd": "^1.0.19",
|
| 51 |
"styled-components": "^6.0.7",
|
| 52 |
"tailwind-merge": "^1.13.2",
|
| 53 |
"tailwindcss": "3.3.3",
|
| 54 |
"tailwindcss-animate": "^1.0.6",
|
| 55 |
-
"temp-dir": "^3.0.0",
|
| 56 |
"ts-node": "^10.9.1",
|
| 57 |
"typescript": "5.1.6",
|
| 58 |
"usehooks-ts": "^2.9.1",
|
| 59 |
-
"uuid": "^9.0.0"
|
|
|
|
| 60 |
},
|
| 61 |
"devDependencies": {
|
| 62 |
"@types/qs": "^6.9.7",
|
|
|
|
| 10 |
},
|
| 11 |
"dependencies": {
|
| 12 |
"@huggingface/inference": "^2.6.1",
|
|
|
|
| 13 |
"@radix-ui/react-accordion": "^1.1.2",
|
| 14 |
"@radix-ui/react-avatar": "^1.0.3",
|
| 15 |
"@radix-ui/react-checkbox": "^1.0.4",
|
|
|
|
| 45 |
"react": "18.2.0",
|
| 46 |
"react-circular-progressbar": "^2.1.0",
|
| 47 |
"react-dom": "18.2.0",
|
| 48 |
+
"react-virtualized-auto-sizer": "^1.0.20",
|
| 49 |
"sbd": "^1.0.19",
|
| 50 |
"styled-components": "^6.0.7",
|
| 51 |
"tailwind-merge": "^1.13.2",
|
| 52 |
"tailwindcss": "3.3.3",
|
| 53 |
"tailwindcss-animate": "^1.0.6",
|
|
|
|
| 54 |
"ts-node": "^10.9.1",
|
| 55 |
"typescript": "5.1.6",
|
| 56 |
"usehooks-ts": "^2.9.1",
|
| 57 |
+
"uuid": "^9.0.0",
|
| 58 |
+
"zustand": "^4.4.1"
|
| 59 |
},
|
| 60 |
"devDependencies": {
|
| 61 |
"@types/qs": "^6.9.7",
|
src/app/engine/presets.ts
CHANGED
|
@@ -100,8 +100,8 @@ export const presets: Record<string, Preset> = {
|
|
| 100 |
"3D render"
|
| 101 |
],
|
| 102 |
},
|
| 103 |
-
|
| 104 |
-
label: "
|
| 105 |
family: "european",
|
| 106 |
color: "monochrome",
|
| 107 |
font: "paeteround",
|
|
|
|
| 100 |
"3D render"
|
| 101 |
],
|
| 102 |
},
|
| 103 |
+
armorican: {
|
| 104 |
+
label: "Armorican",
|
| 105 |
family: "european",
|
| 106 |
color: "monochrome",
|
| 107 |
font: "paeteround",
|
src/app/engine/render.ts
CHANGED
|
@@ -54,6 +54,11 @@ export async function newRender({
|
|
| 54 |
segmentation: "disabled", // one day we will remove this param, to make it automatic
|
| 55 |
width,
|
| 56 |
height,
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 57 |
cache: "ignore"
|
| 58 |
} as Partial<RenderRequest>),
|
| 59 |
cache: 'no-store',
|
|
|
|
| 54 |
segmentation: "disabled", // one day we will remove this param, to make it automatic
|
| 55 |
width,
|
| 56 |
height,
|
| 57 |
+
|
| 58 |
+
// no need to upscale right now as we generate tiny panels
|
| 59 |
+
// maybe later we can provide an "export" button to PDF
|
| 60 |
+
upscalingFactor: 1,
|
| 61 |
+
|
| 62 |
cache: "ignore"
|
| 63 |
} as Partial<RenderRequest>),
|
| 64 |
cache: 'no-store',
|
src/app/interface/panel/index.tsx
CHANGED
|
@@ -1,36 +1,40 @@
|
|
| 1 |
"use client"
|
| 2 |
|
| 3 |
import { useEffect, useRef, useState, useTransition } from "react"
|
| 4 |
-
|
| 5 |
-
import { Preset } from "@/app/engine/presets"
|
| 6 |
|
| 7 |
import { RenderedScene } from "@/types"
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
import { cn } from "@/lib/utils"
|
| 9 |
-
import { FontName } from "@/lib/fonts"
|
| 10 |
-
import { getRender, newRender } from "../../engine/render"
|
| 11 |
import { getInitialRenderedScene } from "@/lib/getInitialRenderedScene"
|
|
|
|
| 12 |
// import { Bubble } from "./bubble"
|
| 13 |
|
| 14 |
-
export
|
| 15 |
-
|
| 16 |
-
font,
|
| 17 |
-
preset,
|
| 18 |
className = "",
|
| 19 |
width = 1,
|
| 20 |
height = 1,
|
| 21 |
delay = 0,
|
| 22 |
}: {
|
| 23 |
-
|
| 24 |
-
font: FontName
|
| 25 |
-
preset: Preset
|
| 26 |
className?: string
|
| 27 |
width?: number
|
| 28 |
height?: number
|
| 29 |
delay?: number
|
| 30 |
}) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 31 |
|
| 32 |
const [_isPending, startTransition] = useTransition()
|
| 33 |
-
const [isLoading, setLoading] = useState<boolean>(false)
|
| 34 |
const [rendered, setRendered] = useState<RenderedScene>(getInitialRenderedScene())
|
| 35 |
const renderedRef = useRef<RenderedScene>()
|
| 36 |
|
|
@@ -42,15 +46,20 @@ export default function Panel({
|
|
| 42 |
startTransition(async () => {
|
| 43 |
// console.log("Panel prompt: "+ prompt)
|
| 44 |
if (!prompt?.length) { return }
|
|
|
|
| 45 |
|
| 46 |
console.log("Loading panel..")
|
| 47 |
-
setLoading(true)
|
| 48 |
|
| 49 |
// console.log("calling:\nconst newRendered = await newRender({ prompt, preset, width, height })")
|
| 50 |
console.log({
|
| 51 |
-
|
| 52 |
})
|
| 53 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 54 |
const newRendered = await newRender({ prompt, width, height })
|
| 55 |
|
| 56 |
if (newRendered) {
|
|
@@ -67,12 +76,11 @@ export default function Panel({
|
|
| 67 |
error: "failed to fetch the data",
|
| 68 |
segments: []
|
| 69 |
})
|
| 70 |
-
|
| 71 |
-
setLoading(false)
|
| 72 |
return
|
| 73 |
}
|
| 74 |
})
|
| 75 |
-
}, [prompt, font,
|
| 76 |
|
| 77 |
|
| 78 |
const checkStatus = () => {
|
|
@@ -84,6 +92,7 @@ export default function Panel({
|
|
| 84 |
return
|
| 85 |
}
|
| 86 |
try {
|
|
|
|
| 87 |
// console.log(`Checking job status API for job ${renderedRef.current?.renderId}`)
|
| 88 |
const newRendered = await getRender(renderedRef.current.renderId)
|
| 89 |
// console.log("got a response!", newRendered)
|
|
@@ -91,7 +100,7 @@ export default function Panel({
|
|
| 91 |
if (JSON.stringify(renderedRef.current) !== JSON.stringify(newRendered)) {
|
| 92 |
console.log("updated panel:", newRendered)
|
| 93 |
setRendered(renderedRef.current = newRendered)
|
| 94 |
-
|
| 95 |
}
|
| 96 |
// console.log("status:", newRendered.status)
|
| 97 |
|
|
@@ -100,7 +109,7 @@ export default function Panel({
|
|
| 100 |
timeoutRef.current = setTimeout(checkStatus, 1000)
|
| 101 |
} else {
|
| 102 |
console.log("panel finished!")
|
| 103 |
-
|
| 104 |
}
|
| 105 |
} catch (err) {
|
| 106 |
console.error(err)
|
|
@@ -119,16 +128,27 @@ export default function Panel({
|
|
| 119 |
}
|
| 120 |
}, [])
|
| 121 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
return (
|
| 123 |
<div className={cn(
|
| 124 |
`w-full h-full`,
|
| 125 |
-
preset.color === "grayscale"
|
| 126 |
className
|
| 127 |
)}>
|
| 128 |
-
{rendered.assetUrl
|
| 129 |
src={rendered.assetUrl}
|
| 130 |
className="w-full h-full object-cover"
|
| 131 |
-
/>
|
| 132 |
|
| 133 |
{/*<Bubble className="absolute top-4 left-4">
|
| 134 |
Hello, world!
|
|
|
|
| 1 |
"use client"
|
| 2 |
|
| 3 |
import { useEffect, useRef, useState, useTransition } from "react"
|
| 4 |
+
// import AutoSizer from "react-virtualized-auto-sizer"
|
|
|
|
| 5 |
|
| 6 |
import { RenderedScene } from "@/types"
|
| 7 |
+
|
| 8 |
+
import { getRender, newRender } from "@/app/engine/render"
|
| 9 |
+
import { useStore } from "@/app/store"
|
| 10 |
+
|
| 11 |
import { cn } from "@/lib/utils"
|
|
|
|
|
|
|
| 12 |
import { getInitialRenderedScene } from "@/lib/getInitialRenderedScene"
|
| 13 |
+
import { Progress } from "@/app/interface/progress"
|
| 14 |
// import { Bubble } from "./bubble"
|
| 15 |
|
| 16 |
+
export function Panel({
|
| 17 |
+
panel,
|
|
|
|
|
|
|
| 18 |
className = "",
|
| 19 |
width = 1,
|
| 20 |
height = 1,
|
| 21 |
delay = 0,
|
| 22 |
}: {
|
| 23 |
+
panel: number
|
|
|
|
|
|
|
| 24 |
className?: string
|
| 25 |
width?: number
|
| 26 |
height?: number
|
| 27 |
delay?: number
|
| 28 |
}) {
|
| 29 |
+
const font = useStore(state => state.font)
|
| 30 |
+
const preset = useStore(state => state.preset)
|
| 31 |
+
const setGeneratingImages = useStore(state => state.setGeneratingImages)
|
| 32 |
+
const panelGenerationStatus = useStore(state => state.panelGenerationStatus)
|
| 33 |
+
const isLoading = panelGenerationStatus[panel] || false
|
| 34 |
+
const panels = useStore(state => state.panels)
|
| 35 |
+
const prompt = panels[panel] || ""
|
| 36 |
|
| 37 |
const [_isPending, startTransition] = useTransition()
|
|
|
|
| 38 |
const [rendered, setRendered] = useState<RenderedScene>(getInitialRenderedScene())
|
| 39 |
const renderedRef = useRef<RenderedScene>()
|
| 40 |
|
|
|
|
| 46 |
startTransition(async () => {
|
| 47 |
// console.log("Panel prompt: "+ prompt)
|
| 48 |
if (!prompt?.length) { return }
|
| 49 |
+
if (isLoading) { return }
|
| 50 |
|
| 51 |
console.log("Loading panel..")
|
|
|
|
| 52 |
|
| 53 |
// console.log("calling:\nconst newRendered = await newRender({ prompt, preset, width, height })")
|
| 54 |
console.log({
|
| 55 |
+
panel, prompt, width, height
|
| 56 |
})
|
| 57 |
|
| 58 |
+
console.log("")
|
| 59 |
+
// important: update the status, and clear the scene
|
| 60 |
+
setGeneratingImages(panel, true)
|
| 61 |
+
setRendered(getInitialRenderedScene())
|
| 62 |
+
|
| 63 |
const newRendered = await newRender({ prompt, width, height })
|
| 64 |
|
| 65 |
if (newRendered) {
|
|
|
|
| 76 |
error: "failed to fetch the data",
|
| 77 |
segments: []
|
| 78 |
})
|
| 79 |
+
setGeneratingImages(panel, false)
|
|
|
|
| 80 |
return
|
| 81 |
}
|
| 82 |
})
|
| 83 |
+
}, [prompt, font, width, height])
|
| 84 |
|
| 85 |
|
| 86 |
const checkStatus = () => {
|
|
|
|
| 92 |
return
|
| 93 |
}
|
| 94 |
try {
|
| 95 |
+
setGeneratingImages(panel, true)
|
| 96 |
// console.log(`Checking job status API for job ${renderedRef.current?.renderId}`)
|
| 97 |
const newRendered = await getRender(renderedRef.current.renderId)
|
| 98 |
// console.log("got a response!", newRendered)
|
|
|
|
| 100 |
if (JSON.stringify(renderedRef.current) !== JSON.stringify(newRendered)) {
|
| 101 |
console.log("updated panel:", newRendered)
|
| 102 |
setRendered(renderedRef.current = newRendered)
|
| 103 |
+
setGeneratingImages(panel, true)
|
| 104 |
}
|
| 105 |
// console.log("status:", newRendered.status)
|
| 106 |
|
|
|
|
| 109 |
timeoutRef.current = setTimeout(checkStatus, 1000)
|
| 110 |
} else {
|
| 111 |
console.log("panel finished!")
|
| 112 |
+
setGeneratingImages(panel, false)
|
| 113 |
}
|
| 114 |
} catch (err) {
|
| 115 |
console.error(err)
|
|
|
|
| 128 |
}
|
| 129 |
}, [])
|
| 130 |
|
| 131 |
+
if (isLoading) {
|
| 132 |
+
return (
|
| 133 |
+
<div className={cn(
|
| 134 |
+
`w-full h-full flex flex-col items-center justify-center`,
|
| 135 |
+
className
|
| 136 |
+
)}>
|
| 137 |
+
<Progress isLoading />
|
| 138 |
+
</div>
|
| 139 |
+
)
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
return (
|
| 143 |
<div className={cn(
|
| 144 |
`w-full h-full`,
|
| 145 |
+
{ "grayscale": preset.color === "grayscale" },
|
| 146 |
className
|
| 147 |
)}>
|
| 148 |
+
{rendered.assetUrl && <img
|
| 149 |
src={rendered.assetUrl}
|
| 150 |
className="w-full h-full object-cover"
|
| 151 |
+
/>}
|
| 152 |
|
| 153 |
{/*<Bubble className="absolute top-4 left-4">
|
| 154 |
Hello, world!
|
src/app/interface/progress/index.tsx
CHANGED
|
@@ -9,7 +9,7 @@ export function Progress({
|
|
| 9 |
className = "",
|
| 10 |
}: {
|
| 11 |
isLoading: boolean
|
| 12 |
-
resetKey
|
| 13 |
className?: string
|
| 14 |
}) {
|
| 15 |
const timeoutRef = useRef<any>()
|
|
@@ -43,7 +43,7 @@ export function Progress({
|
|
| 43 |
|
| 44 |
return (
|
| 45 |
<div className={cn(
|
| 46 |
-
`
|
| 47 |
`animation-all duration-300 text-md`,
|
| 48 |
isLoading
|
| 49 |
? `scale-100 opacity-100`
|
|
|
|
| 9 |
className = "",
|
| 10 |
}: {
|
| 11 |
isLoading: boolean
|
| 12 |
+
resetKey?: string
|
| 13 |
className?: string
|
| 14 |
}) {
|
| 15 |
const timeoutRef = useRef<any>()
|
|
|
|
| 43 |
|
| 44 |
return (
|
| 45 |
<div className={cn(
|
| 46 |
+
`flex w-10 h-10`,
|
| 47 |
`animation-all duration-300 text-md`,
|
| 48 |
isLoading
|
| 49 |
? `scale-100 opacity-100`
|
src/app/interface/top-menu/index.tsx
CHANGED
|
@@ -11,26 +11,22 @@ import { Label } from "@/components/ui/label"
|
|
| 11 |
import { cn } from "@/lib/utils"
|
| 12 |
import { FontName, fontList, fonts } from "@/lib/fonts"
|
| 13 |
import { Input } from "@/components/ui/input"
|
| 14 |
-
import {
|
| 15 |
import { useState } from "react"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
-
export function TopMenu({
|
| 18 |
-
defaultPreset,
|
| 19 |
-
preset,
|
| 20 |
-
onChangePreset,
|
| 21 |
-
font,
|
| 22 |
-
onChangeFont,
|
| 23 |
-
prompt,
|
| 24 |
-
onChangePrompt,
|
| 25 |
-
}: {
|
| 26 |
-
defaultPreset: PresetName
|
| 27 |
-
preset: Preset
|
| 28 |
-
onChangePreset: (newPresetName: PresetName) => void
|
| 29 |
-
font: FontName
|
| 30 |
-
onChangeFont: (newFontName: FontName) => void
|
| 31 |
-
prompt: string
|
| 32 |
-
onChangePrompt: (newPrompt: string) => void
|
| 33 |
-
}) {
|
| 34 |
const [draft, setDraft] = useState("")
|
| 35 |
return (
|
| 36 |
<div className={cn(
|
|
@@ -45,7 +41,9 @@ export function TopMenu({
|
|
| 45 |
<Label className="flex text-sm">Select a preset:</Label>
|
| 46 |
<Select
|
| 47 |
defaultValue={defaultPreset}
|
| 48 |
-
onValueChange={(value) => {
|
|
|
|
|
|
|
| 49 |
<SelectTrigger className="w-[180px]">
|
| 50 |
<SelectValue className="text-sm" placeholder="Type" />
|
| 51 |
</SelectTrigger>
|
|
@@ -60,18 +58,21 @@ export function TopMenu({
|
|
| 60 |
<Input
|
| 61 |
placeholder="Story"
|
| 62 |
className="w-full bg-neutral-300 text-neutral-800 dark:bg-neutral-300 dark:text-neutral-800"
|
|
|
|
| 63 |
onChange={(e) => {
|
| 64 |
setDraft(e.target.value)
|
| 65 |
}}
|
| 66 |
onBlur={(e) => {
|
| 67 |
if (draft !== prompt) {
|
| 68 |
-
|
|
|
|
|
|
|
| 69 |
}
|
| 70 |
}}
|
| 71 |
onKeyDown={({ key }) => {
|
| 72 |
if (key === 'Enter') {
|
| 73 |
if (draft.trim() !== prompt.trim()) {
|
| 74 |
-
|
| 75 |
}
|
| 76 |
}
|
| 77 |
}}
|
|
@@ -82,7 +83,9 @@ export function TopMenu({
|
|
| 82 |
<Label className="flex text-sm">Font:</Label>
|
| 83 |
<Select
|
| 84 |
defaultValue={fontList.includes(preset.font) ? preset.font : "cartoonist"}
|
| 85 |
-
onValueChange={(value) => {
|
|
|
|
|
|
|
| 86 |
<SelectTrigger className="w-[144px]">
|
| 87 |
<SelectValue className="text-sm" placeholder="Type" />
|
| 88 |
</SelectTrigger>
|
|
|
|
| 11 |
import { cn } from "@/lib/utils"
|
| 12 |
import { FontName, fontList, fonts } from "@/lib/fonts"
|
| 13 |
import { Input } from "@/components/ui/input"
|
| 14 |
+
import { defaultPreset, getPreset, presets } from "@/app/engine/presets"
|
| 15 |
import { useState } from "react"
|
| 16 |
+
import { useStore } from "@/app/store"
|
| 17 |
+
|
| 18 |
+
export function TopMenu() {
|
| 19 |
+
const font = useStore(state => state.font)
|
| 20 |
+
const setFont = useStore(state => state.setFont)
|
| 21 |
+
|
| 22 |
+
const preset = useStore(state => state.preset)
|
| 23 |
+
const setPreset = useStore(state => state.setPreset)
|
| 24 |
+
|
| 25 |
+
const prompt = useStore(state => state.prompt)
|
| 26 |
+
const setPrompt = useStore(state => state.setPrompt)
|
| 27 |
+
|
| 28 |
+
const atLeastOnePanelIsBusy = useStore(state => state.atLeastOnePanelIsBusy)
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
const [draft, setDraft] = useState("")
|
| 31 |
return (
|
| 32 |
<div className={cn(
|
|
|
|
| 41 |
<Label className="flex text-sm">Select a preset:</Label>
|
| 42 |
<Select
|
| 43 |
defaultValue={defaultPreset}
|
| 44 |
+
onValueChange={(value) => { setPreset(getPreset(value as FontName)) }}
|
| 45 |
+
disabled={atLeastOnePanelIsBusy}
|
| 46 |
+
>
|
| 47 |
<SelectTrigger className="w-[180px]">
|
| 48 |
<SelectValue className="text-sm" placeholder="Type" />
|
| 49 |
</SelectTrigger>
|
|
|
|
| 58 |
<Input
|
| 59 |
placeholder="Story"
|
| 60 |
className="w-full bg-neutral-300 text-neutral-800 dark:bg-neutral-300 dark:text-neutral-800"
|
| 61 |
+
disabled={atLeastOnePanelIsBusy}
|
| 62 |
onChange={(e) => {
|
| 63 |
setDraft(e.target.value)
|
| 64 |
}}
|
| 65 |
onBlur={(e) => {
|
| 66 |
if (draft !== prompt) {
|
| 67 |
+
if (draft.trim() !== prompt.trim()) {
|
| 68 |
+
setPrompt(draft.trim())
|
| 69 |
+
}
|
| 70 |
}
|
| 71 |
}}
|
| 72 |
onKeyDown={({ key }) => {
|
| 73 |
if (key === 'Enter') {
|
| 74 |
if (draft.trim() !== prompt.trim()) {
|
| 75 |
+
setPrompt(draft.trim())
|
| 76 |
}
|
| 77 |
}
|
| 78 |
}}
|
|
|
|
| 83 |
<Label className="flex text-sm">Font:</Label>
|
| 84 |
<Select
|
| 85 |
defaultValue={fontList.includes(preset.font) ? preset.font : "cartoonist"}
|
| 86 |
+
onValueChange={(value) => { setFont(value as FontName) }}
|
| 87 |
+
disabled={atLeastOnePanelIsBusy}
|
| 88 |
+
>
|
| 89 |
<SelectTrigger className="w-[144px]">
|
| 90 |
<SelectValue className="text-sm" placeholder="Type" />
|
| 91 |
</SelectTrigger>
|
src/app/layouts/index.tsx
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import { Panel } from "@/app/interface/panel"
|
| 2 |
+
import { pick } from "@/lib/pick"
|
| 3 |
+
import { useStore } from "@/app/store"
|
| 4 |
+
|
| 5 |
+
export function Layout1() {
|
| 6 |
+
return (
|
| 7 |
+
<div
|
| 8 |
+
// the "fixed" width ensure our comic keeps a consistent ratio
|
| 9 |
+
className="grid grid-cols-2 grid-rows-3 gap-4 w-[1160px] h-screen">
|
| 10 |
+
<div className="bg-stone-100">
|
| 11 |
+
<Panel
|
| 12 |
+
panel={0}
|
| 13 |
+
width={1024}
|
| 14 |
+
height={512}
|
| 15 |
+
/>
|
| 16 |
+
</div>
|
| 17 |
+
<div className="bg-zinc-100 row-span-2">
|
| 18 |
+
<Panel
|
| 19 |
+
panel={1}
|
| 20 |
+
width={1024}
|
| 21 |
+
height={1024}
|
| 22 |
+
/>
|
| 23 |
+
</div>
|
| 24 |
+
<div className="bg-gray-100 row-span-2 col-span-1">
|
| 25 |
+
<Panel
|
| 26 |
+
panel={2}
|
| 27 |
+
width={1024}
|
| 28 |
+
height={1024}
|
| 29 |
+
/>
|
| 30 |
+
</div>
|
| 31 |
+
<div className="bg-slate-100">
|
| 32 |
+
<Panel
|
| 33 |
+
panel={3}
|
| 34 |
+
width={1024}
|
| 35 |
+
height={512}
|
| 36 |
+
/>
|
| 37 |
+
</div>
|
| 38 |
+
</div>
|
| 39 |
+
)
|
| 40 |
+
}
|
| 41 |
+
|
| 42 |
+
export function Layout2() {
|
| 43 |
+
return (
|
| 44 |
+
<div
|
| 45 |
+
// the "fixed" width ensure our comic keeps a consistent ratio
|
| 46 |
+
className="grid grid-cols-2 grid-rows-3 gap-4 w-[1160px] h-screen">
|
| 47 |
+
<div className="bg-gray-100 row-span-2 col-span-1">
|
| 48 |
+
<Panel
|
| 49 |
+
panel={0}
|
| 50 |
+
width={1024}
|
| 51 |
+
height={1024}
|
| 52 |
+
/>
|
| 53 |
+
</div>
|
| 54 |
+
<div className="bg-slate-100">
|
| 55 |
+
<Panel
|
| 56 |
+
panel={1}
|
| 57 |
+
width={1024}
|
| 58 |
+
height={512}
|
| 59 |
+
/>
|
| 60 |
+
</div>
|
| 61 |
+
<div className="bg-stone-100">
|
| 62 |
+
<Panel
|
| 63 |
+
panel={2}
|
| 64 |
+
width={1024}
|
| 65 |
+
height={512}
|
| 66 |
+
/>
|
| 67 |
+
</div>
|
| 68 |
+
<div className="bg-zinc-100 row-span-2">
|
| 69 |
+
<Panel
|
| 70 |
+
panel={3}
|
| 71 |
+
width={1024}
|
| 72 |
+
height={1024}
|
| 73 |
+
/>
|
| 74 |
+
</div>
|
| 75 |
+
</div>
|
| 76 |
+
)
|
| 77 |
+
}
|
| 78 |
+
|
| 79 |
+
export function Layout3() {
|
| 80 |
+
return (
|
| 81 |
+
<div
|
| 82 |
+
// the "fixed" width ensure our comic keeps a consistent ratio
|
| 83 |
+
className="grid grid-cols-2 grid-rows-3 gap-4 w-[1160px] h-screen">
|
| 84 |
+
<div className="bg-zinc-100 row-span-2">
|
| 85 |
+
<Panel
|
| 86 |
+
panel={0}
|
| 87 |
+
width={1024}
|
| 88 |
+
height={1024}
|
| 89 |
+
/>
|
| 90 |
+
</div>
|
| 91 |
+
<div className="bg-stone-100">
|
| 92 |
+
<Panel
|
| 93 |
+
panel={1}
|
| 94 |
+
width={1024}
|
| 95 |
+
height={512}
|
| 96 |
+
/>
|
| 97 |
+
</div>
|
| 98 |
+
<div className="bg-slate-100">
|
| 99 |
+
<Panel
|
| 100 |
+
panel={2}
|
| 101 |
+
width={1024}
|
| 102 |
+
height={512}
|
| 103 |
+
/>
|
| 104 |
+
</div>
|
| 105 |
+
<div className="bg-gray-100 row-span-2 col-span-1">
|
| 106 |
+
<Panel
|
| 107 |
+
panel={3}
|
| 108 |
+
width={1024}
|
| 109 |
+
height={1024}
|
| 110 |
+
/>
|
| 111 |
+
</div>
|
| 112 |
+
</div>
|
| 113 |
+
)
|
| 114 |
+
}
|
| 115 |
+
|
| 116 |
+
export function Layout4() {
|
| 117 |
+
return (
|
| 118 |
+
<div
|
| 119 |
+
// the "fixed" width ensure our comic keeps a consistent ratio
|
| 120 |
+
className="grid grid-cols-2 grid-rows-3 gap-4 w-[1160px] h-screen">
|
| 121 |
+
<div className="bg-slate-100">
|
| 122 |
+
<Panel
|
| 123 |
+
panel={0}
|
| 124 |
+
width={1024}
|
| 125 |
+
height={512}
|
| 126 |
+
/>
|
| 127 |
+
</div>
|
| 128 |
+
<div className="bg-gray-100 row-span-2 col-span-1">
|
| 129 |
+
<Panel
|
| 130 |
+
panel={1}
|
| 131 |
+
width={1024}
|
| 132 |
+
height={1024}
|
| 133 |
+
/>
|
| 134 |
+
</div>
|
| 135 |
+
<div className="bg-zinc-100 row-span-2">
|
| 136 |
+
<Panel
|
| 137 |
+
panel={2}
|
| 138 |
+
width={1024}
|
| 139 |
+
height={1024}
|
| 140 |
+
/>
|
| 141 |
+
</div>
|
| 142 |
+
<div className="bg-stone-100">
|
| 143 |
+
<Panel
|
| 144 |
+
panel={3}
|
| 145 |
+
width={1024}
|
| 146 |
+
height={512}
|
| 147 |
+
/>
|
| 148 |
+
</div>
|
| 149 |
+
</div>
|
| 150 |
+
)
|
| 151 |
+
}
|
| 152 |
+
|
| 153 |
+
export const layouts = { Layout1, Layout2, Layout3, Layout4 }
|
| 154 |
+
|
| 155 |
+
export type LayoutName = keyof typeof layouts
|
| 156 |
+
|
| 157 |
+
export function getRandomLayoutName(): LayoutName {
|
| 158 |
+
return pick(Object.keys(layouts) as LayoutName[]) as LayoutName
|
| 159 |
+
}
|
| 160 |
+
|
src/app/main.tsx
CHANGED
|
@@ -1,112 +1,76 @@
|
|
| 1 |
"use client"
|
| 2 |
|
| 3 |
-
import {
|
| 4 |
-
import {
|
| 5 |
|
| 6 |
-
import
|
| 7 |
-
|
| 8 |
-
import { Preset, PresetName, defaultPreset, getPreset } from "@/app/engine/presets"
|
| 9 |
|
| 10 |
import { cn } from "@/lib/utils"
|
| 11 |
import { TopMenu } from "./interface/top-menu"
|
| 12 |
-
import { FontName } from "@/lib/fonts"
|
| 13 |
-
import
|
|
|
|
| 14 |
|
| 15 |
export default function Main() {
|
| 16 |
const [_isPending, startTransition] = useTransition()
|
| 17 |
-
const [isLoading, setLoading] = useState<boolean>()
|
| 18 |
-
|
| 19 |
-
const router = useRouter()
|
| 20 |
-
const pathname = usePathname()
|
| 21 |
const searchParams = useSearchParams()
|
| 22 |
|
| 23 |
const requestedPreset = (searchParams.get('preset') as PresetName) || defaultPreset
|
| 24 |
-
const
|
|
|
|
| 25 |
|
| 26 |
-
const
|
|
|
|
| 27 |
|
| 28 |
-
const
|
| 29 |
-
const
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
const
|
| 33 |
-
|
| 34 |
-
|
|
|
|
| 35 |
|
| 36 |
-
const
|
| 37 |
-
setPreset(getPreset(newPresetName))
|
| 38 |
-
}
|
| 39 |
|
| 40 |
-
|
| 41 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 42 |
|
| 43 |
// TODO call the LLM here!
|
| 44 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
| 45 |
|
| 46 |
-
|
| 47 |
-
prompt,
|
| 48 |
-
prompt,
|
| 49 |
-
prompt,
|
| 50 |
-
prompt
|
| 51 |
-
])
|
| 52 |
-
}
|
| 53 |
|
| 54 |
return (
|
| 55 |
<div className={cn(
|
| 56 |
``
|
| 57 |
)}>
|
| 58 |
-
<TopMenu
|
| 59 |
-
defaultPreset={defaultPreset}
|
| 60 |
-
preset={preset}
|
| 61 |
-
onChangePreset={handleChangePreset}
|
| 62 |
-
font={font}
|
| 63 |
-
onChangeFont={handleChangeFont}
|
| 64 |
-
prompt={prompt}
|
| 65 |
-
onChangePrompt={handleChangePrompt}
|
| 66 |
-
/>
|
| 67 |
<div className="flex flex-col items-center w-screen h-screen pt-16 overflow-y-scroll">
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
className="grid grid-cols-2 grid-rows-3 gap-4 w-[1160px] h-screen">
|
| 71 |
-
<div className="bg-stone-100">
|
| 72 |
-
<Panel
|
| 73 |
-
prompt={panelPrompts[0]}
|
| 74 |
-
font={font}
|
| 75 |
-
preset={preset}
|
| 76 |
-
width={1024}
|
| 77 |
-
height={512}
|
| 78 |
-
/>
|
| 79 |
-
</div>
|
| 80 |
-
<div className="bg-zinc-100 row-span-2">
|
| 81 |
-
<Panel
|
| 82 |
-
prompt={panelPrompts[1]}
|
| 83 |
-
font={font}
|
| 84 |
-
preset={preset}
|
| 85 |
-
width={1024}
|
| 86 |
-
height={1024}
|
| 87 |
-
/>
|
| 88 |
-
</div>
|
| 89 |
-
<div className="bg-gray-100 row-span-2 col-span-1">
|
| 90 |
-
<Panel
|
| 91 |
-
prompt={panelPrompts[2]}
|
| 92 |
-
font={font}
|
| 93 |
-
preset={preset}
|
| 94 |
-
width={1024}
|
| 95 |
-
height={1024}
|
| 96 |
-
/>
|
| 97 |
-
</div>
|
| 98 |
-
<div className="bg-slate-100">
|
| 99 |
-
<Panel
|
| 100 |
-
prompt={panelPrompts[3]}
|
| 101 |
-
font={font}
|
| 102 |
-
preset={preset}
|
| 103 |
-
width={1024}
|
| 104 |
-
height={512}
|
| 105 |
-
/>
|
| 106 |
-
</div>
|
| 107 |
-
</div>
|
| 108 |
-
</div>
|
| 109 |
</div>
|
| 110 |
-
|
| 111 |
)
|
| 112 |
}
|
|
|
|
| 1 |
"use client"
|
| 2 |
|
| 3 |
+
import { useEffect, useTransition } from "react"
|
| 4 |
+
import { useSearchParams } from "next/navigation"
|
| 5 |
|
| 6 |
+
import { PresetName, defaultPreset, getPreset } from "@/app/engine/presets"
|
|
|
|
|
|
|
| 7 |
|
| 8 |
import { cn } from "@/lib/utils"
|
| 9 |
import { TopMenu } from "./interface/top-menu"
|
| 10 |
+
import { FontName, defaultFont } from "@/lib/fonts"
|
| 11 |
+
import { getRandomLayoutName, layouts } from "./layouts"
|
| 12 |
+
import { useStore } from "./store"
|
| 13 |
|
| 14 |
export default function Main() {
|
| 15 |
const [_isPending, startTransition] = useTransition()
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
const searchParams = useSearchParams()
|
| 17 |
|
| 18 |
const requestedPreset = (searchParams.get('preset') as PresetName) || defaultPreset
|
| 19 |
+
const requestedFont = (searchParams.get('font') as FontName) || defaultFont
|
| 20 |
+
const requestedPrompt = (searchParams.get('prompt') as string) || ""
|
| 21 |
|
| 22 |
+
const font = useStore(state => state.font)
|
| 23 |
+
const setFont = useStore(state => state.setFont)
|
| 24 |
|
| 25 |
+
const preset = useStore(state => state.preset)
|
| 26 |
+
const setPreset = useStore(state => state.setPreset)
|
| 27 |
+
|
| 28 |
+
const prompt = useStore(state => state.prompt)
|
| 29 |
+
const setPrompt = useStore(state => state.setPrompt)
|
| 30 |
+
|
| 31 |
+
const layout = useStore(state => state.layout)
|
| 32 |
+
const setLayout = useStore(state => state.setLayout)
|
| 33 |
|
| 34 |
+
const setPanels = useStore(state => state.setPanels)
|
|
|
|
|
|
|
| 35 |
|
| 36 |
+
// react to URL params
|
| 37 |
+
useEffect(() => {
|
| 38 |
+
if (requestedPreset && requestedPreset !== preset.label) { setPreset(getPreset(requestedPreset)) }
|
| 39 |
+
}, [requestedPreset])
|
| 40 |
+
|
| 41 |
+
useEffect(() => {
|
| 42 |
+
if (requestedFont && requestedFont !== font) { setFont(requestedFont) }
|
| 43 |
+
}, [requestedFont])
|
| 44 |
+
|
| 45 |
+
useEffect(() => {
|
| 46 |
+
if (requestedPrompt && requestedPrompt !== prompt) { setPrompt(requestedPrompt) }
|
| 47 |
+
}, [requestedPrompt])
|
| 48 |
+
|
| 49 |
+
// react to prompt changes
|
| 50 |
+
useEffect(() => {
|
| 51 |
+
if (!prompt) { return }
|
| 52 |
+
|
| 53 |
+
const newLayout = getRandomLayoutName()
|
| 54 |
+
console.log("using layout " + newLayout)
|
| 55 |
+
setLayout(newLayout)
|
| 56 |
|
| 57 |
// TODO call the LLM here!
|
| 58 |
+
const panelPrompt = preset.imagePrompt(prompt).join(", ")
|
| 59 |
+
|
| 60 |
+
// what we want is for it to invent a small "story"
|
| 61 |
+
setPanels([ panelPrompt, panelPrompt, panelPrompt, panelPrompt ])
|
| 62 |
+
}, [prompt, preset]) // important: we need to react to preset changes too
|
| 63 |
|
| 64 |
+
const LayoutElement = (layouts as any)[layout]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
|
| 66 |
return (
|
| 67 |
<div className={cn(
|
| 68 |
``
|
| 69 |
)}>
|
| 70 |
+
<TopMenu />
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
<div className="flex flex-col items-center w-screen h-screen pt-16 overflow-y-scroll">
|
| 72 |
+
<LayoutElement />
|
| 73 |
+
</div>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 74 |
</div>
|
|
|
|
| 75 |
)
|
| 76 |
}
|
src/app/store/index.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"use client"
|
| 2 |
+
import { create } from "zustand"
|
| 3 |
+
|
| 4 |
+
import { FontName } from "@/lib/fonts"
|
| 5 |
+
import { Preset, getPreset } from "@/app/engine/presets"
|
| 6 |
+
import { LayoutName } from "../layouts"
|
| 7 |
+
|
| 8 |
+
export const useStore = create<{
|
| 9 |
+
prompt: string
|
| 10 |
+
font: FontName
|
| 11 |
+
preset: Preset
|
| 12 |
+
panels: string[]
|
| 13 |
+
layout: LayoutName
|
| 14 |
+
isGeneratingLogic: boolean
|
| 15 |
+
panelGenerationStatus: Record<number, boolean>
|
| 16 |
+
isGeneratingText: boolean
|
| 17 |
+
atLeastOnePanelIsBusy: boolean
|
| 18 |
+
setPrompt: (prompt: string) => void
|
| 19 |
+
setFont: (font: FontName) => void
|
| 20 |
+
setPreset: (preset: Preset) => void
|
| 21 |
+
setPanels: (panels: string[]) => void
|
| 22 |
+
setLayout: (layout: LayoutName) => void
|
| 23 |
+
setGeneratingLogic: (isGeneratingLogic: boolean) => void
|
| 24 |
+
setGeneratingImages: (panelId: number, value: boolean) => void
|
| 25 |
+
setGeneratingText: (isGeneratingText: boolean) => void
|
| 26 |
+
}>((set, get) => ({
|
| 27 |
+
prompt: "",
|
| 28 |
+
font: "cartoonist",
|
| 29 |
+
preset: getPreset("japanese_manga"),
|
| 30 |
+
panels: [],
|
| 31 |
+
layout: "Layout1",
|
| 32 |
+
isGeneratingLogic: false,
|
| 33 |
+
panelGenerationStatus: {},
|
| 34 |
+
isGeneratingText: false,
|
| 35 |
+
atLeastOnePanelIsBusy: false,
|
| 36 |
+
setPrompt: (prompt: string) => set({ prompt }),
|
| 37 |
+
setFont: (font: FontName) => set({ font }),
|
| 38 |
+
setPreset: (preset: Preset) => set({ preset }),
|
| 39 |
+
setPanels: (panels: string[]) => set({ panels }),
|
| 40 |
+
setLayout: (layout: LayoutName) => set({ layout }),
|
| 41 |
+
setGeneratingLogic: (isGeneratingLogic: boolean) => set({ isGeneratingLogic }),
|
| 42 |
+
setGeneratingImages: (panelId: number, value: boolean) => {
|
| 43 |
+
|
| 44 |
+
const panelGenerationStatus: Record<number, boolean> = {
|
| 45 |
+
...get().panelGenerationStatus,
|
| 46 |
+
[panelId]: value
|
| 47 |
+
}
|
| 48 |
+
|
| 49 |
+
const atLeastOnePanelIsBusy = Object.values(panelGenerationStatus).includes(true)
|
| 50 |
+
|
| 51 |
+
set({
|
| 52 |
+
panelGenerationStatus,
|
| 53 |
+
atLeastOnePanelIsBusy
|
| 54 |
+
})
|
| 55 |
+
},
|
| 56 |
+
setGeneratingText: (isGeneratingText: boolean) => set({ isGeneratingText }),
|
| 57 |
+
}))
|
src/lib/fonts.ts
CHANGED
|
@@ -97,6 +97,8 @@ export const fontList = Object.keys(fonts)
|
|
| 97 |
|
| 98 |
export type FontName = keyof typeof fonts
|
| 99 |
|
|
|
|
|
|
|
| 100 |
export const classNames = Object.values(fonts).map(font => font.className)
|
| 101 |
|
| 102 |
export const className = classNames.join(" ")
|
|
|
|
| 97 |
|
| 98 |
export type FontName = keyof typeof fonts
|
| 99 |
|
| 100 |
+
export const defaultFont = "cartoonist" as FontName
|
| 101 |
+
|
| 102 |
export const classNames = Object.values(fonts).map(font => font.className)
|
| 103 |
|
| 104 |
export const className = classNames.join(" ")
|
src/types.ts
CHANGED
|
@@ -29,6 +29,14 @@ export interface RenderRequest {
|
|
| 29 |
width: number // fixed at 1024 for now
|
| 30 |
height: number // fixed at 512 for now
|
| 31 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 32 |
projection: ProjectionMode
|
| 33 |
|
| 34 |
cache: CacheMode
|
|
|
|
| 29 |
width: number // fixed at 1024 for now
|
| 30 |
height: number // fixed at 512 for now
|
| 31 |
|
| 32 |
+
// upscaling factor
|
| 33 |
+
// 0: no upscaling
|
| 34 |
+
// 1: no upscaling
|
| 35 |
+
// 2: 2x larger
|
| 36 |
+
// 3: 3x larger
|
| 37 |
+
// 4x: 4x larger, up to 4096x4096 (warning: a PNG of this size can be 50 Mb!)
|
| 38 |
+
upscalingFactor: number
|
| 39 |
+
|
| 40 |
projection: ProjectionMode
|
| 41 |
|
| 42 |
cache: CacheMode
|