Spaces:
Running
Running
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
|