jbilcke-hf HF staff commited on
Commit
932a7fd
1 Parent(s): 624088c

fixed various issues

Browse files
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": "^9.22.5",
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.30001523",
4286
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001523.tgz",
4287
- "integrity": "sha512-I5q5cisATTPZ1mc588Z//pj/Ox80ERYDfR71YnvY7raS/NOk8xXlZcB0sF7JdqaV//kOaa6aus7lRfpdnt1eBA==",
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.502",
4973
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.502.tgz",
4974
- "integrity": "sha512-xqeGw3Gr6o3uyHy/yKjdnDQHY2RQvXcGC2cfHjccK1IGkH6cX1WQBN8EeC/YpwPhGkBaikDTecJ8+ssxSVRQlw=="
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.13",
5058
- "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.13.tgz",
5059
- "integrity": "sha512-LK3VGwzvaPWobO8xzXXGRUOGw8Dcjyfk62CsY/wfHN75CwsJPbuypOYJxK6g5RyEL8YDjIWcl6jgd8foO6mmrA==",
5060
  "dependencies": {
5061
  "asynciterator.prototype": "^1.0.0",
5062
  "call-bind": "^1.0.2",
5063
  "define-properties": "^1.2.0",
5064
- "es-abstract": "^1.21.3",
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.4",
5627
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz",
5628
- "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==",
5629
  "dependencies": {
5630
- "flatted": "^3.1.0",
 
5631
  "rimraf": "^3.0.2"
5632
  },
5633
  "engines": {
5634
- "node": "^10.12.0 || >=12.0.0"
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": "9.22.5",
7379
- "resolved": "https://registry.npmjs.org/react-virtualized/-/react-virtualized-9.22.5.tgz",
7380
- "integrity": "sha512-YqQMRzlVANBv1L/7r63OHa2b0ZsAaDp1UhVNEdUaXI8A5u6hTpA5NYtUueLH2rFuY/27mTGIBl7ZhqFKzw18YQ==",
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": "^9.22.5",
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
- sanglier: {
104
- label: "Sanglier",
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 default function Panel({
15
- prompt = "",
16
- font,
17
- preset,
18
  className = "",
19
  width = 1,
20
  height = 1,
21
  delay = 0,
22
  }: {
23
- prompt?: string
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
- prompt, preset, width, height
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, preset])
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
- setLoading(true)
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
- setLoading(false)
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" ? "grayscale" : "",
126
  className
127
  )}>
128
- {rendered.assetUrl ? <img
129
  src={rendered.assetUrl}
130
  className="w-full h-full object-cover"
131
- /> : null}
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: string
13
  className?: string
14
  }) {
15
  const timeoutRef = useRef<any>()
@@ -43,7 +43,7 @@ export function Progress({
43
 
44
  return (
45
  <div className={cn(
46
- `fixed flex w-10 h-10 top-16 right-6 z-50`,
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 { Preset, PresetName, presets } from "@/app/engine/presets"
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) => { onChangePreset(value as FontName) }}>
 
 
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
- onChangePrompt(draft)
 
 
69
  }
70
  }}
71
  onKeyDown={({ key }) => {
72
  if (key === 'Enter') {
73
  if (draft.trim() !== prompt.trim()) {
74
- onChangePrompt(draft.trim())
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) => { onChangeFont(value as FontName) }}>
 
 
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 { useState, useTransition } from "react"
4
- import { usePathname, useRouter, useSearchParams } from "next/navigation"
5
 
6
- import "react-virtualized/styles.css" // only needs to be imported once
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 Panel from "./interface/panel"
 
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 [preset, setPreset] = useState<Preset>(getPreset(requestedPreset))
 
25
 
26
- const [font, setFont] = useState<FontName>("cartoonist")
 
27
 
28
- const requestedPrompt = (searchParams.get('prompt') as string) || ""
29
- const [prompt, setPrompt] = useState<string>(requestedPrompt)
30
- const [panelPrompts, setPanelPrompts] = useState<string[]>([])
31
-
32
- const handleChangeFont = (newFont: FontName) => {
33
- setFont(newFont)
34
- }
 
35
 
36
- const handleChangePreset = (newPresetName: PresetName) => {
37
- setPreset(getPreset(newPresetName))
38
- }
39
 
40
- const handleChangePrompt = (newPrompt: string) => {
41
- setPrompt(newPrompt)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
 
43
  // TODO call the LLM here!
44
- const prompt = preset.imagePrompt(newPrompt).join(", ")
 
 
 
 
45
 
46
- setPanelPrompts([
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
- <div
69
- // the "fixed" width ensure our comic keeps a consistent ratio
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