Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bc7cf6b8ed | |||
| 7272d19207 | |||
| 9614d2884b | |||
| c891a8be58 |
Vendored
+7
-2
@@ -1,9 +1,14 @@
|
|||||||
{
|
{
|
||||||
"rust-analyzer.check.command": "clippy",
|
"rust-analyzer.check.command": "clippy",
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"rust-analyzer.cargo.features": "all",
|
|
||||||
"files.eol": "\n",
|
"files.eol": "\n",
|
||||||
"files.insertFinalNewline": true,
|
"files.insertFinalNewline": true,
|
||||||
"files.trimFinalNewlines": true,
|
"files.trimFinalNewlines": true,
|
||||||
"files.trimTrailingWhitespace": true
|
"files.trimTrailingWhitespace": true,
|
||||||
|
"rust-analyzer.cargo.features": [
|
||||||
|
"native",
|
||||||
|
"llm"
|
||||||
|
],
|
||||||
|
"rust-analyzer.cargo.noDefaultFeatures": true,
|
||||||
|
"rust-analyzer.cargo.allFeatures": false
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+168
-160
@@ -4,9 +4,9 @@ version = 4
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ab_glyph"
|
name = "ab_glyph"
|
||||||
version = "0.2.30"
|
version = "0.2.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e0f4f6fbdc5ee39f2ede9f5f3ec79477271a6d6a2baff22310d51736bda6cea"
|
checksum = "e074464580a518d16a7126262fffaaa47af89d4099d4cb403f8ed938ba12ee7d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ab_glyph_rasterizer",
|
"ab_glyph_rasterizer",
|
||||||
"owned_ttf_parser",
|
"owned_ttf_parser",
|
||||||
@@ -14,9 +14,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ab_glyph_rasterizer"
|
name = "ab_glyph_rasterizer"
|
||||||
version = "0.1.9"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b2187590a23ab1e3df8681afdf0987c48504d80291f002fcdb651f0ef5e25169"
|
checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "accesskit"
|
name = "accesskit"
|
||||||
@@ -194,15 +194,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.98"
|
version = "1.0.99"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487"
|
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arbitrary"
|
name = "arbitrary"
|
||||||
version = "1.4.1"
|
version = "1.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
|
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arboard"
|
name = "arboard"
|
||||||
@@ -213,7 +213,7 @@ dependencies = [
|
|||||||
"clipboard-win",
|
"clipboard-win",
|
||||||
"image",
|
"image",
|
||||||
"log",
|
"log",
|
||||||
"objc2 0.6.1",
|
"objc2 0.6.2",
|
||||||
"objc2-app-kit 0.3.1",
|
"objc2-app-kit 0.3.1",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
"objc2-core-graphics",
|
"objc2-core-graphics",
|
||||||
@@ -293,9 +293,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-io"
|
name = "async-io"
|
||||||
version = "2.4.1"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3"
|
checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-lock",
|
"async-lock",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -304,17 +304,16 @@ dependencies = [
|
|||||||
"futures-lite",
|
"futures-lite",
|
||||||
"parking",
|
"parking",
|
||||||
"polling",
|
"polling",
|
||||||
"rustix 1.0.7",
|
"rustix 1.0.8",
|
||||||
"slab",
|
"slab",
|
||||||
"tracing",
|
"windows-sys 0.60.2",
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-lock"
|
name = "async-lock"
|
||||||
version = "3.4.0"
|
version = "3.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18"
|
checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"event-listener-strategy",
|
"event-listener-strategy",
|
||||||
@@ -323,9 +322,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-process"
|
name = "async-process"
|
||||||
version = "2.3.1"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc"
|
checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-channel",
|
"async-channel",
|
||||||
"async-io",
|
"async-io",
|
||||||
@@ -336,8 +335,7 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"event-listener",
|
"event-listener",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"rustix 1.0.7",
|
"rustix 1.0.8",
|
||||||
"tracing",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -353,9 +351,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-signal"
|
name = "async-signal"
|
||||||
version = "0.2.11"
|
version = "0.2.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d"
|
checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-io",
|
"async-io",
|
||||||
"async-lock",
|
"async-lock",
|
||||||
@@ -363,10 +361,10 @@ dependencies = [
|
|||||||
"cfg-if",
|
"cfg-if",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-io",
|
"futures-io",
|
||||||
"rustix 1.0.7",
|
"rustix 1.0.8",
|
||||||
"signal-hook-registry",
|
"signal-hook-registry",
|
||||||
"slab",
|
"slab",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -377,9 +375,9 @@ checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-trait"
|
name = "async-trait"
|
||||||
version = "0.1.88"
|
version = "0.1.89"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5"
|
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -464,9 +462,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "avif-serialize"
|
name = "avif-serialize"
|
||||||
version = "0.8.5"
|
version = "0.8.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ea8ef51aced2b9191c08197f55450d830876d9933f8f48a429b354f1d496b42"
|
checksum = "47c8fbc0f831f4519fe8b810b6a7a91410ec83031b8233f730a0480029f6a23f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
]
|
]
|
||||||
@@ -570,18 +568,18 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck"
|
name = "bytemuck"
|
||||||
version = "1.23.1"
|
version = "1.23.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c76a5792e44e4abe34d3abf15636779261d45a7450612059293d1d2cfc63422"
|
checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck_derive",
|
"bytemuck_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytemuck_derive"
|
name = "bytemuck_derive"
|
||||||
version = "1.9.3"
|
version = "1.10.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ecc273b49b3205b83d648f0690daa588925572cc5063745bfe547fe7ec8e1a1"
|
checksum = "4f154e572231cb6ba2bd1176980827e3d5dc04cc183a75dea38109fbdd672d29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -628,9 +626,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.29"
|
version = "1.2.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362"
|
checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -691,9 +689,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clipboard-win"
|
name = "clipboard-win"
|
||||||
version = "5.4.0"
|
version = "5.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892"
|
checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"error-code",
|
"error-code",
|
||||||
]
|
]
|
||||||
@@ -786,9 +784,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.4.2"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
|
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
]
|
]
|
||||||
@@ -849,7 +847,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"objc2 0.6.1",
|
"objc2 0.6.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -895,9 +893,9 @@ checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dyn-clone"
|
name = "dyn-clone"
|
||||||
version = "1.0.19"
|
version = "1.0.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
|
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ecolor"
|
name = "ecolor"
|
||||||
@@ -1225,9 +1223,9 @@ checksum = "dea2df4cf52843e0452895c455a1a2cfbb842a1e7329671acf418fdc53ed4c59"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "event-listener"
|
name = "event-listener"
|
||||||
version = "5.4.0"
|
version = "5.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae"
|
checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"parking",
|
"parking",
|
||||||
@@ -1371,9 +1369,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-lite"
|
name = "futures-lite"
|
||||||
version = "2.6.0"
|
version = "2.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532"
|
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -1508,7 +1506,7 @@ dependencies = [
|
|||||||
"glutin_glx_sys",
|
"glutin_glx_sys",
|
||||||
"glutin_wgl_sys",
|
"glutin_wgl_sys",
|
||||||
"libloading",
|
"libloading",
|
||||||
"objc2 0.6.1",
|
"objc2 0.6.2",
|
||||||
"objc2-app-kit 0.3.1",
|
"objc2-app-kit 0.3.1",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
"objc2-foundation 0.3.1",
|
"objc2-foundation 0.3.1",
|
||||||
@@ -1562,9 +1560,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "h2"
|
name = "h2"
|
||||||
version = "0.4.11"
|
version = "0.4.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785"
|
checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -1592,9 +1590,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "hashbrown"
|
||||||
version = "0.15.4"
|
version = "0.15.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5"
|
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"foldhash",
|
"foldhash",
|
||||||
]
|
]
|
||||||
@@ -1968,6 +1966,15 @@ dependencies = [
|
|||||||
"either",
|
"either",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "itertools"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.15"
|
version = "1.0.15"
|
||||||
@@ -2036,9 +2043,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.174"
|
version = "0.2.175"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776"
|
checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libfuzzer-sys"
|
name = "libfuzzer-sys"
|
||||||
@@ -2057,7 +2064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"windows-targets 0.53.2",
|
"windows-targets 0.53.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2068,13 +2075,13 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
version = "0.1.4"
|
version = "0.1.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
|
checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall 0.5.13",
|
"redox_syscall 0.5.17",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2097,9 +2104,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litrs"
|
name = "litrs"
|
||||||
version = "0.4.1"
|
version = "0.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
|
checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@@ -2144,9 +2151,9 @@ checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memmap2"
|
name = "memmap2"
|
||||||
version = "0.9.5"
|
version = "0.9.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
|
checksum = "483758ad303d734cec05e5c12b41d7e93e6a6390c5e9dae6bdeb7c1259012d28"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -2225,7 +2232,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"rustc-hash 1.1.0",
|
"rustc-hash 1.1.0",
|
||||||
"strum",
|
"strum",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.14",
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2408,9 +2415,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "objc2"
|
name = "objc2"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551"
|
checksum = "561f357ba7f3a2a61563a186a163d0a3a5247e1089524a3981d49adb775078bc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"objc2-encode",
|
"objc2-encode",
|
||||||
]
|
]
|
||||||
@@ -2438,7 +2445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc"
|
checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"objc2 0.6.1",
|
"objc2 0.6.2",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
"objc2-core-graphics",
|
"objc2-core-graphics",
|
||||||
"objc2-foundation 0.3.1",
|
"objc2-foundation 0.3.1",
|
||||||
@@ -2488,7 +2495,7 @@ checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"dispatch2",
|
"dispatch2",
|
||||||
"objc2 0.6.1",
|
"objc2 0.6.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2499,7 +2506,7 @@ checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"dispatch2",
|
"dispatch2",
|
||||||
"objc2 0.6.1",
|
"objc2 0.6.2",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
"objc2-io-surface",
|
"objc2-io-surface",
|
||||||
]
|
]
|
||||||
@@ -2554,7 +2561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
|
checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"objc2 0.6.1",
|
"objc2 0.6.2",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2565,7 +2572,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c"
|
checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"objc2 0.6.1",
|
"objc2 0.6.2",
|
||||||
"objc2-core-foundation",
|
"objc2-core-foundation",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2741,9 +2748,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owned_ttf_parser"
|
name = "owned_ttf_parser"
|
||||||
version = "0.25.0"
|
version = "0.25.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22ec719bbf3b2a81c109a4e20b1f129b5566b7dce654bc3872f6a05abf82b2c4"
|
checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ttf-parser",
|
"ttf-parser",
|
||||||
]
|
]
|
||||||
@@ -2772,7 +2779,7 @@ checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall 0.5.13",
|
"redox_syscall 0.5.17",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
@@ -2897,17 +2904,16 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "polling"
|
name = "polling"
|
||||||
version = "3.8.0"
|
version = "3.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50"
|
checksum = "b5bd19146350fe804f7cb2669c851c03d69da628803dab0d98018142aaa5d829"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"concurrent-queue",
|
"concurrent-queue",
|
||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustix 1.0.7",
|
"rustix 1.0.8",
|
||||||
"tracing",
|
"windows-sys 0.60.2",
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2945,9 +2951,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.95"
|
version = "1.0.97"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778"
|
checksum = "d61789d7719defeb74ea5fe81f2fdfdbd28a803847077cecce2ff14e1472f6f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
@@ -3075,7 +3081,7 @@ dependencies = [
|
|||||||
"built",
|
"built",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"interpolate_name",
|
"interpolate_name",
|
||||||
"itertools",
|
"itertools 0.12.1",
|
||||||
"libc",
|
"libc",
|
||||||
"libfuzzer-sys",
|
"libfuzzer-sys",
|
||||||
"log",
|
"log",
|
||||||
@@ -3119,9 +3125,9 @@ checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon"
|
name = "rayon"
|
||||||
version = "1.10.0"
|
version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"either",
|
"either",
|
||||||
"rayon-core",
|
"rayon-core",
|
||||||
@@ -3129,9 +3135,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rayon-core"
|
name = "rayon-core"
|
||||||
version = "1.12.1"
|
version = "1.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crossbeam-deque",
|
"crossbeam-deque",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
@@ -3148,9 +3154,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.13"
|
version = "0.5.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
|
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
]
|
]
|
||||||
@@ -3163,9 +3169,9 @@ checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "reqwest"
|
name = "reqwest"
|
||||||
version = "0.12.22"
|
version = "0.12.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531"
|
checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -3205,9 +3211,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rgb"
|
name = "rgb"
|
||||||
version = "0.8.51"
|
version = "0.8.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a457e416a0f90d246a4c3288bd7a25b2304ca727f253f95be383dd17af56be8f"
|
checksum = "0c6a884d2998352bb4daf0183589aec883f16a6da1f4dde84d8e2e9a5409a1ce"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
@@ -3225,9 +3231,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.25"
|
version = "0.1.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
|
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-hash"
|
name = "rustc-hash"
|
||||||
@@ -3256,22 +3262,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "1.0.7"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
|
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys 0.9.4",
|
"linux-raw-sys 0.9.4",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.60.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.29"
|
version = "0.23.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2491382039b29b9b11ff08b76ff6c97cf287671dbb74f0be44bda389fffe9bd1"
|
checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
@@ -3302,9 +3308,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.21"
|
version = "1.0.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d"
|
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
@@ -3400,9 +3406,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.141"
|
version = "1.0.142"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
|
checksum = "030fedb782600dcbd6f02d479bf0d817ac3bb40d644745b769d6a96bc3afc5a7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -3450,9 +3456,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "signal-hook-registry"
|
name = "signal-hook-registry"
|
||||||
version = "1.4.5"
|
version = "1.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410"
|
checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@@ -3480,9 +3486,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "slab"
|
||||||
version = "0.4.10"
|
version = "0.4.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d"
|
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slotmap"
|
name = "slotmap"
|
||||||
@@ -3602,9 +3608,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.104"
|
version = "2.0.105"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40"
|
checksum = "7bc3fcb250e53458e712715cf74285c1f889686520d79294a9ef3bd7aa1fc619"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -3680,7 +3686,7 @@ dependencies = [
|
|||||||
"fastrand",
|
"fastrand",
|
||||||
"getrandom 0.3.3",
|
"getrandom 0.3.3",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"rustix 1.0.7",
|
"rustix 1.0.8",
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -3704,11 +3710,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "2.0.12"
|
version = "2.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
checksum = "0b0949c3a6c842cbde3f1686d6eea5a010516deb7085f79db747562d4102f41e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl 2.0.12",
|
"thiserror-impl 2.0.14",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3724,9 +3730,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "2.0.12"
|
version = "2.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -3781,9 +3787,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.47.0"
|
version = "1.47.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35"
|
checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -3818,9 +3824,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.15"
|
version = "0.7.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
|
checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -3991,9 +3997,9 @@ checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
version = "0.1.14"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "untrusted"
|
name = "untrusted"
|
||||||
@@ -4020,9 +4026,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "uuid"
|
name = "uuid"
|
||||||
version = "1.17.0"
|
version = "1.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
|
checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.3.3",
|
"getrandom 0.3.3",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -4165,13 +4171,13 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-backend"
|
name = "wayland-backend"
|
||||||
version = "0.3.10"
|
version = "0.3.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121"
|
checksum = "673a33c33048a5ade91a6b139580fa174e19fb0d23f396dca9fa15f2e1e49b35"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"downcast-rs",
|
"downcast-rs",
|
||||||
"rustix 0.38.44",
|
"rustix 1.0.8",
|
||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"wayland-sys",
|
"wayland-sys",
|
||||||
@@ -4179,12 +4185,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-client"
|
name = "wayland-client"
|
||||||
version = "0.31.10"
|
version = "0.31.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61"
|
checksum = "c66a47e840dc20793f2264eb4b3e4ecb4b75d91c0dd4af04b456128e0bdd449d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"rustix 0.38.44",
|
"rustix 1.0.8",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
"wayland-scanner",
|
"wayland-scanner",
|
||||||
]
|
]
|
||||||
@@ -4202,20 +4208,20 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-cursor"
|
name = "wayland-cursor"
|
||||||
version = "0.31.10"
|
version = "0.31.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182"
|
checksum = "447ccc440a881271b19e9989f75726d60faa09b95b0200a9b7eb5cc47c3eeb29"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustix 0.38.44",
|
"rustix 1.0.8",
|
||||||
"wayland-client",
|
"wayland-client",
|
||||||
"xcursor",
|
"xcursor",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols"
|
name = "wayland-protocols"
|
||||||
version = "0.32.8"
|
version = "0.32.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "779075454e1e9a521794fed15886323ea0feda3f8b0fc1390f5398141310422a"
|
checksum = "efa790ed75fbfd71283bd2521a1cfdc022aabcc28bdcff00851f9e4ae88d9901"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
@@ -4225,9 +4231,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols-plasma"
|
name = "wayland-protocols-plasma"
|
||||||
version = "0.3.8"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fd38cdad69b56ace413c6bcc1fbf5acc5e2ef4af9d5f8f1f9570c0c83eae175"
|
checksum = "a07a14257c077ab3279987c4f8bb987851bf57081b93710381daea94f2c2c032"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
@@ -4238,9 +4244,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-protocols-wlr"
|
name = "wayland-protocols-wlr"
|
||||||
version = "0.3.8"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1cb6cdc73399c0e06504c437fe3cf886f25568dd5454473d565085b36d6a8bbf"
|
checksum = "efd94963ed43cf9938a090ca4f7da58eb55325ec8200c3848963e98dc25b78ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.9.1",
|
"bitflags 2.9.1",
|
||||||
"wayland-backend",
|
"wayland-backend",
|
||||||
@@ -4251,9 +4257,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-scanner"
|
name = "wayland-scanner"
|
||||||
version = "0.31.6"
|
version = "0.31.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484"
|
checksum = "54cb1e9dc49da91950bdfd8b848c49330536d9d1fb03d4bfec8cae50caa50ae3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quick-xml 0.37.5",
|
"quick-xml 0.37.5",
|
||||||
@@ -4262,9 +4268,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wayland-sys"
|
name = "wayland-sys"
|
||||||
version = "0.31.6"
|
version = "0.31.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615"
|
checksum = "34949b42822155826b41db8e5d0c1be3a2bd296c747577a43a3e6daefc296142"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dlib",
|
"dlib",
|
||||||
"log",
|
"log",
|
||||||
@@ -4302,7 +4308,7 @@ dependencies = [
|
|||||||
"jni",
|
"jni",
|
||||||
"log",
|
"log",
|
||||||
"ndk-context",
|
"ndk-context",
|
||||||
"objc2 0.6.1",
|
"objc2 0.6.2",
|
||||||
"objc2-foundation 0.3.1",
|
"objc2-foundation 0.3.1",
|
||||||
"url",
|
"url",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
@@ -4363,7 +4369,7 @@ dependencies = [
|
|||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"rustc-hash 1.1.0",
|
"rustc-hash 1.1.0",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.14",
|
||||||
"wgpu-core-deps-windows-linux-android",
|
"wgpu-core-deps-windows-linux-android",
|
||||||
"wgpu-hal",
|
"wgpu-hal",
|
||||||
"wgpu-types",
|
"wgpu-types",
|
||||||
@@ -4393,7 +4399,7 @@ dependencies = [
|
|||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
"raw-window-handle",
|
"raw-window-handle",
|
||||||
"renderdoc-sys",
|
"renderdoc-sys",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.14",
|
||||||
"wgpu-types",
|
"wgpu-types",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4407,7 +4413,7 @@ dependencies = [
|
|||||||
"bytemuck",
|
"bytemuck",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"log",
|
"log",
|
||||||
"thiserror 2.0.12",
|
"thiserror 2.0.14",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4588,7 +4594,7 @@ version = "0.60.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.53.2",
|
"windows-targets 0.53.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4639,10 +4645,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.53.2"
|
version = "0.53.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
|
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"windows-link",
|
||||||
"windows_aarch64_gnullvm 0.53.0",
|
"windows_aarch64_gnullvm 0.53.0",
|
||||||
"windows_aarch64_msvc 0.53.0",
|
"windows_aarch64_msvc 0.53.0",
|
||||||
"windows_i686_gnu 0.53.0",
|
"windows_i686_gnu 0.53.0",
|
||||||
@@ -4844,9 +4851,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winit"
|
name = "winit"
|
||||||
version = "0.30.11"
|
version = "0.30.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4409c10174df8779dc29a4788cac85ed84024ccbc1743b776b21a520ee1aaf4"
|
checksum = "c66d4b9ed69c4009f6321f762d6e61ad8a2389cd431b97cb1e146812e9e6c732"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"android-activity",
|
"android-activity",
|
||||||
@@ -4896,9 +4903,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.7.11"
|
version = "0.7.12"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
|
checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
@@ -4923,12 +4930,13 @@ dependencies = [
|
|||||||
"egui_extras",
|
"egui_extras",
|
||||||
"egui_file",
|
"egui_file",
|
||||||
"image",
|
"image",
|
||||||
|
"itertools 0.14.0",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 2.0.12",
|
"tempfile",
|
||||||
|
"thiserror 2.0.14",
|
||||||
"uuid",
|
"uuid",
|
||||||
"walkdir",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5026,9 +5034,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus"
|
name = "zbus"
|
||||||
version = "5.8.0"
|
version = "5.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "597f45e98bc7e6f0988276012797855613cd8269e23b5be62cc4e5d28b7e515d"
|
checksum = "4bb4f9a464286d42851d18a605f7193b8febaf5b0919d71c6399b7b26e5b0aad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-broadcast",
|
"async-broadcast",
|
||||||
"async-executor",
|
"async-executor",
|
||||||
@@ -5083,9 +5091,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zbus_macros"
|
name = "zbus_macros"
|
||||||
version = "5.8.0"
|
version = "5.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5c8e4e14dcdd9d97a98b189cd1220f30e8394ad271e8c987da84f73693862c2"
|
checksum = "ef9859f68ee0c4ee2e8cde84737c78e3f4c54f946f2a38645d0d4c7a95327659"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-crate",
|
"proc-macro-crate",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -5181,9 +5189,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerovec"
|
name = "zerovec"
|
||||||
version = "0.11.2"
|
version = "0.11.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428"
|
checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"yoke",
|
"yoke",
|
||||||
"zerofrom",
|
"zerofrom",
|
||||||
@@ -5218,9 +5226,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-jpeg"
|
name = "zune-jpeg"
|
||||||
version = "0.4.19"
|
version = "0.4.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2c9e525af0a6a658e031e95f14b7f889976b74a11ba0eca5a5fc9ac8a1c43a6a"
|
checksum = "fc1f7e205ce79eb2da3cd71c5f55f3589785cb7c79f6a03d1c8d1491bda5d089"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zune-core",
|
"zune-core",
|
||||||
]
|
]
|
||||||
|
|||||||
+10
-3
@@ -17,8 +17,15 @@ image = { version = "0.25.6", features = ["jpeg", "png"] }
|
|||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
serde_json = "1.0.141"
|
serde_json = "1.0.141"
|
||||||
chrono = { version = "0.4.41", features = ["serde"] }
|
chrono = { version = "0.4.41", features = ["serde"] }
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.14"
|
||||||
egui_commonmark = { version = "0.21.1", features = ["embedded_image"] }
|
egui_commonmark = { version = "0.21.1", features = ["embedded_image"] }
|
||||||
walkdir = "2.5.0"
|
|
||||||
uuid = { version = "1.17.0", features = ["v4"] }
|
uuid = { version = "1.17.0", features = ["v4"] }
|
||||||
reqwest = { version = "0.12.22", features = ["blocking", "json"] }
|
reqwest = { version = "0.12.23", features = ["blocking", "json"] }
|
||||||
|
tempfile = "3.20.0"
|
||||||
|
itertools = "0.14.0"
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = ["native", "llm"]
|
||||||
|
web = []
|
||||||
|
native = []
|
||||||
|
llm = []
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
pkgname=worldcoder
|
pkgname=worldcoder
|
||||||
pkgver=0.1.1
|
pkgver=0.1.1
|
||||||
pkgrel=1
|
pkgrel=3
|
||||||
makedepends=('rust' 'cargo')
|
makedepends=('rust' 'cargo')
|
||||||
arch=('i686' 'x86_64' 'armv6h' 'armv7h')
|
arch=('i686' 'x86_64' 'armv6h' 'armv7h')
|
||||||
|
|
||||||
# Generated in accordance to https://wiki.archlinux.org/title/Rust_package_guidelines.
|
|
||||||
# Might require further modification depending on the package involved.
|
|
||||||
prepare() {
|
prepare() {
|
||||||
cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
|
cargo fetch --locked --target "$CARCH-unknown-linux-gnu"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
use egui::{TextEdit, vec2};
|
use egui::{TextEdit, vec2};
|
||||||
|
|
||||||
use crate::{PROJECT_FOLDER, util};
|
use crate::{
|
||||||
|
PROJECT_FOLDER,
|
||||||
|
filesystem::{FILESYSTEM, FsError, LegacyFileSystem},
|
||||||
|
util,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Asset {
|
pub struct Asset {
|
||||||
@@ -25,15 +29,14 @@ impl Asset {
|
|||||||
println!("old_path: {old_path:?}");
|
println!("old_path: {old_path:?}");
|
||||||
println!("new_path: {new_path:?}");
|
println!("new_path: {new_path:?}");
|
||||||
|
|
||||||
// move from src dir to name path
|
if let Err(FsError::Io(err)) = FILESYSTEM.rename(&old_path, &new_path) {
|
||||||
if let Err(err) = std::fs::rename(&old_path, &new_path) {
|
|
||||||
match err.kind() {
|
match err.kind() {
|
||||||
std::io::ErrorKind::NotFound => {
|
std::io::ErrorKind::NotFound => {
|
||||||
let dir = new_path.parent().unwrap();
|
let dir = new_path.parent().unwrap();
|
||||||
if !dir.exists() {
|
if !dir.exists() {
|
||||||
std::fs::create_dir_all(dir).unwrap();
|
FILESYSTEM.mkdir(dir).unwrap();
|
||||||
}
|
}
|
||||||
std::fs::rename(&old_path, &new_path).unwrap();
|
FILESYSTEM.rename(&old_path, &new_path).unwrap();
|
||||||
}
|
}
|
||||||
_ => panic!("Failed to rename file: {err}"),
|
_ => panic!("Failed to rename file: {err}"),
|
||||||
}
|
}
|
||||||
@@ -73,7 +76,7 @@ impl Asset {
|
|||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
if let Ok(bytes) = std::fs::read(Self::path(&self.name)) {
|
if let Ok(bytes) = FILESYSTEM.read_bytes(&Self::path(&self.name)) {
|
||||||
let image_source = egui::ImageSource::Bytes {
|
let image_source = egui::ImageSource::Bytes {
|
||||||
uri: std::borrow::Cow::Owned(self.name.clone()),
|
uri: std::borrow::Cow::Owned(self.name.clone()),
|
||||||
bytes: bytes.into(),
|
bytes: bytes.into(),
|
||||||
|
|||||||
@@ -1,44 +1,51 @@
|
|||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use egui::TextEdit;
|
use egui::TextEdit;
|
||||||
use egui_commonmark::{CommonMarkCache, CommonMarkViewer};
|
use egui_commonmark::{CommonMarkCache, CommonMarkViewer};
|
||||||
use serde::{self, Deserialize, Serialize};
|
use serde::{self, Deserialize, Serialize};
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
PROJECT_FOLDER,
|
|
||||||
editors::{settings_editor::ProjectSettings, tags::Tag},
|
editors::{settings_editor::ProjectSettings, tags::Tag},
|
||||||
llm_integration::content_llm::{ContentAI, ReadyState, ReasoningEffort},
|
filesystem::{FILESYSTEM, LegacyFileSystem},
|
||||||
util,
|
util,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
use crate::llm_integration::content_llm::{ContentAI, ReadyState};
|
||||||
|
|
||||||
pub struct MainEditor {
|
pub struct MainEditor {
|
||||||
pub content: ContentSection,
|
pub content: ContentSection,
|
||||||
pub show_editor: bool,
|
pub show_editor: bool,
|
||||||
pub editor_separate_window: bool,
|
pub editor_separate_window: bool,
|
||||||
pub show_preview: bool,
|
pub show_preview: bool,
|
||||||
preview_cache: CommonMarkCache,
|
preview_cache: CommonMarkCache,
|
||||||
dialog: Option<ContentAI>,
|
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
dialog: ContentAI,
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
pub show_ai: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Clone for MainEditor {
|
impl Clone for MainEditor {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
Self {
|
Self {
|
||||||
content: self.content.clone(),
|
content: self.content.clone(),
|
||||||
|
|
||||||
show_editor: self.show_editor,
|
show_editor: self.show_editor,
|
||||||
editor_separate_window: self.editor_separate_window,
|
editor_separate_window: self.editor_separate_window,
|
||||||
show_preview: self.show_preview,
|
show_preview: self.show_preview,
|
||||||
preview_cache: CommonMarkCache::default(),
|
preview_cache: CommonMarkCache::default(),
|
||||||
|
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
dialog: self.dialog.clone(),
|
dialog: self.dialog.clone(),
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
show_ai: self.show_ai,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct ContentSection {
|
pub struct ContentSection {
|
||||||
#[serde(default)]
|
|
||||||
pub title: String,
|
pub title: String,
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -72,21 +79,16 @@ impl ContentSection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn save(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let path = PROJECT_FOLDER
|
FILESYSTEM.write(
|
||||||
.join("documents")
|
Path::new(&format!("documents/{id}.json", id = &self.id)),
|
||||||
.join(format!("{}.json", &self.id));
|
self.clone(),
|
||||||
|
)?;
|
||||||
let content = serde_json::to_string_pretty(self)?;
|
|
||||||
std::fs::write(path, content)?;
|
|
||||||
self.saved = true;
|
self.saved = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(id: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
pub fn load(id: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
let path = PROJECT_FOLDER.join("documents").join(format!("{id}.json"));
|
let mut section: Self = FILESYSTEM.read(Path::new(&format!("documents/{id}.json")))?;
|
||||||
|
|
||||||
let content = std::fs::read_to_string(&path)?;
|
|
||||||
let mut section: Self = serde_json::from_str(&content)?;
|
|
||||||
section.saved = true;
|
section.saved = true;
|
||||||
section.id = id.to_string();
|
section.id = id.to_string();
|
||||||
Ok(section)
|
Ok(section)
|
||||||
@@ -108,7 +110,11 @@ impl MainEditor {
|
|||||||
show_preview: false,
|
show_preview: false,
|
||||||
editor_separate_window: false,
|
editor_separate_window: false,
|
||||||
preview_cache: CommonMarkCache::default(),
|
preview_cache: CommonMarkCache::default(),
|
||||||
dialog: None,
|
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
show_ai: false,
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
dialog: ContentAI::new(String::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,7 +125,11 @@ impl MainEditor {
|
|||||||
show_preview: false,
|
show_preview: false,
|
||||||
editor_separate_window: false,
|
editor_separate_window: false,
|
||||||
preview_cache: CommonMarkCache::default(),
|
preview_cache: CommonMarkCache::default(),
|
||||||
dialog: None,
|
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
show_ai: false,
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
dialog: ContentAI::new(String::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,12 +169,12 @@ impl MainEditor {
|
|||||||
|
|
||||||
// delete button
|
// delete button
|
||||||
if ui.button("Delete").clicked() {
|
if ui.button("Delete").clicked() {
|
||||||
std::fs::remove_file(
|
FILESYSTEM
|
||||||
PROJECT_FOLDER
|
.delete(Path::new(&format!(
|
||||||
.join("documents")
|
"documents/{id}.json",
|
||||||
.join(format!("{}.json", self.content.id)),
|
id = &self.content.id
|
||||||
)
|
)))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
*self = Self::new();
|
*self = Self::new();
|
||||||
}
|
}
|
||||||
@@ -177,6 +187,12 @@ impl MainEditor {
|
|||||||
// preview toggle
|
// preview toggle
|
||||||
ui.checkbox(&mut self.show_preview, "Preview");
|
ui.checkbox(&mut self.show_preview, "Preview");
|
||||||
|
|
||||||
|
// assistant toggle
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
if project.ai_enabled() {
|
||||||
|
ui.checkbox(&mut self.show_ai, "AI Assistant");
|
||||||
|
}
|
||||||
|
|
||||||
// editor toggle
|
// editor toggle
|
||||||
ui.checkbox(&mut self.editor_separate_window, "Pop out editor");
|
ui.checkbox(&mut self.editor_separate_window, "Pop out editor");
|
||||||
});
|
});
|
||||||
@@ -222,10 +238,13 @@ impl MainEditor {
|
|||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
if let Some(dialog) = &mut self.dialog {
|
#[cfg(feature = "llm")]
|
||||||
dialog.ui(ui, project);
|
if self.show_ai && project.ai_enabled() {
|
||||||
|
let dialog = &mut self.dialog;
|
||||||
|
|
||||||
dialog.content = self.content.content.clone();
|
dialog.content = self.content.content.clone();
|
||||||
|
dialog.ui(ui, project);
|
||||||
|
|
||||||
if *dialog.ready.lock().unwrap() == ReadyState::Ready {
|
if *dialog.ready.lock().unwrap() == ReadyState::Ready {
|
||||||
self.content
|
self.content
|
||||||
.content
|
.content
|
||||||
@@ -301,7 +320,7 @@ impl MainEditor {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn editor_ui(&mut self, ui: &mut egui::Ui, project: &mut ProjectSettings) {
|
fn editor_ui(&mut self, ui: &mut egui::Ui, _project: &mut ProjectSettings) {
|
||||||
let _response = egui::ScrollArea::both()
|
let _response = egui::ScrollArea::both()
|
||||||
.auto_shrink([false, false])
|
.auto_shrink([false, false])
|
||||||
.id_salt("editor_scroll")
|
.id_salt("editor_scroll")
|
||||||
@@ -319,49 +338,18 @@ impl MainEditor {
|
|||||||
|
|
||||||
ui.set_min_width(max_width as f32);
|
ui.set_min_width(max_width as f32);
|
||||||
|
|
||||||
let text_edit = TextEdit::multiline(&mut self.content.content)
|
let response = ui.add(
|
||||||
.id_source("MainEditor_editor")
|
TextEdit::multiline(&mut self.content.content)
|
||||||
.font(egui::TextStyle::Monospace)
|
.id_source("MainEditor_editor")
|
||||||
.interactive(true)
|
.font(egui::TextStyle::Monospace)
|
||||||
.frame(false)
|
.interactive(true)
|
||||||
.lock_focus(true)
|
.frame(false)
|
||||||
.hint_text("Type here...")
|
.lock_focus(true)
|
||||||
.desired_width(max_width as f32);
|
.hint_text("Type here...")
|
||||||
|
.desired_width(max_width as f32),
|
||||||
let mut ctx_menu = false;
|
);
|
||||||
let response = ui
|
if response.changed() {
|
||||||
.add_sized(
|
self.content.saved = false;
|
||||||
egui::vec2(max_width as f32 - 30.0, ui.available_height()),
|
|
||||||
text_edit,
|
|
||||||
)
|
|
||||||
.on_hover_text("Right click to open context menu")
|
|
||||||
.context_menu(|ui| {
|
|
||||||
ctx_menu = true;
|
|
||||||
|
|
||||||
ui.menu_button("AI Actions", |ui| {
|
|
||||||
ui.add_enabled_ui(project.ai_enabled(), |ui| {
|
|
||||||
if ui.button("AI Assistant").clicked() {
|
|
||||||
self.dialog = Some(ContentAI {
|
|
||||||
content: self.content.content.clone(),
|
|
||||||
instruction: String::new(),
|
|
||||||
max_tokens: 1024,
|
|
||||||
reasoning_effort: ReasoningEffort::default(),
|
|
||||||
context_override: "".to_string(),
|
|
||||||
result: Arc::new(Mutex::new(String::new())),
|
|
||||||
open: true,
|
|
||||||
ready: Arc::new(Mutex::new(ReadyState::Idle)),
|
|
||||||
temperature: 0.7,
|
|
||||||
model_override: "".to_string(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(response) = response {
|
|
||||||
if response.response.changed() || ctx_menu {
|
|
||||||
self.content.saved = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
+41
-16
@@ -1,13 +1,19 @@
|
|||||||
use std::fs;
|
use std::path::Path;
|
||||||
|
|
||||||
use egui::TextEdit;
|
use egui::TextEdit;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::{PROJECT_FOLDER, editors::tags::Tag, util};
|
use crate::{
|
||||||
|
editors::tags::Tag,
|
||||||
|
filesystem::{FILESYSTEM, LegacyFileSystem},
|
||||||
|
util,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
pub struct Note {
|
pub struct Note {
|
||||||
|
pub id: String,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub content: String,
|
pub content: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@@ -17,12 +23,14 @@ pub struct Note {
|
|||||||
pub tags: Vec<String>,
|
pub tags: Vec<String>,
|
||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
pub id: String,
|
#[serde(default = "default_saved")]
|
||||||
|
|
||||||
#[serde(skip)]
|
|
||||||
pub saved: bool,
|
pub saved: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default_saved() -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for Note {
|
impl Default for Note {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@@ -48,18 +56,15 @@ impl Note {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(&mut self) -> std::io::Result<()> {
|
pub fn save(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let id = &self.id;
|
let id = &self.id;
|
||||||
let path = PROJECT_FOLDER.join("notes").join(format!("{id}.json"));
|
FILESYSTEM.write(Path::new(&format!("notes/{id}.json")), self.clone())?;
|
||||||
fs::write(path, serde_json::to_string(&self)?)?;
|
|
||||||
self.saved = true;
|
self.saved = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(id: &str) -> std::io::Result<Self> {
|
pub fn load(id: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
let path = PROJECT_FOLDER.join("notes").join(format!("{id}.json"));
|
let mut note: Self = FILESYSTEM.read(Path::new(&format!("notes/{id}.json")))?;
|
||||||
let content = fs::read_to_string(path)?;
|
|
||||||
let mut note: Note = serde_json::from_str(&content)?;
|
|
||||||
note.id = id.to_string();
|
note.id = id.to_string();
|
||||||
note.saved = true;
|
note.saved = true;
|
||||||
Ok(note)
|
Ok(note)
|
||||||
@@ -74,11 +79,31 @@ impl Note {
|
|||||||
|
|
||||||
util::saved_status(ui, self.saved, &self.id, &self.name);
|
util::saved_status(ui, self.saved, &self.id, &self.name);
|
||||||
|
|
||||||
if ui.button("Save").clicked() {
|
ui.horizontal(|ui| {
|
||||||
if let Err(e) = self.save() {
|
if ui.button("Save").clicked() {
|
||||||
eprintln!("Failed to save: {e}");
|
if let Err(e) = self.save() {
|
||||||
|
eprintln!("Failed to save: {e}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
if ui.button("Create Copy").clicked() {
|
||||||
|
let new_id = uuid::Uuid::new_v4().to_string();
|
||||||
|
let mut new_note = self.clone();
|
||||||
|
new_note.id = new_id;
|
||||||
|
new_note.name = format!("{} (Copy)", self.name);
|
||||||
|
if let Err(e) = new_note.save() {
|
||||||
|
eprintln!("Failed to save copy: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ui.button("Delete").clicked() {
|
||||||
|
if let Err(e) =
|
||||||
|
FILESYSTEM.delete(Path::new(&format!("notes/{id}.json", id = self.id)))
|
||||||
|
{
|
||||||
|
eprintln!("Failed to delete: {e}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let id = ui.make_persistent_id("note_name");
|
let id = ui.make_persistent_id("note_name");
|
||||||
egui::collapsing_header::CollapsingState::load_with_default_open(ui.ctx(), id, true)
|
egui::collapsing_header::CollapsingState::load_with_default_open(ui.ctx(), id, true)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
use core::f32;
|
use core::f32;
|
||||||
use egui::{CollapsingHeader, RichText, Sense, TextEdit, Ui, UiBuilder, vec2};
|
use egui::{CollapsingHeader, RichText, Sense, TextEdit, Ui, UiBuilder, vec2};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
PROJECT_FOLDER, RightPanelContent,
|
PROJECT_FOLDER, RightPanelContent,
|
||||||
@@ -8,6 +9,7 @@ use crate::{
|
|||||||
tags::Tag,
|
tags::Tag,
|
||||||
template_editor::{FieldValue, Template},
|
template_editor::{FieldValue, Template},
|
||||||
},
|
},
|
||||||
|
filesystem::{FILESYSTEM, LegacyFileSystem},
|
||||||
util,
|
util,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -81,21 +83,14 @@ impl ObjectInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn save(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let path = PROJECT_FOLDER
|
let id = &self.id;
|
||||||
.join("objects")
|
FILESYSTEM.write(Path::new(&format!("objects/{id}.json")), self.clone())?;
|
||||||
.join(format!("{}.json", &self.id));
|
|
||||||
|
|
||||||
let content = serde_json::to_string_pretty(self)?;
|
|
||||||
std::fs::write(&path, content)?;
|
|
||||||
self.saved = true;
|
self.saved = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(id: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
pub fn load(id: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
let path = PROJECT_FOLDER.join("objects").join(format!("{id}.json"));
|
let mut instance: Self = FILESYSTEM.read(Path::new(&format!("objects/{id}.json")))?;
|
||||||
|
|
||||||
let content = std::fs::read_to_string(&path)?;
|
|
||||||
let mut instance: ObjectInstance = serde_json::from_str(&content)?;
|
|
||||||
instance.saved = true;
|
instance.saved = true;
|
||||||
Ok(instance)
|
Ok(instance)
|
||||||
}
|
}
|
||||||
@@ -137,12 +132,10 @@ impl ObjectInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ui.button("Delete").clicked() {
|
if ui.button("Delete").clicked() {
|
||||||
std::fs::remove_file(
|
let id = &self.id;
|
||||||
PROJECT_FOLDER
|
FILESYSTEM
|
||||||
.join("objects")
|
.delete(Path::new(&format!("objects/{id}.json")))
|
||||||
.join(format!("{}.json", self.id)),
|
.expect("Failed to delete object");
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
*right_panel = Some(RightPanelContent::None);
|
*right_panel = Some(RightPanelContent::None);
|
||||||
}
|
}
|
||||||
@@ -274,7 +267,7 @@ impl ObjectInstance {
|
|||||||
if !value.is_empty() {
|
if !value.is_empty() {
|
||||||
let path = PROJECT_FOLDER.join("assets").join(&value);
|
let path = PROJECT_FOLDER.join("assets").join(&value);
|
||||||
|
|
||||||
if let Ok(bytes) = std::fs::read(&path) {
|
if let Ok(bytes) = FILESYSTEM.read_bytes(&path) {
|
||||||
let image_source = egui::ImageSource::Bytes {
|
let image_source = egui::ImageSource::Bytes {
|
||||||
uri: std::borrow::Cow::Owned(path.to_str().unwrap().to_string()),
|
uri: std::borrow::Cow::Owned(path.to_str().unwrap().to_string()),
|
||||||
bytes: bytes.into(),
|
bytes: bytes.into(),
|
||||||
|
|||||||
+196
-127
@@ -2,9 +2,12 @@ use chrono::NaiveDate;
|
|||||||
use egui::TextEdit;
|
use egui::TextEdit;
|
||||||
use egui_extras::DatePickerButton;
|
use egui_extras::DatePickerButton;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{io::Read, path::PathBuf, sync::LazyLock};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
use crate::{PROJECT_FOLDER, util::saved_status};
|
use crate::{
|
||||||
|
filesystem::{FILESYSTEM, LegacyFileSystem},
|
||||||
|
util::saved_status,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct ProjectSettings {
|
pub struct ProjectSettings {
|
||||||
@@ -14,6 +17,7 @@ pub struct ProjectSettings {
|
|||||||
project_description: String,
|
project_description: String,
|
||||||
|
|
||||||
// AI settings
|
// AI settings
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
pub ai_context: String,
|
pub ai_context: String,
|
||||||
|
|
||||||
// settings
|
// settings
|
||||||
@@ -29,17 +33,6 @@ pub struct ProjectSettings {
|
|||||||
pub saved: bool,
|
pub saved: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLOBAL_SETTINGS_PATH: LazyLock<String> =
|
|
||||||
LazyLock::new(|| match std::env::var("XDG_CONFIG_HOME") {
|
|
||||||
Ok(path) => path + "/worldcoder/settings.json",
|
|
||||||
Err(_) => {
|
|
||||||
eprintln!(
|
|
||||||
"XDG_CONFIG_HOME not set, using default path of ~/.config/worldcoder/settings.json"
|
|
||||||
);
|
|
||||||
"~/.config/worldcoder/settings.json".to_string()
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
impl ProjectSettings {
|
impl ProjectSettings {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
@@ -47,25 +40,10 @@ impl ProjectSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn load() -> Self {
|
pub fn load() -> Self {
|
||||||
let project_path = PROJECT_FOLDER.join("project.json");
|
if let Ok(mut proj) = FILESYSTEM.read::<Self>(Path::new("project.json")) {
|
||||||
|
|
||||||
let mut file = if let Ok(file) = std::fs::File::open(project_path) {
|
|
||||||
file
|
|
||||||
} else {
|
|
||||||
return Self::default();
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut contents = String::new();
|
|
||||||
file.read_to_string(&mut contents).unwrap();
|
|
||||||
if let Ok(mut proj) = serde_json::from_str::<Self>(&contents) {
|
|
||||||
proj.saved = true;
|
proj.saved = true;
|
||||||
|
|
||||||
// load global settings
|
|
||||||
proj.global_settings = EditorSettings::load_global();
|
proj.global_settings = EditorSettings::load_global();
|
||||||
|
|
||||||
// load local overrides
|
|
||||||
proj.local_overrides = EditorSettings::load();
|
proj.local_overrides = EditorSettings::load();
|
||||||
|
|
||||||
proj
|
proj
|
||||||
} else {
|
} else {
|
||||||
Self::default()
|
Self::default()
|
||||||
@@ -73,9 +51,9 @@ impl ProjectSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(&mut self) {
|
pub fn save(&mut self) {
|
||||||
let project_path = PROJECT_FOLDER.join("project.json");
|
FILESYSTEM
|
||||||
let content = serde_json::to_string_pretty(self).unwrap();
|
.write(Path::new("project.json"), self.clone())
|
||||||
std::fs::write(project_path, content).unwrap();
|
.unwrap();
|
||||||
|
|
||||||
self.global_settings.save();
|
self.global_settings.save();
|
||||||
self.local_overrides.save();
|
self.local_overrides.save();
|
||||||
@@ -83,7 +61,93 @@ impl ProjectSettings {
|
|||||||
self.saved = true;
|
self.saved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(unused)]
|
||||||
|
fn config_str_override(
|
||||||
|
label: &str,
|
||||||
|
field: &mut Option<String>,
|
||||||
|
default: &str,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
) -> bool {
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
|
ui.label(label);
|
||||||
|
|
||||||
|
if let Some(value) = field {
|
||||||
|
if ui.text_edit_singleline(value).changed() {
|
||||||
|
changed = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ui.button("Remove Override").clicked() {
|
||||||
|
*field = None;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} else if ui.button("Override").clicked() {
|
||||||
|
*field = Some(default.to_string());
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.end_row();
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
fn config_bool_override(
|
||||||
|
label: &str,
|
||||||
|
field: &mut Option<bool>,
|
||||||
|
default: bool,
|
||||||
|
ui: &mut egui::Ui,
|
||||||
|
) -> bool {
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
|
ui.label(label);
|
||||||
|
|
||||||
|
if let Some(value) = field {
|
||||||
|
if ui.checkbox(value, "Enable AI").changed() {
|
||||||
|
changed = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if ui.button("Remove Override").clicked() {
|
||||||
|
*field = None;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
} else if ui.button("Override").clicked() {
|
||||||
|
*field = Some(default);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.end_row();
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
fn config_str(field: &mut String, label: &str, ui: &mut egui::Ui) -> bool {
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
|
ui.label(label);
|
||||||
|
if ui.text_edit_singleline(field).changed() {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
|
fn config_bool(label: &str, field: &mut bool, ui: &mut egui::Ui) -> bool {
|
||||||
|
let mut changed = false;
|
||||||
|
|
||||||
|
ui.label(label);
|
||||||
|
if ui.checkbox(field, "Enable AI").changed() {
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
changed
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn ui(&mut self, ui: &mut egui::Ui) {
|
pub fn ui(&mut self, ui: &mut egui::Ui) {
|
||||||
// save state
|
// save state
|
||||||
saved_status(ui, self.saved, "N/A", "Project Settings");
|
saved_status(ui, self.saved, "N/A", "Project Settings");
|
||||||
@@ -91,6 +155,10 @@ impl ProjectSettings {
|
|||||||
self.save();
|
self.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ui.input(|i| i.key_pressed(egui::Key::S) && i.modifiers.ctrl) {
|
||||||
|
self.save();
|
||||||
|
}
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
// project settings
|
// project settings
|
||||||
@@ -99,80 +167,65 @@ impl ProjectSettings {
|
|||||||
.striped(true)
|
.striped(true)
|
||||||
.num_columns(2)
|
.num_columns(2)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
ui.label("Project Name");
|
if Self::config_str(&mut self.project_name, "Project Name", ui) { self.saved = false };
|
||||||
ui.text_edit_singleline(&mut self.project_name);
|
if Self::config_str(&mut self.project_author, "Project Author", ui) { self.saved = false };
|
||||||
|
if Self::config_str(&mut self.project_description, "Project Description", ui) { self.saved = false };
|
||||||
ui.end_row();
|
|
||||||
|
|
||||||
ui.label("Project Author");
|
|
||||||
ui.text_edit_singleline(&mut self.project_author);
|
|
||||||
|
|
||||||
ui.end_row();
|
|
||||||
|
|
||||||
ui.label("Project Description");
|
|
||||||
ui.text_edit_singleline(&mut self.project_description);
|
|
||||||
|
|
||||||
ui.end_row();
|
|
||||||
|
|
||||||
ui.label("Date");
|
ui.label("Date");
|
||||||
ui.add(DatePickerButton::new(&mut self.date));
|
if ui.add(DatePickerButton::new(&mut self.date)).changed() { self.saved = false };
|
||||||
|
|
||||||
ui.end_row();
|
ui.end_row();
|
||||||
|
|
||||||
ui.label("AI Context Prompt");
|
#[cfg(feature = "llm")]
|
||||||
ui.add(TextEdit::multiline(&mut self.ai_context)
|
{
|
||||||
.font(egui::TextStyle::Monospace)
|
ui.label("AI Context Prompt");
|
||||||
.interactive(true)
|
if ui.add(TextEdit::multiline(&mut self.ai_context)
|
||||||
.frame(false)
|
.font(egui::TextStyle::Monospace)
|
||||||
.lock_focus(true)
|
.interactive(true)
|
||||||
.hint_text("What is this project about? what should the LLM know when generating content for this project?"));
|
.frame(false)
|
||||||
|
.lock_focus(true)
|
||||||
ui.end_row();
|
.hint_text("What is this project about? what should the LLM know when generating content for this project?")).changed() { self.saved = false };
|
||||||
|
ui.end_row();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
|
|
||||||
// local settings overrides for editor
|
// local settings overrides for editor
|
||||||
|
|
||||||
ui.heading("Local Overrides");
|
ui.heading("Local Overrides");
|
||||||
egui::Grid::new("local overrides")
|
egui::Grid::new("local overrides")
|
||||||
.striped(true)
|
.striped(true)
|
||||||
.num_columns(2)
|
.num_columns(2)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
ui.label("Enable AI");
|
#[cfg(feature = "llm")]
|
||||||
if let Some(ai_enabled) = &mut self.local_overrides.ai_enabled {
|
if ProjectSettings::config_str_override(
|
||||||
ui.checkbox(ai_enabled, "Enable AI");
|
"LLM API URI",
|
||||||
if ui.button("Remove Override").clicked() {
|
&mut self.local_overrides.llm_api_uri,
|
||||||
self.local_overrides.ai_enabled = None;
|
"http://localhost:1234",
|
||||||
}
|
ui,
|
||||||
} else if ui.button("Override").clicked() {
|
) {
|
||||||
self.local_overrides.ai_enabled = Some(true);
|
self.saved = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.end_row();
|
#[cfg(feature = "llm")]
|
||||||
|
if ProjectSettings::config_str_override(
|
||||||
ui.label("LLM API URI");
|
"LLM API Key",
|
||||||
if let Some(llm_api_uri) = &mut self.local_overrides.llm_api_uri {
|
&mut self.local_overrides.llm_api_key,
|
||||||
ui.text_edit_singleline(llm_api_uri);
|
"1234",
|
||||||
if ui.button("Remove Override").clicked() {
|
ui,
|
||||||
self.local_overrides.llm_api_uri = None;
|
) {
|
||||||
}
|
self.saved = false;
|
||||||
} else if ui.button("Override").clicked() {
|
|
||||||
self.local_overrides.llm_api_uri = Some("http://localhost:1234".to_string());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.end_row();
|
#[cfg(feature = "llm")]
|
||||||
|
if ProjectSettings::config_bool_override(
|
||||||
ui.label("LLM API Key");
|
"Enable AI",
|
||||||
if let Some(llm_api_key) = &mut self.local_overrides.llm_api_key {
|
&mut self.local_overrides.ai_enabled,
|
||||||
ui.text_edit_singleline(llm_api_key);
|
true,
|
||||||
if ui.button("Remove Override").clicked() {
|
ui,
|
||||||
self.local_overrides.llm_api_key = None;
|
) {
|
||||||
}
|
self.saved = false;
|
||||||
} else if ui.button("Override").clicked() {
|
|
||||||
self.local_overrides.llm_api_key = Some("1234".to_string());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.end_row();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.separator();
|
ui.separator();
|
||||||
@@ -183,23 +236,37 @@ impl ProjectSettings {
|
|||||||
.striped(true)
|
.striped(true)
|
||||||
.num_columns(2)
|
.num_columns(2)
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
ui.label("Enable AI");
|
#[cfg(feature = "llm")]
|
||||||
ui.checkbox(&mut self.global_settings.ai_enabled.unwrap(), "Enable AI");
|
if Self::config_bool(
|
||||||
|
"Enable AI",
|
||||||
|
self.global_settings.ai_enabled.as_mut().unwrap(),
|
||||||
|
ui,
|
||||||
|
) {
|
||||||
|
self.saved = false;
|
||||||
|
}
|
||||||
|
|
||||||
ui.end_row();
|
#[cfg(feature = "llm")]
|
||||||
|
if Self::config_str(
|
||||||
|
self.global_settings.llm_api_uri.as_mut().unwrap(),
|
||||||
|
"LLM API URI",
|
||||||
|
ui,
|
||||||
|
) {
|
||||||
|
self.saved = false
|
||||||
|
};
|
||||||
|
|
||||||
ui.label("LLM API URI");
|
#[cfg(feature = "llm")]
|
||||||
ui.text_edit_singleline(self.global_settings.llm_api_uri.as_mut().unwrap());
|
if Self::config_str(
|
||||||
|
self.global_settings.llm_api_key.as_mut().unwrap(),
|
||||||
ui.end_row();
|
"LLM API Key",
|
||||||
|
ui,
|
||||||
ui.label("LLM API Key");
|
) {
|
||||||
ui.text_edit_singleline(self.global_settings.llm_api_key.as_mut().unwrap());
|
self.saved = false
|
||||||
|
};
|
||||||
ui.end_row();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
#[allow(unused)]
|
||||||
pub fn ai_enabled(&mut self) -> bool {
|
pub fn ai_enabled(&mut self) -> bool {
|
||||||
let client = reqwest::blocking::Client::new();
|
let client = reqwest::blocking::Client::new();
|
||||||
|
|
||||||
@@ -236,8 +303,9 @@ impl Default for ProjectSettings {
|
|||||||
project_author: "Your Name".to_string(),
|
project_author: "Your Name".to_string(),
|
||||||
project_description: "Description of your project".to_string(),
|
project_description: "Description of your project".to_string(),
|
||||||
|
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
ai_context: "".to_string(),
|
ai_context: "".to_string(),
|
||||||
global_settings: EditorSettings::new(),
|
global_settings: EditorSettings::default(),
|
||||||
local_overrides: EditorSettings::new(),
|
local_overrides: EditorSettings::new(),
|
||||||
|
|
||||||
// window state
|
// window state
|
||||||
@@ -249,11 +317,15 @@ impl Default for ProjectSettings {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone)]
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
pub struct EditorSettings {
|
pub struct EditorSettings {
|
||||||
pub llm_api_uri: Option<String>,
|
|
||||||
pub llm_api_key: Option<String>,
|
|
||||||
pub ai_enabled: Option<bool>,
|
|
||||||
pub dark_theme: Option<bool>,
|
pub dark_theme: Option<bool>,
|
||||||
|
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
pub llm_api_uri: Option<String>,
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
pub llm_api_key: Option<String>,
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
|
pub ai_enabled: Option<bool>,
|
||||||
|
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
is_global: bool,
|
is_global: bool,
|
||||||
}
|
}
|
||||||
@@ -261,8 +333,11 @@ pub struct EditorSettings {
|
|||||||
impl Default for EditorSettings {
|
impl Default for EditorSettings {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
llm_api_uri: Some("http://localhost:1234".to_string()),
|
llm_api_uri: Some("http://localhost:1234".to_string()),
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
llm_api_key: Some("".to_string()),
|
llm_api_key: Some("".to_string()),
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
ai_enabled: Some(true),
|
ai_enabled: Some(true),
|
||||||
dark_theme: Some(true),
|
dark_theme: Some(true),
|
||||||
|
|
||||||
@@ -275,8 +350,11 @@ impl Default for EditorSettings {
|
|||||||
impl EditorSettings {
|
impl EditorSettings {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
llm_api_uri: None,
|
llm_api_uri: None,
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
llm_api_key: None,
|
llm_api_key: None,
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
ai_enabled: None,
|
ai_enabled: None,
|
||||||
dark_theme: None,
|
dark_theme: None,
|
||||||
|
|
||||||
@@ -285,43 +363,34 @@ impl EditorSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn load() -> Self {
|
pub fn load() -> Self {
|
||||||
let path = PROJECT_FOLDER.join("settings.json");
|
if let Ok(mut settings) = FILESYSTEM.read::<Self>(Path::new("settings.json")) {
|
||||||
let mut file = if let Ok(file) = std::fs::File::open(path) {
|
settings.is_global = false;
|
||||||
file
|
return settings;
|
||||||
} else {
|
}
|
||||||
return Self::default();
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut contents = String::new();
|
Self::new()
|
||||||
file.read_to_string(&mut contents).unwrap();
|
|
||||||
serde_json::from_str(&contents).unwrap()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(&self) {
|
pub fn save(&self) {
|
||||||
let content = serde_json::to_string_pretty(self).unwrap();
|
|
||||||
|
|
||||||
let path = if self.is_global {
|
let path = if self.is_global {
|
||||||
PathBuf::from(GLOBAL_SETTINGS_PATH.clone())
|
FILESYSTEM.config_path()
|
||||||
} else {
|
} else {
|
||||||
PROJECT_FOLDER.join("settings.json")
|
PathBuf::from("settings.json")
|
||||||
};
|
};
|
||||||
|
|
||||||
std::fs::write(path, content).unwrap();
|
FILESYSTEM.write(path.as_path(), self.clone()).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load_global() -> Self {
|
pub fn load_global() -> Self {
|
||||||
let path = PathBuf::from(GLOBAL_SETTINGS_PATH.clone());
|
let path = FILESYSTEM.config_path();
|
||||||
|
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
std::fs::create_dir_all(path.parent().unwrap()).unwrap();
|
FILESYSTEM.mkdir(path.parent().unwrap()).unwrap();
|
||||||
let content = serde_json::to_string_pretty(&Self::default()).unwrap();
|
FILESYSTEM.write(path.as_path(), Self::default()).unwrap();
|
||||||
std::fs::write(&path, content).unwrap();
|
|
||||||
|
|
||||||
// return a default config
|
|
||||||
return Self::default();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = std::fs::read_to_string(path).unwrap();
|
let mut settings = FILESYSTEM.read::<Self>(path.as_path()).unwrap();
|
||||||
serde_json::from_str(&content).unwrap()
|
settings.is_global = true;
|
||||||
|
settings
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,12 @@ use chrono::NaiveDate;
|
|||||||
use core::fmt;
|
use core::fmt;
|
||||||
use egui::ScrollArea;
|
use egui::ScrollArea;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
PROJECT_FOLDER, RightPanelContent,
|
RightPanelContent,
|
||||||
editors::object_editor::ObjectInstance,
|
editors::object_editor::ObjectInstance,
|
||||||
|
filesystem::{FILESYSTEM, LegacyFileSystem},
|
||||||
util::{self, Error},
|
util::{self, Error},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -171,21 +173,14 @@ impl Default for Template {
|
|||||||
|
|
||||||
impl Template {
|
impl Template {
|
||||||
pub fn load(id: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
pub fn load(id: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||||
let path = PROJECT_FOLDER.join("templates").join(format!("{id}.json"));
|
let mut template = FILESYSTEM.read::<Self>(Path::new(&format!("templates/{id}.json")))?;
|
||||||
|
|
||||||
let content = std::fs::read_to_string(&path)?;
|
|
||||||
let mut template: Self = serde_json::from_str(&content)?;
|
|
||||||
template.saved = true;
|
template.saved = true;
|
||||||
Ok(template)
|
Ok(template)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn save(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
pub fn save(&mut self) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let path = PROJECT_FOLDER
|
let id = &self.id;
|
||||||
.join("templates")
|
FILESYSTEM.write(Path::new(&format!("templates/{id}.json")), self.clone())?;
|
||||||
.join(format!("{}.json", &self.id));
|
|
||||||
|
|
||||||
let content = serde_json::to_string_pretty(self)?;
|
|
||||||
std::fs::write(path, content)?;
|
|
||||||
self.saved = true;
|
self.saved = true;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -203,16 +198,6 @@ impl Template {
|
|||||||
|
|
||||||
ScrollArea::vertical().show(ui, |ui| {
|
ScrollArea::vertical().show(ui, |ui| {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
// ui.group(|ui| {
|
|
||||||
// ui.horizontal(|ui| {
|
|
||||||
// if self.saved {
|
|
||||||
// ui.label(RichText::new("✓ Saved").color(egui::Color32::GREEN));
|
|
||||||
// } else {
|
|
||||||
// ui.label(RichText::new("* Unsaved").color(egui::Color32::YELLOW));
|
|
||||||
// }
|
|
||||||
// ui.label(format!("id: {}", self.id));
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
util::saved_status(ui, self.saved, &self.id, &self.name);
|
util::saved_status(ui, self.saved, &self.id, &self.name);
|
||||||
|
|
||||||
// Save/Cancel buttons
|
// Save/Cancel buttons
|
||||||
@@ -231,13 +216,10 @@ impl Template {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ui.button("Delete").clicked() {
|
if ui.button("Delete").clicked() {
|
||||||
std::fs::remove_file(
|
let id = &self.id;
|
||||||
PROJECT_FOLDER
|
FILESYSTEM
|
||||||
.join("templates")
|
.delete(Path::new(&format!("templates/{id}.json")))
|
||||||
.join(format!("{}.json", self.id)),
|
.unwrap();
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
*new_instance = Some(RightPanelContent::None);
|
*new_instance = Some(RightPanelContent::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+60
-106
@@ -1,4 +1,4 @@
|
|||||||
use walkdir::{DirEntry, WalkDir};
|
use std::path::Path;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
PROJECT_FOLDER, RightPanelContent,
|
PROJECT_FOLDER, RightPanelContent,
|
||||||
@@ -7,6 +7,7 @@ use crate::{
|
|||||||
asset_editor::Asset, content_editor::ContentSection, object_editor::ObjectInstance,
|
asset_editor::Asset, content_editor::ContentSection, object_editor::ObjectInstance,
|
||||||
tags::Tag, template_editor::Template,
|
tags::Tag, template_editor::Template,
|
||||||
},
|
},
|
||||||
|
filesystem::{FILESYSTEM, FsError, LegacyFileSystem},
|
||||||
note_editor::Note,
|
note_editor::Note,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -162,14 +163,6 @@ impl Explorer {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively renders a tree of documents.
|
|
||||||
///
|
|
||||||
/// Each document is represented by a single element in the `documents` array.
|
|
||||||
/// The `parent_id` parameter is used to filter out documents that do not have the current
|
|
||||||
/// parent. If `parent_id` is `None`, all documents are rendered.
|
|
||||||
///
|
|
||||||
/// `load_doc` is a mutable reference to a `MainEditor`. When a document is clicked, it
|
|
||||||
/// is loaded into the `MainEditor` and returned as `Some`.
|
|
||||||
fn render_doc_branch(
|
fn render_doc_branch(
|
||||||
ui: &mut egui::Ui,
|
ui: &mut egui::Ui,
|
||||||
documents: &[ContentSection],
|
documents: &[ContentSection],
|
||||||
@@ -238,100 +231,64 @@ impl Explorer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn render_assets(&mut self, ui: &mut egui::Ui, to_load: &mut Option<RightPanelContent>) {
|
fn render_assets(&mut self, ui: &mut egui::Ui, to_load: &mut Option<RightPanelContent>) {
|
||||||
|
Self::render_asset_dir(ui, to_load, Path::new("assets"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_asset_dir(ui: &mut egui::Ui, to_load: &mut Option<RightPanelContent>, path: &Path) {
|
||||||
|
let files = FILESYSTEM.lsfiles(path).unwrap();
|
||||||
|
let dirs = FILESYSTEM.lsdirs(path).unwrap();
|
||||||
|
|
||||||
|
let file_name = path.file_name().unwrap().to_str().unwrap().to_string();
|
||||||
|
|
||||||
egui::collapsing_header::CollapsingState::load_with_default_open(
|
egui::collapsing_header::CollapsingState::load_with_default_open(
|
||||||
ui.ctx(),
|
ui.ctx(),
|
||||||
ui.make_persistent_id("assets"),
|
ui.make_persistent_id(&file_name),
|
||||||
true,
|
false,
|
||||||
)
|
)
|
||||||
.show_header(ui, |ui| {
|
.show_header(ui, |ui| {
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.label("Assets");
|
ui.label(file_name);
|
||||||
|
let _clicked = ui.button("+").on_hover_text("Add new item").clicked();
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.body(|ui| {
|
.body(|ui| {
|
||||||
let entries: Vec<_> = WalkDir::new(PROJECT_FOLDER.join("assets"))
|
// recursive call to render the next level of documents
|
||||||
.min_depth(1)
|
for dir in dirs.iter() {
|
||||||
.max_depth(1) // Only immediate children
|
Self::render_asset_dir(ui, to_load, dir);
|
||||||
.sort_by(|a, b| {
|
}
|
||||||
// Directories first, then files
|
|
||||||
let a_is_dir = a.file_type().is_dir();
|
|
||||||
let b_is_dir = b.file_type().is_dir();
|
|
||||||
if a_is_dir == b_is_dir {
|
|
||||||
a.file_name().cmp(b.file_name())
|
|
||||||
} else if a_is_dir {
|
|
||||||
std::cmp::Ordering::Less
|
|
||||||
} else {
|
|
||||||
std::cmp::Ordering::Greater
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(Result::ok)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
for entry in entries {
|
for file in files.iter() {
|
||||||
Self::render_entry(ui, to_load, &entry);
|
Self::render_asset(ui, to_load, file);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_entry(ui: &mut egui::Ui, to_load: &mut Option<RightPanelContent>, entry: &DirEntry) {
|
fn render_asset(ui: &mut egui::Ui, to_load: &mut Option<RightPanelContent>, path: &Path) {
|
||||||
let file_type = entry.file_type();
|
let file_name = path.file_name().unwrap().to_str().unwrap().to_string();
|
||||||
let is_dir = file_type.is_dir();
|
|
||||||
let file_name = entry.file_name().to_string_lossy();
|
|
||||||
let path = entry.path();
|
|
||||||
|
|
||||||
if is_dir {
|
if ui
|
||||||
let entries: Vec<_> = WalkDir::new(path)
|
.selectable_label(false, format!("📄 {file_name}"))
|
||||||
.min_depth(1)
|
.clicked()
|
||||||
.max_depth(1)
|
{
|
||||||
.sort_by(|a, b| a.file_name().cmp(b.file_name()))
|
// use asset::load to get the file at the path
|
||||||
.into_iter()
|
let asset_path = path.strip_prefix(PROJECT_FOLDER.join("assets")).unwrap();
|
||||||
.filter_map(Result::ok)
|
let asset = Asset::open(asset_path.to_string_lossy().to_string());
|
||||||
.collect();
|
*to_load = Some(RightPanelContent::Asset(Box::new(asset)));
|
||||||
|
|
||||||
egui::collapsing_header::CollapsingState::load_with_default_open(
|
|
||||||
ui.ctx(),
|
|
||||||
ui.make_persistent_id(&file_name),
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.show_header(ui, |ui| {
|
|
||||||
ui.horizontal(|ui| {
|
|
||||||
ui.label(file_name);
|
|
||||||
let _clicked = ui.button("+").on_hover_text("Add new item").clicked();
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.body(|ui| {
|
|
||||||
// recursive call to render the next level of documents
|
|
||||||
for entry in entries {
|
|
||||||
Self::render_entry(ui, to_load, &entry);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Handle file
|
|
||||||
if ui
|
|
||||||
.selectable_label(false, format!("📄 {file_name}"))
|
|
||||||
.clicked()
|
|
||||||
{
|
|
||||||
// use asset::load to get the file at the path
|
|
||||||
let asset_path = path.strip_prefix(PROJECT_FOLDER.join("assets")).unwrap();
|
|
||||||
let asset = Asset::open(asset_path.to_string_lossy().to_string());
|
|
||||||
*to_load = Some(RightPanelContent::Asset(Box::new(asset)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load templates from the templates folder
|
// load templates from the templates folder
|
||||||
fn load_templates(&mut self) -> std::io::Result<()> {
|
fn load_templates(&mut self) -> Result<(), FsError> {
|
||||||
let templates_folder = PROJECT_FOLDER.join("templates");
|
let path = Path::new("templates");
|
||||||
if !templates_folder.exists() {
|
|
||||||
std::fs::create_dir_all(&templates_folder)?;
|
if !FILESYSTEM.exists(path) {
|
||||||
|
FILESYSTEM.mkdir(path)?;
|
||||||
}
|
}
|
||||||
let mut templates = Vec::new();
|
let mut templates = Vec::new();
|
||||||
for entry in std::fs::read_dir(&templates_folder).unwrap() {
|
for entry in FILESYSTEM.lsfiles(path)? {
|
||||||
let path = entry.unwrap().path();
|
match FILESYSTEM.read::<Template>(&entry) {
|
||||||
match Template::load(path.file_stem().unwrap().to_str().unwrap()) {
|
|
||||||
Ok(t) => templates.push(t),
|
Ok(t) => templates.push(t),
|
||||||
Err(err) => eprintln!("Could not parse file {path:?}: {err}"),
|
Err(err) => eprintln!("Could not parse file {entry:?}: {err}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.templates = templates;
|
self.templates = templates;
|
||||||
@@ -340,17 +297,16 @@ impl Explorer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load objects from the objects folder
|
// load objects from the objects folder
|
||||||
fn load_objects(&mut self) -> std::io::Result<()> {
|
fn load_objects(&mut self) -> Result<(), FsError> {
|
||||||
let objects_folder = PROJECT_FOLDER.join("objects");
|
let path = Path::new("objects");
|
||||||
if !objects_folder.exists() {
|
if !FILESYSTEM.exists(path) {
|
||||||
std::fs::create_dir_all(&objects_folder)?;
|
FILESYSTEM.mkdir(path)?;
|
||||||
}
|
}
|
||||||
let mut objects = Vec::new();
|
let mut objects = Vec::new();
|
||||||
for entry in std::fs::read_dir(&objects_folder).unwrap() {
|
for entry in FILESYSTEM.lsfiles(path)? {
|
||||||
let path = entry.unwrap().path();
|
match FILESYSTEM.read::<ObjectInstance>(&entry) {
|
||||||
match ObjectInstance::load(path.file_stem().unwrap().to_str().unwrap()) {
|
|
||||||
Ok(o) => objects.push(o),
|
Ok(o) => objects.push(o),
|
||||||
Err(err) => eprintln!("Could not parse file {path:?}: {err}"),
|
Err(err) => eprintln!("Could not parse file {entry:?}: {err}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.objects = objects;
|
self.objects = objects;
|
||||||
@@ -359,16 +315,15 @@ impl Explorer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load notes from the notes folder
|
// load notes from the notes folder
|
||||||
fn load_notes(&mut self) -> std::io::Result<()> {
|
fn load_notes(&mut self) -> Result<(), FsError> {
|
||||||
let notes_folder = PROJECT_FOLDER.join("notes");
|
let path = Path::new("notes");
|
||||||
if !notes_folder.exists() {
|
if !FILESYSTEM.exists(path) {
|
||||||
std::fs::create_dir_all(¬es_folder)?;
|
FILESYSTEM.mkdir(path)?;
|
||||||
}
|
}
|
||||||
let mut notes = Vec::new();
|
let mut notes = Vec::new();
|
||||||
|
|
||||||
for entry in std::fs::read_dir(¬es_folder).unwrap() {
|
for entry in FILESYSTEM.lsfiles(path)? {
|
||||||
let path = entry.unwrap().path();
|
match FILESYSTEM.read::<Note>(&entry) {
|
||||||
match Note::load(path.file_stem().unwrap().to_str().unwrap()) {
|
|
||||||
Ok(note) => notes.push(note),
|
Ok(note) => notes.push(note),
|
||||||
Err(err) => eprintln!("Could not parse file {path:?}: {err}"),
|
Err(err) => eprintln!("Could not parse file {path:?}: {err}"),
|
||||||
}
|
}
|
||||||
@@ -380,18 +335,17 @@ impl Explorer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load documents from the documents folder
|
// load documents from the documents folder
|
||||||
fn load_documents(&mut self) -> std::io::Result<()> {
|
fn load_documents(&mut self) -> Result<(), FsError> {
|
||||||
let documents_folder = PROJECT_FOLDER.join("documents");
|
let path = Path::new("documents");
|
||||||
if !documents_folder.exists() {
|
if !FILESYSTEM.exists(path) {
|
||||||
std::fs::create_dir_all(&documents_folder)?;
|
FILESYSTEM.mkdir(path)?;
|
||||||
}
|
}
|
||||||
let mut documents = Vec::new();
|
let mut documents = Vec::new();
|
||||||
|
|
||||||
for entry in std::fs::read_dir(&documents_folder).unwrap() {
|
for entry in FILESYSTEM.lsfiles(path)? {
|
||||||
let path = entry.unwrap().path();
|
match FILESYSTEM.read::<ContentSection>(&entry) {
|
||||||
match ContentSection::load(path.file_stem().unwrap().to_str().unwrap()) {
|
|
||||||
Ok(document) => documents.push(MainEditor::open(document)),
|
Ok(document) => documents.push(MainEditor::open(document)),
|
||||||
Err(err) => eprintln!("Could not parse file {path:?}: {err}"),
|
Err(err) => eprintln!("Could not parse file {entry:?}: {err}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,7 +354,7 @@ impl Explorer {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load_tags(&mut self) -> std::io::Result<()> {
|
fn load_tags(&mut self) -> Result<(), FsError> {
|
||||||
self.tags = Tag::load_all();
|
self.tags = Tag::load_all();
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,103 @@
|
|||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
io,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
sync::LazyLock,
|
||||||
|
};
|
||||||
|
|
||||||
|
use serde::{Serialize, de::DeserializeOwned};
|
||||||
|
|
||||||
|
#[cfg(feature = "native")]
|
||||||
|
use crate::PROJECT_FOLDER;
|
||||||
|
use crate::filesystem::native::NativeFileSystem;
|
||||||
|
|
||||||
|
#[cfg(feature = "native")]
|
||||||
|
pub mod native;
|
||||||
|
|
||||||
|
#[cfg(feature = "web")]
|
||||||
|
pub mod web;
|
||||||
|
|
||||||
|
pub static FILESYSTEM: LazyLock<NativeFileSystem> = LazyLock::new(|| {
|
||||||
|
#[cfg(feature = "native")]
|
||||||
|
return NativeFileSystem::new(PROJECT_FOLDER.clone());
|
||||||
|
#[cfg(feature = "web")]
|
||||||
|
return Box::new(web::WebFileSystem::new());
|
||||||
|
});
|
||||||
|
|
||||||
|
pub trait LegacyFileSystem {
|
||||||
|
fn read<T: DeserializeOwned>(&self, path: &Path) -> Result<T, FsError>;
|
||||||
|
fn read_bytes(&self, path: &Path) -> Result<Vec<u8>, FsError>;
|
||||||
|
fn write<T: Serialize>(&self, path: &Path, data: T) -> Result<(), FsError>;
|
||||||
|
fn delete(&self, path: &Path) -> Result<(), FsError>;
|
||||||
|
fn lsfiles(&self, path: &Path) -> Result<Vec<PathBuf>, FsError>;
|
||||||
|
fn lsdirs(&self, path: &Path) -> Result<Vec<PathBuf>, FsError>;
|
||||||
|
fn mkdir(&self, path: &Path) -> Result<(), FsError>;
|
||||||
|
fn rename(&self, path: &Path, new_path: &Path) -> Result<(), FsError>;
|
||||||
|
#[allow(unused)]
|
||||||
|
fn exists(&self, path: &Path) -> bool;
|
||||||
|
fn config_path(&self) -> PathBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ────────────────────────────────────────────────────────────────
|
||||||
|
// Custom error type
|
||||||
|
// ────────────────────────────────────────────────────────────────
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum FsError {
|
||||||
|
Io(io::Error),
|
||||||
|
Serde(serde_json::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for FsError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
FsError::Io(e) => write!(f, "IO error: {e}"),
|
||||||
|
FsError::Serde(e) => write!(f, "Serialization error: {e}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::error::Error for FsError {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
match self {
|
||||||
|
FsError::Io(e) => Some(e),
|
||||||
|
FsError::Serde(e) => Some(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the two underlying error types into our own
|
||||||
|
impl From<io::Error> for FsError {
|
||||||
|
fn from(err: io::Error) -> Self {
|
||||||
|
FsError::Io(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl From<serde_json::Error> for FsError {
|
||||||
|
fn from(err: serde_json::Error) -> Self {
|
||||||
|
FsError::Serde(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct Id(String);
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub trait FileSystem {
|
||||||
|
fn load<T: DeserializeOwned>(&self, id: Id) -> Result<T, FsError>;
|
||||||
|
fn save<T: Serialize>(&self, id: Id, data: T) -> Result<(), FsError>;
|
||||||
|
fn mkdir(&self, path: Path) -> Result<(), FsError>;
|
||||||
|
fn exists(&self, path: Path) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct Index {
|
||||||
|
file_cache: HashMap<Id, PathBuf>,
|
||||||
|
project_root: Directory,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub struct Directory {
|
||||||
|
name: String,
|
||||||
|
id: Id,
|
||||||
|
children: HashMap<Id, Directory>,
|
||||||
|
files: Vec<Id>,
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
use std::fs;
|
||||||
|
use std::io::{ErrorKind, Read};
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
use serde::Serialize;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
|
use crate::filesystem::{FsError, LegacyFileSystem};
|
||||||
|
|
||||||
|
pub struct NativeFileSystem {
|
||||||
|
project_root: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NativeFileSystem {
|
||||||
|
/// Create a new instance.
|
||||||
|
pub fn new(root: impl Into<PathBuf>) -> Self {
|
||||||
|
Self {
|
||||||
|
project_root: root.into(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Resolve the user supplied *relative* path against the project root.
|
||||||
|
#[inline]
|
||||||
|
fn full_path(&self, path: &Path) -> PathBuf {
|
||||||
|
self.project_root.join(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LegacyFileSystem for NativeFileSystem {
|
||||||
|
fn read<T: DeserializeOwned>(&self, path: &Path) -> Result<T, FsError> {
|
||||||
|
let full_path = self.full_path(path);
|
||||||
|
let file = fs::File::open(full_path).map_err(FsError::Io)?;
|
||||||
|
serde_json::from_reader(file).map_err(FsError::Serde)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_bytes(&self, path: &Path) -> Result<Vec<u8>, FsError> {
|
||||||
|
let full_path = self.full_path(path);
|
||||||
|
let mut contents = Vec::new();
|
||||||
|
fs::File::open(full_path)?.read_to_end(&mut contents)?;
|
||||||
|
Ok(contents)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write<T: Serialize>(&self, path: &Path, data: T) -> Result<(), FsError> {
|
||||||
|
let full_path = self.full_path(path);
|
||||||
|
|
||||||
|
// Ensure the parent directory exists.
|
||||||
|
if let Some(parent) = full_path.parent() {
|
||||||
|
fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let file = fs::File::create(full_path)?;
|
||||||
|
serde_json::to_writer(file, &data).map_err(FsError::Serde)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete(&self, path: &Path) -> Result<(), FsError> {
|
||||||
|
let full_path = self.full_path(path);
|
||||||
|
match fs::remove_file(&full_path) {
|
||||||
|
Ok(()) => Ok(()),
|
||||||
|
Err(e) if e.kind() == ErrorKind::IsADirectory => {
|
||||||
|
// Remove a directory tree.
|
||||||
|
fs::remove_dir_all(full_path).map_err(FsError::Io)
|
||||||
|
}
|
||||||
|
Err(e) => Err(FsError::Io(e)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mkdir(&self, path: &Path) -> Result<(), FsError> {
|
||||||
|
let full_path = self.full_path(path);
|
||||||
|
fs::create_dir_all(full_path).map_err(FsError::Io)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lsfiles(&self, path: &Path) -> Result<Vec<PathBuf>, FsError> {
|
||||||
|
let full_path = self.full_path(path);
|
||||||
|
let paths = fs::read_dir(full_path)?
|
||||||
|
.filter_map(|res| res.ok())
|
||||||
|
.filter(|entry| entry.file_type().unwrap().is_file())
|
||||||
|
.map(|entry| entry.path())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(paths)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn lsdirs(&self, path: &Path) -> Result<Vec<PathBuf>, FsError> {
|
||||||
|
let full_path = self.full_path(path);
|
||||||
|
let paths = fs::read_dir(full_path)?
|
||||||
|
.filter_map(|res| res.ok())
|
||||||
|
.filter(|entry| entry.file_type().unwrap().is_dir())
|
||||||
|
.map(|entry| entry.path())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(paths)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exists(&self, path: &Path) -> bool {
|
||||||
|
let full_path = self.full_path(path);
|
||||||
|
full_path.exists()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rename(&self, path: &Path, other: &Path) -> Result<(), FsError> {
|
||||||
|
let full_path = self.full_path(path);
|
||||||
|
let full_other = self.full_path(other);
|
||||||
|
fs::rename(full_path, full_other).map_err(FsError::Io)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn config_path(&self) -> PathBuf {
|
||||||
|
match std::env::var("HOME") {
|
||||||
|
Ok(path) => PathBuf::from(path + "/.config/worldcoder/settings.json"),
|
||||||
|
Err(_) => {
|
||||||
|
eprintln!(
|
||||||
|
"XDG_CONFIG_HOME not set, using default path of ~/.config/worldcoder/settings.json"
|
||||||
|
);
|
||||||
|
"~/.config/worldcoder/settings.json".into()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+298
-198
@@ -10,18 +10,50 @@ use crate::editors::settings_editor::ProjectSettings;
|
|||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ContentAI {
|
pub struct ContentAI {
|
||||||
pub open: bool,
|
pub open: bool,
|
||||||
|
|
||||||
|
// model input
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub instruction: String,
|
pub instruction: String,
|
||||||
pub max_tokens: usize,
|
|
||||||
pub context_override: String,
|
pub context_override: String,
|
||||||
pub result: Arc<Mutex<String>>,
|
pub system_prompt: String,
|
||||||
pub ready: Arc<Mutex<ReadyState>>,
|
|
||||||
|
// model settings
|
||||||
|
pub max_tokens: usize,
|
||||||
pub temperature: f32,
|
pub temperature: f32,
|
||||||
pub reasoning_effort: ReasoningEffort,
|
pub reasoning_effort: ReasoningEffort,
|
||||||
pub model_override: String,
|
pub model_override: String,
|
||||||
|
|
||||||
|
// model output
|
||||||
|
pub reasoning: Arc<Mutex<String>>,
|
||||||
|
pub result: Arc<Mutex<String>>,
|
||||||
|
pub ready: Arc<Mutex<ReadyState>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ContentAI {
|
impl ContentAI {
|
||||||
|
pub fn new(content: String) -> Self {
|
||||||
|
Self {
|
||||||
|
// model input
|
||||||
|
content,
|
||||||
|
instruction: String::new(),
|
||||||
|
context_override: String::new(),
|
||||||
|
system_prompt: String::new(),
|
||||||
|
|
||||||
|
// model settings
|
||||||
|
max_tokens: 2048,
|
||||||
|
reasoning_effort: ReasoningEffort::default(),
|
||||||
|
temperature: 0.7,
|
||||||
|
model_override: String::new(),
|
||||||
|
reasoning: Arc::new(Mutex::new(String::new())),
|
||||||
|
|
||||||
|
// output
|
||||||
|
result: Arc::new(Mutex::new(String::new())),
|
||||||
|
ready: Arc::new(Mutex::new(ReadyState::Idle)),
|
||||||
|
|
||||||
|
// ui
|
||||||
|
open: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ui(&mut self, ui: &mut egui::Ui, project: &mut ProjectSettings) {
|
pub fn ui(&mut self, ui: &mut egui::Ui, project: &mut ProjectSettings) {
|
||||||
let is_open = self.open;
|
let is_open = self.open;
|
||||||
|
|
||||||
@@ -34,203 +66,266 @@ impl ContentAI {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn ui_output_box(&mut self, ui: &mut egui::Ui, project: &mut ProjectSettings) {
|
fn ui_output_box(&mut self, ui: &mut egui::Ui, project: &mut ProjectSettings) {
|
||||||
egui::TopBottomPanel::bottom("llm_output")
|
let mut ready_lock = self.ready.lock().unwrap();
|
||||||
.resizable(true)
|
|
||||||
.show_inside(ui, |ui| {
|
|
||||||
let mut ready_lock = self.ready.lock().unwrap();
|
|
||||||
|
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
if *ready_lock == ReadyState::Generating {
|
if *ready_lock == ReadyState::Generating {
|
||||||
if ui.button("Cancel").clicked() {
|
if ui.button("Cancel").clicked() {
|
||||||
*ready_lock = ReadyState::Halted;
|
*ready_lock = ReadyState::Halted;
|
||||||
|
}
|
||||||
|
if ui.button("Stop").clicked() {
|
||||||
|
*ready_lock = ReadyState::Idle;
|
||||||
|
}
|
||||||
|
ui.spinner();
|
||||||
|
ui.label("Generating...");
|
||||||
|
}
|
||||||
|
|
||||||
|
if *ready_lock == ReadyState::Idle {
|
||||||
|
let continue_content = || {
|
||||||
|
let content = self.content.clone();
|
||||||
|
let project = project.clone();
|
||||||
|
let result = self.result.clone();
|
||||||
|
let reasoning = self.reasoning.clone();
|
||||||
|
let ready = self.ready.clone();
|
||||||
|
|
||||||
|
let options = AIOptions {
|
||||||
|
max_completion_tokens: self.max_tokens,
|
||||||
|
reasoning_effort: self.reasoning_effort,
|
||||||
|
temperature: self.temperature,
|
||||||
|
model_override: if !self.model_override.is_empty() {
|
||||||
|
Some(self.model_override.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let ai_input = AIInput {
|
||||||
|
system_prompt: self.system_prompt.clone(),
|
||||||
|
user_prompt: format!(
|
||||||
|
"{}\n\n{} {}",
|
||||||
|
self.instruction.clone(),
|
||||||
|
project.ai_context.clone(),
|
||||||
|
self.context_override.clone()
|
||||||
|
),
|
||||||
|
previous_content: content.clone(),
|
||||||
|
structure: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
result.lock().unwrap().clear();
|
||||||
|
|
||||||
|
std::thread::spawn(move || {
|
||||||
|
let result = crate::llm_integration::content_llm::continue_content(
|
||||||
|
ai_input,
|
||||||
|
options,
|
||||||
|
project,
|
||||||
|
result,
|
||||||
|
reasoning,
|
||||||
|
ready.clone(),
|
||||||
|
);
|
||||||
|
if let Err(e) = result {
|
||||||
|
eprintln!("Error in content generation: {e}");
|
||||||
}
|
}
|
||||||
if ui.button("Stop").clicked() {
|
});
|
||||||
*ready_lock = ReadyState::Idle;
|
};
|
||||||
}
|
|
||||||
ui.spinner();
|
|
||||||
ui.label("Generating...");
|
|
||||||
}
|
|
||||||
|
|
||||||
if *ready_lock == ReadyState::Idle {
|
if ui.button("Generate ").clicked() {
|
||||||
let continue_content = || {
|
continue_content();
|
||||||
let context_override = self.context_override.clone();
|
}
|
||||||
let content = self.content.clone();
|
|
||||||
let instruction = self.instruction.clone();
|
|
||||||
let project = project.clone();
|
|
||||||
let ai_context = project.ai_context.clone();
|
|
||||||
let result = self.result.clone();
|
|
||||||
let ready = self.ready.clone();
|
|
||||||
|
|
||||||
let options = AIOptions {
|
ui.label("Idle");
|
||||||
max_completion_tokens: self.max_tokens,
|
}
|
||||||
reasoning_effort: self.reasoning_effort,
|
|
||||||
temperature: self.temperature,
|
|
||||||
model_override: if !self.model_override.is_empty() {
|
|
||||||
Some(self.model_override.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
result.lock().unwrap().clear();
|
// show regardless of state
|
||||||
|
if ui.button("Insert").clicked() {
|
||||||
|
*ready_lock = ReadyState::Ready;
|
||||||
|
}
|
||||||
|
|
||||||
std::thread::spawn(move || {
|
if ui.button("Clear").clicked() {
|
||||||
let result = crate::llm_integration::content_llm::continue_content(
|
self.result.lock().unwrap().clear();
|
||||||
ai_context + "\n" + &context_override,
|
self.reasoning.lock().unwrap().clear();
|
||||||
content,
|
}
|
||||||
instruction,
|
});
|
||||||
options,
|
|
||||||
project,
|
|
||||||
result,
|
|
||||||
ready.clone(),
|
|
||||||
);
|
|
||||||
if let Err(e) = result {
|
|
||||||
eprintln!("Error in content generation: {e}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if ui.button("Generate ").clicked() {
|
ui.spacing();
|
||||||
continue_content();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui.label("Idle");
|
ui.vertical(|ui| {
|
||||||
}
|
egui::TopBottomPanel::top("reasoning_output")
|
||||||
|
.resizable(true)
|
||||||
// show regardless of state
|
.show_inside(ui, |ui| {
|
||||||
if ui.button("Insert").clicked() {
|
egui::ScrollArea::both()
|
||||||
*self.ready.lock().unwrap() = ReadyState::Ready;
|
.auto_shrink([false, true])
|
||||||
}
|
.id_salt("reasoning_output")
|
||||||
|
.max_width(ui.available_width())
|
||||||
if ui.button("Clear").clicked() {
|
// .max_height(ui.available_height() / 3.0)
|
||||||
self.result.lock().unwrap().clear();
|
.show(ui, |ui| {
|
||||||
}
|
ui.add(
|
||||||
|
egui::TextEdit::multiline(&mut *self.reasoning.lock().unwrap())
|
||||||
|
.font(egui::TextStyle::Monospace)
|
||||||
|
.interactive(false)
|
||||||
|
.desired_rows(5)
|
||||||
|
.frame(false)
|
||||||
|
.desired_width(ui.available_width())
|
||||||
|
.lock_focus(true)
|
||||||
|
.hint_text("Reasoning will appear here..."),
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ui.separator();
|
egui::ScrollArea::both()
|
||||||
|
.auto_shrink([false, false])
|
||||||
egui::ScrollArea::both()
|
.id_salt("llm_output")
|
||||||
.auto_shrink([false, false])
|
.max_width(ui.available_width())
|
||||||
.id_salt("llm_output")
|
.show(ui, |ui| {
|
||||||
.max_width(ui.available_width())
|
ui.add(
|
||||||
// .max_height(ui.available_height() / 3.0)
|
egui::TextEdit::multiline(&mut *self.result.lock().unwrap())
|
||||||
.show(ui, |ui| {
|
.font(egui::TextStyle::Monospace)
|
||||||
ui.add(
|
.interactive(false)
|
||||||
egui::TextEdit::multiline(&mut *self.result.lock().unwrap())
|
.desired_rows(0)
|
||||||
.font(egui::TextStyle::Monospace)
|
.frame(false)
|
||||||
.interactive(false)
|
.desired_width(ui.available_width())
|
||||||
.desired_rows(0)
|
.lock_focus(true)
|
||||||
.frame(false)
|
.hint_text("Content will appear here..."),
|
||||||
.desired_width(ui.available_width())
|
);
|
||||||
.lock_focus(true)
|
});
|
||||||
.hint_text("Content will appear here..."),
|
});
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ui_main(&mut self, ui: &mut egui::Ui, project: &mut ProjectSettings) {
|
fn ui_main(&mut self, ui: &mut egui::Ui, project: &mut ProjectSettings) {
|
||||||
{
|
{
|
||||||
ui.weak("(The model will see current file content)");
|
ui.weak("(The model will see current file content)");
|
||||||
|
|
||||||
egui::Grid::new("continue_grid")
|
egui::CollapsingHeader::new("Settings")
|
||||||
.num_columns(2)
|
.default_open(true)
|
||||||
.striped(true)
|
|
||||||
.show(ui, |ui| {
|
.show(ui, |ui| {
|
||||||
ui.label("Max Tokens");
|
egui::Grid::new("continue_grid")
|
||||||
ui.add(
|
.num_columns(2)
|
||||||
egui::DragValue::new(&mut self.max_tokens)
|
.striped(true)
|
||||||
.range(128..=u32::MAX)
|
.show(ui, |ui| {
|
||||||
.speed(128),
|
ui.label("Max Tokens");
|
||||||
);
|
ui.add(
|
||||||
ui.end_row();
|
egui::DragValue::new(&mut self.max_tokens)
|
||||||
|
.range(128..=u32::MAX)
|
||||||
|
.speed(128),
|
||||||
|
);
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
ui.label("Temperature");
|
ui.label("Temperature");
|
||||||
ui.add(
|
ui.add(
|
||||||
egui::DragValue::new(&mut self.temperature)
|
egui::DragValue::new(&mut self.temperature)
|
||||||
.range(0.0..=2.0)
|
.range(0.0..=2.0)
|
||||||
.speed(0.1),
|
.speed(0.1),
|
||||||
);
|
);
|
||||||
|
|
||||||
ui.label("Reasoning effort");
|
ui.label("Reasoning effort");
|
||||||
|
|
||||||
egui::ComboBox::from_id_salt("reasoning_effort")
|
egui::ComboBox::from_id_salt("reasoning_effort")
|
||||||
.selected_text(self.reasoning_effort.to_string())
|
.selected_text(self.reasoning_effort.to_string())
|
||||||
.show_ui(ui, |ui| {
|
.show_ui(ui, |ui| {
|
||||||
ui.selectable_value(
|
ui.selectable_value(
|
||||||
&mut self.reasoning_effort,
|
&mut self.reasoning_effort,
|
||||||
ReasoningEffort::Minimal,
|
ReasoningEffort::Minimal,
|
||||||
"Minimal",
|
"Minimal",
|
||||||
);
|
);
|
||||||
ui.selectable_value(
|
ui.selectable_value(
|
||||||
&mut self.reasoning_effort,
|
&mut self.reasoning_effort,
|
||||||
ReasoningEffort::Low,
|
ReasoningEffort::Low,
|
||||||
"Low",
|
"Low",
|
||||||
);
|
);
|
||||||
ui.selectable_value(
|
ui.selectable_value(
|
||||||
&mut self.reasoning_effort,
|
&mut self.reasoning_effort,
|
||||||
ReasoningEffort::Medium,
|
ReasoningEffort::Medium,
|
||||||
"Medium",
|
"Medium",
|
||||||
);
|
);
|
||||||
ui.selectable_value(
|
ui.selectable_value(
|
||||||
&mut self.reasoning_effort,
|
&mut self.reasoning_effort,
|
||||||
ReasoningEffort::High,
|
ReasoningEffort::High,
|
||||||
"High",
|
"High",
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ui.end_row();
|
||||||
|
|
||||||
|
ui.label("Model override");
|
||||||
|
ui.add(egui::TextEdit::singleline(&mut self.model_override));
|
||||||
|
ui.end_row();
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
ui.end_row();
|
egui::TopBottomPanel::top("continue_instruction")
|
||||||
|
.resizable(true)
|
||||||
|
.show_inside(ui, |ui| {
|
||||||
|
egui::CollapsingHeader::new("Instructions")
|
||||||
|
.default_open(true)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
egui::ScrollArea::vertical()
|
||||||
|
.auto_shrink([false, false])
|
||||||
|
.max_height(ui.available_height())
|
||||||
|
.show(ui, |ui| {
|
||||||
|
ui.add(
|
||||||
|
egui::TextEdit::multiline(&mut self.instruction)
|
||||||
|
.frame(false)
|
||||||
|
.desired_width(ui.available_width())
|
||||||
|
.hint_text("Writing Instructions"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
ui.label("Model override");
|
egui::TopBottomPanel::top("continue_context")
|
||||||
ui.add(egui::TextEdit::singleline(&mut self.model_override));
|
.resizable(true)
|
||||||
ui.end_row();
|
.show_inside(ui, |ui| {
|
||||||
|
egui::CollapsingHeader::new("Context")
|
||||||
|
.default_open(true)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
egui::ScrollArea::vertical()
|
||||||
|
.auto_shrink([false, false])
|
||||||
|
.max_height(ui.available_height())
|
||||||
|
.show(ui, |ui| {
|
||||||
|
ui.add(
|
||||||
|
egui::TextEdit::multiline(&mut self.context_override)
|
||||||
|
.frame(false)
|
||||||
|
.desired_width(ui.available_width())
|
||||||
|
.hint_text("Any additional context?"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
egui::TopBottomPanel::top("continue_system_prompt")
|
||||||
|
.resizable(true)
|
||||||
|
.show_inside(ui, |ui| {
|
||||||
|
egui::CollapsingHeader::new("System prompt")
|
||||||
|
.default_open(true)
|
||||||
|
.show(ui, |ui| {
|
||||||
|
egui::ScrollArea::vertical()
|
||||||
|
.auto_shrink([false, false])
|
||||||
|
.max_height(ui.available_height())
|
||||||
|
.show(ui, |ui| {
|
||||||
|
ui.add(
|
||||||
|
egui::TextEdit::multiline(&mut self.system_prompt)
|
||||||
|
.frame(false)
|
||||||
|
.desired_width(ui.available_width())
|
||||||
|
.hint_text("System prompt"),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
self.ui_output_box(ui, project);
|
self.ui_output_box(ui, project);
|
||||||
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
// Instructions
|
|
||||||
egui::ScrollArea::both()
|
|
||||||
.id_salt("continue_instruction")
|
|
||||||
.auto_shrink([true, false])
|
|
||||||
.max_height(ui.available_height() / 2.0)
|
|
||||||
.max_width(ui.available_width())
|
|
||||||
.show(ui, |ui| {
|
|
||||||
ui.add(
|
|
||||||
egui::TextEdit::multiline(&mut self.instruction)
|
|
||||||
.frame(false)
|
|
||||||
.desired_width(ui.available_width())
|
|
||||||
.hint_text("Writing Instructions"),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
ui.separator();
|
|
||||||
|
|
||||||
// Context
|
|
||||||
egui::ScrollArea::both()
|
|
||||||
.id_salt("continue_context")
|
|
||||||
.auto_shrink([true, false])
|
|
||||||
.max_height(ui.available_height())
|
|
||||||
.max_width(ui.available_width())
|
|
||||||
.show(ui, |ui| {
|
|
||||||
ui.add(
|
|
||||||
egui::TextEdit::multiline(&mut self.context_override)
|
|
||||||
.frame(false)
|
|
||||||
.desired_width(ui.available_width())
|
|
||||||
.hint_text("Any additional context?"),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn continue_content(
|
pub fn continue_content(
|
||||||
context: String,
|
ai_input: AIInput,
|
||||||
previous_content: String,
|
// context: String,
|
||||||
instruction: String,
|
// previous_content: String,
|
||||||
|
// instruction: String,
|
||||||
options: AIOptions,
|
options: AIOptions,
|
||||||
project: ProjectSettings,
|
project: ProjectSettings,
|
||||||
result: Arc<Mutex<String>>,
|
result: Arc<Mutex<String>>,
|
||||||
|
reasoning: Arc<Mutex<String>>,
|
||||||
ready: Arc<Mutex<ReadyState>>,
|
ready: Arc<Mutex<ReadyState>>,
|
||||||
) -> Result<(), Box<dyn std::error::Error>> {
|
) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
*ready.lock().unwrap() = ReadyState::Generating;
|
*ready.lock().unwrap() = ReadyState::Generating;
|
||||||
@@ -240,27 +335,15 @@ pub fn continue_content(
|
|||||||
let messages = vec![
|
let messages = vec![
|
||||||
Message {
|
Message {
|
||||||
role: "system".to_string(),
|
role: "system".to_string(),
|
||||||
content: "
|
content: ai_input.system_prompt,
|
||||||
Please generate content that is a continuation of the given text.
|
|
||||||
Your response should be a logical next step in the content and should not repeat any of the text from the instruction or the content.
|
|
||||||
Do not generate any text that is not a direct continuation of the content.
|
|
||||||
if extra instructions are provided, follow them exactly, otherwise continue the text in a logical way.
|
|
||||||
your output should NEVER be a repeat of any previous content
|
|
||||||
".to_string(),
|
|
||||||
},
|
},
|
||||||
Message {
|
Message {
|
||||||
role: "user".to_string(),
|
role: "user".to_string(),
|
||||||
content: format!("Context / General instructions: {context}"),
|
content: format!(
|
||||||
|
"<Instructions> {}\n\n<Previous content> {}\n\n",
|
||||||
|
ai_input.user_prompt, ai_input.previous_content
|
||||||
|
),
|
||||||
},
|
},
|
||||||
Message {
|
|
||||||
role: "user".to_string(),
|
|
||||||
content: format!("Content to continue: {previous_content}"),
|
|
||||||
},
|
|
||||||
Message {
|
|
||||||
role: "user".to_string(),
|
|
||||||
content: format!("Specific instructions: {instruction}"),
|
|
||||||
},
|
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
let request = ChatRequest {
|
let request = ChatRequest {
|
||||||
@@ -288,19 +371,20 @@ pub fn continue_content(
|
|||||||
|
|
||||||
let response = if let Some(k) = api_key {
|
let response = if let Some(k) = api_key {
|
||||||
client
|
client
|
||||||
.post(llm_api_uri + "/v1/chat/completions")
|
.post(llm_api_uri + "/api/v0/chat/completions")
|
||||||
.json(&request)
|
.json(&request)
|
||||||
.bearer_auth(k)
|
.bearer_auth(k)
|
||||||
.send()?
|
.send()?
|
||||||
} else {
|
} else {
|
||||||
client
|
client
|
||||||
.post(llm_api_uri + "/v1/chat/completions")
|
.post(llm_api_uri + "/api/v0/chat/completions")
|
||||||
.json(&request)
|
.json(&request)
|
||||||
.send()?
|
.send()?
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("success!");
|
println!("success!");
|
||||||
|
|
||||||
|
// println!("response: {}", response.text().unwrap());
|
||||||
let reader = BufReader::new(response);
|
let reader = BufReader::new(response);
|
||||||
for line in reader.lines() {
|
for line in reader.lines() {
|
||||||
// initial loop to check if the user has terminated the generation
|
// initial loop to check if the user has terminated the generation
|
||||||
@@ -309,6 +393,7 @@ pub fn continue_content(
|
|||||||
|
|
||||||
if *ready == ReadyState::Halted {
|
if *ready == ReadyState::Halted {
|
||||||
result.lock().unwrap().clear();
|
result.lock().unwrap().clear();
|
||||||
|
reasoning.lock().unwrap().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
if *ready != ReadyState::Generating {
|
if *ready != ReadyState::Generating {
|
||||||
@@ -324,9 +409,17 @@ pub fn continue_content(
|
|||||||
|
|
||||||
if let Some(json) = line.strip_prefix("data: ") {
|
if let Some(json) = line.strip_prefix("data: ") {
|
||||||
if let Ok(chunk) = serde_json::from_str::<StreamingChatResponse>(json) {
|
if let Ok(chunk) = serde_json::from_str::<StreamingChatResponse>(json) {
|
||||||
|
println!("chunk: {chunk:?}");
|
||||||
|
|
||||||
if let Some(content) = chunk.choices[0].delta.content.as_ref() {
|
if let Some(content) = chunk.choices[0].delta.content.as_ref() {
|
||||||
|
println!("content: {content}");
|
||||||
result.lock().unwrap().push_str(content);
|
result.lock().unwrap().push_str(content);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(reasoning_content) = chunk.choices[0].delta.reasoning_content.as_ref() {
|
||||||
|
println!("reasoning_content: {reasoning_content}");
|
||||||
|
reasoning.lock().unwrap().push_str(reasoning_content);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -343,6 +436,14 @@ pub struct AIOptions {
|
|||||||
pub model_override: Option<String>,
|
pub model_override: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct AIInput {
|
||||||
|
pub system_prompt: String,
|
||||||
|
pub user_prompt: String,
|
||||||
|
pub previous_content: String,
|
||||||
|
#[allow(unused)]
|
||||||
|
pub structure: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
pub enum ReadyState {
|
pub enum ReadyState {
|
||||||
Idle,
|
Idle,
|
||||||
@@ -351,10 +452,12 @@ pub enum ReadyState {
|
|||||||
Halted,
|
Halted,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Copy, Clone, PartialEq)]
|
#[derive(Serialize, Copy, Clone, PartialEq, Default)]
|
||||||
pub enum ReasoningEffort {
|
pub enum ReasoningEffort {
|
||||||
#[serde(rename = "minimal")]
|
#[serde(rename = "minimal")]
|
||||||
Minimal,
|
Minimal,
|
||||||
|
|
||||||
|
#[default]
|
||||||
#[serde(rename = "low")]
|
#[serde(rename = "low")]
|
||||||
Low,
|
Low,
|
||||||
#[serde(rename = "medium")]
|
#[serde(rename = "medium")]
|
||||||
@@ -363,19 +466,13 @@ pub enum ReasoningEffort {
|
|||||||
High,
|
High,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ReasoningEffort {
|
impl std::fmt::Display for ReasoningEffort {
|
||||||
fn default() -> Self {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
ReasoningEffort::Low
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToString for ReasoningEffort {
|
|
||||||
fn to_string(&self) -> String {
|
|
||||||
match self {
|
match self {
|
||||||
ReasoningEffort::Minimal => "Minimal".to_string(),
|
ReasoningEffort::Minimal => write!(f, "Minimal"),
|
||||||
ReasoningEffort::Low => "Low".to_string(),
|
ReasoningEffort::Low => write!(f, "Low"),
|
||||||
ReasoningEffort::Medium => "Medium".to_string(),
|
ReasoningEffort::Medium => write!(f, "Medium"),
|
||||||
ReasoningEffort::High => "High".to_string(),
|
ReasoningEffort::High => write!(f, "High"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -413,8 +510,11 @@ struct Delta {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
role: Option<String>,
|
role: Option<String>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
content: Option<String>,
|
content: Option<String>,
|
||||||
|
#[serde(default)]
|
||||||
|
reasoning_content: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
|||||||
@@ -6,10 +6,14 @@ use egui::ScrollArea;
|
|||||||
|
|
||||||
mod editors;
|
mod editors;
|
||||||
mod explorer;
|
mod explorer;
|
||||||
|
|
||||||
|
#[cfg(feature = "llm")]
|
||||||
mod llm_integration;
|
mod llm_integration;
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
mod filesystem;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
editors::{
|
editors::{
|
||||||
asset_editor::Asset, content_editor, note_editor, object_editor::ObjectInstance,
|
asset_editor::Asset, content_editor, note_editor, object_editor::ObjectInstance,
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"llm_api_uri": "http://localhost:1234",
|
|
||||||
"llm_api_key": "",
|
|
||||||
"ai_enabled": true,
|
|
||||||
"dark_theme": true
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user