refactor: move UI into Slint files
This commit is contained in:
672
Cargo.lock
generated
672
Cargo.lock
generated
@@ -46,6 +46,24 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aligned"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685"
|
||||||
|
dependencies = [
|
||||||
|
"as-slice",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "aligned-vec"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b"
|
||||||
|
dependencies = [
|
||||||
|
"equator",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "allocator-api2"
|
name = "allocator-api2"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
@@ -103,6 +121,29 @@ version = "1.0.14"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.104"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arbitrary"
|
||||||
|
version = "1.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arg_enum_proc_macro"
|
||||||
|
version = "0.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayref"
|
name = "arrayref"
|
||||||
version = "0.3.9"
|
version = "0.3.9"
|
||||||
@@ -121,6 +162,15 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
|
checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "as-slice"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516"
|
||||||
|
dependencies = [
|
||||||
|
"stable_deref_trait",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-broadcast"
|
name = "async-broadcast"
|
||||||
version = "0.7.2"
|
version = "0.7.2"
|
||||||
@@ -276,6 +326,49 @@ version = "1.5.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "av-scenechange"
|
||||||
|
version = "0.14.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394"
|
||||||
|
dependencies = [
|
||||||
|
"aligned",
|
||||||
|
"anyhow",
|
||||||
|
"arg_enum_proc_macro",
|
||||||
|
"arrayvec",
|
||||||
|
"log",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"pastey",
|
||||||
|
"rayon",
|
||||||
|
"thiserror 2.0.19",
|
||||||
|
"v_frame",
|
||||||
|
"y4m",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "av1-grain"
|
||||||
|
version = "0.2.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"arrayvec",
|
||||||
|
"log",
|
||||||
|
"nom 8.0.0",
|
||||||
|
"num-rational",
|
||||||
|
"v_frame",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "avif-serialize"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38"
|
||||||
|
dependencies = [
|
||||||
|
"arrayvec",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "aws-lc-rs"
|
name = "aws-lc-rs"
|
||||||
version = "1.17.3"
|
version = "1.17.3"
|
||||||
@@ -335,6 +428,12 @@ dependencies = [
|
|||||||
"syn 2.0.119",
|
"syn 2.0.119",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bit_field"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@@ -350,6 +449,15 @@ dependencies = [
|
|||||||
"serde_core",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitstream-io"
|
||||||
|
version = "4.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f"
|
||||||
|
dependencies = [
|
||||||
|
"no_std_io2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "block2"
|
name = "block2"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
@@ -391,6 +499,12 @@ dependencies = [
|
|||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "built"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.20.3"
|
version = "3.20.3"
|
||||||
@@ -504,7 +618,7 @@ version = "0.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nom",
|
"nom 7.1.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -536,7 +650,7 @@ checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"cpufeatures",
|
"cpufeatures",
|
||||||
"rand_core",
|
"rand_core 0.10.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -757,12 +871,37 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.8.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.9.20"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.22"
|
version = "0.8.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
|
checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crunchy"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctor"
|
name = "ctor"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@@ -951,6 +1090,26 @@ dependencies = [
|
|||||||
"syn 2.0.119",
|
"syn 2.0.119",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equator"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc"
|
||||||
|
dependencies = [
|
||||||
|
"equator-macro",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "equator-macro"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@@ -1002,12 +1161,35 @@ dependencies = [
|
|||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "exr"
|
||||||
|
version = "1.74.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "711fe42c9964295e01ee3fba3f9fe0e1d24b98886950d68efe81b1c76e21adf3"
|
||||||
|
dependencies = [
|
||||||
|
"bit_field",
|
||||||
|
"half",
|
||||||
|
"lebe",
|
||||||
|
"miniz_oxide",
|
||||||
|
"num-complex",
|
||||||
|
"pulp",
|
||||||
|
"rayon-core",
|
||||||
|
"smallvec",
|
||||||
|
"zune-inflate",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.5.0"
|
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 = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fax"
|
||||||
|
version = "0.2.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fdeflate"
|
name = "fdeflate"
|
||||||
version = "0.3.7"
|
version = "0.3.7"
|
||||||
@@ -1347,7 +1529,7 @@ dependencies = [
|
|||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi 6.0.0",
|
"r-efi 6.0.0",
|
||||||
"rand_core",
|
"rand_core 0.10.1",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1481,6 +1663,7 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"slint",
|
"slint",
|
||||||
|
"slint-build",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1512,6 +1695,17 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b40ca9252762c466af32d0b1002e91e4e1bc5398f77455e55474deb466355ff5"
|
checksum = "b40ca9252762c466af32d0b1002e91e4e1bc5398f77455e55474deb466355ff5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "half"
|
||||||
|
version = "2.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crunchy",
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "harfrust"
|
name = "harfrust"
|
||||||
version = "0.8.4"
|
version = "0.8.4"
|
||||||
@@ -1797,6 +1991,7 @@ dependencies = [
|
|||||||
"derive_more",
|
"derive_more",
|
||||||
"i-slint-common",
|
"i-slint-common",
|
||||||
"icu_normalizer",
|
"icu_normalizer",
|
||||||
|
"image",
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"linked_hash_set",
|
"linked_hash_set",
|
||||||
"lyon_extra",
|
"lyon_extra",
|
||||||
@@ -1804,9 +1999,14 @@ dependencies = [
|
|||||||
"num_enum",
|
"num_enum",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
"rayon",
|
||||||
|
"resvg",
|
||||||
"rowan",
|
"rowan",
|
||||||
|
"rspolib",
|
||||||
|
"skrifa 0.42.1",
|
||||||
"smol_str 0.3.2",
|
"smol_str 0.3.2",
|
||||||
"strum",
|
"strum",
|
||||||
|
"swash",
|
||||||
"typed-index-collections",
|
"typed-index-collections",
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"url",
|
"url",
|
||||||
@@ -2131,11 +2331,20 @@ checksum = "e6506c6c10786659413faa717ceebcb8f70731c0a60cbae39795fdf114519c1a"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
"byteorder-lite",
|
"byteorder-lite",
|
||||||
|
"color_quant",
|
||||||
|
"exr",
|
||||||
|
"gif",
|
||||||
|
"image-webp",
|
||||||
"moxcms",
|
"moxcms",
|
||||||
"num-traits",
|
"num-traits",
|
||||||
"png",
|
"png",
|
||||||
"zune-core",
|
"qoi",
|
||||||
"zune-jpeg",
|
"ravif",
|
||||||
|
"rayon",
|
||||||
|
"rgb",
|
||||||
|
"tiff",
|
||||||
|
"zune-core 0.5.1",
|
||||||
|
"zune-jpeg 0.5.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2154,6 +2363,12 @@ version = "0.14.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09e54e57b4c48b40f7aec75635392b12b3421fa26fe8b4332e63138ed278459c"
|
checksum = "09e54e57b4c48b40f7aec75635392b12b3421fa26fe8b4332e63138ed278459c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "imgref"
|
||||||
|
version = "1.12.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "89194689a993ab15268672e99e7b0e19da2da3268ac682e8f02d29d4d1434cd7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.14.0"
|
version = "2.14.0"
|
||||||
@@ -2192,6 +2407,17 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "interpolate_name"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "io-lifetimes"
|
name = "io-lifetimes"
|
||||||
version = "1.0.11"
|
version = "1.0.11"
|
||||||
@@ -2341,12 +2567,34 @@ dependencies = [
|
|||||||
"smallvec",
|
"smallvec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lebe"
|
||||||
|
version = "0.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.189"
|
version = "0.2.189"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libfuzzer-sys"
|
||||||
|
version = "0.4.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2"
|
||||||
|
dependencies = [
|
||||||
|
"arbitrary",
|
||||||
|
"cc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libloading"
|
name = "libloading"
|
||||||
version = "0.8.9"
|
version = "0.8.9"
|
||||||
@@ -2436,6 +2684,15 @@ version = "0.4.33"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "loop9"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062"
|
||||||
|
dependencies = [
|
||||||
|
"imgref",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lru-slab"
|
name = "lru-slab"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@@ -2483,6 +2740,16 @@ dependencies = [
|
|||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maybe-rayon"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "memchr"
|
||||||
version = "2.8.3"
|
version = "2.8.3"
|
||||||
@@ -2579,6 +2846,12 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "natord"
|
||||||
|
version = "1.0.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "308d96db8debc727c3fd9744aac51751243420e46edf401010908da7f8d5e57c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ndk"
|
name = "ndk"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@@ -2609,6 +2882,12 @@ dependencies = [
|
|||||||
"jni-sys 0.3.1",
|
"jni-sys 0.3.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "new_debug_unreachable"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.31.3"
|
version = "0.31.3"
|
||||||
@@ -2621,6 +2900,15 @@ dependencies = [
|
|||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "no_std_io2"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.3"
|
version = "7.1.3"
|
||||||
@@ -2631,6 +2919,72 @@ dependencies = [
|
|||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nom"
|
||||||
|
version = "8.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "noop_proc_macro"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-bigint"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367"
|
||||||
|
dependencies = [
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-complex"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-derive"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.46"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.4.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
|
||||||
|
dependencies = [
|
||||||
|
"num-bigint",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@@ -3122,6 +3476,18 @@ dependencies = [
|
|||||||
"icu_properties",
|
"icu_properties",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "paste"
|
||||||
|
version = "1.0.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pastey"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "percent-encoding"
|
name = "percent-encoding"
|
||||||
version = "2.3.2"
|
version = "2.3.2"
|
||||||
@@ -3251,6 +3617,15 @@ dependencies = [
|
|||||||
"zerovec",
|
"zerovec",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ppv-lite86"
|
||||||
|
version = "0.2.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
|
||||||
|
dependencies = [
|
||||||
|
"zerocopy",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "prettyplease"
|
name = "prettyplease"
|
||||||
version = "0.2.37"
|
version = "0.2.37"
|
||||||
@@ -3279,6 +3654,25 @@ dependencies = [
|
|||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "profiling"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5"
|
||||||
|
dependencies = [
|
||||||
|
"profiling-procmacros",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "profiling-procmacros"
|
||||||
|
version = "1.0.18"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pulldown-cmark"
|
name = "pulldown-cmark"
|
||||||
version = "0.13.4"
|
version = "0.13.4"
|
||||||
@@ -3298,12 +3692,44 @@ version = "0.11.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
|
checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pulp"
|
||||||
|
version = "0.22.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "046aa45b989642ec2e4717c8e72d677b13edd831a4d3b6cf37d9a3e54912496a"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"cfg-if",
|
||||||
|
"libm",
|
||||||
|
"num-complex",
|
||||||
|
"paste",
|
||||||
|
"pulp-wasm-simd-flag",
|
||||||
|
"raw-cpuid",
|
||||||
|
"reborrow",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pulp-wasm-simd-flag"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pxfm"
|
name = "pxfm"
|
||||||
version = "0.1.30"
|
version = "0.1.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
|
checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "qoi"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quick-error"
|
name = "quick-error"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
@@ -3349,7 +3775,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"getrandom 0.4.3",
|
"getrandom 0.4.3",
|
||||||
"lru-slab",
|
"lru-slab",
|
||||||
"rand",
|
"rand 0.10.2",
|
||||||
"rand_pcg",
|
"rand_pcg",
|
||||||
"ring",
|
"ring",
|
||||||
"rustc-hash 2.1.3",
|
"rustc-hash 2.1.3",
|
||||||
@@ -3397,6 +3823,16 @@ version = "6.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9ef1d0d795eb7d84685bca4f72f3649f064e6641543d3a8c415898726a57b41"
|
||||||
|
dependencies = [
|
||||||
|
"rand_chacha",
|
||||||
|
"rand_core 0.9.5",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rand"
|
name = "rand"
|
||||||
version = "0.10.2"
|
version = "0.10.2"
|
||||||
@@ -3405,7 +3841,26 @@ checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"chacha20",
|
"chacha20",
|
||||||
"getrandom 0.4.3",
|
"getrandom 0.4.3",
|
||||||
"rand_core",
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_chacha"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
|
||||||
|
dependencies = [
|
||||||
|
"ppv-lite86",
|
||||||
|
"rand_core 0.9.5",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.9.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.3.4",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3420,7 +3875,66 @@ version = "0.10.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
|
checksum = "caa0f4137e1c0a72f4c651489402276c8e8e1cf081f3b0ba156d2cbeef09e86a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rand_core",
|
"rand_core 0.10.1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rav1e"
|
||||||
|
version = "0.8.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b"
|
||||||
|
dependencies = [
|
||||||
|
"aligned-vec",
|
||||||
|
"arbitrary",
|
||||||
|
"arg_enum_proc_macro",
|
||||||
|
"arrayvec",
|
||||||
|
"av-scenechange",
|
||||||
|
"av1-grain",
|
||||||
|
"bitstream-io",
|
||||||
|
"built",
|
||||||
|
"cfg-if",
|
||||||
|
"interpolate_name",
|
||||||
|
"itertools 0.14.0",
|
||||||
|
"libc",
|
||||||
|
"libfuzzer-sys",
|
||||||
|
"log",
|
||||||
|
"maybe-rayon",
|
||||||
|
"new_debug_unreachable",
|
||||||
|
"noop_proc_macro",
|
||||||
|
"num-derive",
|
||||||
|
"num-traits",
|
||||||
|
"paste",
|
||||||
|
"profiling",
|
||||||
|
"rand 0.9.5",
|
||||||
|
"rand_chacha",
|
||||||
|
"simd_helpers",
|
||||||
|
"thiserror 2.0.19",
|
||||||
|
"v_frame",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ravif"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef69c1990ceef18a116855938e74793a5f7496ee907562bd0857b6ac734ab285"
|
||||||
|
dependencies = [
|
||||||
|
"avif-serialize",
|
||||||
|
"imgref",
|
||||||
|
"loop9",
|
||||||
|
"quick-error",
|
||||||
|
"rav1e",
|
||||||
|
"rayon",
|
||||||
|
"rgb",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "raw-cpuid"
|
||||||
|
version = "11.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.13.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3441,6 +3955,26 @@ dependencies = [
|
|||||||
"objc2-quartz-core 0.3.2",
|
"objc2-quartz-core 0.3.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d"
|
||||||
|
dependencies = [
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "read-fonts"
|
name = "read-fonts"
|
||||||
version = "0.39.2"
|
version = "0.39.2"
|
||||||
@@ -3462,6 +3996,12 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "reborrow"
|
||||||
|
version = "0.5.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@@ -3574,7 +4114,7 @@ dependencies = [
|
|||||||
"svgtypes",
|
"svgtypes",
|
||||||
"tiny-skia 0.12.0",
|
"tiny-skia 0.12.0",
|
||||||
"usvg",
|
"usvg",
|
||||||
"zune-jpeg",
|
"zune-jpeg 0.5.15",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3632,6 +4172,19 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rspolib"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fda9a7796aff63a7b1b39ccc93fffaaf65e20042984b4843041a49ca4677535"
|
||||||
|
dependencies = [
|
||||||
|
"lazy_static",
|
||||||
|
"natord",
|
||||||
|
"snafu",
|
||||||
|
"unicode-linebreak",
|
||||||
|
"unicode-width",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rtoolbox"
|
name = "rtoolbox"
|
||||||
version = "0.0.5"
|
version = "0.0.5"
|
||||||
@@ -3998,6 +4551,15 @@ dependencies = [
|
|||||||
"simdutf8",
|
"simdutf8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "simd_helpers"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6"
|
||||||
|
dependencies = [
|
||||||
|
"quote",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simdutf8"
|
name = "simdutf8"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@@ -4094,6 +4656,19 @@ dependencies = [
|
|||||||
"vtable",
|
"vtable",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slint-build"
|
||||||
|
version = "1.17.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76684c11441f775b10bbc7b0e6b3016a39f17efdd659ffca112f17cfd6bdaed1"
|
||||||
|
dependencies = [
|
||||||
|
"derive_more",
|
||||||
|
"fontique",
|
||||||
|
"i-slint-compiler",
|
||||||
|
"spin_on",
|
||||||
|
"toml_edit",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slint-macros"
|
name = "slint-macros"
|
||||||
version = "1.17.1"
|
version = "1.17.1"
|
||||||
@@ -4203,6 +4778,27 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2"
|
||||||
|
dependencies = [
|
||||||
|
"snafu-derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "snafu-derive"
|
||||||
|
version = "0.8.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451"
|
||||||
|
dependencies = [
|
||||||
|
"heck",
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.119",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.6.5"
|
version = "0.6.5"
|
||||||
@@ -4453,6 +5049,20 @@ dependencies = [
|
|||||||
"syn 3.0.3",
|
"syn 3.0.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiff"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "af9605de7fee8d9551863fd692cce7637f548dbd9db9180fcc07ccc6d26c336f"
|
||||||
|
dependencies = [
|
||||||
|
"fax",
|
||||||
|
"flate2",
|
||||||
|
"half",
|
||||||
|
"quick-error",
|
||||||
|
"weezl",
|
||||||
|
"zune-jpeg 0.4.21",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiny-skia"
|
name = "tiny-skia"
|
||||||
version = "0.11.4"
|
version = "0.11.4"
|
||||||
@@ -4626,6 +5236,7 @@ dependencies = [
|
|||||||
"indexmap",
|
"indexmap",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"toml_parser",
|
"toml_parser",
|
||||||
|
"toml_writer",
|
||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -4916,6 +5527,17 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "v_frame"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2"
|
||||||
|
dependencies = [
|
||||||
|
"aligned-vec",
|
||||||
|
"num-traits",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
version = "0.9.5"
|
version = "0.9.5"
|
||||||
@@ -5695,6 +6317,12 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
|
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "y4m"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yazi"
|
name = "yazi"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -5890,19 +6518,43 @@ version = "1.0.23"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zune-core"
|
||||||
|
version = "0.4.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-core"
|
name = "zune-core"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9"
|
checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zune-inflate"
|
||||||
|
version = "0.2.54"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02"
|
||||||
|
dependencies = [
|
||||||
|
"simd-adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zune-jpeg"
|
||||||
|
version = "0.4.21"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713"
|
||||||
|
dependencies = [
|
||||||
|
"zune-core 0.4.12",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-jpeg"
|
name = "zune-jpeg"
|
||||||
version = "0.5.15"
|
version = "0.5.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
|
checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zune-core",
|
"zune-core 0.5.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -18,3 +18,6 @@ serde_json.workspace = true
|
|||||||
security-framework = "3"
|
security-framework = "3"
|
||||||
slint.workspace = true
|
slint.workspace = true
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
slint-build = "=1.17.1"
|
||||||
|
|||||||
3
crates/app/build.rs
Normal file
3
crates/app/build.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
slint_build::compile("ui/app.slint").unwrap();
|
||||||
|
}
|
||||||
@@ -1,944 +1 @@
|
|||||||
slint::slint! {
|
slint::include_modules!();
|
||||||
import { Button, ComboBox, LineEdit, ListView, Palette, ScrollView, Spinner } from "std-widgets.slint";
|
|
||||||
|
|
||||||
export struct ServerRow { name: string, url: string }
|
|
||||||
export struct RepositoryRow {
|
|
||||||
name: string, owner: string, description: string, meta: string, favorite: bool,
|
|
||||||
}
|
|
||||||
export struct LabelRow { name: string, background: color, foreground: color }
|
|
||||||
export struct IssueRow {
|
|
||||||
number: int, title: string, summary: string, meta: string, labels: [LabelRow],
|
|
||||||
}
|
|
||||||
export struct PullRow {
|
|
||||||
number: int, owner: string, repository: string, title: string, summary: string, meta: string,
|
|
||||||
}
|
|
||||||
export struct MarkdownBlock { text: styled-text, kind: string }
|
|
||||||
export struct CommentRow { author: string, body: [MarkdownBlock], meta: string }
|
|
||||||
export struct GraphLane { color: color, top: bool, bottom: bool, node: bool, connect_left: bool }
|
|
||||||
export struct CommitRow {
|
|
||||||
sha: string, title: string, meta: string, refs: string, lanes: [GraphLane],
|
|
||||||
}
|
|
||||||
export struct FileRow { path: string, status: string }
|
|
||||||
export struct ActivityRow {
|
|
||||||
icon: string, title: string, detail: string, meta: string,
|
|
||||||
target: string, owner: string, repository: string, number: int, sha: string,
|
|
||||||
}
|
|
||||||
export struct DiffLine { old_number: string, new_number: string, text: string, kind: string }
|
|
||||||
export struct HeatCell { week: int, day: int, level: int }
|
|
||||||
|
|
||||||
export global IconTheme {
|
|
||||||
in-out property <int> style: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
export global AppTheme {
|
|
||||||
in-out property <int> mode: 0;
|
|
||||||
private property <color> system-background: Palette.background;
|
|
||||||
out property <bool> dark: mode == 2 || (mode == 0 && system-background.to-oklch().lightness < 0.5);
|
|
||||||
out property <color> accent: dark ? #0a84ff : #0879e1;
|
|
||||||
out property <color> accent-soft: dark ? #17324d : #e5f2fd;
|
|
||||||
out property <color> page: dark ? #1c1c1e : #f2f2f7;
|
|
||||||
out property <color> surface: dark ? #2c2c2e : #ffffff;
|
|
||||||
out property <color> surface-muted: dark ? #3a3a3c : #f5f5f8;
|
|
||||||
out property <color> header: dark ? #242426 : #f8f8fa;
|
|
||||||
out property <color> toolbar: dark ? #242426 : #fbfbfc;
|
|
||||||
out property <color> border: dark ? #48484a : #dedee3;
|
|
||||||
out property <color> separator: dark ? #3a3a3c : #d8d8dd;
|
|
||||||
out property <color> text: dark ? #f2f2f7 : #17171a;
|
|
||||||
out property <color> text-secondary: dark ? #c7c7cc : #5f5f66;
|
|
||||||
out property <color> text-tertiary: dark ? #8e8e93 : #85858c;
|
|
||||||
out property <color> code-background: dark ? #242426 : #e9e9ed;
|
|
||||||
out property <color> quote-background: dark ? #242426 : #f6f6f8;
|
|
||||||
out property <color> loading-overlay: dark ? #00000088 : #ffffff88;
|
|
||||||
changed mode => {
|
|
||||||
Palette.color-scheme = mode == 1 ? ColorScheme.light : mode == 2 ? ColorScheme.dark : ColorScheme.unknown;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component AppIcon inherits Rectangle {
|
|
||||||
in property <string> kind;
|
|
||||||
in property <int> style: IconTheme.style;
|
|
||||||
in property <color> icon-color: AppTheme.accent;
|
|
||||||
background: transparent;
|
|
||||||
|
|
||||||
private property <bool> duotone: root.style == 1;
|
|
||||||
private property <bool> bold: root.style == 2;
|
|
||||||
private property <bool> issue-kind: root.kind == "issues" || root.kind == "issue-open" || root.kind == "issue-close" || root.kind == "issue-reopen" || root.kind == "issue-comment";
|
|
||||||
private property <bool> repository-kind: root.kind == "repositories" || root.kind == "repo-create" || root.kind == "repo-rename" || root.kind == "repo-star" || root.kind == "repo-watch" || root.kind == "update";
|
|
||||||
private property <bool> pull-kind: root.kind == "pulls" || root.kind == "pull-open" || root.kind == "pull-merge" || root.kind == "pull-close" || root.kind == "pull-reopen" || root.kind == "pull-comment" || root.kind == "pull-approve" || root.kind == "pull-reject";
|
|
||||||
private property <bool> tag-kind: root.kind == "tag-push" || root.kind == "tag-delete";
|
|
||||||
private property <bool> branch-kind: root.kind == "branch-create" || root.kind == "branch-delete";
|
|
||||||
private property <bool> closed-shape: root.kind == "home" || root.issue-kind || root.repository-kind || root.kind == "favorite" || root.kind == "favorite-filled" || root.tag-kind || root.kind == "release";
|
|
||||||
private property <bool> has-badge: root.kind == "branch-create" || root.kind == "branch-delete" || root.kind == "push" || root.kind == "repo-create" || root.kind == "repo-rename" || root.kind == "repo-star" || root.kind == "repo-watch" || root.kind == "update" || root.kind == "issue-open" || root.kind == "issue-close" || root.kind == "issue-reopen" || root.kind == "issue-comment" || root.kind == "pull-open" || root.kind == "pull-merge" || root.kind == "pull-close" || root.kind == "pull-reopen" || root.kind == "pull-comment" || root.kind == "pull-approve" || root.kind == "pull-reject" || root.kind == "tag-push" || root.kind == "tag-delete";
|
|
||||||
private property <bool> positive: root.kind == "issue-close" || root.kind == "pull-merge" || root.kind == "pull-approve";
|
|
||||||
private property <bool> destructive: root.kind == "branch-delete" || root.kind == "pull-close" || root.kind == "pull-reject" || root.kind == "tag-delete";
|
|
||||||
private property <color> badge-color: root.positive ? #20a866 : root.destructive ? #e45b4d : root.duotone ? #26bfd1 : root.icon-color;
|
|
||||||
private property <string> shape: root.kind == "home"
|
|
||||||
? "M3 10.5 L12 3 L21 10.5 V21 H15 V14 H9 V21 H3 Z"
|
|
||||||
: root.issue-kind
|
|
||||||
? "M4 5 H20 V9 C18 9 18 15 20 15 V19 H4 V15 C6 15 6 9 4 9 Z"
|
|
||||||
: root.repository-kind
|
|
||||||
? "M6 3 H18 C19.1 3 20 3.9 20 5 V21 H6 C4.9 21 4 20.1 4 19 V5 C4 3.9 4.9 3 6 3 Z"
|
|
||||||
: root.pull-kind
|
|
||||||
? "M7 4 V20 M17 4 V11 C17 15 14 17 10 17 M7 4 H7 M17 4 H17"
|
|
||||||
: root.kind == "settings"
|
|
||||||
? "M12 3 V6 M12 18 V21 M3 12 H6 M18 12 H21 M5.6 5.6 L7.8 7.8 M16.2 16.2 L18.4 18.4 M18.4 5.6 L16.2 7.8 M7.8 16.2 L5.6 18.4"
|
|
||||||
: root.kind == "back"
|
|
||||||
? (root.bold ? "M16 4 L7 12 L16 20 Z" : "M16 4 L7 12 L16 20")
|
|
||||||
: root.kind == "filter"
|
|
||||||
? (root.bold ? "M3 5 H21 L14 13 V20 L10 22 V13 Z" : "M4 6 H20 M4 12 H20 M4 18 H20")
|
|
||||||
: root.kind == "favorite" || root.kind == "favorite-filled"
|
|
||||||
? "M12 3 L14.8 8.7 L21 9.6 L16.5 14 L17.6 20.3 L12 17.3 L6.4 20.3 L7.5 14 L3 9.6 L9.2 8.7 Z"
|
|
||||||
: root.kind == "disclosure"
|
|
||||||
? (root.bold ? "M8 4 L17 12 L8 20 Z" : "M8 4 L17 12 L8 20")
|
|
||||||
: root.branch-kind
|
|
||||||
? "M7 4 V20 M7 11 C11 11 14 9 14 5"
|
|
||||||
: root.kind == "push"
|
|
||||||
? "M4 8 H13 M4 12 H13 M4 16 H13"
|
|
||||||
: root.tag-kind
|
|
||||||
? "M3 5 V13 L11 21 L21 11 L13 3 H5 C3.9 3 3 3.9 3 5 Z"
|
|
||||||
: root.kind == "release"
|
|
||||||
? "M4 8 L12 4 L20 8 V18 L12 22 L4 18 Z"
|
|
||||||
: "M12 4 V20 M4 12 H20";
|
|
||||||
private property <string> detail: root.kind == "home"
|
|
||||||
? "M9 21 V14 H15 V21"
|
|
||||||
: root.issue-kind
|
|
||||||
? "M12 8 V13 M12 16.5 V17"
|
|
||||||
: root.repository-kind
|
|
||||||
? "M7 3 V21 M11 9 L8.5 12 L11 15 M15 9 L17.5 12 L15 15"
|
|
||||||
: root.pull-kind
|
|
||||||
? "M7 4 A1.8 1.8 0 1 1 6.99 4 M7 20 A1.8 1.8 0 1 1 6.99 20 M17 4 A1.8 1.8 0 1 1 16.99 4"
|
|
||||||
: root.kind == "settings"
|
|
||||||
? "M12 8 A4 4 0 1 1 11.99 8"
|
|
||||||
: root.kind == "filter" && !root.bold
|
|
||||||
? "M9 4 V8 M15 10 V14 M8 16 V20"
|
|
||||||
: root.tag-kind
|
|
||||||
? "M8 8 A1.5 1.5 0 1 1 7.99 8"
|
|
||||||
: root.kind == "release"
|
|
||||||
? "M12 18 V8 M9 11 L12 8 L15 11 M7 6 V3 M17 6 V3"
|
|
||||||
: "";
|
|
||||||
private property <string> badge-detail: root.kind == "branch-create" || root.kind == "repo-create" || root.kind == "issue-open" || root.kind == "pull-open"
|
|
||||||
? "M18 15.5 V20.5 M15.5 18 H20.5"
|
|
||||||
: root.kind == "issue-close" || root.kind == "pull-merge" || root.kind == "pull-approve"
|
|
||||||
? "M15.4 18 L17.2 19.8 L20.7 16.2"
|
|
||||||
: root.kind == "branch-delete" || root.kind == "tag-delete"
|
|
||||||
? "M15.3 18 H20.7"
|
|
||||||
: root.kind == "pull-close" || root.kind == "pull-reject"
|
|
||||||
? "M16 16 L20 20 M20 16 L16 20"
|
|
||||||
: root.kind == "push" || root.kind == "tag-push"
|
|
||||||
? "M18 20.5 V15.5 M15.7 17.8 L18 15.5 L20.3 17.8"
|
|
||||||
: root.kind == "repo-rename"
|
|
||||||
? "M15.3 20.6 L16 18 L19.7 14.3 L21.7 16.3 L18 20 Z"
|
|
||||||
: root.kind == "repo-star"
|
|
||||||
? "M18 14.5 L19 16.7 L21.4 17 L19.6 18.7 L20.1 21 L18 19.8 L15.9 21 L16.4 18.7 L14.6 17 L17 16.7 Z"
|
|
||||||
: root.kind == "repo-watch"
|
|
||||||
? "M14.5 18 C16.3 15.8 19.7 15.8 21.5 18 C19.7 20.2 16.3 20.2 14.5 18 M18 17 A1 1 0 1 1 17.99 17"
|
|
||||||
: root.kind == "issue-reopen" || root.kind == "pull-reopen"
|
|
||||||
? "M20.8 17 A3 3 0 1 0 20.2 20.3 M20.8 17 H18.5 M20.8 17 V19.3"
|
|
||||||
: root.kind == "issue-comment" || root.kind == "pull-comment"
|
|
||||||
? "M15.5 17 H20.5 V20 H18 L16 21 V20 H15.5 Z M17 18.5 H17.1 M19 18.5 H19.1"
|
|
||||||
: root.kind == "update"
|
|
||||||
? "M18 14.8 L18.8 17.2 L21.2 18 L18.8 18.8 L18 21.2 L17.2 18.8 L14.8 18 L17.2 17.2 Z"
|
|
||||||
: "";
|
|
||||||
|
|
||||||
Path {
|
|
||||||
width: 100%; height: 100%; viewbox-width: 24; viewbox-height: 24;
|
|
||||||
commands: root.shape;
|
|
||||||
fill: root.closed-shape ? (root.bold || root.kind == "favorite-filled" ? root.icon-color : root.duotone ? #26bfd133 : transparent) : transparent;
|
|
||||||
stroke: root.closed-shape && (root.bold || root.kind == "favorite-filled") ? transparent : root.icon-color;
|
|
||||||
stroke-width: root.bold ? 3px : root.duotone ? 2.2px : 1.8px;
|
|
||||||
stroke-line-cap: round; stroke-line-join: round;
|
|
||||||
}
|
|
||||||
if root.detail != "": Path {
|
|
||||||
width: 100%; height: 100%; viewbox-width: 24; viewbox-height: 24;
|
|
||||||
commands: root.detail; fill: transparent;
|
|
||||||
stroke: root.bold && root.closed-shape ? #ffffff : root.icon-color;
|
|
||||||
stroke-width: root.bold ? 2.4px : 1.8px;
|
|
||||||
stroke-line-cap: round; stroke-line-join: round;
|
|
||||||
}
|
|
||||||
if root.has-badge: Path {
|
|
||||||
width: 100%; height: 100%; viewbox-width: 24; viewbox-height: 24;
|
|
||||||
commands: "M18 13.5 A4.5 4.5 0 1 1 17.99 13.5 Z";
|
|
||||||
fill: root.style == 0 ? AppTheme.surface : root.badge-color;
|
|
||||||
stroke: root.style == 0 ? root.badge-color : #ffffff;
|
|
||||||
stroke-width: root.style == 2 ? 1.5px : 1.2px;
|
|
||||||
}
|
|
||||||
if root.has-badge: Path {
|
|
||||||
width: 100%; height: 100%; viewbox-width: 24; viewbox-height: 24;
|
|
||||||
commands: root.badge-detail; fill: root.style == 0 ? transparent : #ffffff;
|
|
||||||
stroke: root.style == 0 ? root.badge-color : #ffffff;
|
|
||||||
stroke-width: root.bold ? 2px : 1.6px;
|
|
||||||
stroke-line-cap: round; stroke-line-join: round;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component IconStyleChoice inherits Rectangle {
|
|
||||||
in property <int> value;
|
|
||||||
in property <string> label;
|
|
||||||
callback clicked();
|
|
||||||
background: IconTheme.style == root.value ? AppTheme.accent-soft : AppTheme.surface-muted;
|
|
||||||
border-color: IconTheme.style == root.value ? AppTheme.accent : AppTheme.border;
|
|
||||||
border-width: IconTheme.style == root.value ? 2px : 1px;
|
|
||||||
border-radius: 11px;
|
|
||||||
TouchArea { clicked => { root.clicked(); } }
|
|
||||||
AppIcon { x: (parent.width - 30px) / 2; y: 10px; width: 30px; height: 30px; kind: "repositories"; style: root.value; }
|
|
||||||
Text { y: 48px; width: 100%; text: root.label; font-size: 12px; font-weight: IconTheme.style == root.value ? 650 : 500; color: AppTheme.text; horizontal-alignment: center; }
|
|
||||||
}
|
|
||||||
|
|
||||||
component AppearanceChoice inherits Rectangle {
|
|
||||||
in property <int> value;
|
|
||||||
in property <string> label;
|
|
||||||
callback clicked();
|
|
||||||
background: AppTheme.mode == root.value ? AppTheme.accent-soft : AppTheme.surface-muted;
|
|
||||||
border-color: AppTheme.mode == root.value ? AppTheme.accent : AppTheme.border;
|
|
||||||
border-width: AppTheme.mode == root.value ? 2px : 1px;
|
|
||||||
border-radius: 11px;
|
|
||||||
TouchArea { clicked => { root.clicked(); } }
|
|
||||||
Text {
|
|
||||||
width: 100%; height: 100%; text: root.label;
|
|
||||||
font-size: 14px; font-weight: AppTheme.mode == root.value ? 650 : 500;
|
|
||||||
color: AppTheme.mode == root.value ? AppTheme.accent : AppTheme.text;
|
|
||||||
horizontal-alignment: center; vertical-alignment: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component Header inherits Rectangle {
|
|
||||||
in property <string> title;
|
|
||||||
in property <bool> can_back;
|
|
||||||
in property <bool> can_filter: false;
|
|
||||||
callback back();
|
|
||||||
callback filter();
|
|
||||||
height: 58px;
|
|
||||||
width: 100%;
|
|
||||||
background: AppTheme.header;
|
|
||||||
border-color: AppTheme.border;
|
|
||||||
border-width: 0px;
|
|
||||||
|
|
||||||
if can_back: TouchArea {
|
|
||||||
x: 8px; width: 54px;
|
|
||||||
clicked => { root.back(); }
|
|
||||||
AppIcon { x: 7px; y: 17px; width: 24px; height: 24px; kind: "back"; }
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
x: root.can_back || root.can_filter ? 62px : 12px;
|
|
||||||
width: parent.width - 2 * self.x;
|
|
||||||
text: root.title;
|
|
||||||
horizontal-alignment: center;
|
|
||||||
vertical-alignment: center;
|
|
||||||
font-size: 18px;
|
|
||||||
font-weight: 600;
|
|
||||||
color: AppTheme.text;
|
|
||||||
overflow: elide;
|
|
||||||
}
|
|
||||||
if can_filter: TouchArea {
|
|
||||||
x: parent.width - 58px; width: 58px;
|
|
||||||
clicked => { root.filter(); }
|
|
||||||
AppIcon { x: 17px; y: 17px; width: 24px; height: 24px; kind: "filter"; }
|
|
||||||
}
|
|
||||||
Rectangle { y: parent.height - 1px; height: 1px; background: AppTheme.border; }
|
|
||||||
}
|
|
||||||
|
|
||||||
component EdgeBack inherits SwipeGestureHandler {
|
|
||||||
callback back();
|
|
||||||
width: 24px;
|
|
||||||
height: 100%;
|
|
||||||
handle-swipe-right: true;
|
|
||||||
swiped => { root.back(); }
|
|
||||||
}
|
|
||||||
|
|
||||||
component EmptyState inherits VerticalLayout {
|
|
||||||
in property <string> title;
|
|
||||||
in property <string> detail;
|
|
||||||
alignment: center;
|
|
||||||
spacing: 8px;
|
|
||||||
Text { text: root.title; font-size: 21px; font-weight: 600; horizontal-alignment: center; color: AppTheme.text; }
|
|
||||||
Text { text: root.detail; font-size: 15px; horizontal-alignment: center; wrap: word-wrap; color: AppTheme.text-secondary; }
|
|
||||||
}
|
|
||||||
|
|
||||||
component MarkdownContent inherits VerticalLayout {
|
|
||||||
in property <[MarkdownBlock]> blocks;
|
|
||||||
spacing: 8px;
|
|
||||||
|
|
||||||
for block in root.blocks: Rectangle {
|
|
||||||
height: block.kind == "rule" ? 9px : rendered.preferred-height + (block.kind == "code" || block.kind == "table" ? 16px : 0px);
|
|
||||||
background: block.kind == "code" || block.kind == "table" ? AppTheme.code-background : block.kind == "quote" ? AppTheme.quote-background : transparent;
|
|
||||||
border-radius: block.kind == "code" || block.kind == "table" ? 7px : 0px;
|
|
||||||
if block.kind == "quote": Rectangle { width: 3px; height: 100%; background: AppTheme.text-tertiary; border-radius: 2px; }
|
|
||||||
if block.kind == "rule": Rectangle { y: 4px; width: 100%; height: 1px; background: AppTheme.separator; }
|
|
||||||
rendered := StyledText {
|
|
||||||
x: block.kind == "code" || block.kind == "table" ? 8px : block.kind == "quote" ? 11px : 0px;
|
|
||||||
y: block.kind == "code" || block.kind == "table" ? 8px : 0px;
|
|
||||||
width: parent.width - self.x - (block.kind == "code" || block.kind == "table" ? 8px : 0px);
|
|
||||||
text: block.text;
|
|
||||||
default-color: AppTheme.text;
|
|
||||||
link-color: AppTheme.accent;
|
|
||||||
default-font-family: block.kind == "code" || block.kind == "table" ? "monospace" : "";
|
|
||||||
default-font-size: block.kind == "heading1" ? 24px : block.kind == "heading2" ? 21px : block.kind == "heading3" ? 19px : block.kind == "heading4" ? 17px : 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component CommentCard inherits Rectangle {
|
|
||||||
in property <CommentRow> comment;
|
|
||||||
height: content.preferred-height + 24px;
|
|
||||||
background: AppTheme.surface;
|
|
||||||
border-radius: 10px;
|
|
||||||
content := VerticalLayout {
|
|
||||||
x: 12px; y: 10px; width: parent.width - 24px;
|
|
||||||
spacing: 5px;
|
|
||||||
Text { text: root.comment.author; font-size: 13px; font-weight: 600; color: AppTheme.text; }
|
|
||||||
MarkdownContent { width: parent.width; blocks: root.comment.body; }
|
|
||||||
Text { text: root.comment.meta; font-size: 11px; color: AppTheme.text-tertiary; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component FileCard inherits Rectangle {
|
|
||||||
in property <FileRow> file;
|
|
||||||
callback clicked();
|
|
||||||
height: 66px;
|
|
||||||
background: AppTheme.surface;
|
|
||||||
border-color: AppTheme.border;
|
|
||||||
border-width: 1px;
|
|
||||||
border-radius: 10px;
|
|
||||||
TouchArea { clicked => { root.clicked(); } }
|
|
||||||
Text { x: 13px; y: 10px; width: parent.width - 26px; text: root.file.path; font-size: 14px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
|
||||||
Text { x: 13px; y: 38px; width: parent.width - 26px; text: root.file.status; font-size: 12px; color: AppTheme.text-secondary; }
|
|
||||||
}
|
|
||||||
|
|
||||||
component TabButton inherits Rectangle {
|
|
||||||
in property <string> kind;
|
|
||||||
in property <string> label;
|
|
||||||
in property <bool> active;
|
|
||||||
private property <length> icon-area-height: root.height * 3 / 4;
|
|
||||||
private property <length> icon-size: min(42px, self.icon-area-height - 6px);
|
|
||||||
callback clicked();
|
|
||||||
background: transparent;
|
|
||||||
TouchArea { clicked => { root.clicked(); } }
|
|
||||||
AppIcon {
|
|
||||||
x: (parent.width - root.icon-size) / 2;
|
|
||||||
y: (root.icon-area-height - root.icon-size) / 2;
|
|
||||||
width: root.icon-size; height: root.icon-size;
|
|
||||||
kind: root.kind; icon-color: root.active ? AppTheme.accent : AppTheme.text-tertiary;
|
|
||||||
}
|
|
||||||
Text {
|
|
||||||
y: root.icon-area-height; height: parent.height - self.y; width: 100%; text: root.label;
|
|
||||||
color: root.active ? AppTheme.accent : AppTheme.text-tertiary; font-size: 9px;
|
|
||||||
font-weight: root.active ? 600 : 400;
|
|
||||||
horizontal-alignment: center; vertical-alignment: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
component PullToRefreshGesture inherits SwipeGestureHandler {
|
|
||||||
in property <bool> at_top;
|
|
||||||
in property <bool> refreshing;
|
|
||||||
callback refresh();
|
|
||||||
enabled: root.at_top && !root.refreshing;
|
|
||||||
handle-swipe-down: true;
|
|
||||||
swiped => { root.refresh(); }
|
|
||||||
@children
|
|
||||||
if self.swiping: Rectangle {
|
|
||||||
x: (parent.width - 142px) / 2; y: 8px; width: 142px; height: 32px;
|
|
||||||
background: AppTheme.surface-muted; border-radius: 16px;
|
|
||||||
Text { text: "Release to refresh"; font-size: 12px; color: AppTheme.text-secondary; horizontal-alignment: center; vertical-alignment: center; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export component AppWindow inherits Window {
|
|
||||||
title: "Gotcha";
|
|
||||||
preferred-width: 390px;
|
|
||||||
preferred-height: 844px;
|
|
||||||
background: AppTheme.page;
|
|
||||||
private property <length> toolbar-height: 68px;
|
|
||||||
|
|
||||||
in-out property <string> tab: "home";
|
|
||||||
in-out property <string> page: "servers";
|
|
||||||
in-out property <[ServerRow]> servers;
|
|
||||||
in-out property <[RepositoryRow]> repositories;
|
|
||||||
in-out property <[IssueRow]> issues;
|
|
||||||
in-out property <[PullRow]> pulls;
|
|
||||||
in-out property <[CommentRow]> comments;
|
|
||||||
in-out property <[CommitRow]> commits;
|
|
||||||
in-out property <[FileRow]> files;
|
|
||||||
in-out property <[ActivityRow]> activities;
|
|
||||||
in-out property <[HeatCell]> heat_cells;
|
|
||||||
in-out property <int> contribution_count;
|
|
||||||
in-out property <bool> has_active_server;
|
|
||||||
in-out property <string> home_server;
|
|
||||||
in-out property <string> server_title;
|
|
||||||
in-out property <string> repository_title;
|
|
||||||
in-out property <string> issue_title;
|
|
||||||
in-out property <string> issue_meta;
|
|
||||||
in-out property <[MarkdownBlock]> issue_body;
|
|
||||||
in-out property <string> detail_title;
|
|
||||||
in-out property <string> detail_meta;
|
|
||||||
in-out property <string> detail_files_ref;
|
|
||||||
in-out property <[MarkdownBlock]> detail_body;
|
|
||||||
in-out property <[DiffLine]> diff_lines;
|
|
||||||
in-out property <int> diff_columns;
|
|
||||||
in-out property <string> issue_filter: "open";
|
|
||||||
in-out property <string> pull_filter: "open";
|
|
||||||
in-out property <[string]> branch_choices;
|
|
||||||
in-out property <int> branch_index;
|
|
||||||
in-out property <bool> filter_open;
|
|
||||||
in-out property <bool> loading;
|
|
||||||
in-out property <bool> home_loading;
|
|
||||||
in-out property <bool> refreshing;
|
|
||||||
in-out property <string> error;
|
|
||||||
in-out property <int> home_scroll_request;
|
|
||||||
in-out property <int> servers_scroll_request;
|
|
||||||
in-out property <int> repositories_scroll_request;
|
|
||||||
in-out property <int> issues_scroll_request;
|
|
||||||
in-out property <int> issue_scroll_request;
|
|
||||||
private property <bool> home_at_top: true;
|
|
||||||
private property <bool> repositories_at_top: true;
|
|
||||||
private property <bool> issues_at_top: true;
|
|
||||||
private property <bool> issue_at_top: true;
|
|
||||||
|
|
||||||
callback select_tab(string);
|
|
||||||
callback refresh_home();
|
|
||||||
callback refresh_repositories();
|
|
||||||
callback refresh_issues();
|
|
||||||
callback refresh_issue();
|
|
||||||
callback refresh_pulls();
|
|
||||||
callback refresh_pull();
|
|
||||||
callback refresh_commits();
|
|
||||||
callback show_add_server();
|
|
||||||
callback save_server(string, string, string);
|
|
||||||
callback select_server(int);
|
|
||||||
callback select_repository(string, string);
|
|
||||||
callback toggle_favorite(string, string);
|
|
||||||
callback select_issue(int);
|
|
||||||
callback select_pull(string, string, int);
|
|
||||||
callback select_commit(string);
|
|
||||||
callback select_branch(string);
|
|
||||||
callback select_file(string);
|
|
||||||
callback select_pull_file(string);
|
|
||||||
callback select_activity(string, string, string, int, string);
|
|
||||||
callback choose_filter(string);
|
|
||||||
callback choose_icon_style(int);
|
|
||||||
callback choose_appearance(int);
|
|
||||||
callback back();
|
|
||||||
|
|
||||||
if tab == "home": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: root.has_active_server ? root.home_server : "Home"; can_back: false; }
|
|
||||||
|
|
||||||
if !root.has_active_server: EmptyState {
|
|
||||||
x: 32px; width: parent.width - 64px; y: 210px; height: 190px;
|
|
||||||
title: "No server selected";
|
|
||||||
detail: "Open Issues to select a server or add your first one.";
|
|
||||||
}
|
|
||||||
|
|
||||||
if root.has_active_server: Rectangle {
|
|
||||||
x: 16px; y: 72px; width: parent.width - 32px; height: 118px;
|
|
||||||
background: AppTheme.surface; border-radius: 12px;
|
|
||||||
Text { x: 13px; y: 10px; text: "Activity · last 12 months"; font-size: 13px; font-weight: 600; color: AppTheme.text; }
|
|
||||||
Text { x: 13px; y: 86px; text: root.contribution_count + " contributions"; font-size: 12px; color: AppTheme.text-secondary; }
|
|
||||||
for cell in root.heat_cells: Rectangle {
|
|
||||||
x: 13px + cell.week * 6.7px; y: 39px + cell.day * 6.2px;
|
|
||||||
width: 5.2px; height: 5.2px; border-radius: 1px;
|
|
||||||
background: cell.level == 0 ? (AppTheme.dark ? #3a3a3c : #e5e5e9) : cell.level == 1 ? #b8d9f4 : cell.level == 2 ? #72b5e8 : cell.level == 3 ? #278bd4 : #0969b7;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if root.has_active_server && !root.home_loading && root.activities.length == 0: EmptyState {
|
|
||||||
x: 32px; width: parent.width - 64px; y: 250px; height: 150px;
|
|
||||||
title: "No recent activity";
|
|
||||||
detail: "Your recent server actions will appear here.";
|
|
||||||
}
|
|
||||||
|
|
||||||
if root.has_active_server: PullToRefreshGesture {
|
|
||||||
x: 16px; y: 202px; width: parent.width - 32px; height: parent.height - 214px;
|
|
||||||
at_top: root.home_at_top; refreshing: root.home_loading;
|
|
||||||
refresh => { root.refresh_home(); }
|
|
||||||
home_list := ListView {
|
|
||||||
property <int> scroll_request: root.home_scroll_request;
|
|
||||||
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
|
||||||
changed scroll_request => { self.viewport-y = 0px; root.home_at_top = true; }
|
|
||||||
scrolled => { root.home_at_top = self.viewport-y >= 0px; }
|
|
||||||
for activity in root.activities: Rectangle {
|
|
||||||
height: 94px;
|
|
||||||
background: AppTheme.surface; border-radius: 12px;
|
|
||||||
TouchArea {
|
|
||||||
enabled: activity.target != "";
|
|
||||||
clicked => { root.select_activity(activity.target, activity.owner, activity.repository, activity.number, activity.sha); }
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
x: 12px; y: 14px; width: 34px; height: 34px; border-radius: 17px;
|
|
||||||
background: AppTheme.accent-soft;
|
|
||||||
AppIcon { x: 5px; y: 5px; width: 24px; height: 24px; kind: activity.icon; }
|
|
||||||
}
|
|
||||||
Text { x: 57px; y: 11px; width: parent.width - 69px; height: 24px; text: activity.title; font-size: 15px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
|
||||||
Text { x: 57px; y: 36px; width: parent.width - 69px; height: 35px; text: activity.detail; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; overflow: elide; }
|
|
||||||
Text { x: 57px; y: 72px; width: parent.width - 69px; text: activity.meta; font-size: 11px; color: AppTheme.text-tertiary; overflow: elide; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if root.home_loading: Spinner { width: 34px; height: 34px; x: (parent.width - self.width) / 2; y: 222px; }
|
|
||||||
}
|
|
||||||
|
|
||||||
if tab == "settings": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header {
|
|
||||||
x: 0; y: 0; can_back: false;
|
|
||||||
title: "Settings";
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
x: 16px; y: 76px; width: parent.width - 32px; height: 184px;
|
|
||||||
background: AppTheme.surface; border-radius: 12px;
|
|
||||||
Text { x: 15px; y: 13px; text: "Icon style"; font-size: 18px; font-weight: 650; color: AppTheme.text; }
|
|
||||||
Text { x: 15px; y: 43px; width: parent.width - 30px; text: "Choose how navigation and activity icons look throughout Gotcha."; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; }
|
|
||||||
IconStyleChoice { x: 12px; y: 91px; width: (parent.width - 36px) / 3; height: 78px; value: 0; label: "Outline"; clicked => { root.choose_icon_style(0); } }
|
|
||||||
IconStyleChoice { x: 18px + (parent.width - 36px) / 3; y: 91px; width: (parent.width - 36px) / 3; height: 78px; value: 1; label: "Duotone"; clicked => { root.choose_icon_style(1); } }
|
|
||||||
IconStyleChoice { x: 24px + 2 * (parent.width - 36px) / 3; y: 91px; width: (parent.width - 36px) / 3; height: 78px; value: 2; label: "Bold"; clicked => { root.choose_icon_style(2); } }
|
|
||||||
}
|
|
||||||
Rectangle {
|
|
||||||
x: 16px; y: 276px; width: parent.width - 32px; height: 136px;
|
|
||||||
background: AppTheme.surface; border-radius: 12px;
|
|
||||||
Text { x: 15px; y: 13px; text: "Appearance"; font-size: 18px; font-weight: 650; color: AppTheme.text; }
|
|
||||||
Text { x: 15px; y: 43px; width: parent.width - 30px; text: "Follow iOS automatically or choose a fixed light or dark appearance."; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; }
|
|
||||||
AppearanceChoice { x: 12px; y: 81px; width: (parent.width - 36px) / 3; height: 42px; value: 0; label: "Auto"; clicked => { root.choose_appearance(0); } }
|
|
||||||
AppearanceChoice { x: 18px + (parent.width - 36px) / 3; y: 81px; width: (parent.width - 36px) / 3; height: 42px; value: 1; label: "Light"; clicked => { root.choose_appearance(1); } }
|
|
||||||
AppearanceChoice { x: 24px + 2 * (parent.width - 36px) / 3; y: 81px; width: (parent.width - 36px) / 3; height: 42px; value: 2; label: "Dark"; clicked => { root.choose_appearance(2); } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tab == "issues" || tab == "repositories") && page == "servers": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: "Servers"; can_back: false; }
|
|
||||||
if root.servers.length > 0: servers_list := ListView {
|
|
||||||
property <int> scroll_request: root.servers_scroll_request;
|
|
||||||
x: 16px; y: 76px; width: parent.width - 32px; height: parent.height - 154px;
|
|
||||||
mouse-drag-pan-enabled: true;
|
|
||||||
changed scroll_request => { self.viewport-y = 0px; }
|
|
||||||
for server[index] in root.servers: Rectangle {
|
|
||||||
height: 76px;
|
|
||||||
background: AppTheme.surface;
|
|
||||||
border-color: AppTheme.border;
|
|
||||||
border-width: 1px;
|
|
||||||
border-radius: 12px;
|
|
||||||
TouchArea { clicked => { root.select_server(index); } }
|
|
||||||
Text { x: 16px; y: 13px; width: parent.width - 54px; text: server.name; font-size: 17px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
|
||||||
Text { x: 16px; y: 42px; width: parent.width - 54px; text: server.url; font-size: 13px; color: AppTheme.text-secondary; overflow: elide; }
|
|
||||||
AppIcon { x: parent.width - 29px; y: 26px; width: 20px; height: 20px; kind: "disclosure"; icon-color: AppTheme.text-tertiary; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Button { x: 16px; y: parent.height - 66px; width: parent.width - 32px; height: 48px; text: "Add Server"; clicked => { root.show_add_server(); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tab == "issues" || tab == "repositories") && page == "add": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: "Add Server"; can_back: true; back => { root.back(); } }
|
|
||||||
VerticalLayout {
|
|
||||||
x: 20px; y: 92px; width: parent.width - 40px; height: 260px; spacing: 10px;
|
|
||||||
Text { text: "Name"; font-size: 13px; color: AppTheme.text-secondary; }
|
|
||||||
server_name := LineEdit { placeholder-text: "Work"; }
|
|
||||||
Text { text: "Server URL"; font-size: 13px; color: AppTheme.text-secondary; }
|
|
||||||
server_url := LineEdit { placeholder-text: "https://gitea.example.com"; }
|
|
||||||
Text { text: "Access token"; font-size: 13px; color: AppTheme.text-secondary; }
|
|
||||||
server_token := LineEdit { placeholder-text: "Token"; input-type: InputType.password; }
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
x: 20px; y: 380px; width: parent.width - 40px; height: 48px;
|
|
||||||
text: root.loading ? "Connecting…" : "Add Server";
|
|
||||||
enabled: !root.loading;
|
|
||||||
clicked => { root.save_server(server_name.text, server_url.text, server_token.text); }
|
|
||||||
}
|
|
||||||
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tab == "issues" || tab == "repositories") && page == "repositories": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: root.server_title; can_back: true; back => { root.back(); } }
|
|
||||||
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
|
||||||
if !root.loading && root.repositories.length == 0: EmptyState {
|
|
||||||
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
|
||||||
title: "No repositories";
|
|
||||||
detail: "This account does not own any repositories on this server.";
|
|
||||||
}
|
|
||||||
PullToRefreshGesture {
|
|
||||||
x: 20px; y: 70px; width: parent.width - 40px; height: parent.height - 82px;
|
|
||||||
at_top: root.repositories_at_top; refreshing: root.refreshing;
|
|
||||||
refresh => { root.refresh_repositories(); }
|
|
||||||
repositories_list := ListView {
|
|
||||||
property <int> scroll_request: root.repositories_scroll_request;
|
|
||||||
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
|
||||||
changed scroll_request => { self.viewport-y = 0px; root.repositories_at_top = true; }
|
|
||||||
scrolled => { root.repositories_at_top = self.viewport-y >= 0px; }
|
|
||||||
for repo in root.repositories: Rectangle {
|
|
||||||
height: 104px;
|
|
||||||
background: AppTheme.surface;
|
|
||||||
border-color: AppTheme.border;
|
|
||||||
border-width: 1px;
|
|
||||||
border-radius: 12px;
|
|
||||||
TouchArea { clicked => { root.select_repository(repo.owner, repo.name); } }
|
|
||||||
Text { x: 15px; y: 11px; width: parent.width - 62px; text: repo.name; font-size: 17px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
|
||||||
Text { x: 15px; y: 39px; width: parent.width - 30px; text: repo.description; font-size: 14px; color: AppTheme.text-secondary; overflow: elide; }
|
|
||||||
Text { x: 15px; y: 71px; width: parent.width - 30px; text: repo.meta; font-size: 12px; color: AppTheme.text-tertiary; overflow: elide; }
|
|
||||||
TouchArea {
|
|
||||||
x: parent.width - 52px; y: 2px; width: 48px; height: 48px;
|
|
||||||
clicked => { root.toggle_favorite(repo.owner, repo.name); }
|
|
||||||
AppIcon { x: 10px; y: 10px; width: 28px; height: 28px; kind: repo.favorite ? "favorite-filled" : "favorite"; icon-color: repo.favorite ? #f2a900 : AppTheme.text-tertiary; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
if tab == "issues" && page == "issues": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header {
|
|
||||||
x: 0; y: 0; title: root.repository_title; can_back: true; can_filter: true;
|
|
||||||
back => { root.back(); }
|
|
||||||
filter => { root.filter_open = true; }
|
|
||||||
}
|
|
||||||
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
|
||||||
if !root.loading && root.issues.length == 0: EmptyState {
|
|
||||||
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
|
||||||
title: "No " + root.issue_filter + " issues";
|
|
||||||
detail: "No issues match the selected status.";
|
|
||||||
}
|
|
||||||
PullToRefreshGesture {
|
|
||||||
x: 20px; y: 70px; width: parent.width - 40px; height: parent.height - 82px;
|
|
||||||
at_top: root.issues_at_top; refreshing: root.refreshing;
|
|
||||||
refresh => { root.refresh_issues(); }
|
|
||||||
issues_list := ListView {
|
|
||||||
property <int> scroll_request: root.issues_scroll_request;
|
|
||||||
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
|
||||||
changed scroll_request => { self.viewport-y = 0px; root.issues_at_top = true; }
|
|
||||||
scrolled => { root.issues_at_top = self.viewport-y >= 0px; }
|
|
||||||
for issue in root.issues: Rectangle {
|
|
||||||
height: issue.labels.length > 0 ? 138px : 112px;
|
|
||||||
background: AppTheme.surface;
|
|
||||||
border-color: AppTheme.border;
|
|
||||||
border-width: 1px;
|
|
||||||
border-radius: 12px;
|
|
||||||
TouchArea { clicked => { root.select_issue(issue.number); } }
|
|
||||||
Text { x: 15px; y: 11px; width: parent.width - 44px; text: issue.title; font-size: 16px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
|
||||||
Text { x: 15px; y: 39px; width: parent.width - 30px; height: 38px; text: issue.summary; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; overflow: elide; }
|
|
||||||
if issue.labels.length > 0: HorizontalLayout {
|
|
||||||
x: 15px; y: 82px; width: parent.width - 30px; height: 22px; spacing: 5px;
|
|
||||||
for label in issue.labels: Rectangle {
|
|
||||||
width: min(104px, max(48px, (parent.width - (issue.labels.length - 1) * 5px) / issue.labels.length));
|
|
||||||
height: 22px; background: label.background; border-radius: 11px;
|
|
||||||
Text { x: 7px; width: parent.width - 14px; text: label.name; color: label.foreground; font-size: 11px; font-weight: 600; horizontal-alignment: center; vertical-alignment: center; overflow: elide; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Text { x: 15px; y: issue.labels.length > 0 ? 112px : 86px; width: parent.width - 30px; text: issue.meta; font-size: 12px; color: AppTheme.text-tertiary; overflow: elide; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
if tab == "issues" && page == "issue": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: "Issue"; can_back: true; back => { root.back(); } }
|
|
||||||
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
|
||||||
PullToRefreshGesture {
|
|
||||||
x: 18px; y: 78px; width: parent.width - 36px; height: parent.height - 96px;
|
|
||||||
at_top: root.issue_at_top; refreshing: root.refreshing;
|
|
||||||
refresh => { root.refresh_issue(); }
|
|
||||||
issue_scroll := ScrollView {
|
|
||||||
property <int> scroll_request: root.issue_scroll_request;
|
|
||||||
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
|
||||||
changed scroll_request => { self.viewport-y = 0px; root.issue_at_top = true; }
|
|
||||||
scrolled => { root.issue_at_top = self.viewport-y >= 0px; }
|
|
||||||
VerticalLayout {
|
|
||||||
width: parent.width;
|
|
||||||
spacing: 12px;
|
|
||||||
alignment: start;
|
|
||||||
Text { text: root.issue_title; font-size: 23px; font-weight: 650; color: AppTheme.text; wrap: word-wrap; }
|
|
||||||
Text { text: root.issue_meta; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; }
|
|
||||||
Rectangle { height: 1px; background: AppTheme.separator; }
|
|
||||||
MarkdownContent { width: parent.width; blocks: root.issue_body; }
|
|
||||||
if root.comments.length > 0: Text { text: "Comments"; font-size: 17px; font-weight: 600; color: AppTheme.text; }
|
|
||||||
for comment in root.comments: CommentCard { width: parent.width; comment: comment; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
if tab == "pulls" && !root.has_active_server: Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: "Home"; can_back: false; }
|
|
||||||
EmptyState {
|
|
||||||
x: 32px; width: parent.width - 64px; y: 210px; height: 190px;
|
|
||||||
title: "No server selected";
|
|
||||||
detail: "Open Issues or Repositories to select a server or add your first one.";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tab == "pulls" && root.has_active_server && page == "pulls": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header {
|
|
||||||
x: 0; y: 0; title: "Pull Requests"; can_back: false; can_filter: true;
|
|
||||||
filter => { root.filter_open = true; }
|
|
||||||
}
|
|
||||||
if root.refreshing: Spinner { x: parent.width - 92px; y: 17px; width: 24px; height: 24px; }
|
|
||||||
if !root.loading && root.pulls.length == 0: EmptyState {
|
|
||||||
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
|
||||||
title: "No " + root.pull_filter + " pull requests";
|
|
||||||
detail: "No pull requests match the selected status.";
|
|
||||||
}
|
|
||||||
PullToRefreshGesture {
|
|
||||||
x: 16px; y: 70px; width: parent.width - 32px; height: parent.height - 82px;
|
|
||||||
at_top: root.issues_at_top; refreshing: root.refreshing;
|
|
||||||
refresh => { root.refresh_pulls(); }
|
|
||||||
ListView {
|
|
||||||
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
|
||||||
scrolled => { root.issues_at_top = self.viewport-y >= 0px; }
|
|
||||||
for pull in root.pulls: Rectangle {
|
|
||||||
height: 112px;
|
|
||||||
background: AppTheme.surface; border-color: AppTheme.border; border-width: 1px; border-radius: 12px;
|
|
||||||
TouchArea { clicked => { root.select_pull(pull.owner, pull.repository, pull.number); } }
|
|
||||||
Text { x: 14px; y: 10px; width: parent.width - 28px; text: pull.repository + " #" + pull.number; font-size: 12px; color: AppTheme.text-secondary; overflow: elide; }
|
|
||||||
Text { x: 14px; y: 31px; width: parent.width - 28px; text: pull.title; font-size: 16px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
|
||||||
Text { x: 14px; y: 57px; width: parent.width - 28px; text: pull.summary; font-size: 13px; color: AppTheme.text-secondary; overflow: elide; }
|
|
||||||
Text { x: 14px; y: 85px; width: parent.width - 28px; text: pull.meta; font-size: 12px; color: AppTheme.text-tertiary; overflow: elide; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if tab == "pulls" && page == "pull": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: "Pull Request"; can_back: true; back => { root.back(); } }
|
|
||||||
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
|
||||||
PullToRefreshGesture {
|
|
||||||
x: 18px; y: 78px; width: parent.width - 36px; height: parent.height - 96px;
|
|
||||||
at_top: root.issue_at_top; refreshing: root.refreshing;
|
|
||||||
refresh => { root.refresh_pull(); }
|
|
||||||
ScrollView {
|
|
||||||
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
|
||||||
scrolled => { root.issue_at_top = self.viewport-y >= 0px; }
|
|
||||||
VerticalLayout {
|
|
||||||
width: parent.width; spacing: 12px; alignment: start;
|
|
||||||
Text { text: root.detail_title; font-size: 23px; font-weight: 650; color: AppTheme.text; wrap: word-wrap; }
|
|
||||||
Text { text: root.detail_meta; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; }
|
|
||||||
Rectangle { height: 1px; background: AppTheme.separator; }
|
|
||||||
MarkdownContent { width: parent.width; blocks: root.detail_body; }
|
|
||||||
if root.files.length > 0: Text { text: root.detail_files_ref; font-size: 17px; font-weight: 600; color: AppTheme.text; }
|
|
||||||
for file in root.files: FileCard { width: parent.width; file: file; clicked => { root.select_pull_file(file.path); } }
|
|
||||||
if root.comments.length > 0: Text { text: "Comments"; font-size: 17px; font-weight: 600; color: AppTheme.text; }
|
|
||||||
for comment in root.comments: CommentCard { width: parent.width; comment: comment; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
if tab == "repositories" && page == "commits": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: root.repository_title; can_back: true; back => { root.back(); } }
|
|
||||||
ComboBox {
|
|
||||||
x: 16px; y: 66px; width: parent.width - 32px; height: 42px;
|
|
||||||
model: root.branch_choices; current-index: root.branch_index;
|
|
||||||
selected(value) => { root.select_branch(value); }
|
|
||||||
}
|
|
||||||
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
|
||||||
if !root.loading && root.commits.length == 0: EmptyState {
|
|
||||||
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
|
||||||
title: "No commits";
|
|
||||||
detail: "This repository has no commit history.";
|
|
||||||
}
|
|
||||||
PullToRefreshGesture {
|
|
||||||
x: 16px; y: 116px; width: parent.width - 32px; height: parent.height - 128px;
|
|
||||||
at_top: root.repositories_at_top; refreshing: root.refreshing;
|
|
||||||
refresh => { root.refresh_commits(); }
|
|
||||||
ListView {
|
|
||||||
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
|
||||||
scrolled => { root.repositories_at_top = self.viewport-y >= 0px; }
|
|
||||||
for commit in root.commits: commit_row := Rectangle {
|
|
||||||
property <length> graph-width: commit.lanes.length > 0 ? min(72px, commit.lanes.length * 10px + 8px) : 0px;
|
|
||||||
property <length> lane-spacing: (self.graph-width - 8px) / max(1, commit.lanes.length);
|
|
||||||
height: 86px; background: transparent;
|
|
||||||
Rectangle { width: 100%; height: 100%; background: AppTheme.surface; border-color: AppTheme.border; border-width: 1px; border-radius: 12px; }
|
|
||||||
TouchArea { clicked => { root.select_commit(commit.sha); } }
|
|
||||||
for lane[index] in commit.lanes: Rectangle {
|
|
||||||
x: 4px + index * commit_row.lane-spacing;
|
|
||||||
width: 3px; height: 100%; background: transparent;
|
|
||||||
if lane.top: Rectangle {
|
|
||||||
y: -1px; width: 3px;
|
|
||||||
height: lane.connect_left && !lane.bottom ? 37px : 42px;
|
|
||||||
background: lane.color;
|
|
||||||
}
|
|
||||||
if lane.bottom: Rectangle {
|
|
||||||
y: lane.connect_left && !lane.top ? 45px : 40px;
|
|
||||||
width: 3px;
|
|
||||||
height: parent.height - (lane.connect_left && !lane.top ? 44px : 39px);
|
|
||||||
background: lane.color;
|
|
||||||
}
|
|
||||||
if lane.connect_left && lane.top == lane.bottom: Rectangle {
|
|
||||||
x: -commit_row.lane-spacing; y: 39px;
|
|
||||||
width: commit_row.lane-spacing + 3px; height: 3px;
|
|
||||||
background: lane.color;
|
|
||||||
}
|
|
||||||
if lane.connect_left && lane.bottom && !lane.top: Path {
|
|
||||||
x: 1.5px - commit_row.lane-spacing; y: 35px;
|
|
||||||
width: commit_row.lane-spacing; height: 11px;
|
|
||||||
viewbox-width: 10; viewbox-height: 11;
|
|
||||||
commands: "M 0 5.5 L 5 5.5 Q 10 5.5 10 10.5";
|
|
||||||
fill: transparent; stroke: lane.color; stroke-width: 3px; stroke-line-cap: round;
|
|
||||||
}
|
|
||||||
if lane.connect_left && lane.top && !lane.bottom: Path {
|
|
||||||
x: 1.5px - commit_row.lane-spacing; y: 35px;
|
|
||||||
width: commit_row.lane-spacing; height: 11px;
|
|
||||||
viewbox-width: 10; viewbox-height: 11;
|
|
||||||
commands: "M 10 0.5 Q 10 5.5 5 5.5 L 0 5.5";
|
|
||||||
fill: transparent; stroke: lane.color; stroke-width: 3px; stroke-line-cap: round;
|
|
||||||
}
|
|
||||||
if lane.node: Rectangle {
|
|
||||||
x: -3px; y: 36px; width: 9px; height: 9px; border-radius: 5px;
|
|
||||||
background: lane.color; border-color: AppTheme.surface; border-width: 2px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Text { x: parent.graph-width + 14px; y: 8px; width: parent.width - self.x - 14px; text: commit.title; font-size: 15px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
|
||||||
Text { x: parent.graph-width + 14px; y: 33px; width: parent.width - self.x - 14px; text: commit.refs != "" ? commit.refs : commit.meta; font-size: 12px; color: commit.refs != "" ? AppTheme.accent : AppTheme.text-secondary; overflow: elide; }
|
|
||||||
Text { x: parent.graph-width + 14px; y: 53px; width: parent.width - self.x - 14px; text: commit.refs != "" ? commit.meta + " · " + commit.sha : commit.sha; font-size: 11px; color: AppTheme.text-tertiary; overflow: elide; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
if tab == "repositories" && page == "files": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: "Changed Files"; can_back: true; back => { root.back(); } }
|
|
||||||
if !root.loading && root.files.length == 0: EmptyState {
|
|
||||||
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
|
||||||
title: "No changed files";
|
|
||||||
detail: "This commit does not contain file changes.";
|
|
||||||
}
|
|
||||||
ListView {
|
|
||||||
x: 16px; y: 70px; width: parent.width - 32px; height: parent.height - 82px; mouse-drag-pan-enabled: true;
|
|
||||||
for file in root.files: FileCard { file: file; clicked => { root.select_file(file.path); } }
|
|
||||||
}
|
|
||||||
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tab == "repositories" || tab == "pulls") && page == "diff": Rectangle {
|
|
||||||
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
background: AppTheme.page;
|
|
||||||
Header { x: 0; y: 0; title: root.detail_title; can_back: true; back => { root.back(); } }
|
|
||||||
ScrollView {
|
|
||||||
x: 12px; y: 70px; width: parent.width - 24px; height: parent.height - 82px; mouse-drag-pan-enabled: true;
|
|
||||||
viewport-width: max(self.visible-width, root.diff_columns * 7px + 100px);
|
|
||||||
viewport-height: diff_rows.preferred-height;
|
|
||||||
diff_rows := VerticalLayout {
|
|
||||||
width: parent.viewport-width;
|
|
||||||
for line in root.diff_lines: Rectangle {
|
|
||||||
height: 20px;
|
|
||||||
background: line.kind == "addition" ? (AppTheme.dark ? #173d25 : #ddf5e3) : line.kind == "removal" ? (AppTheme.dark ? #4a2020 : #fde2e1) : line.kind == "hunk" ? (AppTheme.dark ? #17324d : #dcecff) : line.kind == "header" ? AppTheme.surface-muted : AppTheme.surface;
|
|
||||||
Text { x: 0; width: 38px; text: line.old_number; font-family: "monospace"; font-size: 11px; color: AppTheme.text-tertiary; horizontal-alignment: right; vertical-alignment: center; }
|
|
||||||
Text { x: 42px; width: 38px; text: line.new_number; font-family: "monospace"; font-size: 11px; color: AppTheme.text-tertiary; horizontal-alignment: right; vertical-alignment: center; }
|
|
||||||
Rectangle { x: 84px; width: 1px; height: 100%; background: AppTheme.separator; }
|
|
||||||
Text {
|
|
||||||
x: 90px; width: parent.width - 94px; text: line.text; font-family: "monospace"; font-size: 11px;
|
|
||||||
color: line.kind == "addition" ? (AppTheme.dark ? #7fe787 : #176b2c) : line.kind == "removal" ? (AppTheme.dark ? #ff7b72 : #a12720) : line.kind == "hunk" ? (AppTheme.dark ? #79c0ff : #175b9e) : AppTheme.text;
|
|
||||||
wrap: no-wrap; overflow: clip; vertical-alignment: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
Rectangle {
|
|
||||||
x: root.safe-area-insets.left;
|
|
||||||
y: root.height - root.safe-area-insets.bottom - root.toolbar-height;
|
|
||||||
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
|
||||||
height: root.toolbar-height;
|
|
||||||
background: AppTheme.toolbar;
|
|
||||||
TabButton {
|
|
||||||
x: 0; width: parent.width / 5; height: parent.height; kind: "home"; label: "Home"; active: root.tab == "home";
|
|
||||||
clicked => {
|
|
||||||
if root.tab == "home" { root.home_scroll_request += 1; }
|
|
||||||
root.select_tab("home");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TabButton {
|
|
||||||
x: parent.width / 5; width: parent.width / 5; height: parent.height; kind: "issues"; label: "Issues"; active: root.tab == "issues";
|
|
||||||
clicked => {
|
|
||||||
if root.tab == "issues" {
|
|
||||||
if root.page == "servers" { root.servers_scroll_request += 1; }
|
|
||||||
if root.page == "repositories" { root.repositories_scroll_request += 1; }
|
|
||||||
if root.page == "issues" { root.issues_scroll_request += 1; }
|
|
||||||
if root.page == "issue" { root.issue_scroll_request += 1; }
|
|
||||||
}
|
|
||||||
root.select_tab("issues");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TabButton { x: parent.width * 2 / 5; width: parent.width / 5; height: parent.height; kind: "repositories"; label: "Repos"; active: root.tab == "repositories"; clicked => { root.select_tab("repositories"); } }
|
|
||||||
TabButton { x: parent.width * 3 / 5; width: parent.width / 5; height: parent.height; kind: "pulls"; label: "Pulls"; active: root.tab == "pulls"; clicked => { root.select_tab("pulls"); } }
|
|
||||||
TabButton { x: parent.width * 4 / 5; width: parent.width / 5; height: parent.height; kind: "settings"; label: "Settings"; active: root.tab == "settings"; clicked => { root.select_tab("settings"); } }
|
|
||||||
}
|
|
||||||
|
|
||||||
if root.loading && (root.tab == "issues" || root.tab == "repositories" || root.tab == "pulls"): Rectangle {
|
|
||||||
width: 100%; height: 100%;
|
|
||||||
background: AppTheme.loading-overlay;
|
|
||||||
TouchArea { }
|
|
||||||
Spinner { width: 38px; height: 38px; x: (parent.width - self.width) / 2; y: (parent.height - self.height) / 2; }
|
|
||||||
}
|
|
||||||
if root.filter_open: Rectangle {
|
|
||||||
width: 100%; height: 100%; background: #00000066;
|
|
||||||
TouchArea { clicked => { root.filter_open = false; } }
|
|
||||||
Rectangle {
|
|
||||||
x: 28px; y: (parent.height - 190px) / 2; width: parent.width - 56px; height: 190px;
|
|
||||||
background: AppTheme.surface; border-radius: 14px;
|
|
||||||
Text { x: 18px; y: 16px; width: parent.width - 36px; text: "Status"; font-size: 19px; font-weight: 650; color: AppTheme.text; }
|
|
||||||
VerticalLayout {
|
|
||||||
x: 18px; y: 54px; width: parent.width - 36px; height: 118px; spacing: 8px;
|
|
||||||
Button { text: "Open"; clicked => { root.choose_filter("open"); root.filter_open = false; } }
|
|
||||||
Button { text: "Closed"; clicked => { root.choose_filter("closed"); root.filter_open = false; } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if root.error != "": Rectangle {
|
|
||||||
x: 14px; y: parent.height - root.safe-area-insets.bottom - 132px; width: parent.width - 28px; height: 66px;
|
|
||||||
background: #d93d35; border-radius: 12px;
|
|
||||||
Text { x: 14px; width: parent.width - 28px; text: root.error; color: white; font-size: 13px; wrap: word-wrap; vertical-alignment: center; }
|
|
||||||
TouchArea { clicked => { root.error = ""; } }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
614
crates/app/ui/app.slint
Normal file
614
crates/app/ui/app.slint
Normal file
@@ -0,0 +1,614 @@
|
|||||||
|
import { Button, ComboBox, LineEdit, ListView, ScrollView, Spinner } from "std-widgets.slint";
|
||||||
|
export {
|
||||||
|
ActivityRow, CommentRow, CommitRow, DiffLine, FileRow, GraphLane, HeatCell, IssueRow,
|
||||||
|
LabelRow, MarkdownBlock, PullRow, RepositoryRow, ServerRow,
|
||||||
|
} from "types.slint";
|
||||||
|
import {
|
||||||
|
ActivityRow, CommentRow, CommitRow, DiffLine, FileRow, GraphLane, HeatCell, IssueRow,
|
||||||
|
MarkdownBlock, PullRow, RepositoryRow, ServerRow,
|
||||||
|
} from "types.slint";
|
||||||
|
export { AppTheme, IconTheme } from "components.slint";
|
||||||
|
import {
|
||||||
|
AppearanceChoice, AppIcon, AppTheme, CommentCard, EdgeBack, EmptyState, FileCard, Header,
|
||||||
|
IconStyleChoice, MarkdownContent, PullToRefreshGesture, TabButton,
|
||||||
|
} from "components.slint";
|
||||||
|
|
||||||
|
export component AppWindow inherits Window {
|
||||||
|
title: "Gotcha";
|
||||||
|
preferred-width: 390px;
|
||||||
|
preferred-height: 844px;
|
||||||
|
background: AppTheme.page;
|
||||||
|
private property <length> toolbar-height: 68px;
|
||||||
|
|
||||||
|
in-out property <string> tab: "home";
|
||||||
|
in-out property <string> page: "servers";
|
||||||
|
in-out property <[ServerRow]> servers;
|
||||||
|
in-out property <[RepositoryRow]> repositories;
|
||||||
|
in-out property <[IssueRow]> issues;
|
||||||
|
in-out property <[PullRow]> pulls;
|
||||||
|
in-out property <[CommentRow]> comments;
|
||||||
|
in-out property <[CommitRow]> commits;
|
||||||
|
in-out property <[FileRow]> files;
|
||||||
|
in-out property <[ActivityRow]> activities;
|
||||||
|
in-out property <[HeatCell]> heat_cells;
|
||||||
|
in-out property <int> contribution_count;
|
||||||
|
in-out property <bool> has_active_server;
|
||||||
|
in-out property <string> home_server;
|
||||||
|
in-out property <string> server_title;
|
||||||
|
in-out property <string> repository_title;
|
||||||
|
in-out property <string> issue_title;
|
||||||
|
in-out property <string> issue_meta;
|
||||||
|
in-out property <[MarkdownBlock]> issue_body;
|
||||||
|
in-out property <string> detail_title;
|
||||||
|
in-out property <string> detail_meta;
|
||||||
|
in-out property <string> detail_files_ref;
|
||||||
|
in-out property <[MarkdownBlock]> detail_body;
|
||||||
|
in-out property <[DiffLine]> diff_lines;
|
||||||
|
in-out property <int> diff_columns;
|
||||||
|
in-out property <string> issue_filter: "open";
|
||||||
|
in-out property <string> pull_filter: "open";
|
||||||
|
in-out property <[string]> branch_choices;
|
||||||
|
in-out property <int> branch_index;
|
||||||
|
in-out property <bool> filter_open;
|
||||||
|
in-out property <bool> loading;
|
||||||
|
in-out property <bool> home_loading;
|
||||||
|
in-out property <bool> refreshing;
|
||||||
|
in-out property <string> error;
|
||||||
|
in-out property <int> home_scroll_request;
|
||||||
|
in-out property <int> servers_scroll_request;
|
||||||
|
in-out property <int> repositories_scroll_request;
|
||||||
|
in-out property <int> issues_scroll_request;
|
||||||
|
in-out property <int> issue_scroll_request;
|
||||||
|
private property <bool> home_at_top: true;
|
||||||
|
private property <bool> repositories_at_top: true;
|
||||||
|
private property <bool> issues_at_top: true;
|
||||||
|
private property <bool> issue_at_top: true;
|
||||||
|
|
||||||
|
callback select_tab(string);
|
||||||
|
callback refresh_home();
|
||||||
|
callback refresh_repositories();
|
||||||
|
callback refresh_issues();
|
||||||
|
callback refresh_issue();
|
||||||
|
callback refresh_pulls();
|
||||||
|
callback refresh_pull();
|
||||||
|
callback refresh_commits();
|
||||||
|
callback show_add_server();
|
||||||
|
callback save_server(string, string, string);
|
||||||
|
callback select_server(int);
|
||||||
|
callback select_repository(string, string);
|
||||||
|
callback toggle_favorite(string, string);
|
||||||
|
callback select_issue(int);
|
||||||
|
callback select_pull(string, string, int);
|
||||||
|
callback select_commit(string);
|
||||||
|
callback select_branch(string);
|
||||||
|
callback select_file(string);
|
||||||
|
callback select_pull_file(string);
|
||||||
|
callback select_activity(string, string, string, int, string);
|
||||||
|
callback choose_filter(string);
|
||||||
|
callback choose_icon_style(int);
|
||||||
|
callback choose_appearance(int);
|
||||||
|
callback back();
|
||||||
|
|
||||||
|
if tab == "home": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: root.has_active_server ? root.home_server : "Home"; can_back: false; }
|
||||||
|
|
||||||
|
if !root.has_active_server: EmptyState {
|
||||||
|
x: 32px; width: parent.width - 64px; y: 210px; height: 190px;
|
||||||
|
title: "No server selected";
|
||||||
|
detail: "Open Issues to select a server or add your first one.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if root.has_active_server: Rectangle {
|
||||||
|
x: 16px; y: 72px; width: parent.width - 32px; height: 118px;
|
||||||
|
background: AppTheme.surface; border-radius: 12px;
|
||||||
|
Text { x: 13px; y: 10px; text: "Activity · last 12 months"; font-size: 13px; font-weight: 600; color: AppTheme.text; }
|
||||||
|
Text { x: 13px; y: 86px; text: root.contribution_count + " contributions"; font-size: 12px; color: AppTheme.text-secondary; }
|
||||||
|
for cell in root.heat_cells: Rectangle {
|
||||||
|
x: 13px + cell.week * 6.7px; y: 39px + cell.day * 6.2px;
|
||||||
|
width: 5.2px; height: 5.2px; border-radius: 1px;
|
||||||
|
background: cell.level == 0 ? (AppTheme.dark ? #3a3a3c : #e5e5e9) : cell.level == 1 ? #b8d9f4 : cell.level == 2 ? #72b5e8 : cell.level == 3 ? #278bd4 : #0969b7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if root.has_active_server && !root.home_loading && root.activities.length == 0: EmptyState {
|
||||||
|
x: 32px; width: parent.width - 64px; y: 250px; height: 150px;
|
||||||
|
title: "No recent activity";
|
||||||
|
detail: "Your recent server actions will appear here.";
|
||||||
|
}
|
||||||
|
|
||||||
|
if root.has_active_server: PullToRefreshGesture {
|
||||||
|
x: 16px; y: 202px; width: parent.width - 32px; height: parent.height - 214px;
|
||||||
|
at_top: root.home_at_top; refreshing: root.home_loading;
|
||||||
|
refresh => { root.refresh_home(); }
|
||||||
|
home_list := ListView {
|
||||||
|
property <int> scroll_request: root.home_scroll_request;
|
||||||
|
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
||||||
|
changed scroll_request => { self.viewport-y = 0px; root.home_at_top = true; }
|
||||||
|
scrolled => { root.home_at_top = self.viewport-y >= 0px; }
|
||||||
|
for activity in root.activities: Rectangle {
|
||||||
|
height: 94px;
|
||||||
|
background: AppTheme.surface; border-radius: 12px;
|
||||||
|
TouchArea {
|
||||||
|
enabled: activity.target != "";
|
||||||
|
clicked => { root.select_activity(activity.target, activity.owner, activity.repository, activity.number, activity.sha); }
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
x: 12px; y: 14px; width: 34px; height: 34px; border-radius: 17px;
|
||||||
|
background: AppTheme.accent-soft;
|
||||||
|
AppIcon { x: 5px; y: 5px; width: 24px; height: 24px; kind: activity.icon; }
|
||||||
|
}
|
||||||
|
Text { x: 57px; y: 11px; width: parent.width - 69px; height: 24px; text: activity.title; font-size: 15px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
||||||
|
Text { x: 57px; y: 36px; width: parent.width - 69px; height: 35px; text: activity.detail; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; overflow: elide; }
|
||||||
|
Text { x: 57px; y: 72px; width: parent.width - 69px; text: activity.meta; font-size: 11px; color: AppTheme.text-tertiary; overflow: elide; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if root.home_loading: Spinner { width: 34px; height: 34px; x: (parent.width - self.width) / 2; y: 222px; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if tab == "settings": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header {
|
||||||
|
x: 0; y: 0; can_back: false;
|
||||||
|
title: "Settings";
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
x: 16px; y: 76px; width: parent.width - 32px; height: 184px;
|
||||||
|
background: AppTheme.surface; border-radius: 12px;
|
||||||
|
Text { x: 15px; y: 13px; text: "Icon style"; font-size: 18px; font-weight: 650; color: AppTheme.text; }
|
||||||
|
Text { x: 15px; y: 43px; width: parent.width - 30px; text: "Choose how navigation and activity icons look throughout Gotcha."; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; }
|
||||||
|
IconStyleChoice { x: 12px; y: 91px; width: (parent.width - 36px) / 3; height: 78px; value: 0; label: "Outline"; clicked => { root.choose_icon_style(0); } }
|
||||||
|
IconStyleChoice { x: 18px + (parent.width - 36px) / 3; y: 91px; width: (parent.width - 36px) / 3; height: 78px; value: 1; label: "Duotone"; clicked => { root.choose_icon_style(1); } }
|
||||||
|
IconStyleChoice { x: 24px + 2 * (parent.width - 36px) / 3; y: 91px; width: (parent.width - 36px) / 3; height: 78px; value: 2; label: "Bold"; clicked => { root.choose_icon_style(2); } }
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
x: 16px; y: 276px; width: parent.width - 32px; height: 136px;
|
||||||
|
background: AppTheme.surface; border-radius: 12px;
|
||||||
|
Text { x: 15px; y: 13px; text: "Appearance"; font-size: 18px; font-weight: 650; color: AppTheme.text; }
|
||||||
|
Text { x: 15px; y: 43px; width: parent.width - 30px; text: "Follow iOS automatically or choose a fixed light or dark appearance."; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; }
|
||||||
|
AppearanceChoice { x: 12px; y: 81px; width: (parent.width - 36px) / 3; height: 42px; value: 0; label: "Auto"; clicked => { root.choose_appearance(0); } }
|
||||||
|
AppearanceChoice { x: 18px + (parent.width - 36px) / 3; y: 81px; width: (parent.width - 36px) / 3; height: 42px; value: 1; label: "Light"; clicked => { root.choose_appearance(1); } }
|
||||||
|
AppearanceChoice { x: 24px + 2 * (parent.width - 36px) / 3; y: 81px; width: (parent.width - 36px) / 3; height: 42px; value: 2; label: "Dark"; clicked => { root.choose_appearance(2); } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tab == "issues" || tab == "repositories") && page == "servers": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: "Servers"; can_back: false; }
|
||||||
|
if root.servers.length > 0: servers_list := ListView {
|
||||||
|
property <int> scroll_request: root.servers_scroll_request;
|
||||||
|
x: 16px; y: 76px; width: parent.width - 32px; height: parent.height - 154px;
|
||||||
|
mouse-drag-pan-enabled: true;
|
||||||
|
changed scroll_request => { self.viewport-y = 0px; }
|
||||||
|
for server[index] in root.servers: Rectangle {
|
||||||
|
height: 76px;
|
||||||
|
background: AppTheme.surface;
|
||||||
|
border-color: AppTheme.border;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 12px;
|
||||||
|
TouchArea { clicked => { root.select_server(index); } }
|
||||||
|
Text { x: 16px; y: 13px; width: parent.width - 54px; text: server.name; font-size: 17px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
||||||
|
Text { x: 16px; y: 42px; width: parent.width - 54px; text: server.url; font-size: 13px; color: AppTheme.text-secondary; overflow: elide; }
|
||||||
|
AppIcon { x: parent.width - 29px; y: 26px; width: 20px; height: 20px; kind: "disclosure"; icon-color: AppTheme.text-tertiary; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button { x: 16px; y: parent.height - 66px; width: parent.width - 32px; height: 48px; text: "Add Server"; clicked => { root.show_add_server(); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tab == "issues" || tab == "repositories") && page == "add": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: "Add Server"; can_back: true; back => { root.back(); } }
|
||||||
|
VerticalLayout {
|
||||||
|
x: 20px; y: 92px; width: parent.width - 40px; height: 260px; spacing: 10px;
|
||||||
|
Text { text: "Name"; font-size: 13px; color: AppTheme.text-secondary; }
|
||||||
|
server_name := LineEdit { placeholder-text: "Work"; }
|
||||||
|
Text { text: "Server URL"; font-size: 13px; color: AppTheme.text-secondary; }
|
||||||
|
server_url := LineEdit { placeholder-text: "https://gitea.example.com"; }
|
||||||
|
Text { text: "Access token"; font-size: 13px; color: AppTheme.text-secondary; }
|
||||||
|
server_token := LineEdit { placeholder-text: "Token"; input-type: InputType.password; }
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
x: 20px; y: 380px; width: parent.width - 40px; height: 48px;
|
||||||
|
text: root.loading ? "Connecting…" : "Add Server";
|
||||||
|
enabled: !root.loading;
|
||||||
|
clicked => { root.save_server(server_name.text, server_url.text, server_token.text); }
|
||||||
|
}
|
||||||
|
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tab == "issues" || tab == "repositories") && page == "repositories": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: root.server_title; can_back: true; back => { root.back(); } }
|
||||||
|
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
||||||
|
if !root.loading && root.repositories.length == 0: EmptyState {
|
||||||
|
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
||||||
|
title: "No repositories";
|
||||||
|
detail: "This account does not own any repositories on this server.";
|
||||||
|
}
|
||||||
|
PullToRefreshGesture {
|
||||||
|
x: 20px; y: 70px; width: parent.width - 40px; height: parent.height - 82px;
|
||||||
|
at_top: root.repositories_at_top; refreshing: root.refreshing;
|
||||||
|
refresh => { root.refresh_repositories(); }
|
||||||
|
repositories_list := ListView {
|
||||||
|
property <int> scroll_request: root.repositories_scroll_request;
|
||||||
|
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
||||||
|
changed scroll_request => { self.viewport-y = 0px; root.repositories_at_top = true; }
|
||||||
|
scrolled => { root.repositories_at_top = self.viewport-y >= 0px; }
|
||||||
|
for repo in root.repositories: Rectangle {
|
||||||
|
height: 104px;
|
||||||
|
background: AppTheme.surface;
|
||||||
|
border-color: AppTheme.border;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 12px;
|
||||||
|
TouchArea { clicked => { root.select_repository(repo.owner, repo.name); } }
|
||||||
|
Text { x: 15px; y: 11px; width: parent.width - 62px; text: repo.name; font-size: 17px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
||||||
|
Text { x: 15px; y: 39px; width: parent.width - 30px; text: repo.description; font-size: 14px; color: AppTheme.text-secondary; overflow: elide; }
|
||||||
|
Text { x: 15px; y: 71px; width: parent.width - 30px; text: repo.meta; font-size: 12px; color: AppTheme.text-tertiary; overflow: elide; }
|
||||||
|
TouchArea {
|
||||||
|
x: parent.width - 52px; y: 2px; width: 48px; height: 48px;
|
||||||
|
clicked => { root.toggle_favorite(repo.owner, repo.name); }
|
||||||
|
AppIcon { x: 10px; y: 10px; width: 28px; height: 28px; kind: repo.favorite ? "favorite-filled" : "favorite"; icon-color: repo.favorite ? #f2a900 : AppTheme.text-tertiary; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if tab == "issues" && page == "issues": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header {
|
||||||
|
x: 0; y: 0; title: root.repository_title; can_back: true; can_filter: true;
|
||||||
|
back => { root.back(); }
|
||||||
|
filter => { root.filter_open = true; }
|
||||||
|
}
|
||||||
|
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
||||||
|
if !root.loading && root.issues.length == 0: EmptyState {
|
||||||
|
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
||||||
|
title: "No " + root.issue_filter + " issues";
|
||||||
|
detail: "No issues match the selected status.";
|
||||||
|
}
|
||||||
|
PullToRefreshGesture {
|
||||||
|
x: 20px; y: 70px; width: parent.width - 40px; height: parent.height - 82px;
|
||||||
|
at_top: root.issues_at_top; refreshing: root.refreshing;
|
||||||
|
refresh => { root.refresh_issues(); }
|
||||||
|
issues_list := ListView {
|
||||||
|
property <int> scroll_request: root.issues_scroll_request;
|
||||||
|
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
||||||
|
changed scroll_request => { self.viewport-y = 0px; root.issues_at_top = true; }
|
||||||
|
scrolled => { root.issues_at_top = self.viewport-y >= 0px; }
|
||||||
|
for issue in root.issues: Rectangle {
|
||||||
|
height: issue.labels.length > 0 ? 138px : 112px;
|
||||||
|
background: AppTheme.surface;
|
||||||
|
border-color: AppTheme.border;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 12px;
|
||||||
|
TouchArea { clicked => { root.select_issue(issue.number); } }
|
||||||
|
Text { x: 15px; y: 11px; width: parent.width - 44px; text: issue.title; font-size: 16px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
||||||
|
Text { x: 15px; y: 39px; width: parent.width - 30px; height: 38px; text: issue.summary; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; overflow: elide; }
|
||||||
|
if issue.labels.length > 0: HorizontalLayout {
|
||||||
|
x: 15px; y: 82px; width: parent.width - 30px; height: 22px; spacing: 5px;
|
||||||
|
for label in issue.labels: Rectangle {
|
||||||
|
width: min(104px, max(48px, (parent.width - (issue.labels.length - 1) * 5px) / issue.labels.length));
|
||||||
|
height: 22px; background: label.background; border-radius: 11px;
|
||||||
|
Text { x: 7px; width: parent.width - 14px; text: label.name; color: label.foreground; font-size: 11px; font-weight: 600; horizontal-alignment: center; vertical-alignment: center; overflow: elide; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text { x: 15px; y: issue.labels.length > 0 ? 112px : 86px; width: parent.width - 30px; text: issue.meta; font-size: 12px; color: AppTheme.text-tertiary; overflow: elide; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if tab == "issues" && page == "issue": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: "Issue"; can_back: true; back => { root.back(); } }
|
||||||
|
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
||||||
|
PullToRefreshGesture {
|
||||||
|
x: 18px; y: 78px; width: parent.width - 36px; height: parent.height - 96px;
|
||||||
|
at_top: root.issue_at_top; refreshing: root.refreshing;
|
||||||
|
refresh => { root.refresh_issue(); }
|
||||||
|
issue_scroll := ScrollView {
|
||||||
|
property <int> scroll_request: root.issue_scroll_request;
|
||||||
|
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
||||||
|
changed scroll_request => { self.viewport-y = 0px; root.issue_at_top = true; }
|
||||||
|
scrolled => { root.issue_at_top = self.viewport-y >= 0px; }
|
||||||
|
VerticalLayout {
|
||||||
|
width: parent.width;
|
||||||
|
spacing: 12px;
|
||||||
|
alignment: start;
|
||||||
|
Text { text: root.issue_title; font-size: 23px; font-weight: 650; color: AppTheme.text; wrap: word-wrap; }
|
||||||
|
Text { text: root.issue_meta; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; }
|
||||||
|
Rectangle { height: 1px; background: AppTheme.separator; }
|
||||||
|
MarkdownContent { width: parent.width; blocks: root.issue_body; }
|
||||||
|
if root.comments.length > 0: Text { text: "Comments"; font-size: 17px; font-weight: 600; color: AppTheme.text; }
|
||||||
|
for comment in root.comments: CommentCard { width: parent.width; comment: comment; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if tab == "pulls" && !root.has_active_server: Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: "Home"; can_back: false; }
|
||||||
|
EmptyState {
|
||||||
|
x: 32px; width: parent.width - 64px; y: 210px; height: 190px;
|
||||||
|
title: "No server selected";
|
||||||
|
detail: "Open Issues or Repositories to select a server or add your first one.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tab == "pulls" && root.has_active_server && page == "pulls": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header {
|
||||||
|
x: 0; y: 0; title: "Pull Requests"; can_back: false; can_filter: true;
|
||||||
|
filter => { root.filter_open = true; }
|
||||||
|
}
|
||||||
|
if root.refreshing: Spinner { x: parent.width - 92px; y: 17px; width: 24px; height: 24px; }
|
||||||
|
if !root.loading && root.pulls.length == 0: EmptyState {
|
||||||
|
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
||||||
|
title: "No " + root.pull_filter + " pull requests";
|
||||||
|
detail: "No pull requests match the selected status.";
|
||||||
|
}
|
||||||
|
PullToRefreshGesture {
|
||||||
|
x: 16px; y: 70px; width: parent.width - 32px; height: parent.height - 82px;
|
||||||
|
at_top: root.issues_at_top; refreshing: root.refreshing;
|
||||||
|
refresh => { root.refresh_pulls(); }
|
||||||
|
ListView {
|
||||||
|
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
||||||
|
scrolled => { root.issues_at_top = self.viewport-y >= 0px; }
|
||||||
|
for pull in root.pulls: Rectangle {
|
||||||
|
height: 112px;
|
||||||
|
background: AppTheme.surface; border-color: AppTheme.border; border-width: 1px; border-radius: 12px;
|
||||||
|
TouchArea { clicked => { root.select_pull(pull.owner, pull.repository, pull.number); } }
|
||||||
|
Text { x: 14px; y: 10px; width: parent.width - 28px; text: pull.repository + " #" + pull.number; font-size: 12px; color: AppTheme.text-secondary; overflow: elide; }
|
||||||
|
Text { x: 14px; y: 31px; width: parent.width - 28px; text: pull.title; font-size: 16px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
||||||
|
Text { x: 14px; y: 57px; width: parent.width - 28px; text: pull.summary; font-size: 13px; color: AppTheme.text-secondary; overflow: elide; }
|
||||||
|
Text { x: 14px; y: 85px; width: parent.width - 28px; text: pull.meta; font-size: 12px; color: AppTheme.text-tertiary; overflow: elide; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if tab == "pulls" && page == "pull": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: "Pull Request"; can_back: true; back => { root.back(); } }
|
||||||
|
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
||||||
|
PullToRefreshGesture {
|
||||||
|
x: 18px; y: 78px; width: parent.width - 36px; height: parent.height - 96px;
|
||||||
|
at_top: root.issue_at_top; refreshing: root.refreshing;
|
||||||
|
refresh => { root.refresh_pull(); }
|
||||||
|
ScrollView {
|
||||||
|
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
||||||
|
scrolled => { root.issue_at_top = self.viewport-y >= 0px; }
|
||||||
|
VerticalLayout {
|
||||||
|
width: parent.width; spacing: 12px; alignment: start;
|
||||||
|
Text { text: root.detail_title; font-size: 23px; font-weight: 650; color: AppTheme.text; wrap: word-wrap; }
|
||||||
|
Text { text: root.detail_meta; font-size: 13px; color: AppTheme.text-secondary; wrap: word-wrap; }
|
||||||
|
Rectangle { height: 1px; background: AppTheme.separator; }
|
||||||
|
MarkdownContent { width: parent.width; blocks: root.detail_body; }
|
||||||
|
if root.files.length > 0: Text { text: root.detail_files_ref; font-size: 17px; font-weight: 600; color: AppTheme.text; }
|
||||||
|
for file in root.files: FileCard { width: parent.width; file: file; clicked => { root.select_pull_file(file.path); } }
|
||||||
|
if root.comments.length > 0: Text { text: "Comments"; font-size: 17px; font-weight: 600; color: AppTheme.text; }
|
||||||
|
for comment in root.comments: CommentCard { width: parent.width; comment: comment; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if tab == "repositories" && page == "commits": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: root.repository_title; can_back: true; back => { root.back(); } }
|
||||||
|
ComboBox {
|
||||||
|
x: 16px; y: 66px; width: parent.width - 32px; height: 42px;
|
||||||
|
model: root.branch_choices; current-index: root.branch_index;
|
||||||
|
selected(value) => { root.select_branch(value); }
|
||||||
|
}
|
||||||
|
if root.refreshing: Spinner { x: parent.width - 42px; y: 17px; width: 24px; height: 24px; }
|
||||||
|
if !root.loading && root.commits.length == 0: EmptyState {
|
||||||
|
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
||||||
|
title: "No commits";
|
||||||
|
detail: "This repository has no commit history.";
|
||||||
|
}
|
||||||
|
PullToRefreshGesture {
|
||||||
|
x: 16px; y: 116px; width: parent.width - 32px; height: parent.height - 128px;
|
||||||
|
at_top: root.repositories_at_top; refreshing: root.refreshing;
|
||||||
|
refresh => { root.refresh_commits(); }
|
||||||
|
ListView {
|
||||||
|
width: 100%; height: 100%; mouse-drag-pan-enabled: true;
|
||||||
|
scrolled => { root.repositories_at_top = self.viewport-y >= 0px; }
|
||||||
|
for commit in root.commits: commit_row := Rectangle {
|
||||||
|
property <length> graph-width: commit.lanes.length > 0 ? min(72px, commit.lanes.length * 10px + 8px) : 0px;
|
||||||
|
property <length> lane-spacing: (self.graph-width - 8px) / max(1, commit.lanes.length);
|
||||||
|
height: 86px; background: transparent;
|
||||||
|
Rectangle { width: 100%; height: 100%; background: AppTheme.surface; border-color: AppTheme.border; border-width: 1px; border-radius: 12px; }
|
||||||
|
TouchArea { clicked => { root.select_commit(commit.sha); } }
|
||||||
|
for lane[index] in commit.lanes: Rectangle {
|
||||||
|
x: 4px + index * commit_row.lane-spacing;
|
||||||
|
width: 3px; height: 100%; background: transparent;
|
||||||
|
if lane.top: Rectangle {
|
||||||
|
y: -1px; width: 3px;
|
||||||
|
height: lane.connect_left && !lane.bottom ? 37px : 42px;
|
||||||
|
background: lane.color;
|
||||||
|
}
|
||||||
|
if lane.bottom: Rectangle {
|
||||||
|
y: lane.connect_left && !lane.top ? 45px : 40px;
|
||||||
|
width: 3px;
|
||||||
|
height: parent.height - (lane.connect_left && !lane.top ? 44px : 39px);
|
||||||
|
background: lane.color;
|
||||||
|
}
|
||||||
|
if lane.connect_left && lane.top == lane.bottom: Rectangle {
|
||||||
|
x: -commit_row.lane-spacing; y: 39px;
|
||||||
|
width: commit_row.lane-spacing + 3px; height: 3px;
|
||||||
|
background: lane.color;
|
||||||
|
}
|
||||||
|
if lane.connect_left && lane.bottom && !lane.top: Path {
|
||||||
|
x: 1.5px - commit_row.lane-spacing; y: 35px;
|
||||||
|
width: commit_row.lane-spacing; height: 11px;
|
||||||
|
viewbox-width: 10; viewbox-height: 11;
|
||||||
|
commands: "M 0 5.5 L 5 5.5 Q 10 5.5 10 10.5";
|
||||||
|
fill: transparent; stroke: lane.color; stroke-width: 3px; stroke-line-cap: round;
|
||||||
|
}
|
||||||
|
if lane.connect_left && lane.top && !lane.bottom: Path {
|
||||||
|
x: 1.5px - commit_row.lane-spacing; y: 35px;
|
||||||
|
width: commit_row.lane-spacing; height: 11px;
|
||||||
|
viewbox-width: 10; viewbox-height: 11;
|
||||||
|
commands: "M 10 0.5 Q 10 5.5 5 5.5 L 0 5.5";
|
||||||
|
fill: transparent; stroke: lane.color; stroke-width: 3px; stroke-line-cap: round;
|
||||||
|
}
|
||||||
|
if lane.node: Rectangle {
|
||||||
|
x: -3px; y: 36px; width: 9px; height: 9px; border-radius: 5px;
|
||||||
|
background: lane.color; border-color: AppTheme.surface; border-width: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Text { x: parent.graph-width + 14px; y: 8px; width: parent.width - self.x - 14px; text: commit.title; font-size: 15px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
||||||
|
Text { x: parent.graph-width + 14px; y: 33px; width: parent.width - self.x - 14px; text: commit.refs != "" ? commit.refs : commit.meta; font-size: 12px; color: commit.refs != "" ? AppTheme.accent : AppTheme.text-secondary; overflow: elide; }
|
||||||
|
Text { x: parent.graph-width + 14px; y: 53px; width: parent.width - self.x - 14px; text: commit.refs != "" ? commit.meta + " · " + commit.sha : commit.sha; font-size: 11px; color: AppTheme.text-tertiary; overflow: elide; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if tab == "repositories" && page == "files": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: "Changed Files"; can_back: true; back => { root.back(); } }
|
||||||
|
if !root.loading && root.files.length == 0: EmptyState {
|
||||||
|
x: 34px; width: parent.width - 68px; y: 220px; height: 160px;
|
||||||
|
title: "No changed files";
|
||||||
|
detail: "This commit does not contain file changes.";
|
||||||
|
}
|
||||||
|
ListView {
|
||||||
|
x: 16px; y: 70px; width: parent.width - 32px; height: parent.height - 82px; mouse-drag-pan-enabled: true;
|
||||||
|
for file in root.files: FileCard { file: file; clicked => { root.select_file(file.path); } }
|
||||||
|
}
|
||||||
|
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tab == "repositories" || tab == "pulls") && page == "diff": Rectangle {
|
||||||
|
x: root.safe-area-insets.left; y: root.safe-area-insets.top;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.height - root.safe-area-insets.top - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
background: AppTheme.page;
|
||||||
|
Header { x: 0; y: 0; title: root.detail_title; can_back: true; back => { root.back(); } }
|
||||||
|
ScrollView {
|
||||||
|
x: 12px; y: 70px; width: parent.width - 24px; height: parent.height - 82px; mouse-drag-pan-enabled: true;
|
||||||
|
viewport-width: max(self.visible-width, root.diff_columns * 7px + 100px);
|
||||||
|
viewport-height: diff_rows.preferred-height;
|
||||||
|
diff_rows := VerticalLayout {
|
||||||
|
width: parent.viewport-width;
|
||||||
|
for line in root.diff_lines: Rectangle {
|
||||||
|
height: 20px;
|
||||||
|
background: line.kind == "addition" ? (AppTheme.dark ? #173d25 : #ddf5e3) : line.kind == "removal" ? (AppTheme.dark ? #4a2020 : #fde2e1) : line.kind == "hunk" ? (AppTheme.dark ? #17324d : #dcecff) : line.kind == "header" ? AppTheme.surface-muted : AppTheme.surface;
|
||||||
|
Text { x: 0; width: 38px; text: line.old_number; font-family: "monospace"; font-size: 11px; color: AppTheme.text-tertiary; horizontal-alignment: right; vertical-alignment: center; }
|
||||||
|
Text { x: 42px; width: 38px; text: line.new_number; font-family: "monospace"; font-size: 11px; color: AppTheme.text-tertiary; horizontal-alignment: right; vertical-alignment: center; }
|
||||||
|
Rectangle { x: 84px; width: 1px; height: 100%; background: AppTheme.separator; }
|
||||||
|
Text {
|
||||||
|
x: 90px; width: parent.width - 94px; text: line.text; font-family: "monospace"; font-size: 11px;
|
||||||
|
color: line.kind == "addition" ? (AppTheme.dark ? #7fe787 : #176b2c) : line.kind == "removal" ? (AppTheme.dark ? #ff7b72 : #a12720) : line.kind == "hunk" ? (AppTheme.dark ? #79c0ff : #175b9e) : AppTheme.text;
|
||||||
|
wrap: no-wrap; overflow: clip; vertical-alignment: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EdgeBack { x: 0; y: 0; back => { root.back(); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
x: root.safe-area-insets.left;
|
||||||
|
y: root.height - root.safe-area-insets.bottom - root.toolbar-height;
|
||||||
|
width: root.width - root.safe-area-insets.left - root.safe-area-insets.right;
|
||||||
|
height: root.toolbar-height;
|
||||||
|
background: AppTheme.toolbar;
|
||||||
|
TabButton {
|
||||||
|
x: 0; width: parent.width / 5; height: parent.height; kind: "home"; label: "Home"; active: root.tab == "home";
|
||||||
|
clicked => {
|
||||||
|
if root.tab == "home" { root.home_scroll_request += 1; }
|
||||||
|
root.select_tab("home");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TabButton {
|
||||||
|
x: parent.width / 5; width: parent.width / 5; height: parent.height; kind: "issues"; label: "Issues"; active: root.tab == "issues";
|
||||||
|
clicked => {
|
||||||
|
if root.tab == "issues" {
|
||||||
|
if root.page == "servers" { root.servers_scroll_request += 1; }
|
||||||
|
if root.page == "repositories" { root.repositories_scroll_request += 1; }
|
||||||
|
if root.page == "issues" { root.issues_scroll_request += 1; }
|
||||||
|
if root.page == "issue" { root.issue_scroll_request += 1; }
|
||||||
|
}
|
||||||
|
root.select_tab("issues");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TabButton { x: parent.width * 2 / 5; width: parent.width / 5; height: parent.height; kind: "repositories"; label: "Repos"; active: root.tab == "repositories"; clicked => { root.select_tab("repositories"); } }
|
||||||
|
TabButton { x: parent.width * 3 / 5; width: parent.width / 5; height: parent.height; kind: "pulls"; label: "Pulls"; active: root.tab == "pulls"; clicked => { root.select_tab("pulls"); } }
|
||||||
|
TabButton { x: parent.width * 4 / 5; width: parent.width / 5; height: parent.height; kind: "settings"; label: "Settings"; active: root.tab == "settings"; clicked => { root.select_tab("settings"); } }
|
||||||
|
}
|
||||||
|
|
||||||
|
if root.loading && (root.tab == "issues" || root.tab == "repositories" || root.tab == "pulls"): Rectangle {
|
||||||
|
width: 100%; height: 100%;
|
||||||
|
background: AppTheme.loading-overlay;
|
||||||
|
TouchArea { }
|
||||||
|
Spinner { width: 38px; height: 38px; x: (parent.width - self.width) / 2; y: (parent.height - self.height) / 2; }
|
||||||
|
}
|
||||||
|
if root.filter_open: Rectangle {
|
||||||
|
width: 100%; height: 100%; background: #00000066;
|
||||||
|
TouchArea { clicked => { root.filter_open = false; } }
|
||||||
|
Rectangle {
|
||||||
|
x: 28px; y: (parent.height - 190px) / 2; width: parent.width - 56px; height: 190px;
|
||||||
|
background: AppTheme.surface; border-radius: 14px;
|
||||||
|
Text { x: 18px; y: 16px; width: parent.width - 36px; text: "Status"; font-size: 19px; font-weight: 650; color: AppTheme.text; }
|
||||||
|
VerticalLayout {
|
||||||
|
x: 18px; y: 54px; width: parent.width - 36px; height: 118px; spacing: 8px;
|
||||||
|
Button { text: "Open"; clicked => { root.choose_filter("open"); root.filter_open = false; } }
|
||||||
|
Button { text: "Closed"; clicked => { root.choose_filter("closed"); root.filter_open = false; } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if root.error != "": Rectangle {
|
||||||
|
x: 14px; y: parent.height - root.safe-area-insets.bottom - 132px; width: parent.width - 28px; height: 66px;
|
||||||
|
background: #d93d35; border-radius: 12px;
|
||||||
|
Text { x: 14px; width: parent.width - 28px; text: root.error; color: white; font-size: 13px; wrap: word-wrap; vertical-alignment: center; }
|
||||||
|
TouchArea { clicked => { root.error = ""; } }
|
||||||
|
}
|
||||||
|
}
|
||||||
318
crates/app/ui/components.slint
Normal file
318
crates/app/ui/components.slint
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
import { Palette } from "std-widgets.slint";
|
||||||
|
import { CommentRow, FileRow, MarkdownBlock } from "types.slint";
|
||||||
|
|
||||||
|
export global IconTheme {
|
||||||
|
in-out property <int> style: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export global AppTheme {
|
||||||
|
in-out property <int> mode: 0;
|
||||||
|
private property <color> system-background: Palette.background;
|
||||||
|
out property <bool> dark: mode == 2 || (mode == 0 && system-background.to-oklch().lightness < 0.5);
|
||||||
|
out property <color> accent: dark ? #0a84ff : #0879e1;
|
||||||
|
out property <color> accent-soft: dark ? #17324d : #e5f2fd;
|
||||||
|
out property <color> page: dark ? #1c1c1e : #f2f2f7;
|
||||||
|
out property <color> surface: dark ? #2c2c2e : #ffffff;
|
||||||
|
out property <color> surface-muted: dark ? #3a3a3c : #f5f5f8;
|
||||||
|
out property <color> header: dark ? #242426 : #f8f8fa;
|
||||||
|
out property <color> toolbar: dark ? #242426 : #fbfbfc;
|
||||||
|
out property <color> border: dark ? #48484a : #dedee3;
|
||||||
|
out property <color> separator: dark ? #3a3a3c : #d8d8dd;
|
||||||
|
out property <color> text: dark ? #f2f2f7 : #17171a;
|
||||||
|
out property <color> text-secondary: dark ? #c7c7cc : #5f5f66;
|
||||||
|
out property <color> text-tertiary: dark ? #8e8e93 : #85858c;
|
||||||
|
out property <color> code-background: dark ? #242426 : #e9e9ed;
|
||||||
|
out property <color> quote-background: dark ? #242426 : #f6f6f8;
|
||||||
|
out property <color> loading-overlay: dark ? #00000088 : #ffffff88;
|
||||||
|
changed mode => {
|
||||||
|
Palette.color-scheme = mode == 1 ? ColorScheme.light : mode == 2 ? ColorScheme.dark : ColorScheme.unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export component AppIcon inherits Rectangle {
|
||||||
|
in property <string> kind;
|
||||||
|
in property <int> style: IconTheme.style;
|
||||||
|
in property <color> icon-color: AppTheme.accent;
|
||||||
|
background: transparent;
|
||||||
|
|
||||||
|
private property <bool> duotone: root.style == 1;
|
||||||
|
private property <bool> bold: root.style == 2;
|
||||||
|
private property <bool> issue-kind: root.kind == "issues" || root.kind == "issue-open" || root.kind == "issue-close" || root.kind == "issue-reopen" || root.kind == "issue-comment";
|
||||||
|
private property <bool> repository-kind: root.kind == "repositories" || root.kind == "repo-create" || root.kind == "repo-rename" || root.kind == "repo-star" || root.kind == "repo-watch" || root.kind == "update";
|
||||||
|
private property <bool> pull-kind: root.kind == "pulls" || root.kind == "pull-open" || root.kind == "pull-merge" || root.kind == "pull-close" || root.kind == "pull-reopen" || root.kind == "pull-comment" || root.kind == "pull-approve" || root.kind == "pull-reject";
|
||||||
|
private property <bool> tag-kind: root.kind == "tag-push" || root.kind == "tag-delete";
|
||||||
|
private property <bool> branch-kind: root.kind == "branch-create" || root.kind == "branch-delete";
|
||||||
|
private property <bool> closed-shape: root.kind == "home" || root.issue-kind || root.repository-kind || root.kind == "favorite" || root.kind == "favorite-filled" || root.tag-kind || root.kind == "release";
|
||||||
|
private property <bool> has-badge: root.kind == "branch-create" || root.kind == "branch-delete" || root.kind == "push" || root.kind == "repo-create" || root.kind == "repo-rename" || root.kind == "repo-star" || root.kind == "repo-watch" || root.kind == "update" || root.kind == "issue-open" || root.kind == "issue-close" || root.kind == "issue-reopen" || root.kind == "issue-comment" || root.kind == "pull-open" || root.kind == "pull-merge" || root.kind == "pull-close" || root.kind == "pull-reopen" || root.kind == "pull-comment" || root.kind == "pull-approve" || root.kind == "pull-reject" || root.kind == "tag-push" || root.kind == "tag-delete";
|
||||||
|
private property <bool> positive: root.kind == "issue-close" || root.kind == "pull-merge" || root.kind == "pull-approve";
|
||||||
|
private property <bool> destructive: root.kind == "branch-delete" || root.kind == "pull-close" || root.kind == "pull-reject" || root.kind == "tag-delete";
|
||||||
|
private property <color> badge-color: root.positive ? #20a866 : root.destructive ? #e45b4d : root.duotone ? #26bfd1 : root.icon-color;
|
||||||
|
private property <string> shape: root.kind == "home"
|
||||||
|
? "M3 10.5 L12 3 L21 10.5 V21 H15 V14 H9 V21 H3 Z"
|
||||||
|
: root.issue-kind
|
||||||
|
? "M4 5 H20 V9 C18 9 18 15 20 15 V19 H4 V15 C6 15 6 9 4 9 Z"
|
||||||
|
: root.repository-kind
|
||||||
|
? "M6 3 H18 C19.1 3 20 3.9 20 5 V21 H6 C4.9 21 4 20.1 4 19 V5 C4 3.9 4.9 3 6 3 Z"
|
||||||
|
: root.pull-kind
|
||||||
|
? "M7 4 V20 M17 4 V11 C17 15 14 17 10 17 M7 4 H7 M17 4 H17"
|
||||||
|
: root.kind == "settings"
|
||||||
|
? "M12 3 V6 M12 18 V21 M3 12 H6 M18 12 H21 M5.6 5.6 L7.8 7.8 M16.2 16.2 L18.4 18.4 M18.4 5.6 L16.2 7.8 M7.8 16.2 L5.6 18.4"
|
||||||
|
: root.kind == "back"
|
||||||
|
? (root.bold ? "M16 4 L7 12 L16 20 Z" : "M16 4 L7 12 L16 20")
|
||||||
|
: root.kind == "filter"
|
||||||
|
? (root.bold ? "M3 5 H21 L14 13 V20 L10 22 V13 Z" : "M4 6 H20 M4 12 H20 M4 18 H20")
|
||||||
|
: root.kind == "favorite" || root.kind == "favorite-filled"
|
||||||
|
? "M12 3 L14.8 8.7 L21 9.6 L16.5 14 L17.6 20.3 L12 17.3 L6.4 20.3 L7.5 14 L3 9.6 L9.2 8.7 Z"
|
||||||
|
: root.kind == "disclosure"
|
||||||
|
? (root.bold ? "M8 4 L17 12 L8 20 Z" : "M8 4 L17 12 L8 20")
|
||||||
|
: root.branch-kind
|
||||||
|
? "M7 4 V20 M7 11 C11 11 14 9 14 5"
|
||||||
|
: root.kind == "push"
|
||||||
|
? "M4 8 H13 M4 12 H13 M4 16 H13"
|
||||||
|
: root.tag-kind
|
||||||
|
? "M3 5 V13 L11 21 L21 11 L13 3 H5 C3.9 3 3 3.9 3 5 Z"
|
||||||
|
: root.kind == "release"
|
||||||
|
? "M4 8 L12 4 L20 8 V18 L12 22 L4 18 Z"
|
||||||
|
: "M12 4 V20 M4 12 H20";
|
||||||
|
private property <string> detail: root.kind == "home"
|
||||||
|
? "M9 21 V14 H15 V21"
|
||||||
|
: root.issue-kind
|
||||||
|
? "M12 8 V13 M12 16.5 V17"
|
||||||
|
: root.repository-kind
|
||||||
|
? "M7 3 V21 M11 9 L8.5 12 L11 15 M15 9 L17.5 12 L15 15"
|
||||||
|
: root.pull-kind
|
||||||
|
? "M7 4 A1.8 1.8 0 1 1 6.99 4 M7 20 A1.8 1.8 0 1 1 6.99 20 M17 4 A1.8 1.8 0 1 1 16.99 4"
|
||||||
|
: root.kind == "settings"
|
||||||
|
? "M12 8 A4 4 0 1 1 11.99 8"
|
||||||
|
: root.kind == "filter" && !root.bold
|
||||||
|
? "M9 4 V8 M15 10 V14 M8 16 V20"
|
||||||
|
: root.tag-kind
|
||||||
|
? "M8 8 A1.5 1.5 0 1 1 7.99 8"
|
||||||
|
: root.kind == "release"
|
||||||
|
? "M12 18 V8 M9 11 L12 8 L15 11 M7 6 V3 M17 6 V3"
|
||||||
|
: "";
|
||||||
|
private property <string> badge-detail: root.kind == "branch-create" || root.kind == "repo-create" || root.kind == "issue-open" || root.kind == "pull-open"
|
||||||
|
? "M18 15.5 V20.5 M15.5 18 H20.5"
|
||||||
|
: root.kind == "issue-close" || root.kind == "pull-merge" || root.kind == "pull-approve"
|
||||||
|
? "M15.4 18 L17.2 19.8 L20.7 16.2"
|
||||||
|
: root.kind == "branch-delete" || root.kind == "tag-delete"
|
||||||
|
? "M15.3 18 H20.7"
|
||||||
|
: root.kind == "pull-close" || root.kind == "pull-reject"
|
||||||
|
? "M16 16 L20 20 M20 16 L16 20"
|
||||||
|
: root.kind == "push" || root.kind == "tag-push"
|
||||||
|
? "M18 20.5 V15.5 M15.7 17.8 L18 15.5 L20.3 17.8"
|
||||||
|
: root.kind == "repo-rename"
|
||||||
|
? "M15.3 20.6 L16 18 L19.7 14.3 L21.7 16.3 L18 20 Z"
|
||||||
|
: root.kind == "repo-star"
|
||||||
|
? "M18 14.5 L19 16.7 L21.4 17 L19.6 18.7 L20.1 21 L18 19.8 L15.9 21 L16.4 18.7 L14.6 17 L17 16.7 Z"
|
||||||
|
: root.kind == "repo-watch"
|
||||||
|
? "M14.5 18 C16.3 15.8 19.7 15.8 21.5 18 C19.7 20.2 16.3 20.2 14.5 18 M18 17 A1 1 0 1 1 17.99 17"
|
||||||
|
: root.kind == "issue-reopen" || root.kind == "pull-reopen"
|
||||||
|
? "M20.8 17 A3 3 0 1 0 20.2 20.3 M20.8 17 H18.5 M20.8 17 V19.3"
|
||||||
|
: root.kind == "issue-comment" || root.kind == "pull-comment"
|
||||||
|
? "M15.5 17 H20.5 V20 H18 L16 21 V20 H15.5 Z M17 18.5 H17.1 M19 18.5 H19.1"
|
||||||
|
: root.kind == "update"
|
||||||
|
? "M18 14.8 L18.8 17.2 L21.2 18 L18.8 18.8 L18 21.2 L17.2 18.8 L14.8 18 L17.2 17.2 Z"
|
||||||
|
: "";
|
||||||
|
|
||||||
|
Path {
|
||||||
|
width: 100%; height: 100%; viewbox-width: 24; viewbox-height: 24;
|
||||||
|
commands: root.shape;
|
||||||
|
fill: root.closed-shape ? (root.bold || root.kind == "favorite-filled" ? root.icon-color : root.duotone ? #26bfd133 : transparent) : transparent;
|
||||||
|
stroke: root.closed-shape && (root.bold || root.kind == "favorite-filled") ? transparent : root.icon-color;
|
||||||
|
stroke-width: root.bold ? 3px : root.duotone ? 2.2px : 1.8px;
|
||||||
|
stroke-line-cap: round; stroke-line-join: round;
|
||||||
|
}
|
||||||
|
if root.detail != "": Path {
|
||||||
|
width: 100%; height: 100%; viewbox-width: 24; viewbox-height: 24;
|
||||||
|
commands: root.detail; fill: transparent;
|
||||||
|
stroke: root.bold && root.closed-shape ? #ffffff : root.icon-color;
|
||||||
|
stroke-width: root.bold ? 2.4px : 1.8px;
|
||||||
|
stroke-line-cap: round; stroke-line-join: round;
|
||||||
|
}
|
||||||
|
if root.has-badge: Path {
|
||||||
|
width: 100%; height: 100%; viewbox-width: 24; viewbox-height: 24;
|
||||||
|
commands: "M18 13.5 A4.5 4.5 0 1 1 17.99 13.5 Z";
|
||||||
|
fill: root.style == 0 ? AppTheme.surface : root.badge-color;
|
||||||
|
stroke: root.style == 0 ? root.badge-color : #ffffff;
|
||||||
|
stroke-width: root.style == 2 ? 1.5px : 1.2px;
|
||||||
|
}
|
||||||
|
if root.has-badge: Path {
|
||||||
|
width: 100%; height: 100%; viewbox-width: 24; viewbox-height: 24;
|
||||||
|
commands: root.badge-detail; fill: root.style == 0 ? transparent : #ffffff;
|
||||||
|
stroke: root.style == 0 ? root.badge-color : #ffffff;
|
||||||
|
stroke-width: root.bold ? 2px : 1.6px;
|
||||||
|
stroke-line-cap: round; stroke-line-join: round;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export component IconStyleChoice inherits Rectangle {
|
||||||
|
in property <int> value;
|
||||||
|
in property <string> label;
|
||||||
|
callback clicked();
|
||||||
|
background: IconTheme.style == root.value ? AppTheme.accent-soft : AppTheme.surface-muted;
|
||||||
|
border-color: IconTheme.style == root.value ? AppTheme.accent : AppTheme.border;
|
||||||
|
border-width: IconTheme.style == root.value ? 2px : 1px;
|
||||||
|
border-radius: 11px;
|
||||||
|
TouchArea { clicked => { root.clicked(); } }
|
||||||
|
AppIcon { x: (parent.width - 30px) / 2; y: 10px; width: 30px; height: 30px; kind: "repositories"; style: root.value; }
|
||||||
|
Text { y: 48px; width: 100%; text: root.label; font-size: 12px; font-weight: IconTheme.style == root.value ? 650 : 500; color: AppTheme.text; horizontal-alignment: center; }
|
||||||
|
}
|
||||||
|
|
||||||
|
export component AppearanceChoice inherits Rectangle {
|
||||||
|
in property <int> value;
|
||||||
|
in property <string> label;
|
||||||
|
callback clicked();
|
||||||
|
background: AppTheme.mode == root.value ? AppTheme.accent-soft : AppTheme.surface-muted;
|
||||||
|
border-color: AppTheme.mode == root.value ? AppTheme.accent : AppTheme.border;
|
||||||
|
border-width: AppTheme.mode == root.value ? 2px : 1px;
|
||||||
|
border-radius: 11px;
|
||||||
|
TouchArea { clicked => { root.clicked(); } }
|
||||||
|
Text {
|
||||||
|
width: 100%; height: 100%; text: root.label;
|
||||||
|
font-size: 14px; font-weight: AppTheme.mode == root.value ? 650 : 500;
|
||||||
|
color: AppTheme.mode == root.value ? AppTheme.accent : AppTheme.text;
|
||||||
|
horizontal-alignment: center; vertical-alignment: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export component Header inherits Rectangle {
|
||||||
|
in property <string> title;
|
||||||
|
in property <bool> can_back;
|
||||||
|
in property <bool> can_filter: false;
|
||||||
|
callback back();
|
||||||
|
callback filter();
|
||||||
|
height: 58px;
|
||||||
|
width: 100%;
|
||||||
|
background: AppTheme.header;
|
||||||
|
border-color: AppTheme.border;
|
||||||
|
border-width: 0px;
|
||||||
|
|
||||||
|
if can_back: TouchArea {
|
||||||
|
x: 8px; width: 54px;
|
||||||
|
clicked => { root.back(); }
|
||||||
|
AppIcon { x: 7px; y: 17px; width: 24px; height: 24px; kind: "back"; }
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
x: root.can_back || root.can_filter ? 62px : 12px;
|
||||||
|
width: parent.width - 2 * self.x;
|
||||||
|
text: root.title;
|
||||||
|
horizontal-alignment: center;
|
||||||
|
vertical-alignment: center;
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: 600;
|
||||||
|
color: AppTheme.text;
|
||||||
|
overflow: elide;
|
||||||
|
}
|
||||||
|
if can_filter: TouchArea {
|
||||||
|
x: parent.width - 58px; width: 58px;
|
||||||
|
clicked => { root.filter(); }
|
||||||
|
AppIcon { x: 17px; y: 17px; width: 24px; height: 24px; kind: "filter"; }
|
||||||
|
}
|
||||||
|
Rectangle { y: parent.height - 1px; height: 1px; background: AppTheme.border; }
|
||||||
|
}
|
||||||
|
|
||||||
|
export component EdgeBack inherits SwipeGestureHandler {
|
||||||
|
callback back();
|
||||||
|
width: 24px;
|
||||||
|
height: 100%;
|
||||||
|
handle-swipe-right: true;
|
||||||
|
swiped => { root.back(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
export component EmptyState inherits VerticalLayout {
|
||||||
|
in property <string> title;
|
||||||
|
in property <string> detail;
|
||||||
|
alignment: center;
|
||||||
|
spacing: 8px;
|
||||||
|
Text { text: root.title; font-size: 21px; font-weight: 600; horizontal-alignment: center; color: AppTheme.text; }
|
||||||
|
Text { text: root.detail; font-size: 15px; horizontal-alignment: center; wrap: word-wrap; color: AppTheme.text-secondary; }
|
||||||
|
}
|
||||||
|
|
||||||
|
export component MarkdownContent inherits VerticalLayout {
|
||||||
|
in property <[MarkdownBlock]> blocks;
|
||||||
|
spacing: 8px;
|
||||||
|
|
||||||
|
for block in root.blocks: Rectangle {
|
||||||
|
height: block.kind == "rule" ? 9px : rendered.preferred-height + (block.kind == "code" || block.kind == "table" ? 16px : 0px);
|
||||||
|
background: block.kind == "code" || block.kind == "table" ? AppTheme.code-background : block.kind == "quote" ? AppTheme.quote-background : transparent;
|
||||||
|
border-radius: block.kind == "code" || block.kind == "table" ? 7px : 0px;
|
||||||
|
if block.kind == "quote": Rectangle { width: 3px; height: 100%; background: AppTheme.text-tertiary; border-radius: 2px; }
|
||||||
|
if block.kind == "rule": Rectangle { y: 4px; width: 100%; height: 1px; background: AppTheme.separator; }
|
||||||
|
rendered := StyledText {
|
||||||
|
x: block.kind == "code" || block.kind == "table" ? 8px : block.kind == "quote" ? 11px : 0px;
|
||||||
|
y: block.kind == "code" || block.kind == "table" ? 8px : 0px;
|
||||||
|
width: parent.width - self.x - (block.kind == "code" || block.kind == "table" ? 8px : 0px);
|
||||||
|
text: block.text;
|
||||||
|
default-color: AppTheme.text;
|
||||||
|
link-color: AppTheme.accent;
|
||||||
|
default-font-family: block.kind == "code" || block.kind == "table" ? "monospace" : "";
|
||||||
|
default-font-size: block.kind == "heading1" ? 24px : block.kind == "heading2" ? 21px : block.kind == "heading3" ? 19px : block.kind == "heading4" ? 17px : 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export component CommentCard inherits Rectangle {
|
||||||
|
in property <CommentRow> comment;
|
||||||
|
height: content.preferred-height + 24px;
|
||||||
|
background: AppTheme.surface;
|
||||||
|
border-radius: 10px;
|
||||||
|
content := VerticalLayout {
|
||||||
|
x: 12px; y: 10px; width: parent.width - 24px;
|
||||||
|
spacing: 5px;
|
||||||
|
Text { text: root.comment.author; font-size: 13px; font-weight: 600; color: AppTheme.text; }
|
||||||
|
MarkdownContent { width: parent.width; blocks: root.comment.body; }
|
||||||
|
Text { text: root.comment.meta; font-size: 11px; color: AppTheme.text-tertiary; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export component FileCard inherits Rectangle {
|
||||||
|
in property <FileRow> file;
|
||||||
|
callback clicked();
|
||||||
|
height: 66px;
|
||||||
|
background: AppTheme.surface;
|
||||||
|
border-color: AppTheme.border;
|
||||||
|
border-width: 1px;
|
||||||
|
border-radius: 10px;
|
||||||
|
TouchArea { clicked => { root.clicked(); } }
|
||||||
|
Text { x: 13px; y: 10px; width: parent.width - 26px; text: root.file.path; font-size: 14px; font-weight: 600; color: AppTheme.text; overflow: elide; }
|
||||||
|
Text { x: 13px; y: 38px; width: parent.width - 26px; text: root.file.status; font-size: 12px; color: AppTheme.text-secondary; }
|
||||||
|
}
|
||||||
|
|
||||||
|
export component TabButton inherits Rectangle {
|
||||||
|
in property <string> kind;
|
||||||
|
in property <string> label;
|
||||||
|
in property <bool> active;
|
||||||
|
private property <length> icon-area-height: root.height * 3 / 4;
|
||||||
|
private property <length> icon-size: min(42px, self.icon-area-height - 6px);
|
||||||
|
callback clicked();
|
||||||
|
background: transparent;
|
||||||
|
TouchArea { clicked => { root.clicked(); } }
|
||||||
|
AppIcon {
|
||||||
|
x: (parent.width - root.icon-size) / 2;
|
||||||
|
y: (root.icon-area-height - root.icon-size) / 2;
|
||||||
|
width: root.icon-size; height: root.icon-size;
|
||||||
|
kind: root.kind; icon-color: root.active ? AppTheme.accent : AppTheme.text-tertiary;
|
||||||
|
}
|
||||||
|
Text {
|
||||||
|
y: root.icon-area-height; height: parent.height - self.y; width: 100%; text: root.label;
|
||||||
|
color: root.active ? AppTheme.accent : AppTheme.text-tertiary; font-size: 9px;
|
||||||
|
font-weight: root.active ? 600 : 400;
|
||||||
|
horizontal-alignment: center; vertical-alignment: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export component PullToRefreshGesture inherits SwipeGestureHandler {
|
||||||
|
in property <bool> at_top;
|
||||||
|
in property <bool> refreshing;
|
||||||
|
callback refresh();
|
||||||
|
enabled: root.at_top && !root.refreshing;
|
||||||
|
handle-swipe-down: true;
|
||||||
|
swiped => { root.refresh(); }
|
||||||
|
@children
|
||||||
|
if self.swiping: Rectangle {
|
||||||
|
x: (parent.width - 142px) / 2; y: 8px; width: 142px; height: 32px;
|
||||||
|
background: AppTheme.surface-muted; border-radius: 16px;
|
||||||
|
Text { text: "Release to refresh"; font-size: 12px; color: AppTheme.text-secondary; horizontal-alignment: center; vertical-alignment: center; }
|
||||||
|
}
|
||||||
|
}
|
||||||
24
crates/app/ui/types.slint
Normal file
24
crates/app/ui/types.slint
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
export struct ServerRow { name: string, url: string }
|
||||||
|
export struct RepositoryRow {
|
||||||
|
name: string, owner: string, description: string, meta: string, favorite: bool,
|
||||||
|
}
|
||||||
|
export struct LabelRow { name: string, background: color, foreground: color }
|
||||||
|
export struct IssueRow {
|
||||||
|
number: int, title: string, summary: string, meta: string, labels: [LabelRow],
|
||||||
|
}
|
||||||
|
export struct PullRow {
|
||||||
|
number: int, owner: string, repository: string, title: string, summary: string, meta: string,
|
||||||
|
}
|
||||||
|
export struct MarkdownBlock { text: styled-text, kind: string }
|
||||||
|
export struct CommentRow { author: string, body: [MarkdownBlock], meta: string }
|
||||||
|
export struct GraphLane { color: color, top: bool, bottom: bool, node: bool, connect_left: bool }
|
||||||
|
export struct CommitRow {
|
||||||
|
sha: string, title: string, meta: string, refs: string, lanes: [GraphLane],
|
||||||
|
}
|
||||||
|
export struct FileRow { path: string, status: string }
|
||||||
|
export struct ActivityRow {
|
||||||
|
icon: string, title: string, detail: string, meta: string,
|
||||||
|
target: string, owner: string, repository: string, number: int, sha: string,
|
||||||
|
}
|
||||||
|
export struct DiffLine { old_number: string, new_number: string, text: string, kind: string }
|
||||||
|
export struct HeatCell { week: int, day: int, level: int }
|
||||||
Reference in New Issue
Block a user