Merge branch 'pop-os:master' into master
This commit is contained in:
commit
38435562ac
12 changed files with 671 additions and 339 deletions
139
Cargo.lock
generated
139
Cargo.lock
generated
|
|
@ -254,9 +254,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.88"
|
||||
version = "1.0.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e1496f8fb1fbf272686b8d37f523dab3e4a7443300055e74cdaa449f3114356"
|
||||
checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6"
|
||||
|
||||
[[package]]
|
||||
name = "apply"
|
||||
|
|
@ -290,9 +290,9 @@ checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
|||
|
||||
[[package]]
|
||||
name = "arrayref"
|
||||
version = "0.3.8"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a"
|
||||
checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb"
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
|
|
@ -519,9 +519,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "async-process"
|
||||
version = "2.2.4"
|
||||
version = "2.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8a07789659a4d385b79b18b9127fc27e1a59e1e89117c78c5ea3b806f016374"
|
||||
checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"async-io 2.3.4",
|
||||
|
|
@ -534,7 +534,6 @@ dependencies = [
|
|||
"futures-lite 2.3.0",
|
||||
"rustix 0.38.37",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -835,9 +834,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
|||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.7.1"
|
||||
version = "1.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50"
|
||||
checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3"
|
||||
|
||||
[[package]]
|
||||
name = "bzip2"
|
||||
|
|
@ -914,9 +913,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.18"
|
||||
version = "1.1.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b62ac837cdb5cb22e10a256099b4fc502b1dfe560cb282963a974d7abd80e476"
|
||||
checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
|
|
@ -1213,7 +1212,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-config"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"atomicwrites",
|
||||
"cosmic-config-derive",
|
||||
|
|
@ -1232,7 +1231,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-config-derive"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
|
|
@ -1242,6 +1241,7 @@ dependencies = [
|
|||
name = "cosmic-files"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bzip2",
|
||||
"chrono",
|
||||
"dirs 5.0.1",
|
||||
"env_logger",
|
||||
|
|
@ -1261,6 +1261,7 @@ dependencies = [
|
|||
"image",
|
||||
"libc",
|
||||
"libcosmic",
|
||||
"liblzma",
|
||||
"log",
|
||||
"mime_guess",
|
||||
"notify-debouncer-full",
|
||||
|
|
@ -1339,7 +1340,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cosmic-theme"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"almost",
|
||||
"cosmic-config",
|
||||
|
|
@ -2073,7 +2074,7 @@ checksum = "b0299020c3ef3f60f526a4f64ab4a3d4ce116b1acbf24cdd22da0068e5d81dc3"
|
|||
dependencies = [
|
||||
"fontconfig-parser",
|
||||
"log",
|
||||
"memmap2 0.9.4",
|
||||
"memmap2 0.9.5",
|
||||
"slotmap",
|
||||
"tinyvec",
|
||||
"ttf-parser 0.20.0",
|
||||
|
|
@ -2758,9 +2759,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.60"
|
||||
version = "0.1.61"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
|
||||
checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"core-foundation-sys",
|
||||
|
|
@ -2782,7 +2783,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"dnd",
|
||||
"iced_accessibility",
|
||||
|
|
@ -2801,7 +2802,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_accessibility"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"accesskit",
|
||||
"accesskit_unix",
|
||||
|
|
@ -2811,7 +2812,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_core"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"dnd",
|
||||
|
|
@ -2833,7 +2834,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_futures"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"futures",
|
||||
"iced_core",
|
||||
|
|
@ -2846,7 +2847,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_graphics"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"bytemuck",
|
||||
|
|
@ -2870,7 +2871,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_renderer"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"iced_graphics",
|
||||
"iced_tiny_skia",
|
||||
|
|
@ -2882,7 +2883,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_runtime"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"dnd",
|
||||
"iced_accessibility",
|
||||
|
|
@ -2896,7 +2897,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_sctk"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"enum-repr",
|
||||
"float-cmp",
|
||||
|
|
@ -2923,7 +2924,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_style"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"iced_core",
|
||||
"once_cell",
|
||||
|
|
@ -2933,7 +2934,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_tiny_skia"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"bytemuck",
|
||||
"cosmic-text",
|
||||
|
|
@ -2950,7 +2951,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_wgpu"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"as-raw-xcb-connection",
|
||||
"bitflags 2.6.0",
|
||||
|
|
@ -2979,7 +2980,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_widget"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"dnd",
|
||||
"iced_accessibility",
|
||||
|
|
@ -2997,7 +2998,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "iced_winit"
|
||||
version = "0.12.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"dnd",
|
||||
"iced_accessibility",
|
||||
|
|
@ -3513,7 +3514,7 @@ checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
|||
[[package]]
|
||||
name = "libcosmic"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#f942977703404e43ade60080f14d61e7aa078733"
|
||||
source = "git+https://github.com/pop-os/libcosmic.git#ddb678ca6966dfdf10911feac5e5ac02d3b2b97e"
|
||||
dependencies = [
|
||||
"apply",
|
||||
"ashpd 0.9.1",
|
||||
|
|
@ -3576,6 +3577,26 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "liblzma"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7c45fc6fcf5b527d3cf89c1dee8c327943984b0dc8bfcf6e100473b00969e63"
|
||||
dependencies = [
|
||||
"liblzma-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "liblzma-sys"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "63117d31458acdb7b406f6c60090aa8e1e7cd6e283f8ee02ce585ed68c53fe39"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.8"
|
||||
|
|
@ -3782,9 +3803,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.9.4"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322"
|
||||
checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
|
@ -4633,7 +4654,7 @@ version = "3.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b"
|
||||
dependencies = [
|
||||
"toml_edit 0.22.20",
|
||||
"toml_edit 0.22.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4701,9 +4722,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.36.1"
|
||||
version = "0.36.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96a05e2e8efddfa51a84ca47cec303fac86c8541b686d37cac5efc0e094417bc"
|
||||
checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
|
|
@ -4812,7 +4833,7 @@ dependencies = [
|
|||
"dirs 5.0.1",
|
||||
"infer",
|
||||
"mime_guess",
|
||||
"quick-xml 0.36.1",
|
||||
"quick-xml 0.36.2",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"url",
|
||||
|
|
@ -5145,7 +5166,7 @@ checksum = "70b31447ca297092c5a9916fc3b955203157b37c19ca8edde4f52e9843e602c7"
|
|||
dependencies = [
|
||||
"ab_glyph",
|
||||
"log",
|
||||
"memmap2 0.9.4",
|
||||
"memmap2 0.9.5",
|
||||
"smithay-client-toolkit 0.18.1",
|
||||
"tiny-skia",
|
||||
]
|
||||
|
|
@ -5331,7 +5352,7 @@ dependencies = [
|
|||
"cursor-icon",
|
||||
"libc",
|
||||
"log",
|
||||
"memmap2 0.9.4",
|
||||
"memmap2 0.9.5",
|
||||
"rustix 0.38.37",
|
||||
"thiserror",
|
||||
"wayland-backend",
|
||||
|
|
@ -5357,7 +5378,7 @@ dependencies = [
|
|||
"cursor-icon",
|
||||
"libc",
|
||||
"log",
|
||||
"memmap2 0.9.4",
|
||||
"memmap2 0.9.5",
|
||||
"pkg-config",
|
||||
"rustix 0.38.37",
|
||||
"thiserror",
|
||||
|
|
@ -5427,7 +5448,7 @@ dependencies = [
|
|||
"foreign-types",
|
||||
"js-sys",
|
||||
"log",
|
||||
"memmap2 0.9.4",
|
||||
"memmap2 0.9.5",
|
||||
"objc",
|
||||
"raw-window-handle",
|
||||
"redox_syscall 0.4.1",
|
||||
|
|
@ -5875,7 +5896,7 @@ dependencies = [
|
|||
"serde",
|
||||
"serde_spanned",
|
||||
"toml_datetime",
|
||||
"toml_edit 0.22.20",
|
||||
"toml_edit 0.22.21",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5900,9 +5921,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.22.20"
|
||||
version = "0.22.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d"
|
||||
checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
|
|
@ -5973,8 +5994,8 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "trash"
|
||||
version = "5.0.0"
|
||||
source = "git+https://github.com/jackpot51/trash-rs.git?branch=delete-info#e9fd256298bf9873a794dfe60a2261d1ed41674c"
|
||||
version = "5.1.1"
|
||||
source = "git+https://github.com/jackpot51/trash-rs.git?branch=cosmic#483f83908beef9166f30dfe7b57568ab01c4e140"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"libc",
|
||||
|
|
@ -6103,9 +6124,9 @@ checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-normalization"
|
||||
version = "0.1.23"
|
||||
version = "0.1.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
|
||||
checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
|
||||
dependencies = [
|
||||
"tinyvec",
|
||||
]
|
||||
|
|
@ -6118,15 +6139,15 @@ checksum = "52ea75f83c0137a9b98608359a5f1af8144876eb67bcb1ce837368e906a9f524"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-script"
|
||||
version = "0.5.6"
|
||||
version = "0.5.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad8d71f5726e5f285a935e9fe8edfd53f0491eb6e9a5774097fdabee7cd8c9cd"
|
||||
checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.11.0"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-vo"
|
||||
|
|
@ -6136,15 +6157,15 @@ checksum = "b1d386ff53b415b7fe27b50bb44679e2cc4660272694b7b6f3326d8480823a94"
|
|||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
version = "0.1.13"
|
||||
version = "0.1.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
|
||||
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
version = "0.2.5"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "229730647fbc343e3a80e463c1db7f78f3855d3f3739bee0dda773c9a037c90a"
|
||||
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
|
||||
|
||||
[[package]]
|
||||
name = "unix_permissions_ext"
|
||||
|
|
@ -6519,7 +6540,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quick-xml 0.36.1",
|
||||
"quick-xml 0.36.2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
|
|
@ -7076,7 +7097,7 @@ dependencies = [
|
|||
"js-sys",
|
||||
"libc",
|
||||
"log",
|
||||
"memmap2 0.9.4",
|
||||
"memmap2 0.9.5",
|
||||
"ndk",
|
||||
"ndk-sys",
|
||||
"objc2 0.4.1",
|
||||
|
|
@ -7346,7 +7367,7 @@ dependencies = [
|
|||
"async-fs 2.1.2",
|
||||
"async-io 2.3.4",
|
||||
"async-lock 3.4.0",
|
||||
"async-process 2.2.4",
|
||||
"async-process 2.3.0",
|
||||
"async-recursion",
|
||||
"async-task",
|
||||
"async-trait",
|
||||
|
|
|
|||
11
Cargo.toml
11
Cargo.toml
|
|
@ -14,7 +14,6 @@ chrono = { version = "0.4", features = ["unstable-locales"] }
|
|||
dirs = "5.0.1"
|
||||
env_logger = "0.11"
|
||||
freedesktop_entry_parser = "1.3"
|
||||
flate2 = "1.0"
|
||||
fs_extra = { git = "https://github.com/pop-os/fs_extra.git" }
|
||||
gio = { version = "0.20", optional = true }
|
||||
glib = { version = "0.20", optional = true }
|
||||
|
|
@ -35,14 +34,18 @@ rayon = "1"
|
|||
regex = "1"
|
||||
serde = { version = "1", features = ["serde_derive"] }
|
||||
shlex = { version = "1.3" }
|
||||
tar = "0.4.41"
|
||||
tokio = { version = "1", features = ["sync"] }
|
||||
trash = { git = "https://github.com/jackpot51/trash-rs.git", branch = "delete-info" }
|
||||
trash = { git = "https://github.com/jackpot51/trash-rs.git", branch = "cosmic" }
|
||||
url = "2.5"
|
||||
walkdir = "2.5.0"
|
||||
wayland-client = { version = "0.31.5", optional = true }
|
||||
xdg = { version = "2.5.2", optional = true }
|
||||
xdg-mime = "0.3"
|
||||
# Compression
|
||||
bzip2 = { version = "0.4", optional = true } #TODO: replace with pure Rust crate
|
||||
flate2 = "1.0"
|
||||
liblzma = { version = "0.3", optional = true } #TODO: replace with pure Rust crate
|
||||
tar = "0.4.41"
|
||||
# Internationalization
|
||||
i18n-embed = { version = "0.14", features = [
|
||||
"fluent-system",
|
||||
|
|
@ -66,7 +69,7 @@ version = "0.2.1"
|
|||
features = ["serde"]
|
||||
|
||||
[features]
|
||||
default = ["desktop", "gvfs", "notify", "winit", "wgpu"]
|
||||
default = ["bzip2", "desktop", "gvfs", "liblzma", "notify", "winit", "wgpu"]
|
||||
desktop = ["libcosmic/desktop", "dep:xdg"]
|
||||
gvfs = ["dep:gio", "dep:glib"]
|
||||
notify = ["dep:notify-rust"]
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
cosmic-files = Файлы COSMIC
|
||||
empty-folder = Пустая папка
|
||||
empty-folder-hidden = Пустая папка (з захаванымі элементамі)
|
||||
no-results = Нічога не знойдзена
|
||||
filesystem = Файлавая сістэма
|
||||
home = Хатняя папка
|
||||
networks = Сеткі
|
||||
notification-in-progress = Ідзе аперацыя з файламі.
|
||||
trash = Сметніца
|
||||
recents = Нядаўняе
|
||||
undo = Адрабіць
|
||||
|
||||
# List view
|
||||
name = Назва
|
||||
|
|
@ -12,6 +17,9 @@ size = Памер
|
|||
|
||||
# Dialogs
|
||||
|
||||
## Compress Dialog
|
||||
create-archive = Стварыць архіў
|
||||
|
||||
## Empty Trash Dialog
|
||||
empty-trash = Ачысціць сметніцу
|
||||
empty-trash-warning = Вы сапраўды хочаце назаўсёды выдаліць усе элементы з сметніцы?
|
||||
|
|
@ -29,11 +37,13 @@ name-no-slashes = Назва не можа ўтрымліваць касыя р
|
|||
|
||||
# Open/Save Dialog
|
||||
cancel = Скасаваць
|
||||
create = Стварыць
|
||||
open = Адкрыць
|
||||
open-file = Адкрыць файл
|
||||
open-folder = Адкрыць папку
|
||||
open-in-new-tab = Адкрыць у новай укладцы
|
||||
open-in-new-window = Адкрыць у навым акне
|
||||
open-item-location = Адкрыць месцазнаходжанне прадмета
|
||||
open-multiple-files = Адкрыць некалькі файлаў
|
||||
open-multiple-folders = Адкрыць некалькі папак
|
||||
save = Захаваць
|
||||
|
|
@ -47,22 +57,106 @@ rename-folder = Перайменаваць папку
|
|||
replace = Замяніць
|
||||
replace-title = {$filename} ужо існуе ў гэтым месцы.
|
||||
replace-warning = Вы сапраўды хочыце замяніць яго на той, які вы захоўваеце? Пры замене яго змесціва будзе перапісана.
|
||||
replace-warning-operation = Вы хочаце замяніць яго? Пры замене яго змесціва будзе перазапісана.
|
||||
original-file = Зыходны файл
|
||||
replace-with = Замяніць на
|
||||
apply-to-all = Прымяніць на ўсіх
|
||||
keep-both = Захаваць абодва
|
||||
skip = Прапусціць
|
||||
|
||||
# List view
|
||||
name = Назва
|
||||
modified = Зменена
|
||||
size = Памер
|
||||
## Metadata Dialog
|
||||
owner = Уладальнік
|
||||
group = Група
|
||||
other = Іншыя
|
||||
read = Чытаць
|
||||
write = Пісаць
|
||||
execute = Выконваць
|
||||
|
||||
# Context Pages
|
||||
|
||||
## About
|
||||
git-description = Git каміт {$hash} ад {$date}
|
||||
|
||||
## Add Network Drive
|
||||
add-network-drive = Дадаць сеткавы дыск
|
||||
connect = Падлучыць
|
||||
connect-anonymously = Падлучыць ананімна
|
||||
connecting = Падлучэнне...
|
||||
domain = Дамен
|
||||
enter-server-address = Увядзіце адрас серверу
|
||||
network-drive-description =
|
||||
Адрасы сервераў ўключаюць у сябе прэфікс пратаколу і адрас.
|
||||
Прыклад: ssh://192.168.0.1, ftp://[2001:db8::1]
|
||||
### Make sure to keep the comma which separates the columns
|
||||
network-drive-schemes =
|
||||
Даступная пратаколы,Прэфікс
|
||||
AppleTalk,afp://
|
||||
File Transfer Protocol,ftp:// або ftps://
|
||||
Network File System,nfs://
|
||||
Server Message Block,smb://
|
||||
SSH File Transfer Protocol,sftp:// або ssh://
|
||||
WebDav,dav:// або davs://
|
||||
network-drive-error = Немагчыма атрымаць доступ да сеткавага дыска
|
||||
password = Пароль
|
||||
remember-password = Запомніць пароль
|
||||
try-again = Паўтарыць спробу
|
||||
username = Імя карыстальніка
|
||||
|
||||
## Operations
|
||||
operations = Аперацыі
|
||||
edit-history = Гісторыя рэдагавання
|
||||
history = Гісторыя
|
||||
no-history = Няма элементаў у гісторыі
|
||||
pending = У чаканні
|
||||
failed = Няўдала
|
||||
complete = Завершана
|
||||
compressing = Сцісканне {$items} {$items ->
|
||||
[one] элементу
|
||||
*[other] элементаў
|
||||
} з {$from} у {$to}
|
||||
compressed = Сціснута {$items} {$items ->
|
||||
[one] элемент
|
||||
*[other] элементаў
|
||||
} з {$from} у {$to}
|
||||
copy_noun = Капіяваць
|
||||
creating = Стварэнне {$name} у {$parent}
|
||||
created = Створана {$name} у {$parent}
|
||||
copying = Капіяванне {$items} {$items ->
|
||||
[one] элементу
|
||||
*[other] элементаў
|
||||
} з {$from} у {$to}
|
||||
copied = Скапіявана {$items} {$items ->
|
||||
[one] элемент
|
||||
*[other] элементаў
|
||||
} з {$from} у {$to}
|
||||
emptying-trash = Emptying {trash}
|
||||
emptied-trash = Emptied {trash}
|
||||
extracting = Выманне {$items} {$items ->
|
||||
[one] элементу
|
||||
*[other] элементаў
|
||||
} з {$from} у {$to}
|
||||
extracted = Вынята {$items} {$items ->
|
||||
[one] элемент
|
||||
*[other] элементаў
|
||||
} з {$from} у {$to}
|
||||
moving = Перамяшчэнне {$items} {$items ->
|
||||
[one] элементу
|
||||
*[other] элементаў
|
||||
} з {$from} у {$to}
|
||||
moved = Перанесена {$items} {$items ->
|
||||
[one] элемент
|
||||
*[other] элементаў
|
||||
} з {$from} у {$to}
|
||||
renaming = Перайменаванне {$from} у {$to}
|
||||
renamed = Перайменавана {$from} у {$to}
|
||||
restoring = Аднаўленне {$items} {$items ->
|
||||
[one] элементу
|
||||
*[other] элементаў
|
||||
} з {trash}
|
||||
restored = Адноўлена {$items} {$items ->
|
||||
[one] элемент
|
||||
*[other] элементаў
|
||||
} з {trash}
|
||||
unknown-folder = невядомая папка
|
||||
|
||||
## Open with
|
||||
open-with = Адкрыць з дапамогай
|
||||
|
|
@ -71,10 +165,14 @@ default-app = {$name} (па змаўчанні)
|
|||
## Properties
|
||||
properties = Уласцівасці
|
||||
|
||||
## Show details
|
||||
show-details = Паказаць дэталі
|
||||
|
||||
## Settings
|
||||
settings = Налады
|
||||
settings-tab = Укладка
|
||||
settings-show-hidden = Паказаць схаваныя файлы
|
||||
default-view = Выгляд па змаўчанні
|
||||
icon-size-list = Памер значка (спіс)
|
||||
icon-size-grid = Памер значка (сетка)
|
||||
sorting-name = Сартаваць
|
||||
|
|
@ -91,6 +189,8 @@ light = Светлая
|
|||
|
||||
# Context menu
|
||||
add-to-sidebar = Дадаць на бакавую панэль
|
||||
compress = Сціснуць
|
||||
extract-here = Выняць
|
||||
new-file = Новы файл
|
||||
new-folder = Новая папка
|
||||
open-in-terminal = Адкрыць у кансолі
|
||||
|
|
@ -108,6 +208,7 @@ file = Файл
|
|||
new-tab = Новая ўкладка
|
||||
new-window = Новае акно
|
||||
rename = Перайменаваць
|
||||
menu-show-details = Паказаць уласцівасці...
|
||||
close-tab = Закрыць укладку
|
||||
quit = Выйсці
|
||||
|
||||
|
|
@ -119,8 +220,22 @@ paste = Уставіць
|
|||
select-all = Вылучыць усё
|
||||
|
||||
## View
|
||||
zoom-in = Павялічыць
|
||||
default-size = Памер па змаўчанні
|
||||
zoom-out = Паменшыць
|
||||
view = Выгляд
|
||||
grid-view = Рэжым сеткі
|
||||
list-view = Рэжым спіса
|
||||
show-hidden-files = Паказваць схаваныя файлы
|
||||
list-directories-first = Размяшчаць папкі перад файламі
|
||||
menu-settings = Налады...
|
||||
menu-about = Пра Файлы COSMIC...
|
||||
|
||||
## Sort
|
||||
sort = Сартаванне
|
||||
sort-a-z = А-Я
|
||||
sort-z-a = Я-А
|
||||
sort-newest-first = Спачатку новыя
|
||||
sort-oldest-first = Спачатку старыя
|
||||
sort-smallest-to-largest = Ад меншага да найбольшага
|
||||
sort-largest-to-smallest = Ад вялікага да найменшага
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ notification-in-progress = Operazioni sui file in corso ...
|
|||
trash = Cestino
|
||||
recents = Recenti
|
||||
undo = Annulla ultima operazione
|
||||
today = Oggi
|
||||
|
||||
# List view
|
||||
name = Nome
|
||||
|
|
|
|||
274
src/app.rs
274
src/app.rs
|
|
@ -112,7 +112,7 @@ pub enum Action {
|
|||
OpenTerminal,
|
||||
OpenWith,
|
||||
Paste,
|
||||
Properties,
|
||||
Preview,
|
||||
Rename,
|
||||
RestoreFromTrash,
|
||||
SearchActivate,
|
||||
|
|
@ -164,7 +164,9 @@ impl Action {
|
|||
Action::OpenTerminal => Message::OpenTerminal(entity_opt),
|
||||
Action::OpenWith => Message::ToggleContextPage(ContextPage::OpenWith),
|
||||
Action::Paste => Message::Paste(entity_opt),
|
||||
Action::Properties => Message::ToggleContextPage(ContextPage::Properties(None)),
|
||||
Action::Preview => {
|
||||
Message::ToggleContextPage(ContextPage::Preview(entity_opt, PreviewKind::Selected))
|
||||
}
|
||||
Action::Rename => Message::Rename(entity_opt),
|
||||
Action::RestoreFromTrash => Message::RestoreFromTrash(entity_opt),
|
||||
Action::SearchActivate => Message::SearchActivate,
|
||||
|
|
@ -210,18 +212,29 @@ impl MenuAction for Action {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub enum ContextItem {
|
||||
NavBar(segmented_button::Entity),
|
||||
TabBar(segmented_button::Entity),
|
||||
BreadCrumbs(usize),
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PreviewItem(pub tab::Item);
|
||||
|
||||
impl PartialEq for PreviewItem {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.0.location_opt == other.0.location_opt
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for PreviewItem {}
|
||||
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum PreviewKind {
|
||||
Custom(PreviewItem),
|
||||
Location(Location),
|
||||
Selected,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
pub enum NavMenuAction {
|
||||
OpenInNewTab(segmented_button::Entity),
|
||||
OpenInNewWindow(segmented_button::Entity),
|
||||
Properties(segmented_button::Entity),
|
||||
Preview(segmented_button::Entity),
|
||||
RemoveFromSidebar(segmented_button::Entity),
|
||||
EmptyTrash,
|
||||
}
|
||||
|
|
@ -279,6 +292,7 @@ pub enum Message {
|
|||
PendingComplete(u64),
|
||||
PendingError(u64, String),
|
||||
PendingProgress(u64, f32),
|
||||
Preview(Entity, PreviewKind, time::Duration),
|
||||
RescanTrash,
|
||||
Rename(Option<Entity>),
|
||||
ReplaceResult(ReplaceResult),
|
||||
|
|
@ -317,13 +331,13 @@ pub enum Message {
|
|||
None,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
pub enum ContextPage {
|
||||
About,
|
||||
EditHistory,
|
||||
NetworkDrive,
|
||||
OpenWith,
|
||||
Properties(Option<ContextItem>),
|
||||
Preview(Option<Entity>, PreviewKind),
|
||||
Settings,
|
||||
}
|
||||
|
||||
|
|
@ -334,7 +348,7 @@ impl ContextPage {
|
|||
Self::EditHistory => fl!("edit-history"),
|
||||
Self::NetworkDrive => fl!("add-network-drive"),
|
||||
Self::OpenWith => fl!("open-with"),
|
||||
Self::Properties(..) => String::default(),
|
||||
Self::Preview(..) => String::default(),
|
||||
Self::Settings => fl!("settings"),
|
||||
}
|
||||
}
|
||||
|
|
@ -461,6 +475,7 @@ pub struct App {
|
|||
pending_operations: BTreeMap<u64, (Operation, f32)>,
|
||||
complete_operations: BTreeMap<u64, Operation>,
|
||||
failed_operations: BTreeMap<u64, (Operation, String)>,
|
||||
preview_opt: Option<(Entity, PreviewKind, time::Instant)>,
|
||||
search_active: bool,
|
||||
search_id: widget::Id,
|
||||
search_input: String,
|
||||
|
|
@ -487,7 +502,10 @@ impl App {
|
|||
let mut tab = Tab::new(location.clone(), self.config.tab);
|
||||
tab.mode = match self.mode {
|
||||
Mode::App => tab::Mode::App,
|
||||
Mode::Desktop => tab::Mode::Desktop,
|
||||
Mode::Desktop => {
|
||||
tab.config.view = tab::View::Grid;
|
||||
tab::Mode::Desktop
|
||||
}
|
||||
};
|
||||
let entity = self
|
||||
.tab_model
|
||||
|
|
@ -668,19 +686,21 @@ impl App {
|
|||
.divider_above()
|
||||
});
|
||||
|
||||
nav_model = nav_model.insert(|b| {
|
||||
b.text(fl!("networks"))
|
||||
.icon(widget::icon::icon(
|
||||
widget::icon::from_name("network-workgroup-symbolic")
|
||||
.size(16)
|
||||
.handle(),
|
||||
))
|
||||
.data(Location::Network(
|
||||
"network:///".to_string(),
|
||||
fl!("networks"),
|
||||
))
|
||||
.divider_above()
|
||||
});
|
||||
if !self.mounters.is_empty() {
|
||||
nav_model = nav_model.insert(|b| {
|
||||
b.text(fl!("networks"))
|
||||
.icon(widget::icon::icon(
|
||||
widget::icon::from_name("network-workgroup-symbolic")
|
||||
.size(16)
|
||||
.handle(),
|
||||
))
|
||||
.data(Location::Network(
|
||||
"network:///".to_string(),
|
||||
fl!("networks"),
|
||||
))
|
||||
.divider_above()
|
||||
});
|
||||
}
|
||||
|
||||
// Collect all mounter items
|
||||
let mut nav_items = Vec::new();
|
||||
|
|
@ -944,59 +964,42 @@ impl App {
|
|||
widget::settings::view_column(children).into()
|
||||
}
|
||||
|
||||
fn properties(&self, entity: Option<ContextItem>) -> Element<Message> {
|
||||
match entity {
|
||||
None => self.tab_properties(self.tab_model.active()),
|
||||
Some(ContextItem::TabBar(entity)) => self.tab_properties(entity),
|
||||
Some(ContextItem::NavBar(item)) => {
|
||||
let mut children = Vec::with_capacity(1);
|
||||
if let Some(location) = self.nav_model.data::<Location>(item) {
|
||||
if let Location::Path(path) = location {
|
||||
//TODO: this should be done once, not when generating the view!
|
||||
if let Ok(item) = tab::item_from_path(path, self.config.tab.icon_sizes) {
|
||||
children.push(item.property_view(IconSizes::default()));
|
||||
fn preview(&self, entity_opt: &Option<Entity>, kind: &PreviewKind) -> Element<Message> {
|
||||
let mut children = Vec::with_capacity(1);
|
||||
let entity = entity_opt.unwrap_or_else(|| self.tab_model.active());
|
||||
match kind {
|
||||
PreviewKind::Custom(PreviewItem(item)) => {
|
||||
children.push(item.property_view(IconSizes::default()));
|
||||
}
|
||||
PreviewKind::Location(location) => {
|
||||
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
|
||||
if let Some(items) = tab.items_opt() {
|
||||
for item in items.iter() {
|
||||
if item.location_opt.as_ref() == Some(location) {
|
||||
children.push(item.property_view(tab.config.icon_sizes));
|
||||
// Only show one property view to avoid issues like hangs when generating
|
||||
// preview images on thousands of files
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
widget::settings::view_column(children).into()
|
||||
}
|
||||
|
||||
Some(ContextItem::BreadCrumbs(index)) => {
|
||||
let mut children = Vec::with_capacity(1);
|
||||
if let Some(tab) = self.tab_model.active_data::<Tab>() {
|
||||
let path_opt = tab
|
||||
.location
|
||||
.path_opt()
|
||||
.and_then(|path| path.ancestors().nth(index))
|
||||
.map(|path| path.to_path_buf());
|
||||
if let Some(ref path) = path_opt {
|
||||
//TODO: this should be done once, not when generating the view!
|
||||
if let Ok(item) = tab::item_from_path(path, self.config.tab.icon_sizes) {
|
||||
children.push(item.property_view(IconSizes::default()));
|
||||
PreviewKind::Selected => {
|
||||
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
|
||||
if let Some(items) = tab.items_opt() {
|
||||
for item in items.iter() {
|
||||
if item.selected {
|
||||
children.push(item.property_view(tab.config.icon_sizes));
|
||||
// Only show one property view to avoid issues like hangs when generating
|
||||
// preview images on thousands of files
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
widget::settings::view_column(children).into()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn tab_properties(&self, entity: segmented_button::Entity) -> Element<Message> {
|
||||
let mut children = Vec::new();
|
||||
|
||||
if let Some(tab) = self.tab_model.data::<Tab>(entity) {
|
||||
if let Some(items) = tab.items_opt() {
|
||||
for item in items.iter() {
|
||||
if item.selected {
|
||||
children.push(item.property_view(tab.config.icon_sizes));
|
||||
// Only show one property view to avoid issues like hangs when generating
|
||||
// preview images on thousands of files
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
widget::settings::view_column(children).into()
|
||||
}
|
||||
|
||||
|
|
@ -1157,6 +1160,7 @@ impl Application for App {
|
|||
|
||||
/// Creates the application, and optionally emits command on initialize.
|
||||
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Self::Message>) {
|
||||
core.window.context_is_overlay = false;
|
||||
match flags.mode {
|
||||
Mode::App => {}
|
||||
Mode::Desktop => {
|
||||
|
|
@ -1199,6 +1203,7 @@ impl Application for App {
|
|||
pending_operations: BTreeMap::new(),
|
||||
complete_operations: BTreeMap::new(),
|
||||
failed_operations: BTreeMap::new(),
|
||||
preview_opt: None,
|
||||
search_active: false,
|
||||
search_id: widget::Id::unique(),
|
||||
search_input: String::new(),
|
||||
|
|
@ -1301,10 +1306,7 @@ impl Application for App {
|
|||
NavMenuAction::OpenInNewWindow(id),
|
||||
),
|
||||
cosmic::widget::menu::Item::Divider,
|
||||
cosmic::widget::menu::Item::Button(
|
||||
fl!("show-details"),
|
||||
NavMenuAction::Properties(id),
|
||||
),
|
||||
cosmic::widget::menu::Item::Button(fl!("show-details"), NavMenuAction::Preview(id)),
|
||||
cosmic::widget::menu::Item::Divider,
|
||||
if is_context_trash {
|
||||
cosmic::widget::menu::Item::Button(
|
||||
|
|
@ -1363,7 +1365,7 @@ impl Application for App {
|
|||
// Usually, the Escape key (for example) closes menus and panes one by one instead
|
||||
// of closing everything on one press
|
||||
if self.core.window.show_context {
|
||||
self.core.window.show_context = false;
|
||||
self.set_show_context(false);
|
||||
return Command::none();
|
||||
}
|
||||
if self.search_active {
|
||||
|
|
@ -1708,7 +1710,7 @@ impl Application for App {
|
|||
Ok(true) => {
|
||||
log::info!("connected to {:?}", uri);
|
||||
if matches!(self.context_page, ContextPage::NetworkDrive) {
|
||||
self.core.window.show_context = false;
|
||||
self.set_show_context(false);
|
||||
}
|
||||
}
|
||||
Ok(false) => {
|
||||
|
|
@ -1877,7 +1879,7 @@ impl Application for App {
|
|||
}
|
||||
|
||||
// Close Open With context view
|
||||
self.core.window.show_context = false;
|
||||
self.set_show_context(false);
|
||||
}
|
||||
Message::OpenInNewTab(entity_opt) => {
|
||||
return Command::batch(self.selected_paths(entity_opt).into_iter().filter_map(
|
||||
|
|
@ -1947,10 +1949,34 @@ impl Application for App {
|
|||
});
|
||||
}
|
||||
ClipboardKind::Cut => {
|
||||
self.operation(Operation::Move {
|
||||
paths: contents.paths,
|
||||
to,
|
||||
});
|
||||
//TODO: determine ability to move on non-Unix systems
|
||||
let mut can_move = true;
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::MetadataExt;
|
||||
//TODO: better error handling, fall back to not moving?
|
||||
if let Ok(to_meta) = fs::metadata(&to) {
|
||||
for path in contents.paths.iter() {
|
||||
if let Ok(meta) = fs::metadata(path) {
|
||||
if meta.dev() != to_meta.dev() {
|
||||
can_move = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if can_move {
|
||||
self.operation(Operation::Move {
|
||||
paths: contents.paths,
|
||||
to,
|
||||
});
|
||||
} else {
|
||||
self.operation(Operation::Copy {
|
||||
paths: contents.paths,
|
||||
to,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1973,9 +1999,8 @@ impl Application for App {
|
|||
.map(cosmic::app::Message::App),
|
||||
);
|
||||
}
|
||||
|
||||
self.complete_operations.insert(id, op);
|
||||
}
|
||||
self.complete_operations.insert(id, op);
|
||||
}
|
||||
// Potentially show a notification
|
||||
commands.push(self.update_notification());
|
||||
|
|
@ -2002,6 +2027,17 @@ impl Application for App {
|
|||
}
|
||||
return self.update_notification();
|
||||
}
|
||||
Message::Preview(entity, kind, timeout) => {
|
||||
if self
|
||||
.preview_opt
|
||||
.as_ref()
|
||||
.is_some_and(|(e, k, i)| *e == entity && *k == kind && i.elapsed() > timeout)
|
||||
{
|
||||
self.context_page = ContextPage::Preview(Some(entity), kind);
|
||||
self.set_show_context(true);
|
||||
self.set_context_title(self.context_page.title());
|
||||
}
|
||||
}
|
||||
Message::RescanTrash => {
|
||||
// Update trash icon if empty/full
|
||||
let maybe_entity = self.nav_model.iter().find(|&entity| {
|
||||
|
|
@ -2229,7 +2265,7 @@ impl Application for App {
|
|||
//TODO: move to Command?
|
||||
if let tab::Message::ContextMenu(_point_opt) = tab_message {
|
||||
// Disable side context page
|
||||
self.core.window.show_context = false;
|
||||
self.set_show_context(false);
|
||||
}
|
||||
|
||||
let tab_commands = match self.tab_model.data_mut::<Tab>(entity) {
|
||||
|
|
@ -2244,10 +2280,9 @@ impl Application for App {
|
|||
commands.push(self.update(action.message(Some(entity))));
|
||||
}
|
||||
tab::Command::AddNetworkDrive => {
|
||||
let context_page = ContextPage::NetworkDrive;
|
||||
self.context_page = context_page;
|
||||
self.core.window.show_context = true;
|
||||
self.set_context_title(context_page.title());
|
||||
self.context_page = ContextPage::NetworkDrive;
|
||||
self.set_show_context(true);
|
||||
self.set_context_title(self.context_page.title());
|
||||
}
|
||||
tab::Command::ChangeLocation(tab_title, tab_path, selection_path) => {
|
||||
self.activate_nav_model_location(&tab_path);
|
||||
|
|
@ -2270,12 +2305,6 @@ impl Application for App {
|
|||
message::app(Message::TabMessage(Some(entity), tab_message))
|
||||
}));
|
||||
}
|
||||
tab::Command::LocationProperties(index) => {
|
||||
self.context_page =
|
||||
ContextPage::Properties(Some(ContextItem::BreadCrumbs(index)));
|
||||
self.core.window.show_context = true;
|
||||
self.set_context_title(self.context_page.title());
|
||||
}
|
||||
tab::Command::MoveToTrash(paths) => {
|
||||
self.operation(Operation::Delete { paths });
|
||||
}
|
||||
|
|
@ -2346,6 +2375,23 @@ impl Application for App {
|
|||
log::error!("failed to get current executable path: {}", err);
|
||||
}
|
||||
},
|
||||
tab::Command::Preview(kind, mut timeout) => {
|
||||
self.preview_opt = Some((entity, kind.clone(), Instant::now()));
|
||||
if self.core.window.show_context {
|
||||
// If the context window is already open, immediately show the preview
|
||||
timeout = time::Duration::new(0, 0)
|
||||
};
|
||||
commands.push(Command::perform(
|
||||
async move {
|
||||
tokio::time::sleep(timeout).await;
|
||||
message::app(Message::Preview(entity, kind, timeout))
|
||||
},
|
||||
|x| x,
|
||||
));
|
||||
}
|
||||
tab::Command::PreviewCancel => {
|
||||
self.preview_opt = None;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Command::batch(commands);
|
||||
|
|
@ -2374,12 +2420,12 @@ impl Application for App {
|
|||
Message::ToggleContextPage(context_page) => {
|
||||
//TODO: ensure context menus are closed
|
||||
if self.context_page == context_page {
|
||||
self.core.window.show_context = !self.core.window.show_context;
|
||||
self.set_show_context(!self.core.window.show_context);
|
||||
} else {
|
||||
self.context_page = context_page;
|
||||
self.core.window.show_context = true;
|
||||
self.set_show_context(true);
|
||||
}
|
||||
self.set_context_title(context_page.title());
|
||||
self.context_page = context_page;
|
||||
self.set_context_title(self.context_page.title());
|
||||
}
|
||||
Message::Undo(id) => {
|
||||
// TODO;
|
||||
|
|
@ -2595,10 +2641,22 @@ impl Application for App {
|
|||
}
|
||||
}
|
||||
|
||||
NavMenuAction::Properties(entity) => {
|
||||
self.context_page = ContextPage::Properties(Some(ContextItem::NavBar(entity)));
|
||||
self.core.window.show_context = true;
|
||||
self.set_context_title(self.context_page.title());
|
||||
NavMenuAction::Preview(entity) => {
|
||||
if let Some(Location::Path(path)) = self.nav_model.data::<Location>(entity) {
|
||||
match tab::item_from_path(path, IconSizes::default()) {
|
||||
Ok(item) => {
|
||||
self.context_page = ContextPage::Preview(
|
||||
None,
|
||||
PreviewKind::Custom(PreviewItem(item)),
|
||||
);
|
||||
self.set_show_context(true);
|
||||
self.set_context_title(self.context_page.title());
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("failed to get item from path {:?}: {}", path, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NavMenuAction::RemoveFromSidebar(entity) => {
|
||||
|
|
@ -2703,12 +2761,12 @@ impl Application for App {
|
|||
return None;
|
||||
}
|
||||
|
||||
Some(match self.context_page {
|
||||
Some(match &self.context_page {
|
||||
ContextPage::About => self.about(),
|
||||
ContextPage::EditHistory => self.edit_history(),
|
||||
ContextPage::NetworkDrive => self.network_drive(),
|
||||
ContextPage::OpenWith => self.open_with(),
|
||||
ContextPage::Properties(entity) => self.properties(entity),
|
||||
ContextPage::Preview(entity_opt, kind) => self.preview(entity_opt, kind),
|
||||
ContextPage::Settings => self.settings(),
|
||||
})
|
||||
}
|
||||
|
|
@ -3182,7 +3240,7 @@ impl Application for App {
|
|||
space_xxs, space_s, ..
|
||||
} = theme::active().cosmic().spacing;
|
||||
|
||||
let mut tab_column = widget::column::with_capacity(1);
|
||||
let mut tab_column = widget::column::with_capacity(3);
|
||||
|
||||
if self.tab_model.iter().count() > 1 {
|
||||
tab_column = tab_column.push(
|
||||
|
|
@ -3218,7 +3276,13 @@ impl Application for App {
|
|||
}
|
||||
}
|
||||
|
||||
let content: Element<_> = widget::toaster(&self.toasts, tab_column).into();
|
||||
// The toaster is added on top of an empty element to ensure that it does not override context menus
|
||||
tab_column = tab_column.push(widget::toaster(
|
||||
&self.toasts,
|
||||
widget::horizontal_space(Length::Fill),
|
||||
));
|
||||
|
||||
let content: Element<_> = tab_column.into();
|
||||
|
||||
// Uncomment to debug layout:
|
||||
//content.explain(cosmic::iced::Color::WHITE)
|
||||
|
|
|
|||
|
|
@ -168,7 +168,7 @@ pub struct TabConfig {
|
|||
impl Default for TabConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
view: View::Grid,
|
||||
view: View::List,
|
||||
folders_first: true,
|
||||
show_hidden: false,
|
||||
sort_name: HeadingOptions::Name,
|
||||
|
|
|
|||
|
|
@ -574,6 +574,7 @@ impl Application for App {
|
|||
|
||||
/// Creates the application, and optionally emits command on initialize.
|
||||
fn init(mut core: Core, flags: Self::Flags) -> (Self, Command<Message>) {
|
||||
core.window.context_is_overlay = false;
|
||||
core.window.show_close = false;
|
||||
core.window.show_maximize = false;
|
||||
core.window.show_minimize = false;
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ pub fn key_binds() -> HashMap<KeyBind, Action> {
|
|||
bind!([Ctrl], Key::Named(Named::Enter), OpenInNewTab);
|
||||
bind!([Shift], Key::Named(Named::Enter), OpenInNewWindow);
|
||||
bind!([Ctrl], Key::Character("v".into()), Paste);
|
||||
bind!([], Key::Named(Named::Space), Properties);
|
||||
bind!([], Key::Named(Named::Space), Preview);
|
||||
bind!([], Key::Named(Named::F2), Rename);
|
||||
bind!([Ctrl], Key::Character("f".into()), SearchActivate);
|
||||
bind!([Ctrl], Key::Character("a".into()), SelectAll);
|
||||
|
|
|
|||
19
src/menu.rs
19
src/menu.rs
|
|
@ -22,7 +22,7 @@ use crate::{
|
|||
|
||||
macro_rules! menu_button {
|
||||
($($x:expr),+ $(,)?) => (
|
||||
button(
|
||||
button::custom(
|
||||
Row::with_children(
|
||||
vec![$(Element::from($x)),+]
|
||||
)
|
||||
|
|
@ -131,9 +131,18 @@ pub fn context_menu<'a>(
|
|||
|
||||
children.push(divider::horizontal::light().into());
|
||||
let supported_archive_types = [
|
||||
"application/gzip",
|
||||
"application/x-compressed-tar",
|
||||
"application/x-tar",
|
||||
"application/zip",
|
||||
#[cfg(feature = "bzip2")]
|
||||
"application/x-bzip",
|
||||
#[cfg(feature = "bzip2")]
|
||||
"application/x-bzip-compressed-tar",
|
||||
#[cfg(feature = "liblzma")]
|
||||
"application/x-xz",
|
||||
#[cfg(feature = "liblzma")]
|
||||
"application/x-xz-compressed-tar",
|
||||
]
|
||||
.iter()
|
||||
.filter_map(|mime_type| mime_type.parse::<Mime>().ok())
|
||||
|
|
@ -146,7 +155,7 @@ pub fn context_menu<'a>(
|
|||
children.push(divider::horizontal::light().into());
|
||||
|
||||
//TODO: Print?
|
||||
children.push(menu_item(fl!("show-details"), Action::Properties).into());
|
||||
children.push(menu_item(fl!("show-details"), Action::Preview).into());
|
||||
children.push(divider::horizontal::light().into());
|
||||
children.push(menu_item(fl!("add-to-sidebar"), Action::AddToSidebar).into());
|
||||
children.push(divider::horizontal::light().into());
|
||||
|
|
@ -222,7 +231,7 @@ pub fn context_menu<'a>(
|
|||
children.push(divider::horizontal::light().into());
|
||||
}
|
||||
if selected > 0 {
|
||||
children.push(menu_item(fl!("show-details"), Action::Properties).into());
|
||||
children.push(menu_item(fl!("show-details"), Action::Preview).into());
|
||||
children.push(divider::horizontal::light().into());
|
||||
children
|
||||
.push(menu_item(fl!("restore-from-trash"), Action::RestoreFromTrash).into());
|
||||
|
|
@ -362,7 +371,7 @@ pub fn menu_bar<'a>(
|
|||
menu::Item::Divider,
|
||||
menu::Item::Button(fl!("rename"), Action::Rename),
|
||||
menu::Item::Divider,
|
||||
menu::Item::Button(fl!("menu-show-details"), Action::Properties),
|
||||
menu::Item::Button(fl!("menu-show-details"), Action::Preview),
|
||||
menu::Item::Divider,
|
||||
menu::Item::Button(fl!("add-to-sidebar"), Action::AddToSidebar),
|
||||
menu::Item::Divider,
|
||||
|
|
@ -477,7 +486,7 @@ pub fn location_context_menu<'a>(ancestor_index: usize) -> Element<'a, tab::Mess
|
|||
divider::horizontal::light().into(),
|
||||
menu_button!(text::body(fl!("show-details")))
|
||||
.on_press(tab::Message::LocationMenuAction(
|
||||
LocationMenuAction::Properties(ancestor_index),
|
||||
LocationMenuAction::Preview(ancestor_index),
|
||||
))
|
||||
.into(),
|
||||
];
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ pub struct MouseArea<'a, Message> {
|
|||
on_press: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_drag_end: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_release: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_resize: Option<Box<dyn Fn(Size) -> Message + 'a>>,
|
||||
on_right_press: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_right_press_no_capture: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
on_right_release: Option<Box<dyn Fn(Option<Point>) -> Message + 'a>>,
|
||||
|
|
@ -85,6 +86,13 @@ impl<'a, Message> MouseArea<'a, Message> {
|
|||
self
|
||||
}
|
||||
|
||||
/// The message to emit on resizing.
|
||||
#[must_use]
|
||||
pub fn on_resize(mut self, message: impl Fn(Size) -> Message + 'a) -> Self {
|
||||
self.on_resize = Some(Box::new(message));
|
||||
self
|
||||
}
|
||||
|
||||
/// The message to emit on a right button press.
|
||||
#[must_use]
|
||||
pub fn on_right_press(mut self, message: impl Fn(Option<Point>) -> Message + 'a) -> Self {
|
||||
|
|
@ -182,6 +190,7 @@ struct State {
|
|||
drag_initiated: Option<Point>,
|
||||
modifiers: Modifiers,
|
||||
prev_click: Option<(mouse::Click, Instant)>,
|
||||
size: Option<Size>,
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
|
@ -235,6 +244,7 @@ impl<'a, Message> MouseArea<'a, Message> {
|
|||
on_double_click: None,
|
||||
on_press: None,
|
||||
on_release: None,
|
||||
on_resize: None,
|
||||
on_right_press: None,
|
||||
on_right_press_no_capture: None,
|
||||
on_right_release: None,
|
||||
|
|
@ -449,6 +459,14 @@ fn update<Message: Clone>(
|
|||
) -> event::Status {
|
||||
let layout_bounds = layout.bounds();
|
||||
|
||||
if let Some(message) = widget.on_resize.as_ref() {
|
||||
let size = layout_bounds.size();
|
||||
if state.size != Some(size) {
|
||||
state.size = Some(size);
|
||||
shell.publish(message(size));
|
||||
}
|
||||
}
|
||||
|
||||
if state.drag_initiated.is_none() && !cursor.is_over(layout_bounds) {
|
||||
return event::Status::Ignored;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -635,22 +635,26 @@ impl Operation {
|
|||
|
||||
if let Some(file_stem) = path.file_stem() {
|
||||
let mut new_dir = to.join(file_stem);
|
||||
// Make sure all extension parts are removed (file_stem may still contain them)
|
||||
while new_dir.extension().is_some() {
|
||||
new_dir.set_extension("");
|
||||
}
|
||||
if new_dir.exists() {
|
||||
let mut extensionless_path = path.to_owned();
|
||||
extensionless_path.set_extension("");
|
||||
if let Some(new_dir_parent) = new_dir.parent() {
|
||||
new_dir = copy_unique_path(&extensionless_path, new_dir_parent);
|
||||
new_dir = copy_unique_path(&new_dir, new_dir_parent);
|
||||
}
|
||||
}
|
||||
|
||||
let mime = mime_for_path(&path);
|
||||
match mime.essence_str() {
|
||||
"application/x-compressed-tar" => fs::File::open(path)
|
||||
.map(io::BufReader::new)
|
||||
.map(flate2::read::GzDecoder::new)
|
||||
.map(tar::Archive::new)
|
||||
.and_then(|mut archive| archive.unpack(new_dir))
|
||||
.map_err(err_str)?,
|
||||
"application/gzip" | "application/x-compressed-tar" => {
|
||||
fs::File::open(path)
|
||||
.map(io::BufReader::new)
|
||||
.map(flate2::read::GzDecoder::new)
|
||||
.map(tar::Archive::new)
|
||||
.and_then(|mut archive| archive.unpack(new_dir))
|
||||
.map_err(err_str)?
|
||||
}
|
||||
"application/x-tar" => fs::File::open(path)
|
||||
.map(io::BufReader::new)
|
||||
.map(tar::Archive::new)
|
||||
|
|
@ -662,6 +666,24 @@ impl Operation {
|
|||
.map_err(err_str)?
|
||||
.and_then(|mut archive| archive.extract(new_dir))
|
||||
.map_err(err_str)?,
|
||||
#[cfg(feature = "bzip2")]
|
||||
"application/x-bzip" | "application/x-bzip-compressed-tar" => {
|
||||
fs::File::open(path)
|
||||
.map(io::BufReader::new)
|
||||
.map(bzip2::read::BzDecoder::new)
|
||||
.map(tar::Archive::new)
|
||||
.and_then(|mut archive| archive.unpack(new_dir))
|
||||
.map_err(err_str)?
|
||||
}
|
||||
#[cfg(feature = "liblzma")]
|
||||
"application/x-xz" | "application/x-xz-compressed-tar" => {
|
||||
fs::File::open(path)
|
||||
.map(io::BufReader::new)
|
||||
.map(liblzma::read::XzDecoder::new)
|
||||
.map(tar::Archive::new)
|
||||
.and_then(|mut archive| archive.unpack(new_dir))
|
||||
.map_err(err_str)?
|
||||
}
|
||||
_ => Err(format!("unsupported mime type {:?}", mime))?,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
378
src/tab.rs
378
src/tab.rs
|
|
@ -55,7 +55,7 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
app::{self, Action},
|
||||
app::{self, Action, PreviewItem, PreviewKind},
|
||||
clipboard::{ClipboardCopy, ClipboardKind, ClipboardPaste},
|
||||
config::{IconSizes, TabConfig, ICON_SCALE_MAX, ICON_SIZE_GRID},
|
||||
dialog::DialogKind,
|
||||
|
|
@ -687,11 +687,9 @@ fn uri_to_path(uri: String) -> Option<PathBuf> {
|
|||
}
|
||||
|
||||
pub fn scan_recents(sizes: IconSizes) -> Vec<Item> {
|
||||
let mut recent_files = recently_used_xbel::parse_file();
|
||||
|
||||
let mut recents = Vec::new();
|
||||
|
||||
match recent_files {
|
||||
match recently_used_xbel::parse_file() {
|
||||
Ok(recent_files) => {
|
||||
for bookmark in recent_files.bookmarks {
|
||||
let uri = bookmark.href;
|
||||
|
|
@ -814,11 +812,12 @@ pub enum Command {
|
|||
DropFiles(PathBuf, ClipboardPaste),
|
||||
EmptyTrash,
|
||||
Iced(cosmic::Command<Message>),
|
||||
LocationProperties(usize),
|
||||
MoveToTrash(Vec<PathBuf>),
|
||||
OpenFile(PathBuf),
|
||||
OpenInNewTab(PathBuf),
|
||||
OpenInNewWindow(PathBuf),
|
||||
Preview(PreviewKind, Duration),
|
||||
PreviewCancel,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
@ -850,6 +849,7 @@ pub enum Message {
|
|||
RightClick(Option<usize>),
|
||||
MiddleClick(usize),
|
||||
Scroll(Viewport),
|
||||
ScrollToFocus,
|
||||
SelectAll,
|
||||
SetSort(HeadingOptions, bool),
|
||||
Thumbnail(PathBuf, ItemThumbnail),
|
||||
|
|
@ -870,7 +870,7 @@ pub enum Message {
|
|||
pub enum LocationMenuAction {
|
||||
OpenInNewTab(usize),
|
||||
OpenInNewWindow(usize),
|
||||
Properties(usize),
|
||||
Preview(usize),
|
||||
}
|
||||
|
||||
impl MenuAction for LocationMenuAction {
|
||||
|
|
@ -1003,7 +1003,7 @@ impl Item {
|
|||
if let Some(Location::Path(path)) = &self.location_opt {
|
||||
for app in self.open_with.iter() {
|
||||
column = column.push(
|
||||
widget::button(
|
||||
widget::button::custom(
|
||||
widget::row::with_children(vec![
|
||||
widget::icon(app.icon.clone()).into(),
|
||||
if app.is_default {
|
||||
|
|
@ -1230,6 +1230,7 @@ pub struct Tab {
|
|||
cached_selected: RefCell<Option<bool>>,
|
||||
clicked: Option<usize>,
|
||||
selected_clicked: bool,
|
||||
last_right_click: Option<usize>,
|
||||
}
|
||||
|
||||
fn folder_name<P: AsRef<Path>>(path: P) -> (String, bool) {
|
||||
|
|
@ -1276,6 +1277,7 @@ impl Tab {
|
|||
clicked: None,
|
||||
dnd_hovered: None,
|
||||
selected_clicked: false,
|
||||
last_right_click: None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1551,6 +1553,7 @@ impl Tab {
|
|||
self.location = location.clone();
|
||||
self.items_opt = None;
|
||||
self.select_focus = None;
|
||||
self.context_menu = None;
|
||||
self.edit_location = None;
|
||||
if let Some(history_i) = history_i_opt {
|
||||
// Navigating in history
|
||||
|
|
@ -1571,6 +1574,7 @@ impl Tab {
|
|||
let mut history_i_opt = None;
|
||||
let mod_ctrl = modifiers.contains(Modifiers::CTRL) && self.mode.multiple();
|
||||
let mod_shift = modifiers.contains(Modifiers::SHIFT) && self.mode.multiple();
|
||||
let last_select_focus = self.select_focus;
|
||||
match message {
|
||||
Message::AddNetworkDrive => {
|
||||
commands.push(Command::AddNetworkDrive);
|
||||
|
|
@ -1624,6 +1628,9 @@ impl Tab {
|
|||
} else {
|
||||
log::warn!("no item for click index {:?}", click_i_opt);
|
||||
}
|
||||
|
||||
// Cancel any preview timers
|
||||
commands.push(Command::PreviewCancel);
|
||||
}
|
||||
Message::Click(click_i_opt) => {
|
||||
self.selected_clicked = false;
|
||||
|
|
@ -1739,7 +1746,7 @@ impl Tab {
|
|||
item.selected = true;
|
||||
self.select_range = Some((i, i));
|
||||
}
|
||||
|
||||
self.select_focus = click_i_opt;
|
||||
self.selected_clicked = true;
|
||||
} else if !dont_unset && item.selected {
|
||||
self.clicked = click_i_opt;
|
||||
|
|
@ -1747,10 +1754,6 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
}
|
||||
if self.select_focus.take().is_some() {
|
||||
// Unfocus currently focused button
|
||||
commands.push(Command::Iced(widget::button::focus(widget::Id::unique())));
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::Config(config) => {
|
||||
|
|
@ -1765,6 +1768,14 @@ impl Tab {
|
|||
Message::ContextMenu(point_opt) => {
|
||||
if point_opt.is_none() || !mod_shift {
|
||||
self.context_menu = point_opt;
|
||||
//TODO: hack for clearing selecting when right clicking empty space
|
||||
if self.context_menu.is_some() && self.last_right_click.take().is_none() {
|
||||
if let Some(ref mut items) = self.items_opt {
|
||||
for item in items.iter_mut() {
|
||||
item.selected = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::LocationContextMenuPoint(point_opt) => {
|
||||
|
|
@ -1795,8 +1806,22 @@ impl Tab {
|
|||
commands.push(Command::OpenInNewWindow(path));
|
||||
}
|
||||
}
|
||||
LocationMenuAction::Properties(ancestor_index) => {
|
||||
commands.push(Command::LocationProperties(ancestor_index));
|
||||
LocationMenuAction::Preview(ancestor_index) => {
|
||||
if let Some(path) = path_for_index(ancestor_index) {
|
||||
//TODO: blocking code, run in command
|
||||
match item_from_path(&path, IconSizes::default()) {
|
||||
Ok(item) => {
|
||||
// Show preview instantly
|
||||
commands.push(Command::Preview(
|
||||
PreviewKind::Custom(PreviewItem(item)),
|
||||
Duration::new(0, 0),
|
||||
));
|
||||
}
|
||||
Err(err) => {
|
||||
log::warn!("failed to get item from path {:?}: {}", path, err);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2039,6 +2064,8 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
}
|
||||
//TODO: hack for clearing selecting when right clicking empty space
|
||||
self.last_right_click = click_i_opt;
|
||||
}
|
||||
Message::MiddleClick(click_i) => {
|
||||
self.update(Message::Click(Some(click_i)), modifiers);
|
||||
|
|
@ -2070,6 +2097,14 @@ impl Tab {
|
|||
Message::Scroll(viewport) => {
|
||||
self.scroll_opt = Some(viewport.absolute_offset());
|
||||
}
|
||||
Message::ScrollToFocus => {
|
||||
if let Some(offset) = self.select_focus_scroll() {
|
||||
commands.push(Command::Iced(scrollable::scroll_to(
|
||||
self.scrollable_id.clone(),
|
||||
offset,
|
||||
)));
|
||||
}
|
||||
}
|
||||
Message::SelectAll => {
|
||||
self.select_all();
|
||||
if self.select_focus.take().is_some() {
|
||||
|
|
@ -2094,7 +2129,8 @@ impl Tab {
|
|||
rgba.as_raw().clone(),
|
||||
);
|
||||
item.icon_handle_grid = handle.clone();
|
||||
item.icon_handle_list = handle;
|
||||
item.icon_handle_list = handle.clone();
|
||||
item.icon_handle_list_condensed = handle;
|
||||
}
|
||||
item.thumbnail_opt = Some(thumbnail);
|
||||
break;
|
||||
|
|
@ -2146,9 +2182,11 @@ impl Tab {
|
|||
self.dnd_hovered = None;
|
||||
}
|
||||
Message::DndHover(loc) => {
|
||||
if self.dnd_hovered.as_ref().is_some_and(|(l, i)| {
|
||||
*l == loc && Instant::now().duration_since(*i) > HOVER_DURATION
|
||||
}) {
|
||||
if self
|
||||
.dnd_hovered
|
||||
.as_ref()
|
||||
.is_some_and(|(l, i)| *l == loc && i.elapsed() > HOVER_DURATION)
|
||||
{
|
||||
cd = Some(loc);
|
||||
}
|
||||
}
|
||||
|
|
@ -2163,6 +2201,9 @@ impl Tab {
|
|||
|x| x,
|
||||
)));
|
||||
}
|
||||
|
||||
// Clear preview timer
|
||||
commands.push(Command::PreviewCancel);
|
||||
}
|
||||
Message::DndLeave(loc) => {
|
||||
if Some(&loc) == self.dnd_hovered.as_ref().map(|(l, _)| l) {
|
||||
|
|
@ -2212,6 +2253,26 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update preview timer
|
||||
//TODO: make this configurable
|
||||
if last_select_focus != self.select_focus {
|
||||
if let Some(index) = self.select_focus {
|
||||
if let Some(ref items) = self.items_opt {
|
||||
if let Some(item) = items.get(index) {
|
||||
if let Some(location) = item.location_opt.clone() {
|
||||
// Show preview after double click timeout
|
||||
commands.push(Command::Preview(
|
||||
PreviewKind::Location(location),
|
||||
DOUBLE_CLICK_DURATION,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Change directory if requested
|
||||
if let Some(location) = cd {
|
||||
if matches!(self.mode, Mode::Desktop) {
|
||||
match location {
|
||||
|
|
@ -2238,6 +2299,7 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
commands
|
||||
}
|
||||
|
||||
|
|
@ -2322,6 +2384,58 @@ impl Tab {
|
|||
Some(items)
|
||||
}
|
||||
|
||||
fn dnd_dest<'a>(
|
||||
&self,
|
||||
location: &Location,
|
||||
element: impl Into<Element<'a, Message>>,
|
||||
) -> Element<'a, Message> {
|
||||
let location1 = location.clone();
|
||||
let location2 = location.clone();
|
||||
let location3 = location.clone();
|
||||
let is_dnd_hovered = self.dnd_hovered.as_ref().map(|(l, _)| l) == Some(&location);
|
||||
widget::container(
|
||||
DndDestination::for_data::<ClipboardPaste>(element, move |data, action| {
|
||||
if let Some(mut data) = data {
|
||||
if action == DndAction::Copy {
|
||||
Message::Drop(Some((location1.clone(), data)))
|
||||
} else if action == DndAction::Move {
|
||||
data.kind = ClipboardKind::Cut;
|
||||
Message::Drop(Some((location1.clone(), data)))
|
||||
} else {
|
||||
log::warn!("unsupported action: {:?}", action);
|
||||
Message::Drop(None)
|
||||
}
|
||||
} else {
|
||||
Message::Drop(None)
|
||||
}
|
||||
})
|
||||
.on_enter(move |_, _, _| Message::DndEnter(location2.clone()))
|
||||
.on_leave(move || Message::DndLeave(location3.clone())),
|
||||
)
|
||||
.style(if is_dnd_hovered {
|
||||
theme::Container::custom(|t| {
|
||||
let mut a = cosmic::iced_style::container::StyleSheet::appearance(
|
||||
t,
|
||||
&theme::Container::default(),
|
||||
);
|
||||
let t = t.cosmic();
|
||||
// todo use theme drop target color
|
||||
let mut bg = t.accent_color();
|
||||
bg.alpha = 0.2;
|
||||
a.background = Some(Color::from(bg).into());
|
||||
a.border = Border {
|
||||
color: t.accent_color().into(),
|
||||
width: 1.0,
|
||||
radius: t.radius_s().into(),
|
||||
};
|
||||
a
|
||||
})
|
||||
} else {
|
||||
theme::Container::default()
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
||||
pub fn location_view(&self) -> Element<Message> {
|
||||
//TODO: responsiveness is done in a hacky way, potentially move this to a custom widget?
|
||||
fn text_width<'a>(
|
||||
|
|
@ -2375,7 +2489,7 @@ impl Tab {
|
|||
let mut w = 0.0;
|
||||
|
||||
let mut prev_button =
|
||||
widget::button(widget::icon::from_name("go-previous-symbolic").size(16))
|
||||
widget::button::custom(widget::icon::from_name("go-previous-symbolic").size(16))
|
||||
.padding(space_xxs)
|
||||
.style(theme::Button::Icon);
|
||||
if self.history_i > 0 && !self.history.is_empty() {
|
||||
|
|
@ -2384,9 +2498,10 @@ impl Tab {
|
|||
row = row.push(prev_button);
|
||||
w += 16.0 + 2.0 * space_xxs as f32;
|
||||
|
||||
let mut next_button = widget::button(widget::icon::from_name("go-next-symbolic").size(16))
|
||||
.padding(space_xxs)
|
||||
.style(theme::Button::Icon);
|
||||
let mut next_button =
|
||||
widget::button::custom(widget::icon::from_name("go-next-symbolic").size(16))
|
||||
.padding(space_xxs)
|
||||
.style(theme::Button::Icon);
|
||||
if self.history_i + 1 < self.history.len() {
|
||||
next_button = next_button.on_press(Message::GoNext);
|
||||
}
|
||||
|
|
@ -2442,10 +2557,12 @@ impl Tab {
|
|||
match location {
|
||||
Location::Path(path) => {
|
||||
row = row.push(
|
||||
widget::button(widget::icon::from_name("window-close-symbolic").size(16))
|
||||
.on_press(Message::EditLocation(None))
|
||||
.padding(space_xxs)
|
||||
.style(theme::Button::Icon),
|
||||
widget::button::custom(
|
||||
widget::icon::from_name("window-close-symbolic").size(16),
|
||||
)
|
||||
.on_press(Message::EditLocation(None))
|
||||
.padding(space_xxs)
|
||||
.style(theme::Button::Icon),
|
||||
);
|
||||
row = row.push(
|
||||
widget::text_input("", path.to_string_lossy())
|
||||
|
|
@ -2479,7 +2596,7 @@ impl Tab {
|
|||
} else if let Location::Path(path) = &self.location {
|
||||
row = row.push(
|
||||
crate::mouse_area::MouseArea::new(
|
||||
widget::button(widget::icon::from_name("edit-symbolic").size(16))
|
||||
widget::button::custom(widget::icon::from_name("edit-symbolic").size(16))
|
||||
.padding(space_xxs)
|
||||
.style(theme::Button::Icon)
|
||||
.on_press(Message::EditLocation(Some(self.location.clone()))),
|
||||
|
|
@ -2489,7 +2606,7 @@ impl Tab {
|
|||
w += 16.0 + 2.0 * space_xxs as f32;
|
||||
} else if let Location::Search(_, term) = &self.location {
|
||||
row = row.push(
|
||||
widget::button(
|
||||
widget::button::custom(
|
||||
widget::row::with_children(vec![
|
||||
widget::icon::from_name("system-search-symbolic")
|
||||
.size(16)
|
||||
|
|
@ -2547,17 +2664,19 @@ impl Tab {
|
|||
w += name_width;
|
||||
}
|
||||
|
||||
let location = match &self.location {
|
||||
Location::Path(_) => Location::Path(ancestor.to_path_buf()),
|
||||
Location::Search(_, term) => {
|
||||
Location::Search(ancestor.to_path_buf(), term.clone())
|
||||
}
|
||||
other => other.clone(),
|
||||
};
|
||||
|
||||
let mut mouse_area = crate::mouse_area::MouseArea::new(
|
||||
widget::button(row)
|
||||
widget::button::custom(row)
|
||||
.padding(space_xxxs)
|
||||
.style(theme::Button::Link)
|
||||
.on_press(Message::Location(match &self.location {
|
||||
Location::Path(_) => Location::Path(ancestor.to_path_buf()),
|
||||
Location::Search(_, term) => {
|
||||
Location::Search(ancestor.to_path_buf(), term.clone())
|
||||
}
|
||||
other => other.clone(),
|
||||
})),
|
||||
.on_press(Message::Location(location.clone())),
|
||||
);
|
||||
|
||||
if self.location_context_menu_index.is_some() {
|
||||
|
|
@ -2577,7 +2696,7 @@ impl Tab {
|
|||
mouse_area
|
||||
};
|
||||
|
||||
children.push(mouse_area.into());
|
||||
children.push(self.dnd_dest(&location, mouse_area));
|
||||
|
||||
if found_home || overflow {
|
||||
break;
|
||||
|
|
@ -2587,7 +2706,7 @@ impl Tab {
|
|||
}
|
||||
Location::Trash => {
|
||||
children.push(
|
||||
widget::button(widget::text::heading(fl!("trash")))
|
||||
widget::button::custom(widget::text::heading(fl!("trash")))
|
||||
.padding(space_xxxs)
|
||||
.on_press(Message::Location(Location::Trash))
|
||||
.style(theme::Button::Text)
|
||||
|
|
@ -2596,7 +2715,7 @@ impl Tab {
|
|||
}
|
||||
Location::Recents => {
|
||||
children.push(
|
||||
widget::button(widget::text::heading(fl!("recents")))
|
||||
widget::button::custom(widget::text::heading(fl!("recents")))
|
||||
.padding(space_xxxs)
|
||||
.on_press(Message::Location(Location::Recents))
|
||||
.style(theme::Button::Text)
|
||||
|
|
@ -2605,7 +2724,7 @@ impl Tab {
|
|||
}
|
||||
Location::Network(uri, display_name) => {
|
||||
children.push(
|
||||
widget::button(widget::text::heading(display_name))
|
||||
widget::button::custom(widget::text::heading(display_name))
|
||||
.padding(space_xxxs)
|
||||
.on_press(Message::Location(Location::Network(
|
||||
uri.clone(),
|
||||
|
|
@ -2776,14 +2895,14 @@ impl Tab {
|
|||
|
||||
//TODO: one focus group per grid item (needs custom widget)
|
||||
let buttons = vec![
|
||||
widget::button(
|
||||
widget::button::custom(
|
||||
widget::icon::icon(item.icon_handle_grid.clone())
|
||||
.content_fit(ContentFit::Contain)
|
||||
.size(icon_sizes.grid()),
|
||||
)
|
||||
.padding(space_xxxs)
|
||||
.style(button_style(item.selected, false, false, false)),
|
||||
widget::button(widget::text::body(&item.display_name))
|
||||
widget::button::custom(widget::text::body(&item.display_name))
|
||||
.id(item.button_id.clone())
|
||||
.padding([0, space_xxxs])
|
||||
.style(button_style(
|
||||
|
|
@ -2810,58 +2929,12 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
|
||||
let column: Element<Message> = if item.metadata.is_dir()
|
||||
&& item.location_opt.is_some()
|
||||
{
|
||||
let tab_location = item.location_opt.clone().unwrap();
|
||||
let tab_location_enter = tab_location.clone();
|
||||
let tab_location_leave = tab_location.clone();
|
||||
let is_dnd_hovered =
|
||||
self.dnd_hovered.as_ref().map(|(l, _)| l) == Some(&tab_location);
|
||||
cosmic::widget::container(
|
||||
DndDestination::for_data::<ClipboardPaste>(column, move |data, action| {
|
||||
if let Some(mut data) = data {
|
||||
if action == DndAction::Copy {
|
||||
Message::Drop(Some((tab_location.clone(), data)))
|
||||
} else if action == DndAction::Move {
|
||||
data.kind = ClipboardKind::Cut;
|
||||
Message::Drop(Some((tab_location.clone(), data)))
|
||||
} else {
|
||||
log::warn!("unsupported action: {:?}", action);
|
||||
Message::Drop(None)
|
||||
}
|
||||
} else {
|
||||
Message::Drop(None)
|
||||
}
|
||||
})
|
||||
.on_enter(move |_, _, _| Message::DndEnter(tab_location_enter.clone()))
|
||||
.on_leave(move || Message::DndLeave(tab_location_leave.clone())),
|
||||
)
|
||||
.style(if is_dnd_hovered {
|
||||
theme::Container::custom(|t| {
|
||||
let mut a = cosmic::iced_style::container::StyleSheet::appearance(
|
||||
t,
|
||||
&theme::Container::default(),
|
||||
);
|
||||
let t = t.cosmic();
|
||||
// todo use theme drop target color
|
||||
let mut bg = t.accent_color();
|
||||
bg.alpha = 0.2;
|
||||
a.background = Some(Color::from(bg).into());
|
||||
a.border = Border {
|
||||
color: t.accent_color().into(),
|
||||
width: 1.0,
|
||||
radius: t.radius_s().into(),
|
||||
};
|
||||
a
|
||||
})
|
||||
let column: Element<Message> =
|
||||
if item.metadata.is_dir() && item.location_opt.is_some() {
|
||||
self.dnd_dest(&item.location_opt.clone().unwrap(), column)
|
||||
} else {
|
||||
theme::Container::default()
|
||||
})
|
||||
.into()
|
||||
} else {
|
||||
column.into()
|
||||
};
|
||||
column.into()
|
||||
};
|
||||
|
||||
if item.selected {
|
||||
dnd_items.push((i, (row, col), item));
|
||||
|
|
@ -2962,7 +3035,7 @@ impl Tab {
|
|||
};
|
||||
if *row == r && *col == c {
|
||||
let buttons = vec![
|
||||
widget::button(
|
||||
widget::button::custom(
|
||||
widget::icon::icon(item.icon_handle_grid.clone())
|
||||
.content_fit(ContentFit::Contain)
|
||||
.size(icon_sizes.grid()),
|
||||
|
|
@ -2975,7 +3048,7 @@ impl Tab {
|
|||
false,
|
||||
false,
|
||||
)),
|
||||
widget::button(widget::text(item.display_name.clone()))
|
||||
widget::button::custom(widget::text(item.display_name.clone()))
|
||||
.id(item.button_id.clone())
|
||||
.on_press(Message::Click(Some(*i)))
|
||||
.padding([0, space_xxxs])
|
||||
|
|
@ -3043,7 +3116,8 @@ impl Tab {
|
|||
let modified_width = 200.0;
|
||||
let size_width = 100.0;
|
||||
let condensed = size.width < (name_width + modified_width + size_width);
|
||||
let icon_size = if condensed {
|
||||
let is_search = matches!(self.location, Location::Search(_, _));
|
||||
let icon_size = if condensed || is_search {
|
||||
icon_sizes.list_condensed()
|
||||
} else {
|
||||
icon_sizes.list()
|
||||
|
|
@ -3140,6 +3214,32 @@ impl Tab {
|
|||
.height(Length::Fixed(row_height as f32))
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(space_xxs)
|
||||
} else if is_search {
|
||||
widget::row::with_children(vec![
|
||||
widget::icon::icon(item.icon_handle_list_condensed.clone())
|
||||
.content_fit(ContentFit::Contain)
|
||||
.size(icon_size)
|
||||
.into(),
|
||||
widget::column::with_children(vec![
|
||||
widget::text(item.display_name.clone()).into(),
|
||||
widget::text::caption(match item.path_opt() {
|
||||
Some(path) => path.display().to_string(),
|
||||
None => String::new(),
|
||||
})
|
||||
.into(),
|
||||
])
|
||||
.width(Length::Fill)
|
||||
.into(),
|
||||
widget::text(modified_text.clone())
|
||||
.width(Length::Fixed(modified_width))
|
||||
.into(),
|
||||
widget::text(size_text.clone())
|
||||
.width(Length::Fixed(size_width))
|
||||
.into(),
|
||||
])
|
||||
.height(Length::Fixed(row_height as f32))
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(space_xxs)
|
||||
} else {
|
||||
widget::row::with_children(vec![
|
||||
widget::icon::icon(item.icon_handle_list.clone())
|
||||
|
|
@ -3163,7 +3263,7 @@ impl Tab {
|
|||
|
||||
let button = |row| {
|
||||
let mouse_area = crate::mouse_area::MouseArea::new(
|
||||
widget::button(row)
|
||||
widget::button::custom(row)
|
||||
.width(Length::Fill)
|
||||
.id(item.button_id.clone())
|
||||
.padding([0, space_xxs])
|
||||
|
|
@ -3186,54 +3286,7 @@ impl Tab {
|
|||
let button_row = button(row.into());
|
||||
let button_row: Element<_> =
|
||||
if item.metadata.is_dir() && item.location_opt.is_some() {
|
||||
let tab_location = item.location_opt.clone().unwrap();
|
||||
let tab_location_enter = tab_location.clone();
|
||||
let tab_location_leave = tab_location.clone();
|
||||
let is_dnd_hovered =
|
||||
self.dnd_hovered.as_ref().map(|(l, _)| l) == Some(&tab_location);
|
||||
cosmic::widget::container(
|
||||
DndDestination::for_data(button_row, move |data, action| {
|
||||
if let Some(mut data) = data {
|
||||
if action == DndAction::Copy {
|
||||
Message::Drop(Some((tab_location.clone(), data)))
|
||||
} else if action == DndAction::Move {
|
||||
data.kind = ClipboardKind::Cut;
|
||||
Message::Drop(Some((tab_location.clone(), data)))
|
||||
} else {
|
||||
log::warn!("unsupported action: {:?}", action);
|
||||
Message::Drop(None)
|
||||
}
|
||||
} else {
|
||||
log::warn!("No data for drop.");
|
||||
Message::Drop(None)
|
||||
}
|
||||
})
|
||||
.on_enter(move |_, _, _| Message::DndEnter(tab_location_enter.clone()))
|
||||
.on_leave(move || Message::DndLeave(tab_location_leave.clone())),
|
||||
)
|
||||
// todo refactor into the dnd destination wrapper
|
||||
.style(if is_dnd_hovered {
|
||||
theme::Container::custom(|t| {
|
||||
let mut a = cosmic::iced_style::container::StyleSheet::appearance(
|
||||
t,
|
||||
&theme::Container::default(),
|
||||
);
|
||||
let t = t.cosmic();
|
||||
// todo use theme drop target color
|
||||
let mut bg = t.accent_color();
|
||||
bg.alpha = 0.2;
|
||||
a.background = Some(Color::from(bg).into());
|
||||
a.border = Border {
|
||||
color: t.accent_color().into(),
|
||||
width: 1.0,
|
||||
radius: t.radius_s().into(),
|
||||
};
|
||||
a
|
||||
})
|
||||
} else {
|
||||
theme::Container::default()
|
||||
})
|
||||
.into()
|
||||
self.dnd_dest(item.location_opt.as_ref().unwrap(), button_row)
|
||||
} else {
|
||||
button_row.into()
|
||||
};
|
||||
|
|
@ -3257,6 +3310,32 @@ impl Tab {
|
|||
.align_items(Alignment::Center)
|
||||
.spacing(space_xxs)
|
||||
.into()
|
||||
} else if is_search {
|
||||
widget::row::with_children(vec![
|
||||
widget::icon::icon(item.icon_handle_list_condensed.clone())
|
||||
.content_fit(ContentFit::Contain)
|
||||
.size(icon_size)
|
||||
.into(),
|
||||
widget::column::with_children(vec![
|
||||
widget::text(item.display_name.clone()).into(),
|
||||
widget::text::caption(match item.path_opt() {
|
||||
Some(path) => path.display().to_string(),
|
||||
None => String::new(),
|
||||
})
|
||||
.into(),
|
||||
])
|
||||
.width(Length::Fill)
|
||||
.into(),
|
||||
widget::text(modified_text.clone())
|
||||
.width(Length::Fixed(modified_width))
|
||||
.into(),
|
||||
widget::text(size_text.clone())
|
||||
.width(Length::Fixed(size_width))
|
||||
.into(),
|
||||
])
|
||||
.align_items(Alignment::Center)
|
||||
.spacing(space_xxs)
|
||||
.into()
|
||||
} else {
|
||||
widget::row::with_children(vec![
|
||||
widget::icon::icon(item.icon_handle_list.clone())
|
||||
|
|
@ -3299,7 +3378,7 @@ impl Tab {
|
|||
}
|
||||
//TODO: HACK If we don't reach the bottom of the view, go ahead and add a spacer to do that
|
||||
{
|
||||
let top_deduct = (if condensed { 6 } else { 9 }) * space_xxs;
|
||||
let top_deduct = (if condensed || is_search { 6 } else { 9 }) * space_xxs;
|
||||
|
||||
self.item_view_size_opt
|
||||
.set(self.size_opt.get().map(|s| Size {
|
||||
|
|
@ -3394,6 +3473,8 @@ impl Tab {
|
|||
let mut mouse_area = mouse_area::MouseArea::new(item_view)
|
||||
.on_press(move |_point_opt| Message::Click(None))
|
||||
.on_release(|_| Message::ClickRelease(None))
|
||||
//TODO: better way to keep focused item in view
|
||||
.on_resize(|_| Message::ScrollToFocus)
|
||||
.on_back_press(move |_point_opt| Message::GoPrevious)
|
||||
.on_forward_press(move |_point_opt| Message::GoNext)
|
||||
.on_scroll(respond_to_scroll_direction);
|
||||
|
|
@ -3591,10 +3672,7 @@ impl Tab {
|
|||
}
|
||||
}
|
||||
|
||||
//TODO: how to properly kill this task?
|
||||
loop {
|
||||
tokio::time::sleep(std::time::Duration::new(1, 0)).await;
|
||||
}
|
||||
std::future::pending().await
|
||||
},
|
||||
));
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue